[Libguestfs] [PATCH 2/5] libvirt: initial support for networked disks

Mike Kelly pioto at pioto.org
Tue May 7 14:50:09 UTC 2013


---
 src/libvirt-domain.c |   87 +++++++++++++++++++++++++++++++++++++++++++++++---
 1 file changed, 82 insertions(+), 5 deletions(-)

diff --git a/src/libvirt-domain.c b/src/libvirt-domain.c
index 0ec0cad..8e94541 100644
--- a/src/libvirt-domain.c
+++ b/src/libvirt-domain.c
@@ -40,7 +40,7 @@
 #if defined(HAVE_LIBVIRT)
 
 static xmlDocPtr get_domain_xml (guestfs_h *g, virDomainPtr dom);
-static ssize_t for_each_disk (guestfs_h *g, xmlDocPtr doc, int (*f) (guestfs_h *g, const char *filename, const char *format, int readonly, void *data), void *data);
+static ssize_t for_each_disk (guestfs_h *g, xmlDocPtr doc, int (*f) (guestfs_h *g, const char *filename, const char *format, int readonly, const char *protocol, char *const *server, const char *username, void *data), void *data);
 static int libvirt_selinux_label (guestfs_h *g, xmlDocPtr doc, char **label_rtn, char **imagelabel_rtn);
 
 static void
@@ -139,7 +139,7 @@ guestfs__add_domain (guestfs_h *g, const char *domain_name,
   return r;
 }
 
