]> xenbits.xensource.com Git - libvirt.git/commitdiff
blockcopy: add a way to parse disk source
authorEric Blake <eblake@redhat.com>
Mon, 25 Aug 2014 18:58:49 +0000 (12:58 -0600)
committerEric Blake <eblake@redhat.com>
Mon, 8 Sep 2014 21:50:39 +0000 (15:50 -0600)
The new blockcopy API wants to reuse only a subset of the disk
hotplug parser - namely, we only care about the embedded
virStorageSourcePtr inside a <disk> XML.  Strange as it may
seem, it was easier to just parse an entire disk definition,
then throw away everything but the embedded source, than it
was to disentangle the source parsing code from the rest of
the overall disk parsing function.  All that I needed was a
couple of tweaks and a new internal flag that determines
whether the normally-mandatory target element can be
gracefully skipped, since everything else was already optional.

* src/conf/domain_conf.h (virDomainDiskSourceParse): New
prototype.
* src/conf/domain_conf.c (VIR_DOMAIN_XML_INTERNAL_DISK_SOURCE):
New flag.
(virDomainDiskDefParseXML): Honor flag to make target optional.
(virDomainDiskSourceParse): New function.

Signed-off-by: Eric Blake <eblake@redhat.com>
src/conf/domain_conf.c
src/conf/domain_conf.h
src/libvirt_private.syms

index 9fe75f8db1b597c46ecf341bbbd191551d475050..aac78a61895bd9fa583d0737ce0901070c1bce1b 100644 (file)
@@ -100,6 +100,8 @@ typedef enum {
    VIR_DOMAIN_XML_INTERNAL_ALLOW_ROM       = 1 << 19,
    VIR_DOMAIN_XML_INTERNAL_ALLOW_BOOT      = 1 << 20,
    VIR_DOMAIN_XML_INTERNAL_CLOCK_ADJUST    = 1 << 21,
+   /* parse only source half of <disk> */
+   VIR_DOMAIN_XML_INTERNAL_DISK_SOURCE     = 1 << 22,
 } virDomainXMLInternalFlags;
 
 #define DUMPXML_FLAGS                           \
