[libvirt] [PATCH v3 7/8] network: Create real network status files

Michal Privoznik mprivozn at redhat.com
Tue Dec 11 16:09:21 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 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     |  207 ++++++++++++++++++++++++++++++++++---------
 src/conf/network_conf.h     |    2 +
 src/libvirt_private.syms    |    1 +
 src/network/bridge_driver.c |   27 +++++--
 4 files changed, 190 insertions(+), 47 deletions(-)

diff --git a/src/conf/network_conf.c b/src/conf/network_conf.c
index ac326e1..29e3127 100644
--- a/src/conf/network_conf.c
+++ b/src/conf/network_conf.c
@@ -1695,6 +1695,79 @@ 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]/@bitmap)", ctxt);
+        if (class_id &&
+            virBitmapParse(class_id, ',',
+                           &net->class_id, CLASS_ID_BITMAP_SIZE) < 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)
@@ -1873,26 +1946,28 @@ 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);
     }
     if (def->ipv6nogw)
-        virBufferAddLit(&buf, " ipv6='yes'");
-    virBufferAddLit(&buf, ">\n");
-    virBufferAdjustIndent(&buf, 2);
-    virBufferEscapeString(&buf, "<name>%s</name>\n", def->name);
+        virBufferAddLit(buf, " ipv6='yes'");
+    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;
@@ -1906,40 +1981,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;
@@ -1947,67 +2022,116 @@ 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;
+    char *class_id = virBitmapFormat(net->class_id);
+
+    if (!class_id)
+        goto no_memory;
+
+    virBufferAddLit(&buf, "<networkstatus>\n");
+    virBufferAsprintf(&buf, "  <class_id bitmap='%s'/>\n", class_id);
+    virBufferAsprintf(&buf, "  <floor sum='%llu'/>\n", net->floor_sum);
+    VIR_FREE(class_id);
+
+    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;
 }
@@ -2079,9 +2203,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 364372d..519f73d 100644
--- a/src/conf/network_conf.h
+++ b/src/conf/network_conf.h
@@ -276,6 +276,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 6564676..ab44642 100644
--- a/src/libvirt_private.syms
+++ b/src/libvirt_private.syms
@@ -873,6 +873,7 @@ virNetworkObjSetDefTransient;
 virNetworkObjUnlock;
 virNetworkObjUnsetDefTransient;
 virNetworkObjUpdate;
+virNetworkObjUpdateParseFile;
 virNetworkRemoveInactive;
 virNetworkSaveConfig;
 virNetworkSaveStatus;
diff --git a/src/network/bridge_driver.c b/src/network/bridge_driver.c
index 0bee453..cad2192 100644
--- a/src/network/bridge_driver.c
+++ b/src/network/bridge_driver.c
@@ -242,7 +242,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);
@@ -260,12 +259,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 &&
@@ -4425,6 +4422,14 @@ networkPlugBandwidth(virNetworkObjPtr net,
     iface->data.network.actual->class_id = class_id;
     /* update sum of 'floor'-s of attached NICs */
     net->floor_sum += iface->bandwidth->in->floor;
+    /* update status file */
+    if (virNetworkSaveStatus(NETWORK_STATE_DIR, net) < 0) {
+        ignore_value(virBitmapClearBit(net->class_id, class_id));
+        net->floor_sum -= iface->bandwidth->in->floor;
+        iface->data.network.actual->class_id = 0;
+        ignore_value(virNetDevBandwidthUnplug(net->def->bridge, class_id));
+        goto cleanup;
+    }
     /* update rate for non guaranteed NICs */
     new_rate -= net->floor_sum;
     if (virNetDevBandwidthUpdateRate(net->def->bridge, "1:2",
@@ -4459,6 +4464,16 @@ networkUnplugBandwidth(virNetworkObjPtr net,
             goto cleanup;
         /* update sum of 'floor'-s of attached NICs */
         net->floor_sum -= iface->bandwidth->in->floor;
+        /* return class ID */
+        ignore_value(virBitmapClearBit(net->class_id,
+                                       iface->data.network.actual->class_id));
+        /* update status file */
+        if (virNetworkSaveStatus(NETWORK_STATE_DIR, net) < 0) {
+            net->floor_sum += iface->bandwidth->in->floor;
+            ignore_value(virBitmapSetBit(net->class_id,
+                                         iface->data.network.actual->class_id));
+            goto cleanup;
+        }
         /* update rate for non guaranteed NICs */
         new_rate -= net->floor_sum;
         if (virNetDevBandwidthUpdateRate(net->def->bridge, "1:2",
-- 
1.7.8.6




More information about the libvir-list mailing list