[libvirt] [PATCH v2 5/6] network: Create status files

Michal Privoznik mprivozn at redhat.com
Thu Jan 12 14:44:45 UTC 2012


Like we keep domain status file to keep some internal data
during daemon restart, now it is needed for network as well.
Because network has now class_id attribute which is hidden
from users and thus not part of network XML.
---
 daemon/libvirtd.c           |    3 +
 src/conf/network_conf.c     |  219 ++++++++++++++++++++++++++++++++++++-------
 src/conf/network_conf.h     |    7 ++
 src/libvirt_private.syms    |    2 +
 src/network/bridge_driver.c |   33 +++++--
 5 files changed, 222 insertions(+), 42 deletions(-)

diff --git a/daemon/libvirtd.c b/daemon/libvirtd.c
index b1b542b..aa0dccb 100644
--- a/daemon/libvirtd.c
+++ b/daemon/libvirtd.c
@@ -1607,6 +1607,9 @@ int main(int argc, char **argv) {
                 0, "shutdown", NULL);
 
 cleanup:
+    /* Notify drivers we are about to quit,
+     * so they can save their stuff */
+    virStateCleanup();
     virNetServerProgramFree(remoteProgram);
     virNetServerProgramFree(qemuProgram);
     virNetServerClose(srv);
diff --git a/src/conf/network_conf.c b/src/conf/network_conf.c
index 019cdc7..9073b08 100644
--- a/src/conf/network_conf.c
+++ b/src/conf/network_conf.c
@@ -1282,6 +1282,99 @@ cleanup:
 }
 
 static int
