]> git.ipfire.org Git - thirdparty/libvirt.git/commitdiff
network: bridge_driver: don't lose transient networks on daemon restart
authorPeter Krempa <pkrempa@redhat.com>
Tue, 16 Apr 2013 16:35:59 +0000 (18:35 +0200)
committerPeter Krempa <pkrempa@redhat.com>
Fri, 19 Apr 2013 14:43:47 +0000 (16:43 +0200)
Until now tranisent networks weren't really useful as libvirtd wasn't
able to remember them across restarts. This patch adds support for
loading status files of transient networks (that already were generated)
so that the status isn't lost.

This patch chops up virNetworkObjUpdateParseFile and turns it into
virNetworkLoadState and a few friends that will help us to load status
XMLs and refactors the functions that are loading the configs to use
them.

src/conf/network_conf.c
src/conf/network_conf.h
src/libvirt_private.syms
src/network/bridge_driver.c

index 75584a026db02f006d8a17c5c7812be2d4c17956..18a7d575fde506e70ddeb54f561aa362308c605a 100644 (file)
@@ -1967,81 +1967,6 @@ 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) {
-            virBitmapFree(net->class_id);
-            if (virBitmapParse(class_id, 0,
-                               &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:
-    xmlFreeDoc(xml);
-    xmlXPathFreeContext(ctxt);
-    return ret;
-}
 
 static int
 virNetworkDNSDefFormat(virBufferPtr buf,
@@ -2554,6 +2479,104 @@ cleanup:
     return ret;
 }
 
+virNetworkObjPtr
+virNetworkLoadState(virNetworkObjListPtr nets,
+                    const char *stateDir,
+                    const char *name)
+{
+    char *configFile = NULL;
+    virNetworkDefPtr def = NULL;
+    virNetworkObjPtr net = NULL;
+    xmlDocPtr xml = NULL;
+    xmlNodePtr node = NULL;
+    xmlXPathContextPtr ctxt = NULL;
+    virBitmapPtr class_id_map = NULL;
+    unsigned long long floor_sum_val = 0;
+
+
+    if ((configFile = virNetworkConfigFile(stateDir, name)) == NULL)
+        goto error;
+
+    if (!(xml = virXMLParseCtxt(configFile, NULL, _("(network status)"), &ctxt)))
+        goto error;
+
+    if (!(node = virXPathNode("//network", ctxt))) {
+        virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+                       _("Could not find any 'network' element in status file"));
+        goto error;
+    }
+
+    /* parse the definition first */
+    ctxt->node = node;
+    if (!(def = virNetworkDefParseXML(ctxt)))
+        goto error;
+
+    if (!STREQ(name, def->name)) {
+        virReportError(VIR_ERR_INTERNAL_ERROR,
+                       _("Network config filename '%s'"
+                         " does not match network name '%s'"),
+                       configFile, def->name);
+        goto error;
+    }
+
+    /* now parse possible status data */
+    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;
+        if ((class_id = virXPathString("string(./class_id[1]/@bitmap)", ctxt))) {
+            if (virBitmapParse(class_id, 0, &class_id_map,
+                               CLASS_ID_BITMAP_SIZE) < 0) {
+                virReportError(VIR_ERR_INTERNAL_ERROR,
+                               _("Malformed 'class_id' attribute: %s"),
+                               class_id);
+                VIR_FREE(class_id);
+                goto error;
+            }
+        }
+        VIR_FREE(class_id);
+
+        floor_sum = virXPathString("string(./floor[1]/@sum)", ctxt);
+        if (floor_sum &&
+            virStrToLong_ull(floor_sum, NULL, 10, &floor_sum_val) < 0) {
+            virReportError(VIR_ERR_INTERNAL_ERROR,
+                           _("Malformed 'floor_sum' attribute: %s"),
+                           floor_sum);
+            VIR_FREE(floor_sum);
+        }
+        VIR_FREE(floor_sum);
+    }
+
+    /* create the object */
+    if (!(net = virNetworkAssignDef(nets, def, true)))
+        goto error;
+    /* do not put any "goto error" below this comment */
+
+    /* assign status data stored in the network object */
+    if (class_id_map) {
+        virBitmapFree(net->class_id);
+        net->class_id = class_id_map;
+    }
+
+    if (floor_sum_val > 0)
+        net->floor_sum = floor_sum_val;
+
+cleanup:
+    VIR_FREE(configFile);
+    xmlFreeDoc(xml);
+    xmlXPathFreeContext(ctxt);
+    return net;
+
+error:
+    virBitmapFree(class_id_map);
+    virNetworkDefFree(def);
+    goto cleanup;
+}
+
 virNetworkObjPtr virNetworkLoadConfig(virNetworkObjListPtr nets,
                                       const char *configDir,
                                       const char *autostartDir,
@@ -2612,6 +2635,40 @@ error:
     return NULL;
 }
 
