]> git.ipfire.org Git - thirdparty/libvirt.git/commitdiff
docs, conf, schemas: Add support for NVMe disks
authorMartin Kletzander <mkletzan@redhat.com>
Thu, 22 May 2025 13:47:27 +0000 (15:47 +0200)
committerMartin Kletzander <mkletzan@redhat.com>
Mon, 9 Jun 2025 13:12:39 +0000 (15:12 +0200)
NVMe disks are essentially a namespace of an NVMe controller, but to
make it easier for the users to just add a disk, the necessary details
like adding the proper controller, setting the serial number for the
controller based on the disk, are done automatically.

Signed-off-by: Martin Kletzander <mkletzan@redhat.com>
Signed-off-by: Honglei Wang <honglei.wang@smartx.com>
Reviewed-by: Ján Tomko <jtomko@redhat.com>
19 files changed:
docs/formatdomain.rst
src/conf/domain_conf.c
src/conf/domain_conf.h
src/conf/domain_postparse.c
src/conf/domain_validate.c
src/conf/schemas/domaincommon.rng
src/hyperv/hyperv_driver.c
src/qemu/qemu_alias.c
src/qemu/qemu_command.c
src/qemu/qemu_domain_address.c
src/qemu/qemu_hotplug.c
src/qemu/qemu_validate.c
src/test/test_driver.c
src/vbox/vbox_common.c
src/vmx/vmx.c
tests/genericxml2xmlindata/disk-nvme-invalid-serials.xml [new file with mode: 0644]
tests/genericxml2xmlindata/disk-nvme.xml [new file with mode: 0644]
tests/genericxml2xmloutdata/disk-nvme.xml [new file with mode: 0644]
tests/genericxml2xmltest.c

index 4c70ff004c9b70ce3f164f8505e1a35423be627e..ae054a52b3c263a87c8fc54d4841c35e79ce99f3 100644 (file)
@@ -2824,7 +2824,7 @@ paravirtualized driver is specified via the ``disk`` element.
      <disk type='file' device='disk'>
        <driver name='qemu' type='qcow2' />
        <source file='/var/lib/libvirt/images/disk.qcow2'/>
-       <target dev='vdh' bus='virtio'/>
+       <target dev='nvme0n1' bus='nvme'/>
        <throttlefilters>
          <throttlefilter group='limit2'/>
          <throttlefilter group='limit012'/>
@@ -3313,7 +3313,8 @@ paravirtualized driver is specified via the ``disk`` element.
    name in the guest OS. Treat it as a device ordering hint. The optional
    ``bus`` attribute specifies the type of disk device to emulate; possible
    values are driver specific, with typical values being "ide", "scsi",
