[libvirt] [PATCH v2 3/3] conf: Allow users to define UUID for devices

Michal Privoznik mprivozn at redhat.com
Tue Oct 3 10:58:59 UTC 2017


https://bugzilla.redhat.com/show_bug.cgi?id=1434451

It comes handy for management application to be able to have a
per-device label so that it can uniquely identify devices it
cares about. The advantage of this approach is that we don't have
to generate aliases at define time (non trivial amount of work
and problems). The only thing we do is parse the user supplied
UUID and format it back. For instance:

    <disk type='block' device='disk'>
      <driver name='qemu' type='raw'/>
      <source dev='/dev/HostVG/QEMUGuest1'/>
      <target dev='hda' bus='ide'/>
      <uuid>1efaf08b-9317-4b0f-b227-912e4bd9f483</uuid>
      <address type='drive' controller='0' bus='0' target='0' unit='0'/>
    </disk>

Signed-off-by: Michal Privoznik <mprivozn at redhat.com>
---

This is just a very basic implementation. If I get a green light on this, I can
implement the feature further, i.e. allow device lookup on the UUID. For
instance:

virsh domiftune fedora $UUID $bandwidth


 docs/formatdomain.html.in                          | 21 +++++++++++++++
 docs/schemas/domaincommon.rng                      | 21 ++++++++++-----
 src/conf/device_conf.c                             |  1 +
 src/conf/device_conf.h                             |  1 +
 src/conf/domain_conf.c                             | 25 +++++++++++++++++
 tests/genericxml2xmlindata/generic-device-uuid.xml | 31 ++++++++++++++++++++++
 tests/genericxml2xmltest.c                         |  1 +
 7 files changed, 95 insertions(+), 6 deletions(-)
 create mode 100644 tests/genericxml2xmlindata/generic-device-uuid.xml

diff --git a/docs/formatdomain.html.in b/docs/formatdomain.html.in
index 5dcf2fedb..b4b2751fd 100644
--- a/docs/formatdomain.html.in
+++ b/docs/formatdomain.html.in
@@ -3512,6 +3512,27 @@
       </dd>
     </dl>
 
+    <p>
+      To help management applications identify devices they care about, devices
+      have an optional <code><uuid/></code> sub-element which can hold
+      UUID label generated by the management application. For instance:
+    </p>
+
+<pre>
+  <disk type='block' device='disk'>
+    <driver name='qemu' type='raw'/>
+    <source dev='/dev/HostVG/QEMUGuest1'/>
+    <target dev='hda' bus='ide'/>
+    <uuid>2d0ad0dc-3eaa-4295-9d62-3e531197ed7a</uuid>
+    <address type='drive' controller='0' bus='0' target='0' unit='0'/>
+  </disk>
+</pre>
+
+    <p>
+      The <code><uuid/></code> is available
+      <span class="since">since 3.9.0</span>.
+    </p>
+
     <h4><a id="elementsVirtio">Virtio-related options</a></h4>
 
     <p>
diff --git a/docs/schemas/domaincommon.rng b/docs/schemas/domaincommon.rng
index bac371ea3..61d8430bb 100644
--- a/docs/schemas/domaincommon.rng
+++ b/docs/schemas/domaincommon.rng
@@ -5863,12 +5863,21 @@
     </data>
   </define>
   <define name='alias'>
-    <element name='alias'>
-      <attribute name='name'>
-        <ref name='aliasName'/>
-      </attribute>
-    </element>
-    <empty/>
+    <interleave>
+      <optional>
+        <element name='alias'>
+          <attribute name='name'>
+            <ref name='aliasName'/>
+          </attribute>
+          <empty/>
+        </element>
+      </optional>
+      <optional>
+        <element name='uuid'>
+          <ref name="UUID"/>
+        </element>
+      </optional>
+    </interleave>
   </define>
   <define name="panic">
     <element name="panic">