+
+int
+virNetworkLoadAllState(virNetworkObjListPtr nets,
+                       const char *stateDir)
+{
+    DIR *dir;
+    struct dirent *entry;
+
+    if (!(dir = opendir(stateDir))) {
+        if (errno == ENOENT)
+            return 0;
+
+        virReportSystemError(errno, _("Failed to open dir '%s'"), stateDir);
+        return -1;
+    }
+
+    while ((entry = readdir(dir))) {
+        virNetworkObjPtr net;
+
+        if (entry->d_name[0] == '.')
+            continue;
+
+        if (!virFileStripSuffix(entry->d_name, ".xml"))
+            continue;
+
+        if ((net = virNetworkLoadState(nets, stateDir, entry->d_name)))
+            virNetworkObjUnlock(net);
+    }
+
+    closedir(dir);
+    return 0;
+}
+
+
 int virNetworkLoadAllConfigs(virNetworkObjListPtr nets,
                              const char *configDir,
                              const char *autostartDir)
index 1a86e3d5628c504aa441ff3bef4e44648b965d50..163478c834f5255bfae36efeff3c8731a098945f 100644 (file)
@@ -280,9 +280,6 @@ 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);
 
 static inline const char *
@@ -318,10 +315,17 @@ virNetworkObjPtr virNetworkLoadConfig(virNetworkObjListPtr nets,
                                       const char *autostartDir,
                                       const char *file);
 
+virNetworkObjPtr virNetworkLoadState(virNetworkObjListPtr nets,
+                                     const char *stateDir,
+                                     const char *name);
+
 int virNetworkLoadAllConfigs(virNetworkObjListPtr nets,
                              const char *configDir,
                              const char *autostartDir);
 
+int virNetworkLoadAllState(virNetworkObjListPtr nets,
+                           const char *stateDir);
+
 int virNetworkDeleteConfig(const char *configDir,
                            const char *autostartDir,
                            virNetworkObjPtr net);
index 30fdcd72d884a2274173d14d5a8b8829e7a01e09..f778e9cd382c0ee29ff671b95109e99c8b0a5995 100644 (file)
@@ -454,6 +454,7 @@ virNetworkIpDefNetmask;
 virNetworkIpDefPrefix;
 virNetworkList;
 virNetworkLoadAllConfigs;
+virNetworkLoadAllState;
 virNetworkObjAssignDef;
 virNetworkObjFree;
 virNetworkObjGetPersistentDef;
@@ -465,7 +466,6 @@ virNetworkObjSetDefTransient;
 virNetworkObjUnlock;
 virNetworkObjUnsetDefTransient;
 virNetworkObjUpdate;
-virNetworkObjUpdateParseFile;
 virNetworkRemoveInactive;
 virNetworkSaveConfig;
 virNetworkSaveStatus;
