[libvirt] [PATCH v1 06/11] network: Create real network status files

Michal Privoznik mprivozn at redhat.com
Mon Nov 19 16:51:46 UTC 2012


Currently, we are only keeping a inactive XML configuration
in status dir. This is no longer enough as we need to keep
this class_id attribute so we don't overwrite old entries
when the daemon restarts. However, since there has already
been a libvirt release which has just <network/> as root element,
and we want to keep things compatible, detect that loaded
status file is older one, and don't scream about it.
---
 src/conf/network_conf.c     |  199 ++++++++++++++++++++++++++++++++++---------
 src/conf/network_conf.h     |    2 +
 src/libvirt_private.syms    |    1 +
 src/network/bridge_driver.c |    9 +--
 4 files changed, 165 insertions(+), 46 deletions(-)

diff --git a/src/conf/network_conf.c b/src/conf/network_conf.c
index 80189e6..9c2e4d4 100644
--- a/src/conf/network_conf.c
+++ b/src/conf/network_conf.c
@@ -1645,6 +1645,78 @@ cleanup:
     return def;
 }
 
+int
+virNetworkObjUpdateParseFile(const char *filename,
+                             virNetworkObjPtr net)
+{
+    int ret = -1;
+    xmlDocPtr xml = NULL;
+    xmlNodePtr node = NULL;
+    virNetworkDefPtr tmp = NULL;
+    xmlXPathContextPtr ctxt = NULL;
+
+    xml = virXMLParse(filename, NULL, _("(network status)"));
+    if (!xml)
+        return -1;
+
+    ctxt = xmlXPathNewContext(xml);
+    if (ctxt == NULL) {
+        virReportOOMError();
+        goto cleanup;
+    }
+
+    node = xmlDocGetRootElement(xml);
+    if (xmlStrEqual(node->name, BAD_CAST "networkstatus")) {
+        /* Newer network status file. Contains useful
+         * info which are not to be found in bare config XML */
+        char *class_id = NULL;
+        char *floor_sum = NULL;
+
+        ctxt->node = node;
+        class_id = virXPathString("string(./class_id[1]/@next)", ctxt);
+        if (class_id &&
+            virStrToLong_ui(class_id, NULL, 10, &net->class_id) < 0) {
+            virReportError(VIR_ERR_INTERNAL_ERROR,
+                           _("Malformed 'class_id' attribute: %s"),
+                           class_id);
+            VIR_FREE(class_id);
+            goto cleanup;
+        }
+        VIR_FREE(class_id);
+
+        floor_sum = virXPathString("string(./floor[1]/@sum)", ctxt);
+        if (floor_sum &&
+            virStrToLong_ull(floor_sum, NULL, 10, &net->floor_sum) < 0) {
+            virReportError(VIR_ERR_INTERNAL_ERROR,
+                           _("Malformed 'floor_sum' attribute: %s"),
+                           floor_sum);
+            VIR_FREE(floor_sum);
+        }
+        VIR_FREE(floor_sum);
+    }
+
+    node = virXPathNode("//network", ctxt);
+    if (!node) {
+        virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+                       _("Could not find any 'network' element"));
+        goto cleanup;
+    }
+
+    ctxt->node = node;
+    tmp = virNetworkDefParseXML(ctxt);
+
+    if (tmp) {
+        net->newDef = net->def;
+        net->def = tmp;
+    }
+
+    ret = 0;
+
+cleanup:
+    xmlXPathFreeContext(ctxt);
+    return ret;
+}
+
 static int
 virNetworkDNSDefFormat(virBufferPtr buf,
                        virNetworkDNSDefPtr def)
@@ -1823,24 +1895,26 @@ virPortGroupDefFormat(virBufferPtr buf,
     return 0;
 }
 
