#341 inventory/standard-inventory-qcow2: Support running on multiple architectures
Merged 4 years ago by astepano. Opened 4 years ago by jkucera.
jkucera/standard-test-roles python3-multiarch-standard-invertory-qcow2  into  master

@@ -22,6 +22,7 @@ 

  import logging

  import argparse

  import tempfile

+ import platform

  import functools

  import subprocess

  import distutils.util
@@ -137,12 +138,19 @@ 

      sys.stdout.write(json.dumps(bad_inv, indent=4, separators=(',', ': ')))

  

  

+ # See https://stackoverflow.com/questions/377017/test-if-executable-exists-in-python/377028#377028

  def which(executable, default=None):

-     for path in os.environ['PATH'].split(os.pathsep):

-         path = path.strip('"')

-         fpath = os.path.join(path, executable)

-         if os.path.isfile(fpath) and os.access(fpath, os.X_OK):

-             return fpath

+     def is_exe(fpath):

+         return os.path.isfile(fpath) and os.access(fpath, os.X_OK)

+     fpath, _ = os.path.split(executable)

+     if fpath:

+         if is_exe(executable):

+             return executable

+     else:

+         for path in os.environ['PATH'].split(os.pathsep):

+             exe_file = os.path.join(path, executable)

+             if is_exe(exe_file):

+                 return exe_file

      return default

  

  
@@ -284,22 +292,106 @@ 

      # Parameters from FMF:

      param_m = str(fmf_get(['qemu', 'm'], "1024"))

      param_net_nic_model = str(fmf_get(['qemu', 'net_nic', 'model'], 'virtio'))

-     # Use -cpu host and -smp by default.

-     path_lookups = ["/usr/bin/qemu-system-x86_64", "/usr/libexec/qemu-kvm"]

-     for qemu_path in path_lookups:

-         if os.path.exists(qemu_path):

+     # QEMU -M param.

+     # Most architectures do not need a -M flag, defaults are fine

+     qemu_M_param = []

+     # List of firmwares QEMU needs to work.

+     qemu_firmwares = []

+     # Common QEMU parameters used both to run VM and virtio-rng probing.

+     qemu_common_params = [

+         # Pass through CPU model of host

+         "-cpu", "host",

+         # Enable KVM full virtualization support

+         "-enable-kvm",

+         # Do not display video output

+         "-display", "none",

+         # Disable VGA card to avoid crash on ppc with PR

+         # https://lists.gnu.org/archive/html/qemu-devel/2018-05/msg07070.html

+         "-vga", "none"

+     ]

+     # Add platform specific settings:

+     if platform.machine() == "aarch64":

+         # Emulate the same generic interrupt controller as the host system has

+         qemu_M_param = ["-M", "virt,gic_version=host"]

+         # Add AAVMF firmware (without this, qemu-kvm will not work on ARM)

+         qemu_firmwares.extend([

+             "-drive", "%s,%s,%s,%s,%s" % (

+                 "file=/usr/share/AAVMF/AAVMF_CODE.fd",

+                 "if=pflash",

+                 "format=raw",

+                 "unit=0",

+                 "readonly=on"

+             )

+         ])

+     # Include -M param and firmwares to common params:

+     qemu_common_params.extend(qemu_M_param)

+     qemu_common_params.extend(qemu_firmwares)

+     # Lookup for qemu:

+     qemu_env = os.environ.get("QEMU_CMD")

+     if qemu_env:

+         path_lookups = [qemu_env]

+     else:

+         path_lookups = []

+     path_lookups.extend([

+         "qemu-kvm", "/usr/libexec/qemu-kvm", "/usr/bin/qemu-system-x86_64"

+     ])

+     for qemu_cmd in path_lookups:

+         qemu_path = which(qemu_cmd)

+         if qemu_path:

              break

+     # Try to probe virtio-rng device:

      # virtio-rng-pci: https://wiki.qemu.org/Features/VirtIORNG

-     qemu_cmd = [qemu_path,

-                 "-cpu", "host", "-smp", get_qemu_smp_arg(),

-                 "-m", param_m, image, "-enable-kvm", "-snapshot", "-cdrom", cloudinit,

-                 "-net", "nic,model=%s" % param_net_nic_model, "-net", "user,hostfwd=tcp:127.0.0.3:{0}-:22".format(port),

-                 "-device", "virtio-rng-pci", "-rtc", "base=utc",

-                 "-device", "isa-serial,chardev=pts2", "-chardev", "file,id=pts2,path=" + log_guest,

-                 "-display", "none"]

+     virtio_rng = []

+     cmd_tmpl = "echo quit | %s -device %%s -S -monitor stdio" % (

+         " ".join([qemu_path] + qemu_common_params)

+     )

+     for x in ["virtio-rng", "virtio-rng-pci", "virtio-rng-ccw"]:

+         try:

+             subprocess.check_call(

+                 cmd_tmpl % x,

+                 stdout=subprocess.DEVNULL,

+                 stderr=subprocess.DEVNULL,

+                 shell=True

+             )

+             virtio_rng = ["-device", x]

+             break

