Currently when we shutdown the virtual networks are all shutdown too.
This is less than useful if we're letting guest VMs hang around post
shutdown of libvirtd, because it means we're tearing their network
connection out from under them. This patch fixes that allowing networks
to survive restarts, and be re-detected next time around.
When starting a virtual network we write the live config into
/var/lib/libvirt/network/$NAME.xml
This is because the bridge device name is potentially auto-generated
and we need to keep track of that
We change dnsmasq args to include an explicit pidfile location
/var/run/libvirt/network/$NAME.pid
and also tell it to put itself into the background - ie daemonize. This
is because we want dnsmasq to survive the daemon.
Now, when libvirtd starts up it
- Looks for the live config, and if found loads it.
- Calls a new method brHasBridge() to see if its desired bridge
actually exists (and thus whether the network is running).
If it exists,the network is marked active
- If DHCP is configured, then reads the dnsmasq PIDfile, and sends
kill($PID, 0) to check if the process is actually alive
In addition I cleanup the network code to remove the configFile and
autostartLink fields in virNetworkObjPtr, so it matches virDomaiObjPtr
usage.
With all this applied you can now restart the daemon, and virbr0 is
left happily running.
THis patch depends on the 25 threading patches I sent earlier, so
you probably won't be able to apply it in isolation
Daniel
diff --git a/src/bridge.c b/src/bridge.c
--- a/src/bridge.c
+++ b/src/bridge.c
@@ -163,6 +163,43 @@ int brAddBridge (brControl *ctl ATTRIBUT
}
#endif
+#ifdef SIOCBRDELBR
+int
+brHasBridge(brControl *ctl,
+ const char *name)
+{
+ struct ifreq ifr;
+ int len;
+
+ if (!ctl || !name) {
+ errno = EINVAL;
+ return -1;
+ }
+
+ if ((len = strlen(name)) >= BR_IFNAME_MAXLEN) {
+ errno = EINVAL;
+ return -1;
+ }
+
+ memset(&ifr, 0, sizeof(struct ifreq));
+
+ strncpy(ifr.ifr_name, name, len);
+ ifr.ifr_name[len] = '\0';
+
+ if (ioctl(ctl->fd, SIOCGIFMTU, &ifr))
+ return -1;
+
+ return 0;
+}
+#else
+int
+brHasBridge(brControl *ctl,
+ const char *name)
+{
+ return EINVAL;
+}
+#endif
+
/**
* brDeleteBridge:
* @ctl: bridge control pointer
diff --git a/src/bridge.h b/src/bridge.h
--- a/src/bridge.h
+++ b/src/bridge.h
@@ -50,6 +50,8 @@ int brAddBridge (brContr
char **name);
int brDeleteBridge (brControl *ctl,
const char *name);
+int brHasBridge (brControl *ctl,
+ const char *name);
int brAddInterface (brControl *ctl,
const char *bridge,
@@ -58,6 +60,7 @@ int brDeleteInterface (brContr
const char *bridge,
const char *iface);
+
int brAddTap (brControl *ctl,
const char *bridge,
char **ifname,
diff --git a/src/libvirt_bridge.syms b/src/libvirt_bridge.syms
--- a/src/libvirt_bridge.syms
+++ b/src/libvirt_bridge.syms
@@ -9,6 +9,7 @@ brAddBridge;
brAddInterface;
brAddTap;
brDeleteBridge;
+brHasBridge;
brInit;
brSetEnableSTP;
brSetForwardDelay;
diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms
--- a/src/libvirt_private.syms
+++ b/src/libvirt_private.syms
@@ -190,6 +190,7 @@ virFree;
# network_conf.h
virNetworkAssignDef;
+virNetworkConfigFile;
virNetworkDefFormat;
virNetworkDefFree;
virNetworkDefParseFile;
@@ -202,6 +203,7 @@ virNetworkLoadAllConfigs;
virNetworkObjListFree;
virNetworkDefParseNode;
virNetworkRemoveInactive;
+virNetworkSaveConfigXML;
virNetworkSaveConfig;
virNetworkObjLock;
virNetworkObjUnlock;
diff --git a/src/network_conf.c b/src/network_conf.c
--- a/src/network_conf.c
+++ b/src/network_conf.c
@@ -125,9 +125,6 @@ void virNetworkObjFree(virNetworkObjPtr
virNetworkDefFree(net->def);
virNetworkDefFree(net->newDef);
- VIR_FREE(net->configFile);
- VIR_FREE(net->autostartLink);
-
virMutexDestroy(&net->lock);
VIR_FREE(net);
@@ -641,31 +638,17 @@ char *virNetworkDefFormat(virConnectPtr
return NULL;
}
-int virNetworkSaveConfig(virConnectPtr conn,
- const char *configDir,
- const char *autostartDir,
- virNetworkObjPtr net)
+int virNetworkSaveXML(virConnectPtr conn,
+ const char *configDir,
+ virNetworkDefPtr def,
+ const char *xml)
{
- char *xml;
+ char *configFile = NULL;
int fd = -1, ret = -1;
size_t towrite;
int err;
- if (!net->configFile &&
- virAsprintf(&net->configFile, "%s/%s.xml",
- configDir, net->def->name) < 0) {
- virNetworkReportError(conn, VIR_ERR_NO_MEMORY, NULL);
- goto cleanup;
- }
- if (!net->autostartLink &&
- virAsprintf(&net->autostartLink, "%s/%s.xml",
- autostartDir, net->def->name) < 0) {
- virNetworkReportError(conn, VIR_ERR_NO_MEMORY, NULL);
- goto cleanup;
- }
-
- if (!(xml = virNetworkDefFormat(conn,
- net->newDef ? net->newDef : net->def)))
+ if ((configFile = virNetworkConfigFile(conn, configDir, def->name)) == NULL)
goto cleanup;
if ((err = virFileMakePath(configDir))) {
@@ -675,19 +658,12 @@ int virNetworkSaveConfig(virConnectPtr c
goto cleanup;
}
- if ((err = virFileMakePath(autostartDir))) {
- virReportSystemError(conn, err,
- _("cannot create autostart directory
'%s'"),
- autostartDir);
- goto cleanup;
- }
-
- if ((fd = open(net->configFile,
+ if ((fd = open(configFile,
O_WRONLY | O_CREAT | O_TRUNC,
S_IRUSR | S_IWUSR )) < 0) {
virReportSystemError(conn, errno,
_("cannot create config file '%s'"),
- net->configFile);
+ configFile);
goto cleanup;
}
@@ -695,48 +671,64 @@ int virNetworkSaveConfig(virConnectPtr c
if (safewrite(fd, xml, towrite) < 0) {
virReportSystemError(conn, errno,
_("cannot write config file '%s'"),
- net->configFile);
+ configFile);
goto cleanup;
}
if (close(fd) < 0) {
virReportSystemError(conn, errno,
_("cannot save config file '%s'"),
- net->configFile);
+ configFile);
goto cleanup;
}
ret = 0;
cleanup:
- VIR_FREE(xml);
if (fd != -1)
close(fd);
+ VIR_FREE(configFile);
+
return ret;
}
+int virNetworkSaveConfig(virConnectPtr conn,
+ const char *configDir,
+ virNetworkDefPtr def)
+{
+ int ret = -1;
+ char *xml;
+
+ if (!(xml = virNetworkDefFormat(conn,
+ def)))
+ goto cleanup;
+
+ if (virNetworkSaveXML(conn, configDir, def, xml))
+ goto cleanup;
+
+ ret = 0;
+cleanup:
+ VIR_FREE(xml);
+ return ret;
+}
+
+
virNetworkObjPtr virNetworkLoadConfig(virConnectPtr conn,
virNetworkObjListPtr nets,
const char *configDir,
const char *autostartDir,
- const char *file)
+ const char *name)
{
char *configFile = NULL, *autostartLink = NULL;
virNetworkDefPtr def = NULL;
virNetworkObjPtr net;
int autostart;
- if (virAsprintf(&configFile, "%s/%s",
- configDir, file) < 0) {
- virNetworkReportError(conn, VIR_ERR_NO_MEMORY, NULL);
+ if ((configFile = virNetworkConfigFile(conn, configDir, name)) == NULL)
goto error;
- }
- if (virAsprintf(&autostartLink, "%s/%s",
- autostartDir, file) < 0) {
- virNetworkReportError(conn, VIR_ERR_NO_MEMORY, NULL);
+ if ((autostartLink = virNetworkConfigFile(conn, autostartDir, name)) == NULL)
goto error;
- }
if ((autostart = virFileLinkPointsTo(autostartLink, configFile)) < 0)
goto error;
@@ -744,7 +736,7 @@ virNetworkObjPtr virNetworkLoadConfig(vi
if (!(def = virNetworkDefParseFile(conn, configFile)))
goto error;
- if (!virFileMatchesNameSuffix(file, def->name, ".xml")) {
+ if (!STREQ(name, def->name)) {
virNetworkReportError(conn, VIR_ERR_INTERNAL_ERROR,
_("Network config filename '%s'"
" does not match network name '%s'"),
@@ -755,10 +747,11 @@ virNetworkObjPtr virNetworkLoadConfig(vi
if (!(net = virNetworkAssignDef(conn, nets, def)))
goto error;
- net->configFile = configFile;
- net->autostartLink = autostartLink;
net->autostart = autostart;
+ VIR_FREE(configFile);
+ VIR_FREE(autostartLink);
+
return net;
error:
@@ -791,7 +784,7 @@ int virNetworkLoadAllConfigs(virConnectP
if (entry->d_name[0] == '.')
continue;
- if (!virFileHasSuffix(entry->d_name, ".xml"))
+ if (!virFileStripSuffix(entry->d_name, ".xml"))
continue;
/* NB: ignoring errors, so one malformed config doesn't
@@ -811,27 +804,51 @@ int virNetworkLoadAllConfigs(virConnectP
}
int virNetworkDeleteConfig(virConnectPtr conn,
+ const char *configDir,
+ const char *autostartDir,
virNetworkObjPtr net)
{
- if (!net->configFile || !net->autostartLink) {
- virNetworkReportError(conn, VIR_ERR_INTERNAL_ERROR,
- _("no config file for %s"),
net->def->name);
- return -1;
- }
+ char *configFile = NULL;
+ char *autostartLink = NULL;
+
+ if ((configFile = virNetworkConfigFile(conn, configDir, net->def->name)) ==
NULL)
+ goto error;
+ if ((autostartLink = virNetworkConfigFile(conn, autostartDir, net->def->name))
== NULL)
+ goto error;
/* Not fatal if this doesn't work */
- unlink(net->autostartLink);
+ unlink(autostartLink);
- if (unlink(net->configFile) < 0) {
+ if (unlink(configFile) < 0) {
virReportSystemError(conn, errno,
_("cannot remove config file '%s'"),
- net->configFile);
- return -1;
+ configFile);
+ goto error;
}
return 0;
+
+error:
+ VIR_FREE(configFile);
+ VIR_FREE(autostartLink);
+ return -1;
}
+char *virNetworkConfigFile(virConnectPtr conn,
+ const char *dir,
+ const char *name)
+{
+ char *ret = NULL;
+
+ if (virAsprintf(&ret, "%s/%s.xml", dir, name) < 0) {
+ virNetworkReportError(conn, VIR_ERR_NO_MEMORY, NULL);
+ return NULL;
+ }
+
+ return ret;
+}
+
+
void virNetworkObjLock(virNetworkObjPtr obj)
{
virMutexLock(&obj->lock);
diff --git a/src/network_conf.h b/src/network_conf.h
--- a/src/network_conf.h
+++ b/src/network_conf.h
@@ -90,9 +90,6 @@ struct _virNetworkObj {
unsigned int autostart : 1;
unsigned int persistent : 1;
- char *configFile; /* Persistent config file path */
- char *autostartLink; /* Symlink path for autostart */
-
virNetworkDefPtr def; /* The current definition */
virNetworkDefPtr newDef; /* New definition to activate at shutdown */
};
@@ -139,10 +136,14 @@ char *virNetworkDefFormat(virConnectPtr
const virNetworkDefPtr def);
+int virNetworkSaveXML(virConnectPtr conn,
+ const char *configDir,
+ virNetworkDefPtr def,
+ const char *xml);
+
int virNetworkSaveConfig(virConnectPtr conn,
const char *configDir,
- const char *autostartDir,
- virNetworkObjPtr net);
+ virNetworkDefPtr def);
virNetworkObjPtr virNetworkLoadConfig(virConnectPtr conn,
virNetworkObjListPtr nets,
@@ -156,8 +157,15 @@ int virNetworkLoadAllConfigs(virConnectP
const char *autostartDir);
int virNetworkDeleteConfig(virConnectPtr conn,
+ const char *configDir,
+ const char *autostartDir,
virNetworkObjPtr net);
+char *virNetworkConfigFile(virConnectPtr conn,
+ const char *dir,
+ const char *name);
+
+
void virNetworkObjLock(virNetworkObjPtr obj);
void virNetworkObjUnlock(virNetworkObjPtr obj);
diff --git a/src/network_driver.c b/src/network_driver.c
--- a/src/network_driver.c
+++ b/src/network_driver.c
@@ -57,6 +57,8 @@
#include "iptables.h"
#include "bridge.h"
+#define NETWORK_PID_DIR LOCAL_STATE_DIR "/run/libvirt/network"
+#define NETWORK_LIB_DIR LOCAL_STATE_DIR "/lib/libvirt/network"
#define VIR_FROM_THIS VIR_FROM_NETWORK
@@ -106,6 +108,64 @@ static struct network_driver *driverStat
static void
+networkFindActiveConfigs(struct network_driver *driver) {
+ unsigned int i;
+
+ for (i = 0 ; i < driver->networks.count ; i++) {
+ virNetworkObjPtr obj = driver->networks.objs[i];
+ virNetworkDefPtr tmp;
+ char *config;
+
+ virNetworkObjLock(obj);
+
+ if ((config = virNetworkConfigFile(NULL,
+ NETWORK_LIB_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 */
+ tmp = virNetworkDefParseFile(NULL,config);
+ VIR_FREE(config);
+ if (tmp) {
+ obj->newDef = obj->def;
+ obj->def = tmp;
+ }
+
+ /* If bridge exists, then mark it active */
+ if (obj->def->bridge &&
+ brHasBridge(driver->brctl, obj->def->bridge) == 0) {
+ obj->active = 1;
+
+ /* Finally try and read dnsmasq pid if any DHCP ranges are set */
+ if (obj->def->nranges &&
+ virFileReadPid(NETWORK_PID_DIR, obj->def->name,
+ &obj->dnsmasqPid) == 0) {
+
+ /* Check its still alive */
+ if (kill(obj->dnsmasqPid, 0) != 0)
+ obj->dnsmasqPid = -1;
+
+ /* XXX ideally we'd check this was actually
+ * the dnsmasq process, not a stale pid file
+ * with someone else's process. But how ?
+ */
+ }
+ }
+
+ virNetworkObjUnlock(obj);
+ }
+}
+
+
+static void
networkAutostartConfigs(struct network_driver *driver) {
unsigned int i;
@@ -132,6 +192,7 @@ static int
networkStartup(void) {
uid_t uid = geteuid();
char *base = NULL;
+ int err;
if (VIR_ALLOC(driverState) < 0)
goto error;
@@ -181,12 +242,26 @@ networkStartup(void) {
VIR_FREE(base);
+ if ((err = brInit(&driverState->brctl))) {
+ virReportSystemError(NULL, err, "%s",
+ _("cannot initialize bridge support"));
+ goto error;
+ }
+
+ if (!(driverState->iptables = iptablesContextNew())) {
+ networkReportError(NULL, NULL, NULL, VIR_ERR_NO_MEMORY,
+ "%s", _("failed to allocate space for IP tables
support"));
+ goto error;
+ }
+
+
if (virNetworkLoadAllConfigs(NULL,
&driverState->networks,
driverState->networkConfigDir,
driverState->networkAutostartDir) < 0)
goto error;
+ networkFindActiveConfigs(driverState);
networkAutostartConfigs(driverState);
networkDriverUnlock(driverState);
@@ -269,23 +344,11 @@ networkActive(void) {
*/
static int
networkShutdown(void) {
- unsigned int i;
-
if (!driverState)
return -1;
networkDriverLock(driverState);
- /* shutdown active networks */
- for (i = 0 ; i < driverState->networks.count ; i++) {
- virNetworkObjPtr net = driverState->networks.objs[i];
- virNetworkObjLock(net);
- if (virNetworkIsActive(net))
- networkShutdownNetworkDaemon(NULL, driverState,
- driverState->networks.objs[i]);
- virNetworkObjUnlock(net);
- }
-
/* free inactive networks */
virNetworkObjListFree(&driverState->networks);
@@ -309,23 +372,23 @@ networkShutdown(void) {
static int
networkBuildDnsmasqArgv(virConnectPtr conn,
- virNetworkObjPtr network,
- const char ***argv) {
+ virNetworkObjPtr network,
+ const char *pidfile,
+ const char ***argv) {
int i, len, r;
- char buf[PATH_MAX];
+ char *pidfileArg;
+ char buf[1024];
len =
1 + /* dnsmasq */
- 1 + /* --keep-in-foreground */
1 + /* --strict-order */
1 + /* --bind-interfaces */
(network->def->domain?2:0) + /* --domain name */
- 2 + /* --pid-file "" */
+ 2 + /* --pid-file /var/run/libvirt/network/$NAME.pid */
2 + /* --conf-file "" */
/*2 + *//* --interface virbr0 */
2 + /* --except-interface lo */
2 + /* --listen-address 10.0.0.1 */
- 1 + /* --dhcp-leasefile=path */
(2 * network->def->nranges) + /* --dhcp-range 10.0.0.2,10.0.0.254 */
/* --dhcp-host 01:23:45:67:89:0a,hostname,10.0.0.3 */
(2 * network->def->nhosts) +
@@ -339,11 +402,13 @@ networkBuildDnsmasqArgv(virConnectPtr co
goto no_memory; \
} while (0)
+#define APPEND_ARG_LIT(v, n, s) \
+ (v)[(n)] = s
+
i = 0;
APPEND_ARG(*argv, i++, DNSMASQ);
- APPEND_ARG(*argv, i++, "--keep-in-foreground");
/*
* Needed to ensure dnsmasq uses same algorithm for processing
* multiple namedriver entries in /etc/resolv.conf as GLibC.
@@ -356,10 +421,11 @@ networkBuildDnsmasqArgv(virConnectPtr co
APPEND_ARG(*argv, i++, network->def->domain);
}
- APPEND_ARG(*argv, i++, "--pid-file");
- APPEND_ARG(*argv, i++, "");
+ if (virAsprintf(&pidfileArg, "--pid-file=%s", pidfile) < 0)
+ goto no_memory;
+ APPEND_ARG_LIT(*argv, i++, pidfileArg);
- APPEND_ARG(*argv, i++, "--conf-file");
+ APPEND_ARG(*argv, i++, "--conf-file=");
APPEND_ARG(*argv, i++, "");
/*
@@ -377,15 +443,6 @@ networkBuildDnsmasqArgv(virConnectPtr co
APPEND_ARG(*argv, i++, "--except-interface");
APPEND_ARG(*argv, i++, "lo");
- /*
- * NB, dnsmasq command line arg bug means we need to
- * use a single arg '--dhcp-leasefile=path' rather than
- * two separate args in '--dhcp-leasefile path' style
- */
- snprintf(buf, sizeof(buf),
"--dhcp-leasefile=%s/lib/libvirt/dhcp-%s.leases",
- LOCAL_STATE_DIR, network->def->name);
- APPEND_ARG(*argv, i++, buf);
-
for (r = 0 ; r < network->def->nranges ; r++) {
snprintf(buf, sizeof(buf), "%s,%s",
network->def->ranges[r].start,
@@ -434,7 +491,10 @@ dhcpStartDhcpDaemon(virConnectPtr conn,
virNetworkObjPtr network)
{
const char **argv;
- int ret, i;
+ char *pidfile;
+ int ret = -1, i, err;
+
+ network->dnsmasqPid = -1;
if (network->def->ipAddress == NULL) {
networkReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR,
@@ -442,13 +502,49 @@ dhcpStartDhcpDaemon(virConnectPtr conn,
return -1;
}
+ if ((err = virFileMakePath(NETWORK_PID_DIR)) < 0) {
+ virReportSystemError(conn, err,
+ _("cannot create directory %s"),
+ NETWORK_PID_DIR);
+ return -1;
+ }
+ if ((err = virFileMakePath(NETWORK_LIB_DIR)) < 0) {
+ virReportSystemError(conn, err,
+ _("cannot create directory %s"),
+ NETWORK_LIB_DIR);
+ return -1;
+ }
+
+ if (!(pidfile = virFilePid(NETWORK_PID_DIR, network->def->name))) {
+ virReportOOMError(conn);
+ return -1;
+ }
+
argv = NULL;
- if (networkBuildDnsmasqArgv(conn, network, &argv) < 0)
+ if (networkBuildDnsmasqArgv(conn, network, pidfile, &argv) < 0) {
+ VIR_FREE(pidfile);
return -1;
+ }
- ret = virExec(conn, argv, NULL, NULL,
- &network->dnsmasqPid, -1, NULL, NULL, VIR_EXEC_NONBLOCK);
+ if (virRun(conn, argv, NULL) < 0)
+ goto cleanup;
+ /*
+ * There really is no race here - when dnsmasq daemonizes,
+ * its leader process stays around until its child has
+ * actually written its pidfile. So by time virRun exits
+ * it has waitpid'd and guarenteed the proess has started
+ * and writtena pid
+ */
+
+ if (virFileReadPid(NETWORK_PID_DIR, network->def->name,
+ &network->dnsmasqPid) < 0)
+ goto cleanup;
+
+ ret = 0;
+
+cleanup:
+ VIR_FREE(pidfile);
for (i = 0; argv[i]; i++)
VIR_FREE(argv[i]);
VIR_FREE(argv);
@@ -554,13 +650,6 @@ networkAddIptablesRules(virConnectPtr co
virNetworkObjPtr network) {
int err;
- if (!driver->iptables && !(driver->iptables = iptablesContextNew())) {
- networkReportError(conn, NULL, NULL, VIR_ERR_NO_MEMORY,
- "%s", _("failed to allocate space for IP tables
support"));
- return 0;
- }
-
-
/* allow DHCP requests through to dnsmasq */
if ((err = iptablesAddTcpInput(driver->iptables, network->def->bridge, 67)))
{
virReportSystemError(conn, err,
@@ -716,12 +805,6 @@ static int networkStartNetworkDaemon(vir
return -1;
}
- if (!driver->brctl && (err = brInit(&driver->brctl))) {
- virReportSystemError(conn, err, "%s",
- _("cannot initialize bridge support"));
- return -1;
- }
-
if ((err = brAddBridge(driver->brctl, &network->def->bridge))) {
virReportSystemError(conn, err,
_("cannot create bridge '%s'"),
@@ -729,7 +812,6 @@ static int networkStartNetworkDaemon(vir
return -1;
}
-
if (brSetForwardDelay(driver->brctl, network->def->bridge,
network->def->delay) < 0)
goto err_delbr;
@@ -774,10 +856,22 @@ static int networkStartNetworkDaemon(vir
dhcpStartDhcpDaemon(conn, network) < 0)
goto err_delbr2;
+
+ /* Persist the live configuration now we have bridge info */
+ if (virNetworkSaveConfig(conn, NETWORK_LIB_DIR, network->def) < 0) {
+ goto err_kill;
+ }
+
network->active = 1;
return 0;
+ err_kill:
+ if (network->dnsmasqPid > 0) {
+ kill(network->dnsmasqPid, SIGTERM);
+ network->dnsmasqPid = -1;
+ }
+
err_delbr2:
networkRemoveIptablesRules(driver, network);
@@ -798,16 +892,24 @@ static int networkStartNetworkDaemon(vir
}
-static int networkShutdownNetworkDaemon(virConnectPtr conn ATTRIBUTE_UNUSED,
- struct network_driver *driver,
- virNetworkObjPtr network) {
+static int networkShutdownNetworkDaemon(virConnectPtr conn,
+ struct network_driver *driver,
+ virNetworkObjPtr network) {
int err;
+ char *configFile;
networkLog(NETWORK_INFO, _("Shutting down network '%s'\n"),
network->def->name);
if (!virNetworkIsActive(network))
return 0;
+ configFile = virNetworkConfigFile(conn, NETWORK_LIB_DIR, network->def->name);
+ if (!configFile)
+ return -1;
+
+ unlink(configFile);
+ VIR_FREE(configFile);
+
if (network->dnsmasqPid > 0)
kill(network->dnsmasqPid, SIGTERM);
@@ -824,13 +926,10 @@ static int networkShutdownNetworkDaemon(
network->def->bridge, strerror(err));
}
+ /* See if its still alive and really really kill it */
if (network->dnsmasqPid > 0 &&
- waitpid(network->dnsmasqPid, NULL, WNOHANG) != network->dnsmasqPid) {
+ (kill(network->dnsmasqPid, 0) == 0))
kill(network->dnsmasqPid, SIGKILL);
- if (waitpid(network->dnsmasqPid, NULL, 0) != network->dnsmasqPid)
- networkLog(NETWORK_WARN,
- "%s", _("Got unexpected pid for dnsmasq\n"));
- }
network->dnsmasqPid = -1;
network->active = 0;
@@ -1048,8 +1147,7 @@ static virNetworkPtr networkDefine(virCo
if (virNetworkSaveConfig(conn,
driver->networkConfigDir,
- driver->networkAutostartDir,
- network) < 0) {
+ network->newDef ? network->newDef : network->def)
< 0) {
virNetworkRemoveInactive(&driver->networks,
network);
network = NULL;
@@ -1086,7 +1184,10 @@ static int networkUndefine(virNetworkPtr
goto cleanup;
}
- if (virNetworkDeleteConfig(net->conn, network) < 0)
+ if (virNetworkDeleteConfig(net->conn,
+ driver->networkConfigDir,
+ driver->networkAutostartDir,
+ network) < 0)
goto cleanup;
virNetworkRemoveInactive(&driver->networks,
@@ -1140,7 +1241,7 @@ static int networkDestroy(virNetworkPtr
}
ret = networkShutdownNetworkDaemon(net->conn, driver, network);
- if (!network->configFile) {
+ if (!network->persistent) {
virNetworkRemoveInactive(&driver->networks,
network);
network = NULL;
@@ -1233,9 +1334,10 @@ cleanup:
}
static int networkSetAutostart(virNetworkPtr net,
- int autostart) {
+ int autostart) {
struct network_driver *driver = net->conn->networkPrivateData;
virNetworkObjPtr network;
+ char *configFile = NULL, *autostartLink = NULL;
int ret = -1;
networkDriverLock(driver);
@@ -1251,6 +1353,11 @@ static int networkSetAutostart(virNetwor
autostart = (autostart != 0);
if (network->autostart != autostart) {
+ if ((configFile = virNetworkConfigFile(net->conn, driver->networkConfigDir,
network->def->name)) == NULL)
+ goto cleanup;
+ if ((autostartLink = virNetworkConfigFile(net->conn,
driver->networkAutostartDir, network->def->name)) == NULL)
+ goto cleanup;
+
if (autostart) {
int err;
@@ -1261,17 +1368,17 @@ static int networkSetAutostart(virNetwor
goto cleanup;
}
- if (symlink(network->configFile, network->autostartLink) < 0) {
+ if (symlink(configFile, autostartLink) < 0) {
virReportSystemError(net->conn, errno,
_("Failed to create symlink '%s' to
'%s'"),
- network->autostartLink, network->configFile);
+ autostartLink, configFile);
goto cleanup;
}
} else {
- if (unlink(network->autostartLink) < 0 && errno != ENOENT
&& errno != ENOTDIR) {
+ if (unlink(autostartLink) < 0 && errno != ENOENT && errno
!= ENOTDIR) {
virReportSystemError(net->conn, errno,
_("Failed to delete symlink
'%s'"),
- network->autostartLink);
+ autostartLink);
goto cleanup;
}
}
@@ -1281,6 +1388,8 @@ static int networkSetAutostart(virNetwor
ret = 0;
cleanup:
+ VIR_FREE(configFile);
+ VIR_FREE(autostartLink);
if (network)
virNetworkObjUnlock(network);
return ret;
--
|: Red Hat, Engineering, London -o-
http://people.redhat.com/berrange/ :|
|:
http://libvirt.org -o-
http://virt-manager.org -o-
http://ovirt.org :|
|:
http://autobuild.org -o-
http://search.cpan.org/~danberr/ :|
|: GnuPG: 7D3B9505 -o- F3C9 553F A1DA 4AC2 5648 23C1 B3DF F742 7D3B 9505 :|