Change in vdsm[master]: netconf: Improve unified persistence's rollback in memory.

wudxw at linux.vnet.ibm.com wudxw at linux.vnet.ibm.com
Wed Oct 9 13:11:38 UTC 2013


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 at 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 at linux.vnet.ibm.com>


More information about the vdsm-patches mailing list