+         except subprocess.CalledProcessError:

+             pass

+     if virtio_rng:

+         logger.info("qemu-kvm is using %s device" % virtio_rng[1])

+     # Assemble QEMU command with its parameters:

+     qemu_cmd = [

+         qemu_path

+         # Add common parameters

+     ] + qemu_common_params + [

+         # Simulate SMP system with get_qemu_smp_arg() CPUs

+         "-smp", get_qemu_smp_arg(),

+         # Set startup RAM size

+         "-m", param_m,

+         # Add image with RHEL as drive (if=virtio is important for newer

+         # RHEL 8 images)

+         "-drive", "file={0},if=virtio".format(image),

+         # Write to temporary files instead of disk image files

+         "-snapshot",

+         # Use `cloudinit` as CD-ROM image

+         "-cdrom", cloudinit,

+         # Configure/create an on-board (or machine default) NIC

+         "-net", "nic,model=%s" % param_net_nic_model,

+         # Configure a host network backend

+         "-net", "user,hostfwd=tcp:127.0.0.3:{0}-:22".format(port)

+         # Add a source of randomness

+     ] + virtio_rng + [

+         # Let the RTC start at the current UTC

+         "-rtc", "base=utc",

+         # Connect the virtual serial port with pts2

+         "-serial", "chardev:pts2",

+         # Log all traffic received from the guest to log_quest

+         "-chardev", "file,id=pts2,path=" + log_guest

+     ]

      qemu_cmd += AdditionalDrives.generate()

      if diagnose:

          qemu_cmd += ["-vnc", DEF_HOST + ":1,to=4095"]

+     # Launch QEMU:

      qemu_proc = subprocess.Popen(qemu_cmd, stdout=open(log_qemu, 'a'), stderr=subprocess.STDOUT)

      time.sleep(5)

      if qemu_proc and diagnose:
@@ -350,7 +442,7 @@ 

      if proc is None:

          raise RuntimeError("Could not launch VM for qcow2 image"

                             " '{0}':{1}".format(image, cpe.output))

-     for _ in range(0, 30):

+     for _ in range(0, 600):

          try:

              # The variables

              variables = {

With these changes, it can be possible to use standard-inventory-qcow2 for running tests on multiple architectures. The proposed changes were tested on RHEL 8 and all its supported architectures: x86_64, aarch64, ppc64le, and s390x.

The purpose of these changes was the requirement of Quality Engineering to test rhel-system-roles on all supported architectures.

How standard-inventory-qcow2 was tested?

First, the Beaker machines were reserved:

(a) for x86_64:

wow rhel-8 --reserve --bare --arch x86_64 --edit

in job.xml, between <hostRequires><and>...</and></hostRequires>:

<cpu>
  <or>
    <flag op="=" value="vmx" />
    <flag op="=" value="svm" />
  </or>
</cpu>

(b) for aarch64:

wow rhel-8 --reserve --bare --arch aarch64

(c) for ppc64le:

wow rhel-8 --reserve --arch ppc64le --kernel-options-post=disable_radix --edit

in job.xml:

<hostRequires>
  <system>
    <or>
      <hypervisor op="=" value="" />
      <hypervisor op="=" value="PowerVM" />
    </or>
  </system>
</hostRequires>

(d) for s390x:

wow rhel-8 --reserve --arch s390x --edit

in job.xml:

<hostRequires>
  <system>
    <memory op=">=" value="2048" />
  </system>
</hostRequires>

Second, the beaker machines were prepared:

dnf -y install ansible qemu-kvm genisoimage rhel-system-roles python3-fmf

Finally, the test was run:

TEST_SUBJECTS=./rhel8-image-latest.$(uname -m).qcow2 ansible-playbook -vvv -i ./standard-inventory-qcow2 /usr/share/ansible/roles/rhel-system-roles.timesync/tests/tests_default.yml

2 new commits added

  • inventory/standard-inventory-qcow2: Support running on multiple architectures
  • inventory/standard-inventory-qcow2: Wait for SSH to come up a bit longer
4 years ago

2 new commits added

  • inventory/standard-inventory-qcow2: Support running on multiple architectures
  • inventory/standard-inventory-qcow2: Wait for SSH to come up a bit longer
4 years ago

Note: the idea is to launch a VM of the same architecture as the host we are running on. No cross-platform emulation is attempted (would probably be very slow).

Jenkins is failing, but this does not seem a problem in the PR. Jenkins log shows lots of "Permission denied" errors.

pretty please pagure-ci rebuild

4 years ago

2 new commits added

  • inventory/standard-inventory-qcow2: Support running on multiple architectures
  • inventory/standard-inventory-qcow2: Wait for SSH to come up a bit longer
4 years ago

pretty please pagure-ci rebuild

4 years ago

pretty please pagure-ci rebuild

4 years ago

@pcahyna @jkucera seems a great addition to the provisioner!
Thank you for the contribution.
CI passed. ACK to merge.

Commit 14022d5 fixes this pull-request

Pull-Request has been merged by astepano

4 years ago

Pull-Request has been merged by astepano

4 years ago