-   "virtio", "xen", "usb", "sata", or "sd" :since:`"sd" since 1.1.2`. If
+   "virtio", "xen", "usb", "sata", "sd", or "nvme"
+   :since:`"sd" since 1.1.2, "nvme" since 11.5.0`. If
    omitted, the bus type is inferred from the style of the device name (e.g. a
    device named 'sda' will typically be exported using a SCSI bus). The optional
    attribute ``tray`` indicates the tray status of the removable disks (i.e.
@@ -3651,7 +3652,9 @@ paravirtualized driver is specified via the ``disk`` element.
    If present, this specify serial number of virtual hard drive. For example, it
    may look like ``<serial>WD-WMAP9A966149</serial>``. Not supported for
    scsi-block devices, that is those using disk ``type`` 'block' using
-   ``device`` 'lun' on ``bus`` 'scsi'. :since:`Since 0.7.1`
+   ``device`` 'lun' on ``bus`` 'scsi'. Also not supported for multiple NVMe
+   devices on the same controller since those have serial number per controller
+   and not per disk. :since:`Since 0.7.1`
 
    Note that depending on hypervisor and device type the serial number may be
    truncated silently. IDE/SATA devices are commonly limited to 20 characters.
index 4371b25e3b8822b7bda18478e5ef233d8c48872c..1a6c8afb1ddde63cfdd84c4ccb063f4220d64330 100644 (file)
@@ -372,6 +372,7 @@ VIR_ENUM_IMPL(virDomainDiskBus,
               "uml",
               "sata",
               "sd",
+              "nvme",
 );
 
 VIR_ENUM_IMPL(virDomainDiskCache,
@@ -6813,8 +6814,10 @@ virDomainDiskDefAssignAddress(virDomainXMLOption *xmlopt G_GNUC_UNUSED,
                               virDomainDiskDef *def,
                               const virDomainDef *vmdef)
 {
-    int idx = virDiskNameToIndex(def->dst);
-    if (idx < 0) {
+    int idx = 0;
+    int nvme_ctrl = 0;
+
+    if (virDiskNameParse(def->dst, &nvme_ctrl, &idx, NULL) < 0) {
         virReportError(VIR_ERR_XML_ERROR,
                        _("Unknown disk name '%1$s' and no address specified"),
                        def->dst);
@@ -6891,6 +6894,13 @@ virDomainDiskDefAssignAddress(virDomainXMLOption *xmlopt G_GNUC_UNUSED,
         def->info.addr.drive.unit = idx % 2;
         break;
 
+    case VIR_DOMAIN_DISK_BUS_NVME:
+        def->info.type = VIR_DOMAIN_DEVICE_ADDRESS_TYPE_DRIVE;
+        def->info.addr.drive.controller = nvme_ctrl;
+        def->info.addr.drive.bus = 0;
+        def->info.addr.drive.unit = idx;
+        break;
+
     case VIR_DOMAIN_DISK_BUS_NONE:
     case VIR_DOMAIN_DISK_BUS_VIRTIO:
     case VIR_DOMAIN_DISK_BUS_XEN:
@@ -15015,6 +15025,10 @@ virDomainDiskControllerMatch(int controller_type, int disk_bus)
         disk_bus == VIR_DOMAIN_DISK_BUS_SATA)
         return true;
 
+    if (controller_type == VIR_DOMAIN_CONTROLLER_TYPE_NVME &&
+        disk_bus == VIR_DOMAIN_DISK_BUS_NVME)
+        return true;
+
     return false;
 }
 
@@ -22664,6 +22678,36 @@ virDomainDefMaybeAddSmartcardController(virDomainDef *def)
     }
 }
 
+static int
+virDomainDefMaybeAssignNvmeControllerSerials(virDomainDef *def)
+{
+    size_t i = 0;
+
+    for (i = 0; i < def->ndisks; i++) {
+        virDomainDiskDef *disk = def->disks[i];
+        virDomainControllerDef *ctrl = NULL;
+
+        if (!disk->serial ||
+            disk->bus != VIR_DOMAIN_DISK_BUS_NVME ||
+            def->disks[i]->info.type != VIR_DOMAIN_DEVICE_ADDRESS_TYPE_DRIVE)
+            continue;
+
+        ctrl = virDomainDeviceFindNvmeController(def, &disk->info.addr.drive);
+        if (ctrl) {
+            if (!ctrl->opts.nvmeopts.serial) {
+                ctrl->opts.nvmeopts.serial = g_strdup(disk->serial);
+            } else if (STRNEQ_NULLABLE(disk->serial, ctrl->opts.nvmeopts.serial)) {
+                virReportError(VIR_ERR_XML_DETAIL, "%s",
+                               _("Conflicting NVME disk serial number, all disks on a controller must have the same serial number as the controller itself"));
+                return -1;
+            }
+        }
+    }
+
+    return 0;
+}
+
+
 /*
  * Based on the declared <address/> info for any devices,
  * add necessary drive controllers which are not already present
@@ -22681,6 +22725,8 @@ virDomainDefAddImplicitControllers(virDomainDef *def)
                                           VIR_DOMAIN_DISK_BUS_IDE);
     virDomainDefAddDiskControllersForType(def, VIR_DOMAIN_CONTROLLER_TYPE_SATA,
                                           VIR_DOMAIN_DISK_BUS_SATA);
+    virDomainDefAddDiskControllersForType(def, VIR_DOMAIN_CONTROLLER_TYPE_NVME,
+                                          VIR_DOMAIN_DISK_BUS_NVME);
 
     virDomainDefMaybeAddVirtioSerialController(def);
     virDomainDefMaybeAddSmartcardController(def);
@@ -22713,6 +22759,9 @@ virDomainDefAddImplicitDevices(virDomainDef *def, virDomainXMLOption *xmlopt)
     }
     virDomainDefAddImplicitControllers(def);
 
+    if (virDomainDefMaybeAssignNvmeControllerSerials(def) < 0)
+        return -1;
+
     if (virDomainDefAddImplicitVideo(def, xmlopt) < 0)
         return -1;
 
@@ -29674,8 +29723,10 @@ virDiskNameToBusDeviceIndex(virDomainDiskDef *disk,
                             int *busIdx,
                             int *devIdx)
 {
-    int idx = virDiskNameToIndex(disk->dst);
-    if (idx < 0)
+    int idx = -1;
+    int nvme_ctrl = 0;
+
+    if (virDiskNameParse(disk->dst, &nvme_ctrl, &idx, NULL) < 0 || idx < 0)
         return -1;
 
     switch (disk->bus) {
@@ -29687,6 +29738,10 @@ virDiskNameToBusDeviceIndex(virDomainDiskDef *disk,
             *busIdx = idx / 7;
             *devIdx = idx % 7;
             break;
+        case VIR_DOMAIN_DISK_BUS_NVME:
+            *busIdx = nvme_ctrl;
+            *devIdx = idx;
+            break;
         case VIR_DOMAIN_DISK_BUS_FDC:
         case VIR_DOMAIN_DISK_BUS_USB:
         case VIR_DOMAIN_DISK_BUS_VIRTIO:
index 4adc952b6b53b74b21beb75104242610041b72af..3d380073cf22a47b1f663a48633242735cf69928 100644 (file)
@@ -401,6 +401,7 @@ typedef enum {
     VIR_DOMAIN_DISK_BUS_UML,
     VIR_DOMAIN_DISK_BUS_SATA,
     VIR_DOMAIN_DISK_BUS_SD,
+    VIR_DOMAIN_DISK_BUS_NVME,
 
     VIR_DOMAIN_DISK_BUS_LAST
 } virDomainDiskBus;
index bf33f29638ff81459ea80189189297f2554d96a7..a07ec8d94e6533802235956cb6a65b1a929a4846 100644 (file)
@@ -523,6 +523,8 @@ virDomainDiskDefPostParse(virDomainDiskDef *disk,
                 disk->bus = VIR_DOMAIN_DISK_BUS_XEN;
             else if (STRPREFIX(disk->dst, "ubd"))
                 disk->bus = VIR_DOMAIN_DISK_BUS_UML;
+            else if (STRPREFIX(disk->dst, "nvme"))
+                disk->bus = VIR_DOMAIN_DISK_BUS_NVME;
         }
     }
 
index d0d4bc0bf4b70e8e746d6ae97a33767b6e531bec..96f76f2f7bba964ada6c96af7bf05f4b5648dc90 100644 (file)
@@ -260,6 +260,7 @@ virDomainDiskAddressDiskBusCompatibility(virDomainDiskBus bus,
     case VIR_DOMAIN_DISK_BUS_FDC:
     case VIR_DOMAIN_DISK_BUS_SCSI:
     case VIR_DOMAIN_DISK_BUS_SATA:
+    case VIR_DOMAIN_DISK_BUS_NVME:
         return addressType == VIR_DOMAIN_DEVICE_ADDRESS_TYPE_DRIVE;
     case VIR_DOMAIN_DISK_BUS_VIRTIO:
     case VIR_DOMAIN_DISK_BUS_XEN:
@@ -948,7 +949,8 @@ virDomainDiskDefValidate(const virDomainDef *def,
         !STRPREFIX(disk->dst, "sd") &&
         !STRPREFIX(disk->dst, "vd") &&
         !STRPREFIX(disk->dst, "xvd") &&
-        !STRPREFIX(disk->dst, "ubd")) {
+        !STRPREFIX(disk->dst, "ubd") &&
+        !STRPREFIX(disk->dst, "nvme")) {
         virReportError(VIR_ERR_INTERNAL_ERROR,
                        _("Invalid harddisk device name: %1$s"), disk->dst);
         return -1;
index 3317cf1665f6eb2e18eda141d27be73bbc497651..b1fe51f5190e6154d83f0c2567b1bf747682a4bf 100644 (file)
   </define>
 
   <define name="diskTargetDev">
-    <data type="string">
-      <param name="pattern">(ioemu:)?(fd|hd|sd|vd|xvd|ubd)[a-zA-Z0-9_]+</param>
-    </data>
+    <choice>
+      <data type="string">
+        <param name="pattern">(ioemu:)?(fd|hd|sd|vd|xvd|ubd)[a-zA-Z0-9_]+</param>
+      </data>
+      <data type="string">
+        <param name="pattern">nvme[0-9]+n[0-9]+(p[0-9]+)?</param>
+      </data>
+    </choice>
   </define>
 
   <define name="diskTarget">
             <value>uml</value> <!-- NOT USED ANYMORE -->
             <value>sata</value>
             <value>sd</value>
+            <value>nvme</value>
           </choice>
         </attribute>
       </optional>
index 25eb8872b3bf340a5ab13cc5dae1338800574bce..0c17ef16ec76949c94842561bf5a46ea39bd551b 100644 (file)
@@ -948,6 +948,7 @@ hypervDomainAttachStorage(virDomainPtr domain, virDomainDef *def, const char *ho
         case VIR_DOMAIN_DISK_BUS_UML:
         case VIR_DOMAIN_DISK_BUS_SATA:
         case VIR_DOMAIN_DISK_BUS_SD:
+        case VIR_DOMAIN_DISK_BUS_NVME:
         case VIR_DOMAIN_DISK_BUS_LAST:
         default:
             virReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("Unsupported controller type"));
@@ -3078,6 +3079,7 @@ hypervDomainAttachDeviceFlags(virDomainPtr domain, const char *xml, unsigned int
         case VIR_DOMAIN_DISK_BUS_UML:
         case VIR_DOMAIN_DISK_BUS_SATA:
         case VIR_DOMAIN_DISK_BUS_SD:
+        case VIR_DOMAIN_DISK_BUS_NVME:
         case VIR_DOMAIN_DISK_BUS_LAST:
         default:
             virReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("Invalid disk bus in definition"));
index 3e6bced4a88538a040dd8a65f40dc9f7f56b8ec9..9d39ebd63da16b5fb4520cc89eb607115411f327 100644 (file)
@@ -258,6 +258,7 @@ qemuAssignDeviceDiskAlias(virDomainDef *def,
         case VIR_DOMAIN_DISK_BUS_IDE:
         case VIR_DOMAIN_DISK_BUS_SATA:
         case VIR_DOMAIN_DISK_BUS_SCSI:
+        case VIR_DOMAIN_DISK_BUS_NVME:
             diskPriv->qomName = g_strdup(disk->info.alias);
             break;
 
index d7fb88cbc13359a3a31a445718285671f8aa87cf..f193ba8cca369753c796ade7817a8c1b20544ef0 100644 (file)
@@ -532,6 +532,7 @@ qemuBuildDeviceAddresDriveProps(virJSONValue *props,
 
         break;
 
+    case VIR_DOMAIN_DISK_BUS_NVME:
     case VIR_DOMAIN_DISK_BUS_VIRTIO:
     case VIR_DOMAIN_DISK_BUS_USB:
     case VIR_DOMAIN_DISK_BUS_XEN:
@@ -1722,6 +1723,7 @@ qemuBuildDiskDeviceProps(const virDomainDef *def,
         driver = "floppy";
         break;
 
+    case VIR_DOMAIN_DISK_BUS_NVME:
     case VIR_DOMAIN_DISK_BUS_XEN:
     case VIR_DOMAIN_DISK_BUS_UML:
     case VIR_DOMAIN_DISK_BUS_SD:
index 7bc769fc1934c77a01fea3aa94fd9f477de17e3a..9b2faf1e8e375d0ad53c38ce694e5232e36a48e5 100644 (file)
@@ -739,6 +739,7 @@ qemuDomainDeviceCalculatePCIConnectFlags(virDomainDeviceDef *dev,
         case VIR_DOMAIN_DISK_BUS_UML:
         case VIR_DOMAIN_DISK_BUS_SATA:
         case VIR_DOMAIN_DISK_BUS_SD:
+        case VIR_DOMAIN_DISK_BUS_NVME:
         case VIR_DOMAIN_DISK_BUS_NONE:
         case VIR_DOMAIN_DISK_BUS_LAST:
             return 0;
index 7a1170b2ddd14234879d1863efd7f306db0b22f3..9427eec643842dcd44c0e6b37038d983cbd45e8f 100644 (file)
@@ -1058,6 +1058,7 @@ qemuDomainAttachDeviceDiskLiveInternal(virQEMUDriver *driver,
         /* Note that SD card hotplug support should be added only once
          * they support '-device' (don't require -drive only).
          * See also: qemuDiskBusIsSD */
+    case VIR_DOMAIN_DISK_BUS_NVME:
     case VIR_DOMAIN_DISK_BUS_NONE:
     case VIR_DOMAIN_DISK_BUS_LAST:
         virReportError(VIR_ERR_OPERATION_UNSUPPORTED,
@@ -5776,6 +5777,7 @@ qemuDomainDetachPrepDisk(virDomainObj *vm,
         case VIR_DOMAIN_DISK_BUS_SCSI:
             break;
 
+        case VIR_DOMAIN_DISK_BUS_NVME:
         case VIR_DOMAIN_DISK_BUS_IDE:
         case VIR_DOMAIN_DISK_BUS_FDC:
         case VIR_DOMAIN_DISK_BUS_XEN:
index ab75a3e0469df18dffe7e591ad2a60553f966473..fee5e1ed87cb351faeb6823b3fa98a4d1a3e1bb6 100644 (file)
@@ -2945,6 +2945,7 @@ qemuValidateDomainDeviceDefDiskIOThreads(const virDomainDef *def,
     case VIR_DOMAIN_DISK_BUS_SATA:
     case VIR_DOMAIN_DISK_BUS_SD:
     case VIR_DOMAIN_DISK_BUS_NONE:
+    case VIR_DOMAIN_DISK_BUS_NVME:
     case VIR_DOMAIN_DISK_BUS_LAST:
         virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
                        _("IOThreads not available for bus %1$s target %2$s"),
@@ -3086,6 +3087,7 @@ qemuValidateDomainDeviceDefDiskFrontend(const virDomainDiskDef *disk,
         case VIR_DOMAIN_DISK_BUS_UML:
         case VIR_DOMAIN_DISK_BUS_SATA:
         case VIR_DOMAIN_DISK_BUS_SD:
+        case VIR_DOMAIN_DISK_BUS_NVME:
             virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
                            _("disk device='lun' is not supported for bus='%1$s'"),
                            virDomainDiskBusTypeToString(disk->bus));
@@ -3201,6 +3203,7 @@ qemuValidateDomainDeviceDefDiskFrontend(const virDomainDiskDef *disk,
 
         break;
 
+    case VIR_DOMAIN_DISK_BUS_NVME:
     case VIR_DOMAIN_DISK_BUS_XEN:
     case VIR_DOMAIN_DISK_BUS_SD:
     case VIR_DOMAIN_DISK_BUS_NONE:
@@ -3397,6 +3400,7 @@ qemuValidateDomainDeviceDefDiskTransient(const virDomainDiskDef *disk,
         case VIR_DOMAIN_DISK_BUS_UML:
         case VIR_DOMAIN_DISK_BUS_SATA:
         case VIR_DOMAIN_DISK_BUS_SD:
+        case VIR_DOMAIN_DISK_BUS_NVME:
         case VIR_DOMAIN_DISK_BUS_NONE:
         case VIR_DOMAIN_DISK_BUS_LAST:
         default:
@@ -3418,6 +3422,7 @@ qemuValidateDomainDeviceDefDisk(const virDomainDiskDef *disk,
 {
     const char *driverName = virDomainDiskGetDriver(disk);
     virStorageSource *n;
+    int nvme_ctrl;
     int idx;
     int partition;
 
@@ -3445,7 +3450,7 @@ qemuValidateDomainDeviceDefDisk(const virDomainDiskDef *disk,
         return -1;
     }
 
-    if (virDiskNameParse(disk->dst, NULL, &idx, &partition) < 0) {
+    if (virDiskNameParse(disk->dst, &nvme_ctrl, &idx, &partition) < 0) {
         virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
                        _("invalid disk target '%1$s'"), disk->dst);
         return -1;
index 6f18b2b2c820f5d0610a62ac7797d2651a83f3ab..25335d90027e10b0ff5494c55a4774e139a562ea 100644 (file)
@@ -10344,6 +10344,7 @@ testDomainAttachDeviceDiskLiveInternal(testDriver *driver G_GNUC_UNUSED,
     case VIR_DOMAIN_DISK_BUS_UML:
     case VIR_DOMAIN_DISK_BUS_SATA:
     case VIR_DOMAIN_DISK_BUS_SD:
+    case VIR_DOMAIN_DISK_BUS_NVME:
     case VIR_DOMAIN_DISK_BUS_NONE:
     case VIR_DOMAIN_DISK_BUS_LAST:
         virReportError(VIR_ERR_OPERATION_UNSUPPORTED,
@@ -10792,6 +10793,7 @@ testDomainDetachPrepDisk(virDomainObj *vm,
         case VIR_DOMAIN_DISK_BUS_UML:
         case VIR_DOMAIN_DISK_BUS_SATA:
         case VIR_DOMAIN_DISK_BUS_SD:
+        case VIR_DOMAIN_DISK_BUS_NVME:
             virReportError(VIR_ERR_OPERATION_UNSUPPORTED, "%s",
                            _("This type of disk cannot be hot unplugged"));
             return -1;
index 735c241fb337017bd3e1d15988f9d3c83c89e017..26c5fdfef68aae24558110af7970eddb48c26b30 100644 (file)
@@ -1239,6 +1239,7 @@ vboxAttachDrives(virDomainDef *def, struct _vboxDriver *data, IMachine *machine)
         case VIR_DOMAIN_DISK_BUS_USB:
         case VIR_DOMAIN_DISK_BUS_UML:
         case VIR_DOMAIN_DISK_BUS_SD:
+        case VIR_DOMAIN_DISK_BUS_NVME:
         case VIR_DOMAIN_DISK_BUS_NONE:
         case VIR_DOMAIN_DISK_BUS_LAST:
             vboxReportError(VIR_ERR_CONFIG_UNSUPPORTED,
index 4a9ad11b42c4ee79023b4dcf956c9c2615f09190..7fa00669a717a4d8417415adfef6cd57d4dddf12 100644 (file)
@@ -2240,6 +2240,7 @@ virVMXGenerateDiskTarget(virDomainDiskDef *def,
         prefix = "fd";
         break;
 
+    case VIR_DOMAIN_DISK_BUS_NVME:
     case VIR_DOMAIN_DISK_BUS_VIRTIO:
     case VIR_DOMAIN_DISK_BUS_XEN:
     case VIR_DOMAIN_DISK_BUS_USB:
diff --git a/tests/genericxml2xmlindata/disk-nvme-invalid-serials.xml b/tests/genericxml2xmlindata/disk-nvme-invalid-serials.xml
new file mode 100644 (file)
index 0000000..dcfe6ea
--- /dev/null
@@ -0,0 +1,29 @@
+<domain type='qemu'>
+  <name>bar</name>
+  <uuid>00010203-0405-4607-8809-0a0b0c0d0e0f</uuid>
+  <memory unit='KiB'>219136</memory>
+  <currentMemory unit='KiB'>219136</currentMemory>
+  <vcpu placement='static'>1</vcpu>
+  <os>
+    <type arch='x86_64' machine='pc'>hvm</type>
+    <boot dev='hd'/>
+  </os>
+  <clock offset='utc'/>
+  <on_poweroff>destroy</on_poweroff>
+  <on_reboot>restart</on_reboot>
+  <on_crash>destroy</on_crash>
+  <devices>
+    <disk type='block' device='disk'>
+      <driver name='qemu' type='raw'/>
+      <source dev='/dev/HostVG/QEMUGuest1'/>
+      <target dev='nvme0n1' bus='nvme'/>
+      <serial>abcdefgh</serial>
+    </disk>
+    <disk type='block' device='disk'>
+      <driver name='qemu' type='raw'/>
+      <source dev='/dev/HostVG/QEMUGuest2'/>
+      <target dev='nvme0n2' bus='nvme'/>
+      <serial>IJKLMNOP</serial>
+    </disk>
+  </devices>
+</domain>
diff --git a/tests/genericxml2xmlindata/disk-nvme.xml b/tests/genericxml2xmlindata/disk-nvme.xml
new file mode 100644 (file)
index 0000000..bdfec4e
--- /dev/null
@@ -0,0 +1,32 @@
+<domain type='qemu'>
+  <name>bar</name>
+  <uuid>00010203-0405-4607-8809-0a0b0c0d0e0f</uuid>
+  <memory unit='KiB'>219136</memory>
+  <currentMemory unit='KiB'>219136</currentMemory>
+  <vcpu placement='static'>1</vcpu>
+  <os>
+    <type arch='x86_64' machine='pc'>hvm</type>
+    <boot dev='hd'/>
+  </os>
+  <clock offset='utc'/>
+  <on_poweroff>destroy</on_poweroff>
+  <on_reboot>restart</on_reboot>
+  <on_crash>destroy</on_crash>
+  <devices>
+    <disk type='block' device='disk'>
+      <driver name='qemu' type='raw'/>
+      <source dev='/dev/HostVG/QEMUGuest1'/>
+      <target dev='nvme0n1' bus='nvme'/>
+    </disk>
+    <disk type='block' device='disk'>
+      <driver name='qemu' type='raw'/>
+      <source dev='/dev/HostVG/QEMUGuest2'/>
+      <target dev='nvme3n2' bus='nvme'/>
+      <serial>abcdefgh</serial>
+    </disk>
+    <controller type='nvme' index='0'/>
+    <controller type='nvme' index='1'>
+      <serial>CDEFGAHC</serial>
+    </controller>
+  </devices>
+</domain>
diff --git a/tests/genericxml2xmloutdata/disk-nvme.xml b/tests/genericxml2xmloutdata/disk-nvme.xml
new file mode 100644 (file)
index 0000000..4251e12
--- /dev/null
@@ -0,0 +1,38 @@
+<domain type='qemu'>
+  <name>bar</name>
+  <uuid>00010203-0405-4607-8809-0a0b0c0d0e0f</uuid>
+  <memory unit='KiB'>219136</memory>
+  <currentMemory unit='KiB'>219136</currentMemory>
+  <vcpu placement='static'>1</vcpu>
+  <os>
+    <type arch='x86_64' machine='pc'>hvm</type>
+    <boot dev='hd'/>
+  </os>
+  <clock offset='utc'/>
+  <on_poweroff>destroy</on_poweroff>
+  <on_reboot>restart</on_reboot>
+  <on_crash>destroy</on_crash>
+  <devices>
+    <disk type='block' device='disk'>
+      <driver name='qemu' type='raw'/>
+      <source dev='/dev/HostVG/QEMUGuest1'/>
+      <target dev='nvme0n1' bus='nvme'/>
+      <address type='drive' controller='0' bus='0' target='0' unit='0'/>
+    </disk>
+    <disk type='block' device='disk'>
+      <driver name='qemu' type='raw'/>
+      <source dev='/dev/HostVG/QEMUGuest2'/>
+      <target dev='nvme3n2' bus='nvme'/>
+      <serial>abcdefgh</serial>
+      <address type='drive' controller='3' bus='0' target='0' unit='1'/>
+    </disk>
+    <controller type='nvme' index='0'/>
+    <controller type='nvme' index='1'>
+      <serial>CDEFGAHC</serial>
+    </controller>
+    <controller type='nvme' index='2'/>
+    <controller type='nvme' index='3'>
+      <serial>abcdefgh</serial>
+    </controller>
+  </devices>
+</domain>
index f4e04d84f8250f93a030e087a8dce3bca1f0df74..6757fc44ded1b3732429ff27d477254aac276377 100644 (file)
@@ -232,6 +232,8 @@ mymain(void)
     DO_TEST("fibrechannel-appid");
 
     DO_TEST("controller-nvme");
+    DO_TEST_DIFFERENT("disk-nvme");
+    DO_TEST_FAIL_INACTIVE("disk-nvme-invalid-serials");
 
 #define DO_TEST_BACKUP_FULL(name, intrnl) \
     do { \