c401cc
From 38d996886dd96d39f2c812150ad2edcf53c00e0b Mon Sep 17 00:00:00 2001
c401cc
Message-Id: <38d996886dd96d39f2c812150ad2edcf53c00e0b@dist-git>
c401cc
From: Peter Krempa <pkrempa@redhat.com>
c401cc
Date: Wed, 26 Feb 2014 14:54:11 +0100
c401cc
Subject: [PATCH] conf: Split out code to parse the source of a disk definition
c401cc
c401cc
https://bugzilla.redhat.com/show_bug.cgi?id=1032370
c401cc
c401cc
To avoid code duplication between snapshot configuration code that
c401cc
parses the disk source too we need to split out this code that will be
c401cc
reused later on.
c401cc
c401cc
This patch tries to be code movement, some aspects of this function will
c401cc
be refactored later.
c401cc
c401cc
(cherry picked from commit 16bc7864087707c84e71a03b3a28a8912e44ae67)
c401cc
c401cc
Signed-off-by: Jiri Denemark <jdenemar@redhat.com>
c401cc
---
c401cc
 src/conf/domain_conf.c | 266 +++++++++++++++++++++++++++----------------------
c401cc
 1 file changed, 149 insertions(+), 117 deletions(-)
c401cc
c401cc
diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c
c401cc
index 96185ca..60e8849 100644
c401cc
--- a/src/conf/domain_conf.c
c401cc
+++ b/src/conf/domain_conf.c
c401cc
@@ -4831,6 +4831,142 @@ cleanup:
c401cc
     return ret;
c401cc
 }
c401cc
 
