mirror of
https://gitlab.com/libvirt/libvirt.git
synced 2025-01-11 09:17:52 +03:00
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:
parent
8aaa5b68ef
commit
b9e95491d1
@ -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();
|
||||
|
Loading…
Reference in New Issue
Block a user