]> git.ipfire.org Git - thirdparty/libvirt.git/commitdiff
qemu: Allow the user to specify vendor and product for disk
authorOsier Yang <jyang@redhat.com>
Thu, 6 Dec 2012 10:23:02 +0000 (18:23 +0800)
committerOsier Yang <jyang@redhat.com>
Fri, 7 Dec 2012 08:53:27 +0000 (16:53 +0800)
QEMU supports setting vendor and product strings for disk since
1.2.0 (only scsi-disk, scsi-hd, scsi-cd support it), this patch
exposes it with new XML elements <vendor> and <product> of disk
device.

13 files changed:
docs/formatdomain.html.in
docs/schemas/domaincommon.rng
src/conf/domain_conf.c
src/conf/domain_conf.h
src/libvirt_private.syms
src/qemu/qemu_command.c
src/util/util.c
src/util/util.h
tests/qemuxml2argvdata/qemuxml2argv-disk-scsi-disk-vpd-build-error.xml [new file with mode: 0644]
tests/qemuxml2argvdata/qemuxml2argv-disk-scsi-disk-vpd.args [new file with mode: 0644]
tests/qemuxml2argvdata/qemuxml2argv-disk-scsi-disk-vpd.xml [new file with mode: 0644]
tests/qemuxml2argvtest.c
tests/qemuxml2xmltest.c

index 0574e68d5313370f692221ead75550b44e746714..c81af8a892e71e55cfbe9318df3fc4565f73b93f 100644 (file)
         of 16 hexadecimal digits.
         <span class='since'>Since 0.10.1</span>
       </dd>
+      <dt><code>vendor</code></dt>
+      <dd>If present, this element specifies the vendor of a virtual hard
+        disk or CD-ROM device. It must not be longer than 8 printable
+        characters.
+        <span class='since'>Since 1.0.1</span>
+      </dd>
+      <dt><code>product</code></dt>
+      <dd>If present, this element specifies the product of a virtual hard
+        disk or CD-ROM device. It must not be longer than 16 printable
+        characters.
+        <span class='since'>Since 1.0.1</span>
+      </dd>
       <dt><code>host</code></dt>
       <dd>The <code>host</code> element supports 4 attributes, viz.  "name",
         "port", "transport" and "socket", which specify the hostname, the port
index 0e85739989ba26c86d49a0507edf4b32ebf16567..14344e2029d8d904fddd9da0e6bc4cd087f63b9b 100644 (file)
           <ref name="wwn"/>
         </element>
       </optional>
+      <optional>
+        <element name="vendor">
+          <data type="string">
+            <param name="pattern">[x20-x7E]{0,8}</param>
+          </data>
+        </element>
+      </optional>
+      <optional>
+        <element name="product">
+          <data type="string">
+            <param name="pattern">[x20-x7E]{0,16}</param>
+          </data>
+        </element>
+      </optional>
     </interleave>
   </define>
   <define name="snapshot">
index 4ffb39def31799ac585a94564c7f15387aea710f..6aa5f79ca3d908f95fc7850d11ab383cfedd7af1 100644 (file)
@@ -985,6 +985,8 @@ void virDomainDiskDefFree(virDomainDiskDefPtr def)
     VIR_FREE(def->mirror);
     VIR_FREE(def->auth.username);
     VIR_FREE(def->wwn);
+    VIR_FREE(def->vendor);
+    VIR_FREE(def->product);
     if (def->auth.secretType == VIR_DOMAIN_DISK_SECRET_TYPE_USAGE)
         VIR_FREE(def->auth.secret.usage);
     virStorageEncryptionFree(def->encryption);
@@ -3505,6 +3507,8 @@ cleanup:
     goto cleanup;
 }
 