c401cc
+
c401cc
+static int
c401cc
+virDomainDiskSourceDefParse(xmlNodePtr node,
c401cc
+                            int type,
c401cc
+                            char **source,
c401cc
+                            int *proto,
c401cc
+                            size_t *ndefhosts,
c401cc
+                            virDomainDiskHostDefPtr *defhosts,
c401cc
+                            virDomainDiskSourcePoolDefPtr *srcpool)
c401cc
+{
c401cc
+    char *protocol = NULL;
c401cc
+    char *transport = NULL;
c401cc
+    virDomainDiskHostDefPtr hosts = NULL;
c401cc
+    int nhosts = 0;
c401cc
+    xmlNodePtr child;
c401cc
+    int ret = -1;
c401cc
+
c401cc
+    switch (type) {
c401cc
+    case VIR_DOMAIN_DISK_TYPE_FILE:
c401cc
+        *source = virXMLPropString(node, "file");
c401cc
+        break;
c401cc
+    case VIR_DOMAIN_DISK_TYPE_BLOCK:
c401cc
+        *source = virXMLPropString(node, "dev");
c401cc
+        break;
c401cc
+    case VIR_DOMAIN_DISK_TYPE_DIR:
c401cc
+        *source = virXMLPropString(node, "dir");
c401cc
+        break;
c401cc
+    case VIR_DOMAIN_DISK_TYPE_NETWORK:
c401cc
+        protocol = virXMLPropString(node, "protocol");
c401cc
+        if (protocol == NULL) {
c401cc
+            virReportError(VIR_ERR_INTERNAL_ERROR,
c401cc
+                           "%s", _("missing protocol type"));
c401cc
+            goto error;
c401cc
+        }
c401cc
+        *proto = virDomainDiskProtocolTypeFromString(protocol);
c401cc
+        if (*proto < 0) {
c401cc
+            virReportError(VIR_ERR_INTERNAL_ERROR,
c401cc
+                           _("unknown protocol type '%s'"),
c401cc
+                           protocol);
c401cc
+            goto error;
c401cc
+        }
c401cc
+
c401cc
+        if (!(*source = virXMLPropString(node, "name")) &&
c401cc
+            *proto != VIR_DOMAIN_DISK_PROTOCOL_NBD) {
c401cc
+            virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
c401cc
+                           _("missing name for disk source"));
c401cc
+            goto error;
c401cc
+        }
c401cc
+        child = node->children;
c401cc
+        while (child != NULL) {
c401cc
+            if (child->type == XML_ELEMENT_NODE &&
c401cc
+                xmlStrEqual(child->name, BAD_CAST "host")) {
c401cc
+                if (VIR_REALLOC_N(hosts, nhosts + 1) < 0)
c401cc
+                    goto error;
c401cc
+                hosts[nhosts].name = NULL;
c401cc
+                hosts[nhosts].port = NULL;
c401cc
+                hosts[nhosts].transport = VIR_DOMAIN_DISK_PROTO_TRANS_TCP;
c401cc
+                hosts[nhosts].socket = NULL;
c401cc
+                nhosts++;
c401cc
+
c401cc
+                /* transport can be tcp (default), unix or rdma.  */
c401cc
+                transport = virXMLPropString(child, "transport");
c401cc
+                if (transport != NULL) {
c401cc
+                    hosts[nhosts - 1].transport = virDomainDiskProtocolTransportTypeFromString(transport);
c401cc
+                    if (hosts[nhosts - 1].transport < 0) {
c401cc
+                        virReportError(VIR_ERR_XML_ERROR,
c401cc
+                                       _("unknown protocol transport type '%s'"),
c401cc
+                                       transport);
c401cc
+                        goto error;
c401cc
+                    }
c401cc
+                }
c401cc
+                hosts[nhosts - 1].socket = virXMLPropString(child, "socket");
c401cc
+                if (hosts[nhosts - 1].transport == VIR_DOMAIN_DISK_PROTO_TRANS_UNIX &&
c401cc
+                    hosts[nhosts - 1].socket == NULL) {
c401cc
+                    virReportError(VIR_ERR_XML_ERROR,
c401cc
+                                   "%s", _("missing socket for unix transport"));
c401cc
+                    goto error;
c401cc
+                }
c401cc
+                if (hosts[nhosts - 1].transport != VIR_DOMAIN_DISK_PROTO_TRANS_UNIX &&
c401cc
+                    hosts[nhosts - 1].socket != NULL) {
c401cc
+                    virReportError(VIR_ERR_XML_ERROR,
c401cc
+                                   _("transport %s does not support socket attribute"),
c401cc
+                                   transport);
c401cc
+                    goto error;
c401cc
+                }
c401cc
+                VIR_FREE(transport);
c401cc
+                if (hosts[nhosts - 1].transport != VIR_DOMAIN_DISK_PROTO_TRANS_UNIX) {
c401cc
+                    hosts[nhosts - 1].name = virXMLPropString(child, "name");
c401cc
+                    if (!hosts[nhosts - 1].name) {
c401cc
+                        virReportError(VIR_ERR_XML_ERROR,
c401cc
+                                       "%s", _("missing name for host"));
c401cc
+                        goto error;
c401cc
+                    }
c401cc
+                    hosts[nhosts - 1].port = virXMLPropString(child, "port");
c401cc
+                }
c401cc
+            }
c401cc
+            child = child->next;
c401cc
+        }
c401cc
+        break;
c401cc
+    case VIR_DOMAIN_DISK_TYPE_VOLUME:
c401cc
+        if (virDomainDiskSourcePoolDefParse(node, srcpool) < 0)
c401cc
+            goto error;
c401cc
+        break;
c401cc
+    default:
c401cc
+        virReportError(VIR_ERR_INTERNAL_ERROR,
c401cc
+                       _("unexpected disk type %s"),
c401cc
+                       virDomainDiskTypeToString(type));
c401cc
+        goto error;
c401cc
+    }
c401cc
+
c401cc
+    /* People sometimes pass a bogus '' source path
c401cc
+       when they mean to omit the source element
c401cc
+       completely (e.g. CDROM without media). This is
c401cc
+       just a little compatibility check to help
c401cc
+       those broken apps */
c401cc
+    if (*source && STREQ(*source, ""))
c401cc
+        VIR_FREE(*source);
c401cc
+
c401cc
+    *ndefhosts = nhosts;
c401cc
+    *defhosts = hosts;
c401cc
+    nhosts = 0;
c401cc
+
c401cc
+    ret = 0;
c401cc
+
c401cc
+error:
c401cc
+    VIR_FREE(protocol);
c401cc
+    VIR_FREE(transport);
c401cc
+    while (nhosts > 0) {
c401cc
+        virDomainDiskHostDefFree(&hosts[nhosts - 1]);
c401cc
+        nhosts--;
c401cc
+    }
c401cc
+
c401cc
+    return ret;
c401cc
+}
c401cc
+
c401cc
+
c401cc
 #define VENDOR_LEN  8