index 6ea09faad8b46791760680e462cec4a3776c8189..27dd230ee781f79c8b70c1a9fbc0a4b5d287dda2 100644 (file)
@@ -180,6 +180,7 @@ networkRemoveInactive(struct network_driver *driver,
     char *radvdconfigfile = NULL;
     char *configfile = NULL;
     char *radvdpidbase = NULL;
+    char *statusfile = NULL;
     dnsmasqContext *dctx = NULL;
     virNetworkDefPtr def = virNetworkObjGetPersistentDef(net);
 
@@ -201,6 +202,9 @@ networkRemoveInactive(struct network_driver *driver,
     if (!(configfile = networkDnsmasqConfigFileName(def->name)))
         goto no_memory;
 
+    if (!(statusfile = virNetworkConfigFile(NETWORK_STATE_DIR, def->name)))
+        goto no_memory;
+
     /* dnsmasq */
     dnsmasqDelete(dctx);
     unlink(leasefile);
@@ -210,6 +214,9 @@ networkRemoveInactive(struct network_driver *driver,
     unlink(radvdconfigfile);
     virPidFileDelete(NETWORK_PID_DIR, radvdpidbase);
 
+    /* remove status file */
+    unlink(statusfile);
+
     /* remove the network definition */
     virNetworkRemoveInactive(&driver->networks, net);
 
@@ -220,6 +227,7 @@ cleanup:
     VIR_FREE(configfile);
     VIR_FREE(radvdconfigfile);
     VIR_FREE(radvdpidbase);
+    VIR_FREE(statusfile);
     dnsmasqContextFree(dctx);
     return ret;
 
@@ -253,33 +261,15 @@ networkBridgeDummyNicName(const char *brname)
 }
 
 static void
-networkFindActiveConfigs(struct network_driver *driver) {
+networkFindActiveConfigs(struct network_driver *driver)
+{
     unsigned int i;
 
     for (i = 0 ; i < driver->networks.count ; i++) {
         virNetworkObjPtr obj = driver->networks.objs[i];
-        char *config;
 
         virNetworkObjLock(obj);
 
-        if ((config = virNetworkConfigFile(NETWORK_STATE_DIR,
-                                           obj->def->name)) == NULL) {
-            virNetworkObjUnlock(obj);
-            continue;
-        }
-
-        if (access(config, R_OK) < 0) {
-            VIR_FREE(config);
-            virNetworkObjUnlock(obj);
-            continue;
-        }
-
-        /* Try and load the live config */
-        if (virNetworkObjUpdateParseFile(config, obj) < 0)
-            VIR_WARN("Unable to update config of '%s' network",
-                     obj->def->name);
-        VIR_FREE(config);
-
         /* If bridge exists, then mark it active */
         if (obj->def->bridge &&
             virNetDevExists(obj->def->bridge) == 1) {
@@ -306,6 +296,21 @@ networkFindActiveConfigs(struct network_driver *driver) {
     cleanup:
         virNetworkObjUnlock(obj);
     }
+
+    /* remove inactive transient networks */
+    i = 0;
+    while (i < driver->networks.count) {
+        virNetworkObjPtr obj = driver->networks.objs[i];
+        virNetworkObjLock(obj);
+
+        if (!obj->persistent && !obj->active) {
+            networkRemoveInactive(driver, obj);
+            continue;
+        }
+
+        virNetworkObjUnlock(obj);
+        i++;
+    }
 }
 
 
@@ -415,6 +420,10 @@ networkStartup(bool privileged,
     /* if this fails now, it will be retried later with dnsmasqCapsRefresh() */
     driverState->dnsmasqCaps = dnsmasqCapsNewFromBinary(DNSMASQ);
 
+    if (virNetworkLoadAllState(&driverState->networks,
+                               NETWORK_STATE_DIR) < 0)
+        goto error;
+
     if (virNetworkLoadAllConfigs(&driverState->networks,
                                  driverState->networkConfigDir,
                                  driverState->networkAutostartDir) < 0)
@@ -479,6 +488,8 @@ networkReload(void) {
         return 0;
 
     networkDriverLock(driverState);
+    virNetworkLoadAllState(&driverState->networks,
+                           NETWORK_STATE_DIR);
     virNetworkLoadAllConfigs(&driverState->networks,
                              driverState->networkConfigDir,
                              driverState->networkAutostartDir);