+#define VENDOR_LEN  8
+#define PRODUCT_LEN 16
 
 /* Parse the XML definition for a disk
  * @param node XML nodeset to parse for disk definition
@@ -3558,6 +3562,8 @@ virDomainDiskDefParseXML(virCapsPtr caps,
     char *logical_block_size = NULL;
     char *physical_block_size = NULL;
     char *wwn = NULL;
+    char *vendor = NULL;
+    char *product = NULL;
 
     if (VIR_ALLOC(def) < 0) {
         virReportOOMError();
@@ -3926,6 +3932,36 @@ virDomainDiskDefParseXML(virCapsPtr caps,
 
                 if (!virValidateWWN(wwn))
                     goto error;
+            } else if (!vendor &&
+                       xmlStrEqual(cur->name, BAD_CAST "vendor")) {
+                vendor = (char *)xmlNodeGetContent(cur);
+
+                if (strlen(vendor) > VENDOR_LEN) {
+                    virReportError(VIR_ERR_XML_ERROR, "%s",
+                                   _("disk vendor is more than 8 characters"));
+                    goto error;
+                }
+
+                if (!virStrIsPrint(vendor)) {
+                    virReportError(VIR_ERR_XML_ERROR, "%s",
+                                   _("disk vendor is not printable string"));
+                    goto error;
+                }
+            } else if (!product &&
+                       xmlStrEqual(cur->name, BAD_CAST "product")) {
+                product = (char *)xmlNodeGetContent(cur);
+
+                if (strlen(vendor) > PRODUCT_LEN) {
+                    virReportError(VIR_ERR_XML_ERROR, "%s",
+                                   _("disk product is more than 16 characters"));
+                    goto error;
+                }
+
+                if (!virStrIsPrint(product)) {
+                    virReportError(VIR_ERR_XML_ERROR, "%s",
+                                   _("disk product is not printable string"));
+                    goto error;
+                }
             } else if (xmlStrEqual(cur->name, BAD_CAST "boot")) {
                 /* boot is parsed as part of virDomainDeviceInfoParseXML */
             }