c401cc
 #define PRODUCT_LEN 16
c401cc
 
c401cc
@@ -4859,11 +4995,7 @@ virDomainDiskDefParseXML(virDomainXMLOptionPtr xmlopt,
c401cc
     char *driverType = NULL;
c401cc
     char *source = NULL;
c401cc
     char *target = NULL;
c401cc
-    char *protocol = NULL;
c401cc
-    char *protocol_transport = NULL;
c401cc
     char *trans = NULL;
c401cc
-    virDomainDiskHostDefPtr hosts = NULL;
c401cc
-    int nhosts = 0;
c401cc
     char *bus = NULL;
c401cc
     char *cachetag = NULL;
c401cc
     char *error_policy = NULL;
c401cc
@@ -4925,116 +5057,27 @@ virDomainDiskDefParseXML(virDomainXMLOptionPtr xmlopt,
c401cc
     cur = node->children;
c401cc
     while (cur != NULL) {
c401cc
         if (cur->type == XML_ELEMENT_NODE) {
c401cc
-            if (!source && !hosts && !def->srcpool &&
c401cc
+            if (!source && !def->hosts && !def->srcpool &&
c401cc
                 xmlStrEqual(cur->name, BAD_CAST "source")) {
c401cc
                 sourceNode = cur;
c401cc
 
c401cc
-                switch (def->type) {
c401cc
-                case VIR_DOMAIN_DISK_TYPE_FILE:
c401cc
-                    source = virXMLPropString(cur, "file");
c401cc
-                    break;
c401cc
-                case VIR_DOMAIN_DISK_TYPE_BLOCK:
c401cc
-                    source = virXMLPropString(cur, "dev");
c401cc
-                    break;
c401cc
-                case VIR_DOMAIN_DISK_TYPE_DIR:
c401cc
-                    source = virXMLPropString(cur, "dir");
c401cc
-                    break;
c401cc
-                case VIR_DOMAIN_DISK_TYPE_NETWORK:
c401cc
-                    protocol = virXMLPropString(cur, "protocol");
c401cc
-                    if (protocol == NULL) {
c401cc
-                        virReportError(VIR_ERR_INTERNAL_ERROR,
c401cc
-                                       "%s", _("missing protocol type"));
c401cc
-                        goto error;
c401cc
-                    }
c401cc
-                    def->protocol = virDomainDiskProtocolTypeFromString(protocol);
c401cc
-                    if (def->protocol < 0) {
c401cc
-                        virReportError(VIR_ERR_INTERNAL_ERROR,
c401cc
-                                       _("unknown protocol type '%s'"),
c401cc
-                                       protocol);
c401cc
-                        goto error;
c401cc
-                    }
c401cc
-                    if (def->protocol == VIR_DOMAIN_DISK_PROTOCOL_ISCSI) {
c401cc
+                if (virDomainDiskSourceDefParse(cur, def->type,
c401cc
+                                                &source,
c401cc
+                                                &def->protocol,
c401cc
+                                                &def->nhosts,
c401cc
+                                                &def->hosts,
c401cc
+                                                &def->srcpool) < 0)
c401cc
+                    goto error;
c401cc
+
c401cc
+                if (def->type == VIR_DOMAIN_DISK_TYPE_NETWORK) {
c401cc
+                    if (def->protocol == VIR_DOMAIN_DISK_PROTOCOL_ISCSI)
c401cc
                         expected_secret_usage = VIR_SECRET_USAGE_TYPE_ISCSI;
c401cc
-                    } else if (def->protocol == VIR_DOMAIN_DISK_PROTOCOL_RBD) {
c401cc
+                    else if (def->protocol == VIR_DOMAIN_DISK_PROTOCOL_RBD)
c401cc
                         expected_secret_usage = VIR_SECRET_USAGE_TYPE_CEPH;
c401cc
-                    }
c401cc
-                    if (!(source = virXMLPropString(cur, "name")) &&
c401cc
-                        def->protocol != VIR_DOMAIN_DISK_PROTOCOL_NBD) {
c401cc
-                        virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
c401cc
-                                       _("missing name for disk source"));
c401cc
-                        goto error;
c401cc
-                    }
c401cc
-                    child = cur->children;
c401cc
-                    while (child != NULL) {
c401cc
-                        if (child->type == XML_ELEMENT_NODE &&
c401cc
-                            xmlStrEqual(child->name, BAD_CAST "host")) {
c401cc
-                            if (VIR_REALLOC_N(hosts, nhosts + 1) < 0)
c401cc
-                                goto error;
c401cc
-                            hosts[nhosts].name = NULL;
c401cc
-                            hosts[nhosts].port = NULL;
c401cc
-                            hosts[nhosts].transport = VIR_DOMAIN_DISK_PROTO_TRANS_TCP;
c401cc
-                            hosts[nhosts].socket = NULL;
c401cc
-                            nhosts++;
c401cc
-
c401cc
-                            /* transport can be tcp (default), unix or rdma.  */
c401cc
-                            protocol_transport = virXMLPropString(child, "transport");
c401cc
-                            if (protocol_transport != NULL) {
c401cc
-                                hosts[nhosts - 1].transport = virDomainDiskProtocolTransportTypeFromString(protocol_transport);
c401cc
-                                if (hosts[nhosts - 1].transport < 0) {
c401cc
-                                    virReportError(VIR_ERR_XML_ERROR,
c401cc
-                                                   _("unknown protocol transport type '%s'"),
c401cc
-                                                   protocol_transport);
c401cc
-                                    goto error;
c401cc
-                                }
c401cc
-                            }
c401cc
-                            hosts[nhosts - 1].socket = virXMLPropString(child, "socket");
c401cc
-                            if (hosts[nhosts - 1].transport == VIR_DOMAIN_DISK_PROTO_TRANS_UNIX &&
c401cc
-                                hosts[nhosts - 1].socket == NULL) {
c401cc
-                                virReportError(VIR_ERR_XML_ERROR,
c401cc
-                                               "%s", _("missing socket for unix transport"));
c401cc
-                                goto error;
c401cc
-                            }
c401cc
-                            if (hosts[nhosts - 1].transport != VIR_DOMAIN_DISK_PROTO_TRANS_UNIX &&
c401cc
-                                hosts[nhosts - 1].socket != NULL) {
c401cc
-                                virReportError(VIR_ERR_XML_ERROR,
c401cc
-                                               _("transport %s does not support socket attribute"),
c401cc
-                                               protocol_transport);
c401cc
-                                goto error;
c401cc
-                            }
c401cc
-                            VIR_FREE(protocol_transport);
c401cc
-                            if (hosts[nhosts - 1].transport != VIR_DOMAIN_DISK_PROTO_TRANS_UNIX) {
c401cc
-                                hosts[nhosts - 1].name = virXMLPropString(child, "name");
c401cc
-                                if (!hosts[nhosts - 1].name) {
c401cc
-                                    virReportError(VIR_ERR_XML_ERROR,
c401cc
-                                                   "%s", _("missing name for host"));
c401cc
-                                    goto error;
c401cc
-                                }
c401cc
-                                hosts[nhosts - 1].port = virXMLPropString(child, "port");
c401cc
-                            }
c401cc
-                        }
c401cc
-                        child = child->next;
c401cc
-                    }
c401cc
-                    break;
c401cc
-                case VIR_DOMAIN_DISK_TYPE_VOLUME:
c401cc
-                    if (virDomainDiskSourcePoolDefParse(cur, &def->srcpool) < 0)
c401cc
-                        goto error;
c401cc
-                    break;
c401cc
-                default:
c401cc
-                    virReportError(VIR_ERR_INTERNAL_ERROR,
c401cc
-                                   _("unexpected disk type %s"),
c401cc
-                                   virDomainDiskTypeToString(def->type));
c401cc
-                    goto error;
c401cc
                 }
c401cc
 
c401cc
                 startupPolicy = virXMLPropString(cur, "startupPolicy");
c401cc
 
c401cc
-                /* People sometimes pass a bogus '' source path
c401cc
-                   when they mean to omit the source element
c401cc
-                   completely (e.g. CDROM without media). This is
c401cc
-                   just a little compatibility check to help
c401cc
-                   those broken apps */
c401cc
-                if (source && STREQ(source, ""))
c401cc
-                    VIR_FREE(source);
c401cc
             } else if (!target &&
c401cc
                        xmlStrEqual(cur->name, BAD_CAST "target")) {
c401cc
                 target = virXMLPropString(cur, "dev");
c401cc
@@ -5329,7 +5372,7 @@ virDomainDiskDefParseXML(virDomainXMLOptionPtr xmlopt,
c401cc
     /* Only CDROM and Floppy devices are allowed missing source path
c401cc
      * to indicate no media present. LUN is for raw access CD-ROMs
c401cc
      * that are not attached to a physical device presently */
c401cc
-    if (source == NULL && hosts == NULL && !def->srcpool &&
c401cc
+    if (source == NULL && def->hosts == NULL && !def->srcpool &&
c401cc
         def->device != VIR_DOMAIN_DISK_DEVICE_CDROM &&
c401cc
         def->device != VIR_DOMAIN_DISK_DEVICE_LUN &&
c401cc
         def->device != VIR_DOMAIN_DISK_DEVICE_FLOPPY) {
c401cc
@@ -5626,10 +5669,6 @@ virDomainDiskDefParseXML(virDomainXMLOptionPtr xmlopt,
c401cc
     source = NULL;
c401cc
     def->dst = target;
c401cc
     target = NULL;
c401cc
-    def->hosts = hosts;
c401cc
-    hosts = NULL;
c401cc
-    def->nhosts = nhosts;
c401cc
-    nhosts = 0;
c401cc
     def->auth.username = authUsername;
c401cc
     authUsername = NULL;
c401cc
     def->driverName = driverName;
c401cc
@@ -5682,13 +5721,6 @@ cleanup:
c401cc
     VIR_FREE(source);
c401cc
     VIR_FREE(tray);
c401cc
     VIR_FREE(trans);
c401cc
-    while (nhosts > 0) {
c401cc
-        virDomainDiskHostDefFree(&hosts[nhosts - 1]);
c401cc
-        nhosts--;
c401cc
-    }
c401cc
-    VIR_FREE(hosts);
c401cc
-    VIR_FREE(protocol);
c401cc
-    VIR_FREE(protocol_transport);
c401cc
     VIR_FREE(device);
c401cc
     VIR_FREE(authUsername);
c401cc
     VIR_FREE(usageType);
c401cc
-- 
c401cc
1.9.0
c401cc