This eliminates problems with upgrading from older libvirt that stores
network status in /var/lib/libvirt/network to newer libvirt that
stores it in /var/run/libvirt/network, by also reading any status
files from the old location, saving them to the new location, and
removing them from the old location.
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, 2) downgrade, 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).
I have an idea of how to make these cases work properly as well
(involving symlinks in /var/lib pointing to /var/run) but want to
avoid keeping such an ugly legacy around (forever) unlesss others
think it is absolutely necessary to support flawless downgrades across
this line *while remaining in service*.
---
src/network/bridge_driver.c | 40 ++++++++++++++++++++++++++++++++++++
src/network/bridge_driver_platform.h | 3 ++-
2 files changed, 42 insertions(+), 1 deletion(-)
diff --git a/src/network/bridge_driver.c b/src/network/bridge_driver.c
index a027b47..98d10bd 100644
--- a/src/network/bridge_driver.c
+++ b/src/network/bridge_driver.c
@@ -459,6 +459,8 @@ networkStateInitialize(bool privileged,
SYSCONFDIR "/libvirt/qemu/networks/autostart") < 0
||
VIR_STRDUP(driverState->stateDir,
LOCALSTATEDIR "/run/libvirt/network") < 0 ||
+ VIR_STRDUP(driverState->oldStateDir,
+ LOCALSTATEDIR "/lib/libvirt/network") < 0 ||
VIR_STRDUP(driverState->pidDir,
LOCALSTATEDIR "/run/libvirt/network") < 0 ||
VIR_STRDUP(driverState->dnsmasqStateDir,
@@ -498,6 +500,44 @@ networkStateInitialize(bool privileged,
/* if this fails now, it will be retried later with dnsmasqCapsRefresh() */
driverState->dnsmasqCaps = dnsmasqCapsNewFromBinary(DNSMASQ);
+ /* Due to a change in location of network state xml beginning in
+ * libvirt 1.2.4, 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.
+ */
+ if (driverState->oldStateDir &&
+ STRNEQ(driverState->stateDir, driverState->oldStateDir)) {
+ size_t i;
+
+ /* read all */
+ if (virNetworkLoadAllState(&driverState->networks,
+ driverState->oldStateDir) < 0)
+ goto error;
+
+ for (i = 0; i < driverState->networks.count; i++) {
+ virNetworkObjPtr network = driverState->networks.objs[i];
+ char *oldFile;
+ int status;
+
+ /* save in new location */
+ virNetworkObjLock(network);
+ status = virNetworkSaveStatus(driverState->stateDir, network);
+ virNetworkObjUnlock(network);
+ if (status < 0)
+ goto cleanup;
+
+ /* remove from old location */
+ oldFile = virNetworkConfigFile(driverState->oldStateDir,
+ network->def->name);
+ if (!oldFile)
+ goto cleanup;
+ unlink(oldFile);
+ VIR_FREE(oldFile);
+ }
+ /* these will all be re-read from their new location */
+ virNetworkObjListFree(&driverState->networks);
+ }
+
if (virNetworkLoadAllState(&driverState->networks,
driverState->stateDir) < 0)
goto error;
diff --git a/src/network/bridge_driver_platform.h b/src/network/bridge_driver_platform.h
index 6a571da..491068a 100644
--- a/src/network/bridge_driver_platform.h
+++ b/src/network/bridge_driver_platform.h
@@ -1,7 +1,7 @@
/*
* bridge_driver_platform.h: platform specific routines for bridge driver
*
- * Copyright (C) 2006-2013 Red Hat, Inc.
+ * Copyright (C) 2006-2014 Red Hat, Inc.
* Copyright (C) 2006 Daniel P. Berrange
*
* This library is free software; you can redistribute it and/or
@@ -39,6 +39,7 @@ struct _virNetworkDriverState {
char *networkConfigDir;
char *networkAutostartDir;
char *stateDir;
+ char *oldStateDir;
char *pidDir;
char *dnsmasqStateDir;
char *radvdStateDir;
--
1.9.0