vswitches/ovs: delete flows on stop
[vswitchperf.git] / vswitches / ovs.py
index 12620e2..be7b77d 100644 (file)
@@ -1,4 +1,4 @@
-# Copyright 2015-2017 Intel Corporation.
+# Copyright 2015-2018 Intel Corporation, Tieto and Others.
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.
@@ -48,7 +48,8 @@ class IVSwitchOvs(IVSwitch, tasks.Process):
         self._vswitchd_pidfile_path = os.path.join(settings.getValue('TOOLS')['ovs_var_tmp'],
                                                    "{}.pid".format(self._proc_name))
         self._logger = logging.getLogger(__name__)
-        self._expect = r'bridge|INFO|{}'.format(self._proc_name)
+        # sign '|' must be escaped or avoided, otherwise it is handled as 'or' by regex
+        self._expect = r'bridge.INFO.{}'.format(self._proc_name)
         self._timeout = 30
         self._bridges = {}
         self._vswitchd_args = ['--pidfile=' + self._vswitchd_pidfile_path,
@@ -90,6 +91,27 @@ class IVSwitchOvs(IVSwitch, tasks.Process):
 
         self._logger.info("Vswitchd...Started.")
 
+    def restart(self):
+        """ Restart ``ovs-vswitchd`` instance. ``ovsdb-server`` is not restarted.
+
+        :raises: pexpect.EOF, pexpect.TIMEOUT
+        """
+        self._logger.info("Restarting vswitchd...")
+        if os.path.isfile(self._vswitchd_pidfile_path):
+            self._logger.info('Killing ovs-vswitchd...')
+            with open(self._vswitchd_pidfile_path, "r") as pidfile:
+                vswitchd_pid = pidfile.read().strip()
+                tasks.terminate_task(vswitchd_pid, logger=self._logger)
+
+        try:
+            tasks.Process.start(self)
+            self.relinquish()
+        except (pexpect.EOF, pexpect.TIMEOUT) as exc:
+            logging.error("Exception during VSwitch start.")
+            self._kill_ovsdb()
+            raise exc
+        self._logger.info("Vswitchd...Started.")
+
     def configure(self):
         """ Configure vswitchd through ovsdb if needed
         """
@@ -106,8 +128,11 @@ class IVSwitchOvs(IVSwitch, tasks.Process):
     def stop(self):
         """See IVswitch for general description
         """
+        for switch_name in list(self._bridges):
+            self.del_switch(switch_name)
         self._logger.info("Terminating vswitchd...")
         self.kill()
+        self._bridges = {}
         self._logger.info("Vswitchd...Terminated.")
 
     def add_switch(self, switch_name, params=None):
@@ -124,6 +149,9 @@ class IVSwitchOvs(IVSwitch, tasks.Process):
         """See IVswitch for general description
         """
         bridge = self._bridges[switch_name]
+        bridge.del_flow({})
+        for port in list(bridge.get_ports()):
+            bridge.del_port(port)
         self._bridges.pop(switch_name)
         bridge.destroy()
 
@@ -143,7 +171,7 @@ class IVSwitchOvs(IVSwitch, tasks.Process):
 
         """
         if switch_name is None or remote_switch_name is None:
-            return
+            return None
 
         bridge = self._bridges[switch_name]
         remote_bridge = self._bridges[remote_switch_name]
@@ -359,7 +387,7 @@ class IVSwitchOvs(IVSwitch, tasks.Process):
             with open(self._ovsdb_pidfile_path, "r") as pidfile:
                 ovsdb_pid = pidfile.read().strip()
 
-            self._logger.info("Killing ovsdb with pid: " + ovsdb_pid)
+            self._logger.info("Killing ovsdb with pid: %s", ovsdb_pid)
 
             if ovsdb_pid:
                 tasks.terminate_task(ovsdb_pid, logger=self._logger)
@@ -386,7 +414,7 @@ class IVSwitchOvs(IVSwitch, tasks.Process):
     #
     # validate methods required for integration testcases
     #
-    def validate_add_switch(self, dummy_result, switch_name, dummy_params=None):
+    def validate_add_switch(self, _dummy_result, switch_name, _dummy_params=None):
         """Validate - Create a new logical switch with no ports
         """
         bridge = self._bridges[switch_name]
@@ -397,7 +425,7 @@ class IVSwitchOvs(IVSwitch, tasks.Process):
 
     # Method could be a function
     # pylint: disable=no-self-use
-    def validate_del_switch(self, dummy_result, switch_name):
+    def validate_del_switch(self, _dummy_result, switch_name):
         """Validate removal of switch
         """
         bridge = OFBridge('tmp')
@@ -421,7 +449,7 @@ class IVSwitchOvs(IVSwitch, tasks.Process):
         """
         return self.validate_add_phy_port(result, switch_name)
 
-    def validate_del_port(self, dummy_result, switch_name, port_name):
+    def validate_del_port(self, _dummy_result, switch_name, port_name):
         """ Validate that port_name was removed from bridge.
         """
         bridge = self._bridges[switch_name]
@@ -430,7 +458,7 @@ class IVSwitchOvs(IVSwitch, tasks.Process):
         assert 'Port "%s"' % port_name not in output[0]
         return True
 
-    def validate_add_flow(self, dummy_result, switch_name, flow, dummy_cache='off'):
+    def validate_add_flow(self, _dummy_result, switch_name, flow, _dummy_cache='off'):
         """ Validate insertion of the flow into the switch
         """
 
@@ -451,39 +479,44 @@ class IVSwitchOvs(IVSwitch, tasks.Process):
                 return True
         return False
 
-    def validate_del_flow(self, dummy_result, switch_name, flow=None):
+    def validate_del_flow(self, _dummy_result, switch_name, flow=None):
         """ Validate removal of the flow
         """
         if not flow:
             # what else we can do?
             return True
-        return not self.validate_add_flow(dummy_result, switch_name, flow)
+        return not self.validate_add_flow(_dummy_result, switch_name, flow)
 
-    def validate_dump_flows(self, dummy_result, dummy_switch_name):
+    def validate_dump_flows(self, _dummy_result, _dummy_switch_name):
         """ Validate call of flow dump
         """
         return True
 
-    def validate_disable_rstp(self, dummy_result, switch_name):
+    def validate_disable_rstp(self, _dummy_result, switch_name):
         """ Validate rstp disable
         """
         bridge = self._bridges[switch_name]
         return 'rstp_enable         : false' in ''.join(bridge.bridge_info())
 
-    def validate_enable_rstp(self, dummy_result, switch_name):
+    def validate_enable_rstp(self, _dummy_result, switch_name):
         """ Validate rstp enable
         """
         bridge = self._bridges[switch_name]
         return 'rstp_enable         : true' in ''.join(bridge.bridge_info())
 
-    def validate_disable_stp(self, dummy_result, switch_name):
+    def validate_disable_stp(self, _dummy_result, switch_name):
         """ Validate stp disable
         """
         bridge = self._bridges[switch_name]
         return 'stp_enable          : false' in ''.join(bridge.bridge_info())
 
-    def validate_enable_stp(self, dummy_result, switch_name):
+    def validate_enable_stp(self, _dummy_result, switch_name):
         """ Validate stp enable
         """
         bridge = self._bridges[switch_name]
         return 'stp_enable          : true' in ''.join(bridge.bridge_info())
+
+    def validate_restart(self, _dummy_result):
+        """ Validate restart
+        """
+        return True