+virNetworkObjParseXML(virNetworkObjPtr obj,
+                      xmlDocPtr xml ATTRIBUTE_UNUSED,
+                      xmlXPathContextPtr ctxt)
+{
+    int ret = -1;
+    xmlNodePtr config;
+    char *class_id = NULL;
+
+    if ((config = virXPathNode("./network", ctxt))) {
+        xmlNodePtr oldnode;
+        virNetworkDefPtr tmp_def;
+
+        oldnode = ctxt->node;
+        ctxt->node = config;
+        tmp_def = virNetworkDefParseXML(ctxt);
+        ctxt->node = oldnode;
+
+        if (tmp_def) {
+            obj->newDef = obj->def;
+            obj->def = tmp_def;
+        } else {
+            goto cleanup;
+        }
+    }
+
+    if ((class_id=virXPathString("string(./class_id[1]/@next)", ctxt))) {
+        if (virStrToLong_ui(class_id, NULL, 10, &obj->class_id) < 0) {
+            virNetworkReportError(VIR_ERR_XML_ERROR,
+                                  _("Malformed class_id attribute: %s"),
+                                  class_id);
+            goto cleanup;
+        }
+    }
+
+    ret = 0;
+
+cleanup:
+    VIR_FREE(class_id);
+    return ret;
+}
+
+static int
+virNetworkObjParseNode(virNetworkObjPtr obj,
+                       xmlDocPtr xml,
+                       xmlNodePtr root)
+{
+    int ret = -1;
+    xmlXPathContextPtr ctxt = NULL;
+
+    if (!xmlStrEqual(root->name, BAD_CAST "networkstatus")) {
+        virNetworkReportError(VIR_ERR_XML_ERROR,
+                              _("unexpected root element <%s>, "
+                                "expecting <networkstatus>"),
+                              root->name);
+        return -1;
+    }
+
+    if (!(ctxt = xmlXPathNewContext(xml))) {
+        virReportOOMError();
+        goto cleanup;
+    }
+
+    ctxt->node = root;
+    ret = virNetworkObjParseXML(obj, xml, ctxt);
+
+cleanup:
+    xmlXPathFreeContext(ctxt);
+    return ret;
+}
+
+static int
+virNetworkObjParseFile(virNetworkObjPtr obj,
+                       const char *filename)
+{
+    int ret = -1;
+    xmlDocPtr xml;
+
+    if ((xml = virXMLParseFile(filename))) {
+        ret = virNetworkObjParseNode(obj, xml, xmlDocGetRootElement(xml));
+        xmlFreeDoc(xml);
+    }
+
+    return ret;
+}
+
+int
+virNetworkObjUpdateStatus(virNetworkObjPtr net,
+                          const char *filename)
+{
+    return virNetworkObjParseFile(net, filename);
+}
+
+static int
 virNetworkDNSDefFormat(virBufferPtr buf,
                        virNetworkDNSDefPtr def)
 {
@@ -1449,19 +1542,21 @@ 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>\n");
-    virBufferEscapeString(&buf, "  <name>%s</name>\n", def->name);
+    virBufferAddLit(buf, "<network>\n");
+    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;
@@ -1475,86 +1570,97 @@ 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'%s>\n", mode,
+        virBufferAddLit(buf, "  <forward");
+        virBufferEscapeString(buf, " dev='%s'", dev);
+        virBufferAsprintf(buf, " mode='%s'%s>\n", mode,
                           (def->nForwardIfs || def->nForwardPfs) ? "" : "/");
 
         /* 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++) {
-                virBufferEscapeString(&buf, "    <interface dev='%s'/>\n",
+                virBufferEscapeString(buf, "    <interface dev='%s'/>\n",
                                       def->forwardIfs[ii].dev);
             }
         }
         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) {
 
-        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];
         virFormatMacAddr(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;
 
-    virBufferAdjustIndent(&buf, 2);
-    if (virNetDevBandwidthFormat(def->bandwidth, &buf) < 0)
+    virBufferAdjustIndent(buf, 2);
+    if (virNetDevBandwidthFormat(def->bandwidth, buf) < 0)
         goto error;
-    virBufferAdjustIndent(&buf, -2);
+    virBufferAdjustIndent(buf, -2);
 
     for (ii = 0; ii < def->nips; ii++) {
-        if (virNetworkIpDefFormat(&buf, &def->ips[ii]) < 0)
+        if (virNetworkIpDefFormat(buf, &def->ips[ii]) < 0)
             goto error;
     }
 
-    virBufferAdjustIndent(&buf, 2);
-    if (virNetDevVPortProfileFormat(def->virtPortProfile, &buf) < 0)
+    virBufferAdjustIndent(buf, 2);
+    if (virNetDevVPortProfileFormat(def->virtPortProfile, buf) < 0)
         goto error;
-    virBufferAdjustIndent(&buf, -2);
+    virBufferAdjustIndent(buf, -2);
 
     for (ii = 0; ii < def->nPortGroups; ii++)
-        if (virPortGroupDefFormat(&buf, &def->portGroups[ii]) < 0)
+        if (virPortGroupDefFormat(buf, &def->portGroups[ii]) < 0)
             goto error;
 
-    virBufferAddLit(&buf, "</network>\n");
+    virBufferAddLit(buf, "</network>\n");
 
-    if (virBufferError(&buf))
+    if (virBufferError(buf))
         goto no_memory;
 
-    return virBufferContentAndReset(&buf);
+    return 0;
 
- no_memory:
+no_memory:
     virReportOOMError();
-  error:
-    virBufferFreeAndReset(&buf);
-    return NULL;
+error:
+    return -1;
+}
+
+char *virNetworkDefFormat(const virNetworkDefPtr def, unsigned int flags)
+{
+    virBuffer buf = VIR_BUFFER_INITIALIZER;
+
+    if (virNetworkDefFormatInternal(&buf, def, flags) < 0) {
+        virBufferFreeAndReset(&buf);
+        return NULL;
+    }
+
+    return virBufferContentAndReset(&buf);
 }
 
 virPortGroupDefPtr virPortGroupFindByName(virNetworkDefPtr net,
@@ -1573,6 +1679,34 @@ virPortGroupDefPtr virPortGroupFindByName(virNetworkDefPtr net,
     return NULL;
 }
 
+static char *
+virNetworkObjFormat(virNetworkObjPtr obj)
+{
+    virBuffer buf = VIR_BUFFER_INITIALIZER;
+
+    virBufferAddLit(&buf, "<networkstatus>\n");
+    if (obj->class_id)
+        virBufferAsprintf(&buf, "  <class_id next='%u'/>\n", obj->class_id);
+
+    virBufferAdjustIndent(&buf, 2);
+    if (virNetworkDefFormatInternal(&buf, obj->def, 0) < 0)
+        goto error;
+    virBufferAdjustIndent(&buf, -2);
+
+    virBufferAddLit(&buf, "</networkstatus>\n");
+
+    if (virBufferError(&buf))
+        goto no_memory;
+
+    return virBufferContentAndReset(&buf);
+
+no_memory:
+    virReportOOMError();
+error:
+    virBufferFreeAndReset(&buf);
+    return NULL;
+}
+
 int virNetworkSaveXML(const char *configDir,
                       virNetworkDefPtr def,
                       const char *xml)
@@ -1597,6 +1731,24 @@ int virNetworkSaveXML(const char *configDir,
     return ret;
 }
 
+int virNetworkSaveObj(const char *configDir,
+                      virNetworkObjPtr net)
+{
+    int ret = -1;
+    char *xml;
+
+    if (!(xml = virNetworkObjFormat(net)))
+        goto cleanup;
+
+    if (virNetworkSaveXML(configDir, net->def, xml))
+        goto cleanup;
+
+    ret = 0;
+cleanup:
+    VIR_FREE(xml);
+    return ret;
+}
+
 int virNetworkSaveConfig(const char *configDir,
                          virNetworkDefPtr def)
 {
@@ -1615,7 +1767,6 @@ cleanup:
     return ret;
 }
 
-
 virNetworkObjPtr virNetworkLoadConfig(virNetworkObjListPtr nets,
                                       const char *configDir,
                                       const char *autostartDir,
diff --git a/src/conf/network_conf.h b/src/conf/network_conf.h
index dcbf84d..1161acf 100644
--- a/src/conf/network_conf.h
+++ b/src/conf/network_conf.h
@@ -255,11 +255,18 @@ int virNetworkSaveXML(const char *configDir,
 int virNetworkSaveConfig(const char *configDir,
                          virNetworkDefPtr def);
 
+int virNetworkSaveObj(const char *configDir,
+                      virNetworkObjPtr net);
+
 virNetworkObjPtr virNetworkLoadConfig(virNetworkObjListPtr nets,
                                       const char *configDir,
                                       const char *autostartDir,
                                       const char *file);
 
+int virNetworkObjUpdateStatus(virNetworkObjPtr net,
+                              const char *filename)
+    ATTRIBUTE_NONNULL(1);
+
 int virNetworkLoadAllConfigs(virNetworkObjListPtr nets,
                              const char *configDir,
                              const char *autostartDir);
diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms
index ca4beb1..bd74050 100644
--- a/src/libvirt_private.syms
+++ b/src/libvirt_private.syms
@@ -759,8 +759,10 @@ virNetworkObjIsDuplicate;
 virNetworkObjListFree;
 virNetworkObjLock;
 virNetworkObjUnlock;
+virNetworkObjUpdateStatus;
 virNetworkRemoveInactive;
 virNetworkSaveConfig;
+virNetworkSaveObj;
 virNetworkSetBridgeMacAddr;
 virNetworkSetBridgeName;
 virPortGroupFindByName;
diff --git a/src/network/bridge_driver.c b/src/network/bridge_driver.c
index 4cea7c2..2f3da60 100644
--- a/src/network/bridge_driver.c
+++ b/src/network/bridge_driver.c
@@ -184,7 +184,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);
@@ -201,13 +200,12 @@ networkFindActiveConfigs(struct network_driver *driver) {
             continue;
         }
 
-        /* Try and load the live config */
-        tmp = virNetworkDefParseFile(config);
-        VIR_FREE(config);
-        if (tmp) {
-            obj->newDef = obj->def;
-            obj->def = tmp;
+        /* Try to update the live config */
+        if (virNetworkObjUpdateStatus(obj, config) < 0) {
+            VIR_WARN("Unable to update config on '%s' network",
+                     obj->def->name);
         }
+        VIR_FREE(config);
 
         /* If bridge exists, then mark it active */
         if (obj->def->bridge &&
@@ -396,11 +394,25 @@ networkActive(void) {
  */
 static int
 networkShutdown(void) {
+    unsigned int i;
+
     if (!driverState)
         return -1;
 
     networkDriverLock(driverState);
 
+    for (i = 0; i < driverState->networks.count; i++) {
+        virNetworkObjPtr obj = driverState->networks.objs[i];
+
+        if (!virNetworkObjIsActive(obj))
+            continue;
+
+        if (virNetworkSaveObj(NETWORK_STATE_DIR, obj) < 0) {
+            VIR_WARN("Unable to save network '%s'",
+                     obj->def->name);
+        }
+    }
+
     /* free inactive networks */
     virNetworkObjListFree(&driverState->networks);
 
@@ -1990,7 +2002,7 @@ networkStartNetwork(struct network_driver *driver,
     /* Persist the live configuration now that anything autogenerated
      * is setup.
      */
-    if ((ret = virNetworkSaveConfig(NETWORK_STATE_DIR, network->def)) < 0) {
+    if ((ret = virNetworkSaveObj(NETWORK_STATE_DIR, network)) < 0) {
         goto error;
     }
 
@@ -3299,6 +3311,11 @@ networkNotifyPlug(virNetworkPtr net,
         network->class_id++;
     }
 
+    if (virNetworkSaveObj(NETWORK_STATE_DIR, network) < 0) {
+        VIR_WARN("Unable to save network '%s'",
+                 network->def->name);
+    }
+
     ret = 0;
 
 cleanup:
-- 
1.7.3.4




More information about the libvir-list mailing list