-char *virNetworkDefFormat(const virNetworkDefPtr def, unsigned int flags)
+static int
+virNetworkDefFormatInternal(virBufferPtr buf,
+                            const virNetworkDefPtr def,
+                            unsigned int flags)
 {
-    virBuffer buf = VIR_BUFFER_INITIALIZER;
     unsigned char *uuid;
     char uuidstr[VIR_UUID_STRING_BUFLEN];
     int ii;
 
-    virBufferAddLit(&buf, "<network");
+    virBufferAddLit(buf, "<network");
     if (!(flags & VIR_NETWORK_XML_INACTIVE) && (def->connections > 0)) {
-        virBufferAsprintf(&buf, " connections='%d'", def->connections);
+        virBufferAsprintf(buf, " connections='%d'", def->connections);
     }
-    virBufferAddLit(&buf, ">\n");
-    virBufferAdjustIndent(&buf, 2);
-    virBufferEscapeString(&buf, "<name>%s</name>\n", def->name);
+    virBufferAddLit(buf, ">\n");
+    virBufferAdjustIndent(buf, 2);
+    virBufferEscapeString(buf, "<name>%s</name>\n", def->name);
 
     uuid = def->uuid;
     virUUIDFormat(uuid, uuidstr);
-    virBufferAsprintf(&buf, "<uuid>%s</uuid>\n", uuidstr);
+    virBufferAsprintf(buf, "<uuid>%s</uuid>\n", uuidstr);
 
     if (def->forwardType != VIR_NETWORK_FORWARD_NONE) {
         const char *dev = NULL;
@@ -1854,40 +1928,40 @@ char *virNetworkDefFormat(const virNetworkDefPtr def, unsigned int flags)
                            def->forwardType, def->name);
             goto error;
         }
-        virBufferAddLit(&buf, "<forward");
-        virBufferEscapeString(&buf, " dev='%s'", dev);
-        virBufferAsprintf(&buf, " mode='%s'", mode);
+        virBufferAddLit(buf, "<forward");
+        virBufferEscapeString(buf, " dev='%s'", dev);
+        virBufferAsprintf(buf, " mode='%s'", mode);
         if (def->forwardType == VIR_NETWORK_FORWARD_HOSTDEV) {
             if (def->managed == 1)
-                virBufferAddLit(&buf, " managed='yes'");
+                virBufferAddLit(buf, " managed='yes'");
             else
-                virBufferAddLit(&buf, " managed='no'");
+                virBufferAddLit(buf, " managed='no'");
         }
