#405 add TEST_SKIP_MISSING_DEVICE
Merged 2 years ago by astepano. Opened 2 years ago by rmeggins.
rmeggins/standard-test-roles nvme-check  into  master

file modified
+8
@@ -215,5 +215,13 @@ 

  `--sshd-usedns-no` or set `TEST_SSHD_USEDNS_NO=True` to configure the VM to use

  `UseDNS no` instead.

  

+ ## TEST_SKIP_MISSING_DEVICE

+ 

+ If you are using the same provision.fmf on multiple systems, the qemu on some

+ systems may not support all of the specified devices.  For example, qemu on many

+ platforms does not support NVMe.  By default, the script will issue an error if

+ you attempt to use an unsupported device. Use this flag to skip missing devices,

+ with a warning.

Is this boolean, which takes yes|no?

+ 

  [1]: https://fedoraproject.org/wiki/CI/Metadata

  [2]: http://fmf.readthedocs.io/

@@ -101,7 +101,7 @@ 

      _tempfiles = list()

  

      @classmethod

-     def generate(cls):

+     def generate(cls, supported_devices, skip_missing_device):

          """Generate sparse files and return drive qemu options

          Returns

          -------
@@ -127,16 +127,26 @@ 

              if interface is None or interface.lower() == 'virtio':

                  result += ["-drive", "file=%s,media=disk,if=virtio" % drive_file.name]

              elif interface.lower() == 'nvme':

-                 result += ["-device", "nvme,drive=nvme%s,serial=def%s" % (dev_id, dev_id)]

-                 result += ["-drive", "file=%s,media=disk,if=none,id=nvme%s" % (drive_file.name, dev_id)]

-                 dev_id += 1

+                 if 'nvme' in supported_devices:

+                     result += ["-device", "nvme,drive=nvme%s,serial=def%s" % (dev_id, dev_id)]

+                     result += ["-drive", "file=%s,media=disk,if=none,id=nvme%s" % (drive_file.name, dev_id)]

+                     dev_id += 1

+                 elif not skip_missing_device:

+                     raise Exception("Cannot use device of size '%d' - no NVMe support on this platform" % size)

+                 else:

+                     logger.warn("NVMe drive of size '%d' will be skipped - no NVMe support on this platform", size)

              elif interface.lower() == 'scsi':

-                 if not scsi_device_exists:

-                     result += ["-device", "virtio-scsi-pci,id=scsi0"]

-                     scsi_device_exists = True

-                 result += ["-device", "scsi-hd,drive=drive%s,bus=scsi0.0" % dev_id]

-                 result += ["-drive", "if=none,file=%s,id=drive%s" % (drive_file.name, dev_id)]

-                 dev_id += 1

+                 if 'scsi' in supported_devices:

+                     if not scsi_device_exists:

+                         result += ["-device", "virtio-scsi-pci,id=scsi0"]

+                         scsi_device_exists = True

+                     result += ["-device", "scsi-hd,drive=drive%s,bus=scsi0.0" % dev_id]

+                     result += ["-drive", "if=none,file=%s,id=drive%s" % (drive_file.name, dev_id)]

+                     dev_id += 1

+                 elif not skip_missing_device:

+                     raise Exception("Cannot use device of size '%d' - no SCSI support on this platform" % size)

+                 else:

+                     logger.warn("SCSI drive of size '%d' will be skipped - no SCSI support on this platform", size)

  

          usb_drives = fmf_get(['qemu', 'usb_drive'], list())

          if usb_drives:
@@ -329,7 +339,7 @@ 

      return value

  

  

- def start_qemu(image, cloudinit, portrange=(2222, 5555)):

+ def start_qemu(image, cloudinit, skip_missing_device, portrange=(2222, 5555)):

      for _ in range(10):

          port = random.randint(*portrange)

          sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
@@ -422,6 +432,25 @@ 

              pass

      if virtio_rng:

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

+     # check for supported devices

+     # - key is the name used in provision.fmf

+     # - value is the name used by qemu

+     supported_devices = {"nvme": "nvme",

+                          "scsi": "virtio-scsi-pci"}

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

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

+     )

+     for name, qemu_name in list(supported_devices.items()):

+         try:

+             subprocess.check_call(

+                 cmd_tmpl % qemu_name,

+                 stdout=subprocess.DEVNULL,

+                 stderr=subprocess.DEVNULL,

+                 shell=True

+             )

+         except subprocess.CalledProcessError:

+             del supported_devices[name]

+ 

      # Assemble QEMU command with its parameters:

      qemu_cmd = [

          qemu_path
@@ -451,7 +480,7 @@ 

          # Log all traffic received from the guest to log_quest

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

      ]

-     qemu_cmd += AdditionalDrives.generate()

+     qemu_cmd += AdditionalDrives.generate(supported_devices, skip_missing_device)

      if diagnose:

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

      # Launch QEMU:
@@ -510,7 +539,7 @@ 

      log = None

      for _ in range(0, 5):

          try:

-             proc, port, log = start_qemu(image, cloudinit)

+             proc, port, log = start_qemu(image, cloudinit, opts.skip_missing_device)

              break

          except subprocess.CalledProcessError as cpe:

              time.sleep(1)
@@ -674,6 +703,14 @@ 

      --sshd-usedns-no to configure the VM to use 'UseDNS no' instead."""

  

  