-static int add_disk (guestfs_h *g, const char *filename, const char *format, int readonly, void *data);
+static int add_disk (guestfs_h *g, const char *filename, const char *format, int readonly, const char *protocol, char *const *server, const char *username, void *data);
 static int connect_live (guestfs_h *g, virDomainPtr dom);
 
 enum readonlydisk {
@@ -268,6 +268,7 @@ guestfs___add_libvirt_dom (guestfs_h *g, virDomainPtr dom,
 static int
 add_disk (guestfs_h *g,
           const char *filename, const char *format, int readonly_in_xml,
+          const char *protocol, char *const *server, const char *username,
           void *datavp)
 {
   struct add_disk_data *data = datavp;
@@ -313,6 +314,18 @@ add_disk (guestfs_h *g,
     optargs.bitmask |= GUESTFS_ADD_DRIVE_OPTS_FORMAT_BITMASK;
     optargs.format = format;
   }
+  if (protocol) {
+    optargs.bitmask |= GUESTFS_ADD_DRIVE_OPTS_PROTOCOL_BITMASK;
+    optargs.protocol = protocol;
+  }
+  if (server) {
+    optargs.bitmask |= GUESTFS_ADD_DRIVE_OPTS_SERVER_BITMASK;
+    optargs.server = server;
+  }
+  if (username) {
+    optargs.bitmask |= GUESTFS_ADD_DRIVE_OPTS_USERNAME_BITMASK;
+    optargs.username = username;
+  }
 
   return guestfs__add_drive_opts (g, filename, &optargs);
 }
@@ -404,6 +417,8 @@ for_each_disk (guestfs_h *g,
                int (*f) (guestfs_h *g,
                          const char *filename, const char *format,
                          int readonly,
+                         const char *protocol, char *const *server,
+                         const char *username,
                          void *data),
                void *data)
 {
@@ -432,11 +447,14 @@ for_each_disk (guestfs_h *g,
   if (nodes != NULL) {
     nr_nodes = nodes->nodeNr;
     for (i = 0; i < nr_nodes; ++i) {
-      CLEANUP_FREE char *type = NULL, *filename = NULL, *format = NULL;
+      CLEANUP_FREE char *type = NULL, *filename = NULL, *format = NULL, *protocol = NULL, *username = NULL;
+      CLEANUP_FREE_STRING_LIST char **server = NULL;
       CLEANUP_XMLXPATHFREEOBJECT xmlXPathObjectPtr xptype = NULL;
       CLEANUP_XMLXPATHFREEOBJECT xmlXPathObjectPtr xpformat = NULL;
       CLEANUP_XMLXPATHFREEOBJECT xmlXPathObjectPtr xpreadonly = NULL;
       CLEANUP_XMLXPATHFREEOBJECT xmlXPathObjectPtr xpfilename = NULL;
+      CLEANUP_XMLXPATHFREEOBJECT xmlXPathObjectPtr xpprotocol = NULL;
+      CLEANUP_XMLXPATHFREEOBJECT xmlXPathObjectPtr xphost = NULL;
       xmlAttrPtr attr;
       int readonly;
       int t;
@@ -479,8 +497,66 @@ for_each_disk (guestfs_h *g,
             xpfilename->nodesetval->nodeNr == 0) {
           continue;           /* disk filename not found, skip this */
         }
+      } else if (STREQ (type, "network")) { /* type = "network", use source/@name */
+        debug(g, _("disk[%zu]: network device"), i);
+        xpathCtx->node = nodes->nodeTab[i];
+        xpfilename = xmlXPathEvalExpression (BAD_CAST "./source/@name",
+                                             xpathCtx);
+        if (xpfilename == NULL ||
+            xpfilename->nodesetval == NULL ||
+            xpfilename->nodesetval->nodeNr == 0) {
+          continue;
+        }
+
+        xpprotocol = xmlXPathEvalExpression (BAD_CAST "./source/@protocol",
+                                             xpathCtx);
+        /* Get the protocol (e.g. "rbd"). */
+        if (xpprotocol == NULL ||
+            xpprotocol->nodesetval == NULL ||
+            xpprotocol->nodesetval->nodeNr == 0) {
+          continue;
+        }
+        assert (xpprotocol->nodesetval->nodeTab[0]);
+        assert (xpprotocol->nodesetval->nodeTab[0]->type == XML_ATTRIBUTE_NODE);
+        attr = (xmlAttrPtr) xpprotocol->nodesetval->nodeTab[0];
+        protocol = (char *) xmlNodeListGetString (doc, attr->children, 1);
+        debug(g, _("disk[%zu]: protocol: %s"), i, protocol);
+
+        xphost = xmlXPathEvalExpression (BAD_CAST "./source/host",
+                                             xpathCtx);
+        if (xphost == NULL ||
+            xphost->nodesetval == NULL ||
+            xphost->nodesetval->nodeNr == 0) {
+          continue;
+        }
+        /* This gives us a list of <host> elements, which each have a
+         * 'name' and 'port' attribute which we want to put into a
+         * string, joined by a ':'.
+         */
+        server = safe_malloc (g, sizeof (char *) * (xphost->nodesetval->nodeNr + 1));
+        for (int hi = 0; hi < xphost->nodesetval->nodeNr ; hi++) {
+          xmlChar *name, *port;
+          xmlNodePtr h = xphost->nodesetval->nodeTab[hi];
+          assert (h);
+          assert (h->type == XML_ELEMENT_NODE);
+          name = xmlGetProp(h, "name");
+          assert(name);
+          port = xmlGetProp(h, "port");
+          assert(port);
+          debug(g, _("disk[%zu]: host: %s:%s"), i, name, port);
+          if (asprintf(&server[hi], "%s:%s", name, port) == -1) {
+            perror("asprintf");
+            return -1;
+          }
+        }
+        server[xphost->nodesetval->nodeNr] = NULL;
+
+        /*
+         * TODO: usernames, secrets: ./auth/secret/@type,
+         * ./auth/secret/@usage || ./auth/secret/@uuid
+         */
       } else
-        continue;             /* type <> "file" or "block", skip it */
+        continue;             /* type <> "file", "block", or "network", skip it */
 
       assert (xpfilename);
       assert (xpfilename->nodesetval);
@@ -488,6 +564,7 @@ for_each_disk (guestfs_h *g,
       assert (xpfilename->nodesetval->nodeTab[0]->type == XML_ATTRIBUTE_NODE);
       attr = (xmlAttrPtr) xpfilename->nodesetval->nodeTab[0];
       filename = (char *) xmlNodeListGetString (doc, attr->children, 1);
+      debug(g, _("disk[%zu]: filename: %s"), i, filename);
 
       /* Get the disk format (may not be set). */
       xpathCtx->node = nodes->nodeTab[i];
@@ -511,7 +588,7 @@ for_each_disk (guestfs_h *g,
         readonly = 1;
 
       if (f)
-        t = f (g, filename, format, readonly, data);
+        t = f (g, filename, format, readonly, protocol, server, username, data);
       else
         t = 0;
 
-- 
1.7.9.5




More information about the Libguestfs mailing list