-        virBufferAsprintf(&buf, "%s>\n",
+        virBufferAsprintf(buf, "%s>\n",
                           (def->nForwardIfs || def->nForwardPfs) ? "" : "/");
-        virBufferAdjustIndent(&buf, 2);
+        virBufferAdjustIndent(buf, 2);
 
         /* For now, hard-coded to at most 1 forwardPfs */
         if (def->nForwardPfs)
-            virBufferEscapeString(&buf, "<pf dev='%s'/>\n",
+            virBufferEscapeString(buf, "<pf dev='%s'/>\n",
                                   def->forwardPfs[0].dev);
 
         if (def->nForwardIfs &&
             (!def->nForwardPfs || !(flags & VIR_NETWORK_XML_INACTIVE))) {
             for (ii = 0; ii < def->nForwardIfs; ii++) {
                 if (def->forwardType != VIR_NETWORK_FORWARD_HOSTDEV) {
-                    virBufferEscapeString(&buf, "<interface dev='%s'",
+                    virBufferEscapeString(buf, "<interface dev='%s'",
                                           def->forwardIfs[ii].device.dev);
                     if (!(flags & VIR_NETWORK_XML_INACTIVE) &&
                         (def->forwardIfs[ii].connections > 0)) {
-                        virBufferAsprintf(&buf, " connections='%d'",
+                        virBufferAsprintf(buf, " connections='%d'",
                                           def->forwardIfs[ii].connections);
                     }
-                    virBufferAddLit(&buf, "/>\n");
+                    virBufferAddLit(buf, "/>\n");
                 }
                 else {
                     if (def->forwardIfs[ii].type ==  VIR_NETWORK_FORWARD_HOSTDEV_DEVICE_PCI) {
-                        if (virDevicePCIAddressFormat(&buf,
+                        if (virDevicePCIAddressFormat(buf,
                                                       def->forwardIfs[ii].device.pci,
                                                       true) < 0)
                             goto error;
@@ -1895,67 +1969,111 @@ char *virNetworkDefFormat(const virNetworkDefPtr def, unsigned int flags)
                 }
             }
         }
-        virBufferAdjustIndent(&buf, -2);
+        virBufferAdjustIndent(buf, -2);
         if (def->nForwardPfs || def->nForwardIfs)
-            virBufferAddLit(&buf, "</forward>\n");
+            virBufferAddLit(buf, "</forward>\n");
     }
 
     if (def->forwardType == VIR_NETWORK_FORWARD_NONE ||
-         def->forwardType == VIR_NETWORK_FORWARD_NAT ||
-         def->forwardType == VIR_NETWORK_FORWARD_ROUTE) {
+        def->forwardType == VIR_NETWORK_FORWARD_NAT ||
+        def->forwardType == VIR_NETWORK_FORWARD_ROUTE) {
 
-        virBufferAddLit(&buf, "<bridge");
+        virBufferAddLit(buf, "<bridge");
         if (def->bridge)
-            virBufferEscapeString(&buf, " name='%s'", def->bridge);
-        virBufferAsprintf(&buf, " stp='%s' delay='%ld' />\n",
+            virBufferEscapeString(buf, " name='%s'", def->bridge);
+        virBufferAsprintf(buf, " stp='%s' delay='%ld' />\n",
                           def->stp ? "on" : "off",
                           def->delay);
     } else if (def->forwardType == VIR_NETWORK_FORWARD_BRIDGE &&
                def->bridge) {
-       virBufferEscapeString(&buf, "<bridge name='%s' />\n", def->bridge);
+        virBufferEscapeString(buf, "<bridge name='%s' />\n", def->bridge);
     }
 
 
     if (def->mac_specified) {
         char macaddr[VIR_MAC_STRING_BUFLEN];
         virMacAddrFormat(&def->mac, macaddr);
-        virBufferAsprintf(&buf, "<mac address='%s'/>\n", macaddr);
+        virBufferAsprintf(buf, "<mac address='%s'/>\n", macaddr);
     }
 
     if (def->domain)
-        virBufferAsprintf(&buf, "<domain name='%s'/>\n", def->domain);
+        virBufferAsprintf(buf, "<domain name='%s'/>\n", def->domain);
 
-    if (virNetworkDNSDefFormat(&buf, def->dns) < 0)
+    if (virNetworkDNSDefFormat(buf, def->dns) < 0)
         goto error;
 
-    if (virNetDevVlanFormat(&def->vlan, &buf) < 0)
+    if (virNetDevVlanFormat(&def->vlan, buf) < 0)
         goto error;
-    if (virNetDevBandwidthFormat(def->bandwidth, &buf) < 0)
+    if (virNetDevBandwidthFormat(def->bandwidth, buf) < 0)
         goto error;
 
     for (ii = 0; ii < def->nips; ii++) {
-        if (virNetworkIpDefFormat(&buf, &def->ips[ii]) < 0)
+        if (virNetworkIpDefFormat(buf, &def->ips[ii]) < 0)
             goto error;
     }
 
-    if (virNetDevVPortProfileFormat(def->virtPortProfile, &buf) < 0)
+    if (virNetDevVPortProfileFormat(def->virtPortProfile, buf) < 0)
         goto error;
 
     for (ii = 0; ii < def->nPortGroups; ii++)
-        if (virPortGroupDefFormat(&buf, &def->portGroups[ii]) < 0)
+        if (virPortGroupDefFormat(buf, &def->portGroups[ii]) < 0)
             goto error;
 
+    virBufferAdjustIndent(buf, -2);
+    virBufferAddLit(buf, "</network>\n");
+
+    return 0;
+
+error:
+    return -1;
+}
+
+char *
+virNetworkDefFormat(virNetworkDefPtr def,
+                    unsigned int flags)
+{
+    virBuffer buf = VIR_BUFFER_INITIALIZER;
+
+    if (virNetworkDefFormatInternal(&buf, def, flags) < 0)
+        goto error;
+
+    if (virBufferError(&buf))
+        goto no_memory;
+
+    return virBufferContentAndReset(&buf);
+
+no_memory:
+    virReportOOMError();
+error:
+    virBufferFreeAndReset(&buf);
+    return NULL;
+}
+
+static char *
+virNetworkObjFormat(virNetworkObjPtr net,
+                    unsigned int flags)
+{
+    virBuffer buf = VIR_BUFFER_INITIALIZER;
+
+    virBufferAddLit(&buf, "<networkstatus>\n");
+    virBufferAsprintf(&buf, "  <class_id next='%u'/>\n", net->class_id);
+    virBufferAsprintf(&buf, "  <floor sum='%llu'/>\n", net->floor_sum);
+
+    virBufferAdjustIndent(&buf, 2);
+    if (virNetworkDefFormatInternal(&buf, net->def, flags) < 0)
+        goto error;
+
     virBufferAdjustIndent(&buf, -2);
-    virBufferAddLit(&buf, "</network>\n");
+    virBufferAddLit(&buf, "</networkstatus>");
 
     if (virBufferError(&buf))
         goto no_memory;
 
     return virBufferContentAndReset(&buf);
 
- no_memory:
+no_memory:
     virReportOOMError();
-  error:
+error:
     virBufferFreeAndReset(&buf);
     return NULL;
 }
@@ -2027,9 +2145,10 @@ int virNetworkSaveStatus(const char *statusDir,
                          virNetworkObjPtr network)
 {
     int ret = -1;
+    int flags = 0;
     char *xml;
 
-    if (!(xml = virNetworkDefFormat(network->def, 0)))
+    if (!(xml = virNetworkObjFormat(network, flags)))
         goto cleanup;
 
     if (virNetworkSaveXML(statusDir, network->def, xml))
diff --git a/src/conf/network_conf.h b/src/conf/network_conf.h
index 8a8d1e4..efa9dea 100644
--- a/src/conf/network_conf.h
+++ b/src/conf/network_conf.h
@@ -270,6 +270,8 @@ virNetworkDefPtr virNetworkDefParseString(const char *xmlStr);
 virNetworkDefPtr virNetworkDefParseFile(const char *filename);
 virNetworkDefPtr virNetworkDefParseNode(xmlDocPtr xml,
                                         xmlNodePtr root);
+int virNetworkObjUpdateParseFile(const char *filename,
+                                 virNetworkObjPtr net);
 
 char *virNetworkDefFormat(const virNetworkDefPtr def, unsigned int flags);
 
diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms
index 5a07139..3ed0c97 100644
--- a/src/libvirt_private.syms
+++ b/src/libvirt_private.syms
@@ -858,6 +858,7 @@ virNetworkObjSetDefTransient;
 virNetworkObjUnlock;
 virNetworkObjUnsetDefTransient;
 virNetworkObjUpdate;
+virNetworkObjUpdateParseFile;
 virNetworkRemoveInactive;
 virNetworkSaveConfig;
 virNetworkSaveStatus;
diff --git a/src/network/bridge_driver.c b/src/network/bridge_driver.c
index 44fa56e..8dc9d19 100644
--- a/src/network/bridge_driver.c
+++ b/src/network/bridge_driver.c
@@ -236,7 +236,6 @@ networkFindActiveConfigs(struct network_driver *driver) {
 
     for (i = 0 ; i < driver->networks.count ; i++) {
         virNetworkObjPtr obj = driver->networks.objs[i];
-        virNetworkDefPtr tmp;
         char *config;
 
         virNetworkObjLock(obj);
@@ -254,12 +253,10 @@ networkFindActiveConfigs(struct network_driver *driver) {
         }
 
         /* Try and load the live config */
-        tmp = virNetworkDefParseFile(config);
+        if (virNetworkObjUpdateParseFile(config, obj) < 0)
+            VIR_WARN("Unable to update config of '%s' network",
+                     obj->def->name);
         VIR_FREE(config);
-        if (tmp) {
-            obj->newDef = obj->def;
-            obj->def = tmp;
-        }
 
         /* If bridge exists, then mark it active */
         if (obj->def->bridge &&
-- 
1.7.8.6




More information about the libvir-list mailing list