+ def help_skip_missing_device():

+     return """If you are using the same provision.fmf on multiple systems, the

+     qemu on some systems may not support all of the specified devices.  For

+     example, qemu on many platforms does not support NVMe.  By default, the

+     script will issue an error if you attempt to use an unsupported device.

+     Use this flag to skip missing devices, with a warning."""

+ 

+ 

  def main():

      global logger

      global diagnose
@@ -704,6 +741,7 @@ 

      parser.add_argument("--use-basename", default=bool(distutils.util.strtobool(os.environ.get("TEST_USE_BASENAME", "False"))), action="store_true", help=help_hostalias())

      parser.add_argument("--hostalias", default=shlex.split(os.environ.get("TEST_HOSTALIASES", "")), action="append", help=help_hostalias())

      parser.add_argument("--sshd-usedns-no", default=bool(distutils.util.strtobool(os.environ.get("TEST_SSHD_USEDNS_NO", "False"))), action="store_true", help=help_sshd_usedns_no())

+     parser.add_argument("--skip-missing-device", default=bool(distutils.util.strtobool(os.environ.get("TEST_SKIP_MISSING_DEVICE", "False"))), action="store_true", help=help_skip_missing_device())

      parser.add_argument("subjects", nargs="*", default=shlex.split(os.environ.get("TEST_SUBJECTS", "")))

      opts = parser.parse_args()

      # Send logs to common logfile for all default provisioners.

If you are using the same provision.fmf on multiple systems, the qemu on some
systems may not support all of the specified devices. For example, qemu on many
platforms does not support NVMe. By default, the script will issue an error if
you attempt to use an unsupported device. Use this flag to skip missing devices,
with a warning.

Is this boolean, which takes yes|no?

Is this boolean, which takes yes|no?

yes, it is a boolean
It takes "True" or "False" - whatever is processed by the argument to distutils.util.strtobool

All right. Thanks!
lgtm

This PR is ready to be merged

I wonder, if it would be easier to read if include directly -device nvme
This command is used only once: to check if nvme is available.
Double template is a bit confusing.

Is there way how to improve this function call?
Point is: nvme_support is very specific.
skip_missing_device is more common.
Imagine you add another arg: 'XXX_is_supported'... then it will become 3rd argument:
def generate(cls, nvme_support, skip_missing_device, xxx_is_supported)
Please rename nvme_support to nvme_is_supported
Or maybe pass dictionary: supported_dev[] = ['nvme' : True/False]

1 new commit added

  • use supported_devices instead of nvme_support
2 years ago

Is there way how to improve this function call?
Point is: nvme_support is very specific.
skip_missing_device is more common.
Imagine you add another arg: 'XXX_is_supported'... then it will become 3rd argument:
def generate(cls, nvme_support, skip_missing_device, xxx_is_supported)
Please rename nvme_support to nvme_is_supported
Or maybe pass dictionary: supported_dev[] = ['nvme' : True/False]

I used the dictionary approach

This PR is ready to be merged.

@rmeggins thank you for contribution.

Commit 3ff8466 fixes this pull-request

Pull-Request has been merged by astepano

2 years ago

Pull-Request has been merged by astepano

2 years ago