Mark Wu has uploaded a new change for review.
Change subject: netconf: Improve unified persistence's rollback in memory.
......................................................................
netconf: Improve unified persistence's rollback in memory.
This patch removes the dependency on ifcfg's code for the unified
persistence's rollback in memory. It also move transaction management
implementaion from ifcfg to its base class Configurator. With this
change, the rollback function be reused for the iproute2 configuration.
This patch also adds a functional test for live rollback. It passes with
ifcfg persistence and unified persistence.
Change-Id: I7436976d8bacbfaa1c4b059c71c4abb46192f99a
Signed-off-by: Mark Wu <wudxw(a)linux.vnet.ibm.com>
---
M lib/vdsm/constants.py.in
M tests/functional/networkTests.py
M vdsm/netconf/__init__.py
M vdsm/netconf/ifcfg.py
M vdsm/vdsm-restore-net-config
5 files changed, 95 insertions(+), 19 deletions(-)
git pull ssh://gerrit.ovirt.org:29418/vdsm refs/changes/32/20032/1
diff --git a/lib/vdsm/constants.py.in b/lib/vdsm/constants.py.in
index 1fb729b..a1a0dd6 100644
--- a/lib/vdsm/constants.py.in
+++ b/lib/vdsm/constants.py.in
@@ -139,6 +139,7 @@
EXT_UNPERSIST = '@UNPERSIST_PATH@'
EXT_VDSM_STORE_NET_CONFIG = '@VDSMDIR@/vdsm-store-net-config'
+EXT_VDSM_RESTORE_NET_CONFIG = '@VDSMDIR@/vdsm-restore-net-config'
EXT_WGET = '@WGET_PATH@'
diff --git a/tests/functional/networkTests.py b/tests/functional/networkTests.py
index b6c747f..d1f2329 100644
--- a/tests/functional/networkTests.py
+++ b/tests/functional/networkTests.py
@@ -1425,3 +1425,36 @@
status, msg = self.vdsm_net.setupNetworks(delete_networks,
{}, {})
self.assertEqual(status, SUCCESS, msg)
+
+ @cleanupNet
+ @permutations([[True], [False]])
+ @RequireDummyMod
+ @ValidateRunningAsRoot
+ def testSetupNetworksRollback(self, bridged):
+ with dummyIf(1) as nics:
+ with self.vdsm_net.pinger():
+ nic, = nics
+ tags = (10, 11, 12000)
+ networks = [NETWORK_NAME + str(tag) for tag in tags]
+ attrs = [dict(vlan=tag, nic=nic, bridged=bridged)
+ for tag in tags]
+ status, msg = self.vdsm_net.setupNetworks({networks[0]:
+ attrs[0]}, {}, {})
+
+ self.assertEqual(status, SUCCESS, msg)
+ self.assertTrue(self.vdsm_net.networkExists(networks[0]))
+
+ status, msg = self.vdsm_net.setupNetworks({networks[0]:
+ dict(remove=True),
+ networks[1]:
+ attrs[1],
+ networks[2]:
+ attrs[2]}, {}, {})
+ self.assertFalse(self.vdsm_net.networkExists(networks[1]))
+ self.assertFalse(self.vdsm_net.networkExists(networks[2]))
+ self.assertTrue(self.vdsm_net.networkExists(networks[0]))
+
+ status, msg = self.vdsm_net.setupNetworks({networks[0]:
+ dict(remove=True)},
+ {}, {})
+ self.assertEqual(status, SUCCESS, msg)
diff --git a/vdsm/netconf/__init__.py b/vdsm/netconf/__init__.py
index c0e3ee9..9dc0f70 100644
--- a/vdsm/netconf/__init__.py
+++ b/vdsm/netconf/__init__.py
@@ -18,13 +18,16 @@
#
import logging
+import pickle
from netmodels import Bond, Bridge
from sourceRoute import DynamicSourceRoute
from sourceRoute import StaticSourceRoute
+from vdsm import constants
from vdsm import netinfo
from vdsm.config import config
from vdsm.netconfpersistence import RunningConfig
+from vdsm.utils import execCmd
class Configurator(object):
@@ -46,6 +49,28 @@
else:
self.rollback()
+ def begin(self, configApplierClass):
+ if self.configApplier is None:
+ self.configApplier = configApplierClass()
+ if self.unifiedPersistence and self.runningConfig is None:
+ self.runningConfig = RunningConfig()
+
+ def rollback(self):
+ if self.unifiedPersistence:
+ liveConfig = pickle.dumps(self.runningConfig)
+ execCmd([constants.EXT_VDSM_RESTORE_NET_CONFIG, '--memory',
+ liveConfig])
+ self.runningConfig = None
+ else:
+ self.configApplier.restoreBackups()
+ self.configApplier = None
+
+ def commit(self):
+ self.configApplier = None
+ if self.unifiedPersistence:
+ self.runningConfig.save()
+ self.runningConfig = None
+
def configureBridge(self, bridge, **opts):
raise NotImplementedError
diff --git a/vdsm/netconf/ifcfg.py b/vdsm/netconf/ifcfg.py
index 0747b04..e0705d7 100644
--- a/vdsm/netconf/ifcfg.py
+++ b/vdsm/netconf/ifcfg.py
@@ -36,7 +36,6 @@
from vdsm import constants
from vdsm import netinfo
from vdsm import utils
-from vdsm.netconfpersistence import RunningConfig
import dsaversion
import libvirtCfg
import neterrors as ne
@@ -48,22 +47,7 @@
super(Ifcfg, self).__init__(ConfigWriter())
def begin(self):
- if self.configApplier is None:
- self.configApplier = ConfigWriter()
- if self.unifiedPersistence and self.runningConfig is None:
- self.runningConfig = RunningConfig()
-
- def rollback(self):
- self.configApplier.restoreBackups()
- self.configApplier = None
- if self.unifiedPersistence:
- self.runningConfig = None
-
- def commit(self):
- self.configApplier = None
- if self.unifiedPersistence:
- self.runningConfig.save()
- self.runningConfig = None
+ super(Ifcfg, self).begin(ConfigWriter)
def configureBridge(self, bridge, **opts):
self.configApplier.addBridge(bridge, **opts)
@@ -286,8 +270,8 @@
"(until next 'set safe config')", backup)
def _networkBackup(self, network):
- self._atomicNetworkBackup(network)
if config.get('vars', 'persistence') != 'unified':
+ self._atomicNetworkBackup(network)
self._persistentNetworkBackup(network)
def _atomicNetworkBackup(self, network):
@@ -328,8 +312,8 @@
logging.info('Restored %s', network)
def _backup(self, filename):
- self._atomicBackup(filename)
if config.get('vars', 'persistence') != 'unified':
+ self._atomicBackup(filename)
self._persistentBackup(filename)
def _atomicBackup(self, filename):
diff --git a/vdsm/vdsm-restore-net-config b/vdsm/vdsm-restore-net-config
index 374387f..451d560 100755
--- a/vdsm/vdsm-restore-net-config
+++ b/vdsm/vdsm-restore-net-config
@@ -19,6 +19,9 @@
# Refer to the README and COPYING files for full details of the license
#
+import getopt
+import pickle
+import sys
import logging
import logging.config
@@ -64,6 +67,28 @@
ifcfg_restoration()
+def restore_from_memory(liveConfig):
+ assert config.get('vars', 'persistence') == 'unified'
+ lastConfig = RunningConfig() # snapshot of running config on disk
+
+ def get_restore_configs(liveConfig, lastConfig):
+ restoreConfigs = {}
+ for name in liveConfig:
+ if name not in lastConfig:
+ restoreConfigs[name] = {'remove': True}
+
+ for name, attr in lastConfig.iteritems():
+ if name not in liveConfig or attr != lastConfig[name]:
+ restoreConfigs[name] = lastConfig[name]
+ return restoreConfigs
+
+ nets = get_restore_configs(liveConfig.networks, lastConfig.networks)
+ bonds = get_restore_configs(liveConfig.bonds, lastConfig.bonds)
+ logging.debug("Calling setupNetworks with networks: %s, bondings: %s" %
+ (nets, bonds))
+ setupNetworks(nets, bonds, connectivityCheck=False)
+
+
if __name__ == '__main__':
try:
logging.config.fileConfig("/etc/vdsm/svdsm.logger.conf")
@@ -72,4 +97,12 @@
level=logging.DEBUG)
logging.error("Could not init proper logging", exc_info=True)
+ opts, args = getopt.getopt(sys.argv[1:], "m:", ["memory="])
+ for opt, arg in opts:
+ if opt in ('-m', '--memory'):
+ restore_from_memory(pickle.loads(arg))
+ sys.exit(0)
+ else:
+ assert False, "Unhandled option"
+
restore()
--
To view, visit
http://gerrit.ovirt.org/20032
To unsubscribe, visit
http://gerrit.ovirt.org/settings
Gerrit-MessageType: newchange
Gerrit-Change-Id: I7436976d8bacbfaa1c4b059c71c4abb46192f99a
Gerrit-PatchSet: 1
Gerrit-Project: vdsm
Gerrit-Branch: master
Gerrit-Owner: Mark Wu <wudxw(a)linux.vnet.ibm.com>