network: change location of network state xml files

For some reason these have been stored in /var/lib, although other
drivers (e.g. qemu and lxc) store their state files in /var/run.

It's much nicer to store state files in /var/run because it is
automatically cleared out when the system reboots. We can then use
existence of the state file as a convenient indicator of whether or
not a particular network is active.

Since changing the location of the state files by itself will cause
problems in the case of a *live* upgrade from an older libvirt that
uses /var/lib (because current status of active networks will be
lost), the network driver initialization has been modified to migrate
any network state files from /var/lib to /var/run.

This will not help those trying to *downgrade*, but in practice this
will only be problematic in two cases

1) If there are networks with network-wide bandwidth limits configured
   *and in use* by a guest during a downgrade to "old" libvirt. In this
   case, the class ID's used for that network's tc rules, as well as
   the currently in-use bandwidth "floor" will be forgotten.

2) If someone does this: 1) upgrade libvirt, 2) downgrade libvirt, 3)
   modify running state of network (e.g. add a static dhcp host, etc),
   4) upgrade. In this case, the modifications to the running network
   will be lost (but not any persistent changes to the network's
   config).
This commit is contained in:
Laine Stump 2014-04-04 16:48:54 +03:00
parent 8aaa5b68ef
commit b9e95491d1

View File

@ -41,6 +41,7 @@
#include <sys/wait.h>
#include <sys/ioctl.h>
#include <net/if.h>
#include <dirent.h>
#if HAVE_SYS_SYSCTL_H
# include <sys/sysctl.h>
#endif
@ -416,6 +417,88 @@ firewalld_dbus_filter_bridge(DBusConnection *connection ATTRIBUTE_UNUSED,
}
#endif
static int
networkMigrateStateFiles(virNetworkDriverStatePtr driver)
{
/* Due to a change in location of network state xml beginning in
* libvirt 1.2.4 (from /var/lib/libvirt/network to
* /var/run/libvirt/network), we must check for state files in two
* locations. Anything found in the old location must be written
* to the new location, then erased from the old location. (Note
* that we read/write the file rather than calling rename()
* because the old and new state directories are likely in
* different filesystems).
*/
int ret = -1;
const char *oldStateDir = LOCALSTATEDIR "/lib/libvirt/network";
DIR *dir;
struct dirent *entry;
char *oldPath = NULL, *newPath = NULL;
char *contents = NULL;
if (!(dir = opendir(oldStateDir))) {
if (errno == ENOENT)
return 0;
virReportSystemError(errno, _("failed to open directory '%s'"),
oldStateDir);
return -1;
}
if (virFileMakePath(driver->stateDir) < 0) {
virReportSystemError(errno, _("cannot create directory %s"),
driver->stateDir);
goto cleanup;
}
for (;;) {
errno = 0;
entry = readdir(dir);
if (!entry) {
if (errno) {
virReportSystemError(errno, _("failed to read directory '%s'"),
oldStateDir);
goto cleanup;
}
break;
}
if (entry->d_type != DT_REG ||
STREQ(entry->d_name, ".") ||
STREQ(entry->d_name, ".."))
continue;
if (virAsprintf(&oldPath, "%s/%s",
oldStateDir, entry->d_name) < 0)
goto cleanup;
if (virFileReadAll(oldPath, 1024*1024, &contents) < 0)
goto cleanup;
if (virAsprintf(&newPath, "%s/%s",
driver->stateDir, entry->d_name) < 0)
goto cleanup;
if (virFileWriteStr(newPath, contents, S_IRUSR | S_IWUSR) < 0) {
virReportSystemError(errno,
_("failed to write network status file '%s'"),
newPath);
goto cleanup;
}
unlink(oldPath);
VIR_FREE(oldPath);
VIR_FREE(newPath);
VIR_FREE(contents);
}
ret = 0;
cleanup:
closedir(dir);
VIR_FREE(oldPath);
VIR_FREE(newPath);
VIR_FREE(contents);
return ret;
}
/**
* networkStateInitialize:
*
@ -445,11 +528,6 @@ networkStateInitialize(bool privileged,
/* configuration/state paths are one of
* ~/.config/libvirt/... (session/unprivileged)
* /etc/libvirt/... && /var/(run|lib)/libvirt/... (system/privileged).
*
* NB: The qemu driver puts its domain state in /var/run, and I
* think the network driver should have used /var/run too (instead
* of /var/lib), but it's been this way for a long time, and we
* probably shouldn't change it now.
*/
if (privileged) {
if (VIR_STRDUP(driverState->networkConfigDir,
@ -457,7 +535,7 @@ networkStateInitialize(bool privileged,
VIR_STRDUP(driverState->networkAutostartDir,
SYSCONFDIR "/libvirt/qemu/networks/autostart") < 0 ||
VIR_STRDUP(driverState->stateDir,
LOCALSTATEDIR "/lib/libvirt/network") < 0 ||
LOCALSTATEDIR "/run/libvirt/network") < 0 ||
VIR_STRDUP(driverState->pidDir,
LOCALSTATEDIR "/run/libvirt/network") < 0 ||
VIR_STRDUP(driverState->dnsmasqStateDir,
@ -465,6 +543,13 @@ networkStateInitialize(bool privileged,
VIR_STRDUP(driverState->radvdStateDir,
LOCALSTATEDIR "/lib/libvirt/radvd") < 0)
goto error;
/* migration from old to new location is only applicable for
* privileged mode - unprivileged mode directories haven't
* changed location.
*/
if (networkMigrateStateFiles(driverState) < 0)
goto error;
} else {
configdir = virGetUserConfigDirectory();
rundir = virGetUserRuntimeDirectory();