diff --git a/src/conf/device_conf.c b/src/conf/device_conf.c
index d69f94fad..a732731eb 100644
--- a/src/conf/device_conf.c
+++ b/src/conf/device_conf.c
@@ -57,6 +57,7 @@ void
 virDomainDeviceInfoClear(virDomainDeviceInfoPtr info)
 {
     VIR_FREE(info->alias);
+    VIR_FREE(info->uuid);
     memset(&info->addr, 0, sizeof(info->addr));
     info->type = VIR_DOMAIN_DEVICE_ADDRESS_TYPE_NONE;
     VIR_FREE(info->romfile);
diff --git a/src/conf/device_conf.h b/src/conf/device_conf.h
index f87d6f1fc..f80017291 100644
--- a/src/conf/device_conf.h
+++ b/src/conf/device_conf.h
@@ -135,6 +135,7 @@ typedef struct _virDomainDeviceInfo virDomainDeviceInfo;
 typedef virDomainDeviceInfo *virDomainDeviceInfoPtr;
 struct _virDomainDeviceInfo {
     char *alias;
+    unsigned char *uuid;    /* user defined UUID for the device, might be NULL */
     int type; /* virDomainDeviceAddressType */
     union {
         virPCIDeviceAddress pci;
diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c
index 67095114c..2ea26dd9f 100644
--- a/src/conf/domain_conf.c
+++ b/src/conf/domain_conf.c
@@ -5764,11 +5764,18 @@ virDomainDeviceInfoFormat(virBufferPtr buf,
 
         virBufferAddLit(buf, "/>\n");
     }
+
     if (info->alias &&
         !(flags & VIR_DOMAIN_DEF_FORMAT_INACTIVE)) {
         virBufferAsprintf(buf, "<alias name='%s'/>\n", info->alias);
     }
 
+    if (info->uuid) {
+        char uuidstr[VIR_UUID_STRING_BUFLEN];
+        virUUIDFormat(info->uuid, uuidstr);
+        virBufferAsprintf(buf, "<uuid>%s</uuid>\n", uuidstr);
+    }
+
     if (info->mastertype == VIR_DOMAIN_CONTROLLER_MASTER_USB) {
         virBufferAsprintf(buf, "<master startport='%d'/>\n",
                           info->master.usb.startport);
@@ -6403,10 +6410,12 @@ virDomainDeviceInfoParseXML(xmlNodePtr node,
     xmlNodePtr address = NULL;
     xmlNodePtr master = NULL;
     xmlNodePtr alias = NULL;
+    xmlNodePtr uuid = NULL;
     xmlNodePtr boot = NULL;
     xmlNodePtr rom = NULL;
     char *type = NULL;
     char *rombar = NULL;
+    char *uuidstr = NULL;
     int ret = -1;
 
     virDomainDeviceInfoClear(info);
@@ -6418,6 +6427,9 @@ virDomainDeviceInfoParseXML(xmlNodePtr node,
                 !(flags & VIR_DOMAIN_DEF_PARSE_INACTIVE) &&
                 virXMLNodeNameEqual(cur, "alias")) {
                 alias = cur;
+            } else if (uuid == NULL &&
+                       virXMLNodeNameEqual(cur, "uuid")) {
+                uuid = cur;
             } else if (address == NULL &&
                        virXMLNodeNameEqual(cur, "address")) {
                 address = cur;
@@ -6440,6 +6452,18 @@ virDomainDeviceInfoParseXML(xmlNodePtr node,
     if (alias)
         info->alias = virXMLPropString(alias, "name");
 
+    if (uuid &&
+        (uuidstr = virXMLNodeContentString(uuid))) {
+        if (VIR_ALLOC_N(info->uuid, VIR_UUID_BUFLEN) < 0)
+            goto cleanup;
+
+        if (virUUIDParse(uuidstr, info->uuid) < 0) {
+            virReportError(VIR_ERR_INTERNAL_ERROR,
+                           "%s", _("malformed uuid element"));
+            goto cleanup;
+        }
+    }
+
     if (master) {
         info->mastertype = VIR_DOMAIN_CONTROLLER_MASTER_USB;
         if (virDomainDeviceUSBMasterParseXML(master, &info->master.usb) < 0)
@@ -6472,6 +6496,7 @@ virDomainDeviceInfoParseXML(xmlNodePtr node,
         virDomainDeviceInfoClear(info);
     VIR_FREE(type);
     VIR_FREE(rombar);
+    VIR_FREE(uuidstr);
     return ret;
 }
 
diff --git a/tests/genericxml2xmlindata/generic-device-uuid.xml b/tests/genericxml2xmlindata/generic-device-uuid.xml
new file mode 100644
index 000000000..6deac5f9c
--- /dev/null
+++ b/tests/genericxml2xmlindata/generic-device-uuid.xml
@@ -0,0 +1,31 @@
+<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-system-i686</emulator>
+    <disk type='block' device='disk'>
+      <driver name='qemu' type='raw'/>
+      <source dev='/dev/HostVG/QEMUGuest1'/>
+      <target dev='hda' bus='ide'/>
+      <uuid>2d0ad0dc-3eaa-4295-9d62-3e531197ed7a</uuid>
+      <address type='drive' controller='0' bus='0' target='0' unit='0'/>
+    </disk>
+    <controller type='usb' index='0'>
+      <uuid>4d21cdd8-ab68-4964-a879-9b9198f9f097</uuid>
+    </controller>
+    <controller type='ide' index='0'/>
+    <controller type='pci' index='0' model='pci-root'/>
+    <memballoon model='none'/>
+  </devices>
+</domain>
diff --git a/tests/genericxml2xmltest.c b/tests/genericxml2xmltest.c
index 0377a05e9..e0665aa25 100644
--- a/tests/genericxml2xmltest.c
+++ b/tests/genericxml2xmltest.c
@@ -130,6 +130,7 @@ mymain(void)
     DO_TEST_FULL("chardev-reconnect-invalid-mode", 0, false,
                  TEST_COMPARE_DOM_XML2XML_RESULT_FAIL_PARSE);
 
+    DO_TEST("device-uuid");
     virObjectUnref(caps);
     virObjectUnref(xmlopt);
 
-- 
2.13.5




More information about the libvir-list mailing list