@@ -113,7 +115,8 @@ verify(((VIR_DOMAIN_XML_INTERNAL_STATUS |
          VIR_DOMAIN_XML_INTERNAL_PCI_ORIG_STATES |
          VIR_DOMAIN_XML_INTERNAL_ALLOW_ROM |
          VIR_DOMAIN_XML_INTERNAL_ALLOW_BOOT |
-         VIR_DOMAIN_XML_INTERNAL_CLOCK_ADJUST)
+         VIR_DOMAIN_XML_INTERNAL_CLOCK_ADJUST |
+         VIR_DOMAIN_XML_INTERNAL_DISK_SOURCE)
         & DUMPXML_FLAGS) == 0);
 
 VIR_ENUM_IMPL(virDomainTaint, VIR_DOMAIN_TAINT_LAST,
@@ -5847,9 +5850,8 @@ virDomainDiskDefParseXML(virDomainXMLOptionPtr xmlopt,
      * to indicate no media present. LUN is for raw access CD-ROMs
      * that are not attached to a physical device presently */
     if (source == NULL && def->src->hosts == NULL && !def->src->srcpool &&
-        def->device != VIR_DOMAIN_DISK_DEVICE_CDROM &&
-        def->device != VIR_DOMAIN_DISK_DEVICE_LUN &&
-        def->device != VIR_DOMAIN_DISK_DEVICE_FLOPPY) {
+        (def->device == VIR_DOMAIN_DISK_DEVICE_DISK ||
+         (flags & VIR_DOMAIN_XML_INTERNAL_DISK_SOURCE))) {
         virReportError(VIR_ERR_NO_SOURCE,
                        target ? "%s" : NULL, target);
         goto error;
@@ -5869,7 +5871,7 @@ virDomainDiskDefParseXML(virDomainXMLOptionPtr xmlopt,
         ctxt->node = saved_node;
     }
 
-    if (target == NULL) {
+    if (!target && !(flags & VIR_DOMAIN_XML_INTERNAL_DISK_SOURCE)) {
         if (def->src->srcpool) {
             char *tmp;
             if (virAsprintf(&tmp, "pool = '%s', volume = '%s'",
@@ -5884,27 +5886,29 @@ virDomainDiskDefParseXML(virDomainXMLOptionPtr xmlopt,
         goto error;
     }
 
-    if (def->device == VIR_DOMAIN_DISK_DEVICE_FLOPPY &&
-        !STRPREFIX(target, "fd")) {
-        virReportError(VIR_ERR_INTERNAL_ERROR,
-                       _("Invalid floppy device name: %s"), target);
-        goto error;
-    }
+    if (!(flags & VIR_DOMAIN_XML_INTERNAL_DISK_SOURCE)) {
+        if (def->device == VIR_DOMAIN_DISK_DEVICE_FLOPPY &&
+            !STRPREFIX(target, "fd")) {
+            virReportError(VIR_ERR_INTERNAL_ERROR,
+                           _("Invalid floppy device name: %s"), target);
+            goto error;
+        }
 
-    /* Force CDROM to be listed as read only */
-    if (def->device == VIR_DOMAIN_DISK_DEVICE_CDROM)
-        def->src->readonly = true;
+        /* Force CDROM to be listed as read only */
+        if (def->device == VIR_DOMAIN_DISK_DEVICE_CDROM)
+            def->src->readonly = true;
 
-    if ((def->device == VIR_DOMAIN_DISK_DEVICE_DISK ||
-         def->device == VIR_DOMAIN_DISK_DEVICE_LUN) &&
-        !STRPREFIX((const char *)target, "hd") &&
-        !STRPREFIX((const char *)target, "sd") &&
-        !STRPREFIX((const char *)target, "vd") &&
-        !STRPREFIX((const char *)target, "xvd") &&
-        !STRPREFIX((const char *)target, "ubd")) {
-        virReportError(VIR_ERR_INTERNAL_ERROR,
-                       _("Invalid harddisk device name: %s"), target);
-        goto error;
+        if ((def->device == VIR_DOMAIN_DISK_DEVICE_DISK ||
+             def->device == VIR_DOMAIN_DISK_DEVICE_LUN) &&
+            !STRPREFIX((const char *)target, "hd") &&
+            !STRPREFIX((const char *)target, "sd") &&
+            !STRPREFIX((const char *)target, "vd") &&
+            !STRPREFIX((const char *)target, "xvd") &&
+            !STRPREFIX((const char *)target, "ubd")) {
+            virReportError(VIR_ERR_INTERNAL_ERROR,
+                           _("Invalid harddisk device name: %s"), target);
+            goto error;
+        }
     }
 
     if (snapshot) {
@@ -5958,7 +5962,7 @@ virDomainDiskDefParseXML(virDomainXMLOptionPtr xmlopt,
     } else {
         if (def->device == VIR_DOMAIN_DISK_DEVICE_FLOPPY) {
             def->bus = VIR_DOMAIN_DISK_BUS_FDC;
-        } else {
+        } else if (!(flags & VIR_DOMAIN_XML_INTERNAL_DISK_SOURCE)) {
             if (STRPREFIX(target, "hd"))
                 def->bus = VIR_DOMAIN_DISK_BUS_IDE;
             else if (STRPREFIX(target, "sd"))
@@ -6193,12 +6197,14 @@ virDomainDiskDefParseXML(virDomainXMLOptionPtr xmlopt,
         }
     }
 
-    if (def->info.type == VIR_DOMAIN_DEVICE_ADDRESS_TYPE_NONE
-        && virDomainDiskDefAssignAddress(xmlopt, def) < 0)
-        goto error;
+    if (!(flags & VIR_DOMAIN_XML_INTERNAL_DISK_SOURCE)) {
+        if (def->info.type == VIR_DOMAIN_DEVICE_ADDRESS_TYPE_NONE
+            && virDomainDiskDefAssignAddress(xmlopt, def) < 0)
+            goto error;
 
-    if (virDomainDiskBackingStoreParse(ctxt, def->src) < 0)
-        goto error;
+        if (virDomainDiskBackingStoreParse(ctxt, def->src) < 0)
+            goto error;
+    }
 
  cleanup:
     VIR_FREE(bus);
@@ -10412,6 +10418,47 @@ virDomainDeviceDefParse(const char *xmlStr,
 }
 
 
+virStorageSourcePtr
+virDomainDiskDefSourceParse(const char *xmlStr,
+                            const virDomainDef *def,
+                            virDomainXMLOptionPtr xmlopt,
+                            unsigned int flags)
+{
+    xmlDocPtr xml;
+    xmlNodePtr node;
+    xmlXPathContextPtr ctxt = NULL;
+    virDomainDiskDefPtr disk = NULL;
+    virStorageSourcePtr ret = NULL;
+
+    if (!(xml = virXMLParseStringCtxt(xmlStr, _("(disk_definition)"), &ctxt)))
+        goto cleanup;
+    node = ctxt->node;
+
+    if (!xmlStrEqual(node->name, BAD_CAST "disk")) {
+        virReportError(VIR_ERR_XML_ERROR,
+                       _("expecting root element of 'disk', not '%s'"),
+                       node->name);
+        goto cleanup;
+    }
+
+    flags |= VIR_DOMAIN_XML_INTERNAL_DISK_SOURCE;
+    if (!(disk = virDomainDiskDefParseXML(xmlopt, node, ctxt,
+                                          NULL, def->seclabels,
+                                          def->nseclabels,
+                                          flags)))
+        goto cleanup;
+
+    ret = disk->src;
+    disk->src = NULL;
+
+ cleanup:
+    virDomainDiskDefFree(disk);
+    xmlFreeDoc(xml);
+    xmlXPathFreeContext(ctxt);
+    return ret;
+}
+
+
 static const char *
 virDomainChrTargetTypeToString(int deviceType,
                                int targetType)
index 9586c3be165f961bcd6b05393669d91fd0dc74b6..1107fa80212e28f3380f084eb33cea2e446768ec 100644 (file)
@@ -2297,6 +2297,10 @@ virDomainDeviceDefPtr virDomainDeviceDefParse(const char *xmlStr,
                                               virCapsPtr caps,
                                               virDomainXMLOptionPtr xmlopt,
                                               unsigned int flags);
+virStorageSourcePtr virDomainDiskDefSourceParse(const char *xmlStr,
+                                                const virDomainDef *def,
+                                                virDomainXMLOptionPtr xmlopt,
+                                                unsigned int flags);
 virDomainDefPtr virDomainDefParseString(const char *xmlStr,
                                         virCapsPtr caps,
                                         virDomainXMLOptionPtr xmlopt,
index f136d244b1b5e3ff7bda5b36e90be1e1b75447e0..10ebd121b96758d6af57d42e15be91507702a873 100644 (file)
@@ -222,6 +222,7 @@ virDomainDiskDefAssignAddress;
 virDomainDiskDefForeachPath;
 virDomainDiskDefFree;
 virDomainDiskDefNew;
+virDomainDiskDefSourceParse;
 virDomainDiskDeviceTypeToString;
 virDomainDiskDiscardTypeToString;
 virDomainDiskErrorPolicyTypeFromString;