@@ -4222,6 +4258,10 @@ virDomainDiskDefParseXML(virCapsPtr caps,
     serial = NULL;
     def->wwn = wwn;
     wwn = NULL;
+    def->vendor = vendor;
+    vendor = NULL;
+    def->product = product;
+    product = NULL;
 
     if (driverType) {
         def->format = virStorageFileFormatTypeFromString(driverType);
@@ -4296,6 +4336,8 @@ cleanup:
     VIR_FREE(logical_block_size);
     VIR_FREE(physical_block_size);
     VIR_FREE(wwn);
+    VIR_FREE(vendor);
+    VIR_FREE(product);
 
     ctxt->node = save_ctxt;
     return def;
@@ -12144,6 +12186,8 @@ virDomainDiskDefFormat(virBufferPtr buf,
         virBufferAddLit(buf, "      <transient/>\n");
     virBufferEscapeString(buf, "      <serial>%s</serial>\n", def->serial);
     virBufferEscapeString(buf, "      <wwn>%s</wwn>\n", def->wwn);
+    virBufferEscapeString(buf, "      <vendor>%s</vendor>\n", def->vendor);
+    virBufferEscapeString(buf, "      <product>%s</product>\n", def->product);
     if (def->encryption) {
         virBufferAdjustIndent(buf, 6);
         if (virStorageEncryptionFormat(buf, def->encryption) < 0)
index 4ab15e9c23a3e95f85f32d204d2fcd7ed3a2e8ef..7ad537772ed5c385b00c9a08b8c1876ba23f3768 100644 (file)
@@ -602,6 +602,8 @@ struct _virDomainDiskDef {
 
     char *serial;
     char *wwn;
+    char *vendor;
+    char *product;
     int cachemode;
     int error_policy;  /* enum virDomainDiskErrorPolicy */
     int rerror_policy; /* enum virDomainDiskErrorPolicy */
index bc01fe5bac3c9e4a7041959edd6f270ef4cc3969..499ab3bc273296a21ad510d62f4ea764c1d14279 100644 (file)
@@ -1298,6 +1298,7 @@ virSetUIDGID;
 virSkipSpaces;
 virSkipSpacesAndBackslash;
 virSkipSpacesBackwards;
+virStrIsPrint;
 virStrToDouble;
 virStrToLong_i;
 virStrToLong_l;
index 1805625c51e2545c8233502258550eeda051437a..5335dcf5a1a8951bcc9f51f28105b7a2db807798 100644 (file)
@@ -2576,6 +2576,13 @@ qemuBuildDriveDevStr(virDomainDefPtr def,
         }
     }
 
+    if ((disk->vendor || disk->product) &&
+        disk->bus != VIR_DOMAIN_DISK_BUS_SCSI) {
+            virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
+                           _("Only scsi disk supports vendor and product"));
+            goto error;
+    }
+
     if (disk->device == VIR_DOMAIN_DISK_DEVICE_LUN) {
         /* make sure that both the bus and the qemu binary support
          *  type='lun' (SG_IO).
@@ -2603,6 +2610,12 @@ qemuBuildDriveDevStr(virDomainDefPtr def,
                            _("Setting wwn is not supported for lun device"));
             goto error;
         }
+        if (disk->vendor || disk->product) {
+            virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
+                           _("Setting vendor or product is not supported "
+                             "for lun device"));
+            goto error;
+        }
     }
 
     switch (disk->bus) {
@@ -2652,6 +2665,17 @@ qemuBuildDriveDevStr(virDomainDefPtr def,
             goto error;
         }
 
+        /* Properties wwn, vendor and product were introduced in the
+         * same QEMU release (1.2.0).
+         */
+        if ((disk->vendor || disk->product) &&
+            !qemuCapsGet(caps, QEMU_CAPS_SCSI_DISK_WWN)) {
+            virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
+                           _("Setting vendor or product for scsi disk is not "
+                             "supported by this QEMU"));
+            goto error;
+        }
+
         controllerModel =
             virDomainDiskFindControllerModel(def, disk,
                                              VIR_DOMAIN_CONTROLLER_TYPE_SCSI);
@@ -2797,6 +2821,12 @@ qemuBuildDriveDevStr(virDomainDefPtr def,
     if (disk->wwn)
         virBufferAsprintf(&opt, ",wwn=%s", disk->wwn);
 
+    if (disk->vendor)
+        virBufferAsprintf(&opt, ",vendor=%s", disk->vendor);
+
+    if (disk->product)
+        virBufferAsprintf(&opt, ",product=%s", disk->product);
+
     if (virBufferError(&opt)) {
         virReportOOMError();
         goto error;
index 2ca291ea4c09c658c9b910f5bc102a16332de702..3f244f595c5cd7b49afa37b935c6a4cfb90ea24c 100644 (file)
@@ -3131,3 +3131,15 @@ virValidateWWN(const char *wwn) {
 
     return true;
 }
+
+bool
+virStrIsPrint(const char *str)
+{
+    int i;
+
+    for (i = 0; str[i]; i++)
+        if (!c_isprint(str[i]))
+            return false;
+
+    return true;
+}
index 4316ab17f1701637c61fa2c56e649bee23887025..6d5dd038e1c81bb3e3f9e6f15ab02b2938d100a5 100644 (file)
@@ -280,4 +280,5 @@ bool virIsDevMapperDevice(const char *dev_name) ATTRIBUTE_NONNULL(1);
 
 bool virValidateWWN(const char *wwn);
 
+bool virStrIsPrint(const char *str);
 #endif /* __VIR_UTIL_H__ */
diff --git a/tests/qemuxml2argvdata/qemuxml2argv-disk-scsi-disk-vpd-build-error.xml b/tests/qemuxml2argvdata/qemuxml2argv-disk-scsi-disk-vpd-build-error.xml
new file mode 100644 (file)
index 0000000..ca68275
--- /dev/null
@@ -0,0 +1,35 @@
+<domain type='qemu'>
+  <name>QEMUGuest1</name>
+  <uuid>c7a5fdbd-edaf-9455-926a-d65c16db1809</uuid>
+  <memory unit='KiB'>219136</memory>
+  <currentMemory unit='KiB'>219136</currentMemory>
+  <vcpu placement='static'>1</vcpu>
+  <os>
+    <type arch='i686' 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>
+    <emulator>/usr/bin/qemu</emulator>
+    <disk type='block' device='cdrom'>
+      <source dev='/dev/HostVG/QEMUGuest1'/>
+      <target dev='sda' bus='virtio'/>
+      <vendor>SEAGATE</vendor>
+      <product>ST3146707LC</product>
+    </disk>
+    <disk type='block' device='disk'>
+      <source dev='/dev/HostVG/QEMUGuest2'/>
+      <target dev='sdb' bus='scsi'/>
+      <vendor>SEAGATE</vendor>
+      <product>ST3567807GD</product>
+      <address type='drive' controller='0' bus='0' target='0' unit='0'/>
+    </disk>
+    <controller type='usb' index='0'/>
+    <controller type='scsi' index='0' model='virtio-scsi'/>
+    <controller type='scsi' index='1' model='lsilogic'/>
+    <memballoon model='virtio'/>
+  </devices>
+</domain>
diff --git a/tests/qemuxml2argvdata/qemuxml2argv-disk-scsi-disk-vpd.args b/tests/qemuxml2argvdata/qemuxml2argv-disk-scsi-disk-vpd.args
new file mode 100644 (file)
index 0000000..f5c1999
--- /dev/null
@@ -0,0 +1,13 @@
+LC_ALL=C PATH=/bin HOME=/home/test USER=test LOGNAME=test \
+/usr/bin/qemu -S -M pc -m 214 -smp 1 -nographic -nodefconfig -nodefaults \
+-monitor unix:/tmp/test-monitor,server,nowait -no-acpi -boot c \
+-device virtio-scsi-pci,id=scsi0,bus=pci.0,addr=0x3 \
+-device lsi,id=scsi1,bus=pci.0,addr=0x4 \
+-usb \
+-drive file=/dev/HostVG/QEMUGuest1,if=none,id=drive-scsi0-0-0-0 \
+-device scsi-cd,bus=scsi0.0,channel=0,scsi-id=0,lun=0,drive=drive-scsi0-0-0-0,\
+id=scsi0-0-0-0,vendor=SEAGATE,product=ST3146707LC \
+-drive file=/dev/HostVG/QEMUGuest2,if=none,id=drive-scsi1-0-0 \
+-device scsi-hd,bus=scsi1.0,scsi-id=0,drive=drive-scsi1-0-0,\
+id=scsi1-0-0,vendor=SEAGATE,product=ST3567807GD \
+-device virtio-balloon-pci,id=balloon0,bus=pci.0,addr=0x5
diff --git a/tests/qemuxml2argvdata/qemuxml2argv-disk-scsi-disk-vpd.xml b/tests/qemuxml2argvdata/qemuxml2argv-disk-scsi-disk-vpd.xml
new file mode 100644 (file)
index 0000000..96786e3
--- /dev/null
@@ -0,0 +1,38 @@
+<domain type='qemu'>
+  <name>QEMUGuest1</name>
+  <uuid>c7a5fdbd-edaf-9455-926a-d65c16db1809</uuid>
+  <memory unit='KiB'>219136</memory>
+  <currentMemory unit='KiB'>219136</currentMemory>
+  <vcpu placement='static'>1</vcpu>
+  <os>
+    <type arch='i686' 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>
+    <emulator>/usr/bin/qemu</emulator>
+    <disk type='block' device='cdrom'>
+      <source dev='/dev/HostVG/QEMUGuest1'/>
+      <target dev='sda' bus='scsi'/>
+      <readonly/>
+      <vendor>SEAGATE</vendor>
+      <product>ST3146707LC</product>
+      <address type='drive' controller='0' bus='0' target='0' unit='0'/>
+    </disk>
+    <disk type='block' device='disk'>
+      <source dev='/dev/HostVG/QEMUGuest2'/>
+      <target dev='sdb' bus='scsi'/>
+      <readonly/>
+      <vendor>SEAGATE</vendor>
+      <product>ST3567807GD</product>
+      <address type='drive' controller='1' bus='0' target='0' unit='0'/>
+    </disk>
+    <controller type='usb' index='0'/>
+    <controller type='scsi' index='0' model='virtio-scsi'/>
+    <controller type='scsi' index='1' model='lsilogic'/>
+    <memballoon model='virtio'/>
+  </devices>
+</domain>
index 5822cae2d88acbf7d56b26bf0d6acbb617963140..bb233ed64401fa981f466709a6abda3b88df6e81 100644 (file)
@@ -507,6 +507,14 @@ mymain(void)
             QEMU_CAPS_DRIVE, QEMU_CAPS_DEVICE, QEMU_CAPS_NODEFCONFIG,
             QEMU_CAPS_SCSI_CD, QEMU_CAPS_SCSI_LSI, QEMU_CAPS_VIRTIO_SCSI_PCI,
             QEMU_CAPS_SCSI_DISK_WWN);
+    DO_TEST("disk-scsi-disk-vpd",
+            QEMU_CAPS_DRIVE, QEMU_CAPS_DEVICE, QEMU_CAPS_NODEFCONFIG,
+            QEMU_CAPS_SCSI_CD, QEMU_CAPS_SCSI_LSI, QEMU_CAPS_VIRTIO_SCSI_PCI,
+            QEMU_CAPS_SCSI_DISK_WWN);
+    DO_TEST_FAILURE("disk-scsi-disk-vpd-build-error",
+            QEMU_CAPS_DRIVE, QEMU_CAPS_DEVICE, QEMU_CAPS_NODEFCONFIG,
+            QEMU_CAPS_SCSI_CD, QEMU_CAPS_SCSI_LSI, QEMU_CAPS_VIRTIO_SCSI_PCI,
+            QEMU_CAPS_SCSI_DISK_WWN);
     DO_TEST("disk-scsi-vscsi",
             QEMU_CAPS_DRIVE, QEMU_CAPS_DEVICE, QEMU_CAPS_NODEFCONFIG);
     DO_TEST("disk-scsi-virtio-scsi",
index 3d8176c718a9d0f51803032be1d0570593d3b308..c2d3dd3892d207293b7eac31f5b812b8f688db90 100644 (file)
@@ -239,6 +239,8 @@ mymain(void)
     DO_TEST("seclabel-none");
     DO_TEST("numad-static-vcpu-no-numatune");
 
+    DO_TEST("disk-scsi-disk-vpd");
+
     /* These tests generate different XML */
     DO_TEST_DIFFERENT("balloon-device-auto");
     DO_TEST_DIFFERENT("channel-virtio-auto");