]> review.fuel-infra Code Review - openstack-build/neutron-build.git/commitdiff
Add unit tests for Open vSwitch Quantum plugin
authorVasiliy Khomenko <vasiliyk@yahoo-inc.com>
Tue, 15 Jan 2013 00:22:00 +0000 (22:22 -0200)
committerVasyl Khomenko <vasiliyk@yahoo-inc.com>
Thu, 7 Feb 2013 14:01:04 +0000 (09:01 -0500)
OVSQuantumAgent missed unit tests for tunneling
functionality. This change add these tests and couple
of other minor tests.

Implements: blueprint quantum-unittests

Change-Id: I809711de8292ff7610b3fdb496c6bd043e7b6031

quantum/tests/unit/openvswitch/test_ovs_quantum_agent.py
quantum/tests/unit/openvswitch/test_ovs_tunnel.py

index a759a0b27e721cee9fc5c0a1004846ae46ef7fd6..93d47c82ed38389e1305efec54848742e04f6814 100644 (file)
@@ -137,12 +137,39 @@ class TestOvsQuantumAgent(unittest.TestCase):
         details = dict(exists=port_exists)
         with mock.patch.object(self.agent.plugin_rpc, 'update_device_down',
                                return_value=details):
-            with mock.patch.object(self.agent, 'port_unbound') as func:
+            with mock.patch.object(self.agent, 'port_unbound') as port_unbound:
                 self.assertFalse(self.agent.treat_devices_removed([{}]))
-        self.assertEqual(func.called, not port_exists)
+        self.assertEqual(port_unbound.called, not port_exists)
 
     def test_treat_devices_removed_unbinds_port(self):
         self.mock_treat_devices_removed(False)
 
     def test_treat_devices_removed_ignores_missing_port(self):
         self.mock_treat_devices_removed(False)
+
+    def test_port_update(self):
+        port = {'id': 1,
+                'network_id': 1,
+                'admin_state_up': True}
+        with mock.patch.object(self.agent.int_br, 'get_vif_port_by_id',
+                               return_value='2'):
+            with mock.patch.object(self.agent, 'port_bound') as port_bound:
+                self.agent.port_update(mock.Mock(), port=port)
+                self.assertTrue(port_bound.called)
+
+            with mock.patch.object(self.agent, 'port_dead') as port_dead:
+                port['admin_state_up'] = False
+                self.agent.port_update(mock.Mock(), port=port)
+                self.assertTrue(port_dead.called)
+
+    def test_process_network_ports(self):
+        reply = {'current': set(['tap0']),
+                 'removed': set(['eth0']),
+                 'added': set(['eth1'])}
+        with mock.patch.object(self.agent, 'treat_devices_added',
+                               return_value=False) as device_added:
+            with mock.patch.object(self.agent, 'treat_devices_removed',
+                                   return_value=False) as device_removed:
+                self.assertFalse(self.agent.process_network_ports(reply))
+                self.assertTrue(device_added.called)
+                self.assertTrue(device_removed.called)
index a597193f33b1042096a08f4d53c3f7870388c0b6..dcc1d0fd1543b71faae3ad0c8441f39f6f26e4e0 100644 (file)
@@ -20,13 +20,19 @@ import unittest
 
 import mox
 
+from quantum.agent.linux import ip_lib
 from quantum.agent.linux import ovs_lib
 from quantum.agent.linux import utils
+from quantum.agent import rpc
+from quantum.openstack.common import cfg
+from quantum.openstack.common import log
 from quantum.plugins.openvswitch.agent import ovs_quantum_agent
+from quantum.plugins.openvswitch.common import constants
+
 
 # Useful global dummy variables.
 NET_UUID = '3faeebfe-5d37-11e1-a64b-000c29d5f0a7'
-LS_ID = '42'
+LS_ID = 42
 LV_ID = 42
 LV_IDS = [42, 43]
 VIF_ID = '404deaec-5d37-11e1-a64b-000c29d5f0a8'
@@ -36,6 +42,10 @@ VIF_PORT = ovs_lib.VifPort('port', OFPORT_NUM,
                            VIF_ID, VIF_MAC, 'switch')
 VIF_PORTS = {LV_ID: VIF_PORT}
 LVM = ovs_quantum_agent.LocalVLANMapping(LV_ID, 'gre', None, LS_ID, VIF_PORTS)
+LVM_FLAT = ovs_quantum_agent.LocalVLANMapping(
+    LV_ID, 'flat', 'net1', LS_ID, VIF_PORTS)
+LVM_VLAN = ovs_quantum_agent.LocalVLANMapping(
+    LV_ID, 'vlan', 'net1', LS_ID, VIF_PORTS)
 BCAST_MAC = "01:00:00:00:00:00/01:00:00:00:00:00"
 
 
@@ -51,14 +61,21 @@ class DummyVlanBinding:
 
 
 class TunnelTest(unittest.TestCase):
-
     def setUp(self):
+        cfg.CONF.set_override('rpc_backend',
+                              'quantum.openstack.common.rpc.impl_fake')
         self.mox = mox.Mox()
-
         self.INT_BRIDGE = 'integration_bridge'
         self.TUN_BRIDGE = 'tunnel_bridge'
+        self.MAP_TUN_BRIDGE = 'tunnel_bridge_mapping'
+        self.NET_MAPPING = {'net1': self.MAP_TUN_BRIDGE}
         self.INT_OFPORT = 11111
         self.TUN_OFPORT = 22222
+        self.MAP_TUN_OFPORT = 33333
+        self.inta = self.mox.CreateMock(ip_lib.IPDevice)
+        self.intb = self.mox.CreateMock(ip_lib.IPDevice)
+        self.inta.link = self.mox.CreateMock(ip_lib.IpLinkCommand)
+        self.intb.link = self.mox.CreateMock(ip_lib.IpLinkCommand)
 
         self.mox.StubOutClassWithMocks(ovs_lib, 'OVSBridge')
         self.mock_int_bridge = ovs_lib.OVSBridge(self.INT_BRIDGE, 'sudo')
@@ -66,6 +83,21 @@ class TunnelTest(unittest.TestCase):
         self.mock_int_bridge.remove_all_flows()
         self.mock_int_bridge.add_flow(priority=1, actions='normal')
 
+        self.mock_map_tun_bridge = ovs_lib.OVSBridge(
+            self.MAP_TUN_BRIDGE, 'sudo')
+        self.mock_map_tun_bridge.remove_all_flows()
+        self.mock_map_tun_bridge.add_flow(priority=1, actions='normal')
+        self.mock_int_bridge.delete_port('int-tunnel_bridge_mapping')
+        self.mock_map_tun_bridge.delete_port('phy-tunnel_bridge_mapping')
+        self.mock_int_bridge.add_port(self.inta)
+        self.mock_map_tun_bridge.add_port(self.intb)
+        self.inta.link.set_up()
+        self.intb.link.set_up()
+
+        self.mock_int_bridge.add_flow(priority=2, in_port=None, actions='drop')
+        self.mock_map_tun_bridge.add_flow(
+            priority=2, in_port=None, actions='drop')
+
         self.mock_tun_bridge = ovs_lib.OVSBridge(self.TUN_BRIDGE, 'sudo')
         self.mock_tun_bridge.reset_bridge()
         self.mock_int_bridge.add_patch_port(
@@ -75,6 +107,19 @@ class TunnelTest(unittest.TestCase):
         self.mock_tun_bridge.remove_all_flows()
         self.mock_tun_bridge.add_flow(priority=1, actions='drop')
 
+        self.mox.StubOutWithMock(ip_lib, 'device_exists')
+        ip_lib.device_exists('tunnel_bridge_mapping', 'sudo').AndReturn(True)
+        ip_lib.device_exists(
+            'int-tunnel_bridge_mapping', 'sudo').AndReturn(True)
+
+        self.mox.StubOutWithMock(ip_lib.IpLinkCommand, 'delete')
+        ip_lib.IPDevice('int-tunnel_bridge_mapping').link.delete()
+
+        self.mox.StubOutClassWithMocks(ip_lib, 'IPWrapper')
+        ip_lib.IPWrapper('sudo').add_veth(
+            'int-tunnel_bridge_mapping',
+            'phy-tunnel_bridge_mapping').AndReturn([self.inta, self.intb])
+
         self.mox.StubOutWithMock(utils, 'get_interface_mac')
         utils.get_interface_mac(self.INT_BRIDGE).AndReturn('000000000001')
 
@@ -83,10 +128,9 @@ class TunnelTest(unittest.TestCase):
 
     def testConstruct(self):
         self.mox.ReplayAll()
-
         b = ovs_quantum_agent.OVSQuantumAgent(self.INT_BRIDGE,
                                               self.TUN_BRIDGE,
-                                              '10.0.0.1', {},
+                                              '10.0.0.1', self.NET_MAPPING,
                                               'sudo', 2, True)
         self.mox.VerifyAll()
 
@@ -103,10 +147,73 @@ class TunnelTest(unittest.TestCase):
 
         a = ovs_quantum_agent.OVSQuantumAgent(self.INT_BRIDGE,
                                               self.TUN_BRIDGE,
-                                              '10.0.0.1', {},
+                                              '10.0.0.1', self.NET_MAPPING,
+                                              'sudo', 2, True)
+        a.available_local_vlans = set([LV_ID])
+        a.provision_local_vlan(NET_UUID, constants.TYPE_GRE, None, LS_ID)
+        self.mox.VerifyAll()
+
+    def testProvisionLocalVlanFlat(self):
+        action_string = 'strip_vlan,normal'
+        self.mock_map_tun_bridge.add_flow(
+            priority=4, in_port=self.MAP_TUN_OFPORT,
+            dl_vlan=LV_ID, actions=action_string)
+
+        action_string = 'mod_vlan_vid:%s,normal' % LV_ID
+        self.mock_int_bridge.add_flow(priority=3, in_port=self.INT_OFPORT,
+                                      dl_vlan=65535, actions=action_string)
+
+        self.mox.ReplayAll()
+
+        a = ovs_quantum_agent.OVSQuantumAgent(self.INT_BRIDGE,
+                                              self.TUN_BRIDGE,
+                                              '10.0.0.1', self.NET_MAPPING,
                                               'sudo', 2, True)
         a.available_local_vlans = set([LV_ID])
-        a.provision_local_vlan(NET_UUID, 'gre', None, LS_ID)
+        a.phys_brs['net1'] = self.mock_map_tun_bridge
+        a.phys_ofports['net1'] = self.MAP_TUN_OFPORT
+        a.int_ofports['net1'] = self.INT_OFPORT
+        a.provision_local_vlan(NET_UUID, constants.TYPE_FLAT, 'net1', LS_ID)
+        self.mox.VerifyAll()
+
+    def testProvisionLocalVlanFlatFail(self):
+        self.mox.ReplayAll()
+        a = ovs_quantum_agent.OVSQuantumAgent(self.INT_BRIDGE,
+                                              self.TUN_BRIDGE,
+                                              '10.0.0.1', self.NET_MAPPING,
+                                              'sudo', 2, True)
+        a.provision_local_vlan(NET_UUID, constants.TYPE_FLAT, 'net2', LS_ID)
+        self.mox.VerifyAll()
+
+    def testProvisionLocalVlanVlan(self):
+        action_string = 'mod_vlan_vid:%s,normal' % LS_ID
+        self.mock_map_tun_bridge.add_flow(
+            priority=4, in_port=self.MAP_TUN_OFPORT,
+            dl_vlan=LV_ID, actions=action_string)
+
+        action_string = 'mod_vlan_vid:%s,normal' % LS_ID
+        self.mock_int_bridge.add_flow(priority=3, in_port=self.INT_OFPORT,
+                                      dl_vlan=LV_ID, actions=action_string)
+
+        self.mox.ReplayAll()
+        a = ovs_quantum_agent.OVSQuantumAgent(self.INT_BRIDGE,
+                                              self.TUN_BRIDGE,
+                                              '10.0.0.1', self.NET_MAPPING,
+                                              'sudo', 2, True)
+        a.available_local_vlans = set([LV_ID])
+        a.phys_brs['net1'] = self.mock_map_tun_bridge
+        a.phys_ofports['net1'] = self.MAP_TUN_OFPORT
+        a.int_ofports['net1'] = self.INT_OFPORT
+        a.provision_local_vlan(NET_UUID, constants.TYPE_VLAN, 'net1', LS_ID)
+        self.mox.VerifyAll()
+
+    def testProvisionLocalVlanVlanFail(self):
+        self.mox.ReplayAll()
+        a = ovs_quantum_agent.OVSQuantumAgent(self.INT_BRIDGE,
+                                              self.TUN_BRIDGE,
+                                              '10.0.0.1', self.NET_MAPPING,
+                                              'sudo', 2, True)
+        a.provision_local_vlan(NET_UUID, constants.TYPE_VLAN, 'net2', LS_ID)
         self.mox.VerifyAll()
 
     def testReclaimLocalVlan(self):
@@ -117,7 +224,7 @@ class TunnelTest(unittest.TestCase):
         self.mox.ReplayAll()
         a = ovs_quantum_agent.OVSQuantumAgent(self.INT_BRIDGE,
                                               self.TUN_BRIDGE,
-                                              '10.0.0.1', {},
+                                              '10.0.0.1', self.NET_MAPPING,
                                               'sudo', 2, True)
         a.available_local_vlans = set()
         a.local_vlan_map[NET_UUID] = LVM
@@ -125,6 +232,50 @@ class TunnelTest(unittest.TestCase):
         self.assertTrue(LVM.vlan in a.available_local_vlans)
         self.mox.VerifyAll()
 
+    def testReclaimLocalVlanFlat(self):
+        self.mock_map_tun_bridge.delete_flows(
+            in_port=self.MAP_TUN_OFPORT, dl_vlan=LVM_FLAT.vlan)
+
+        self.mock_int_bridge.delete_flows(
+            dl_vlan=65535, in_port=self.INT_OFPORT)
+
+        self.mox.ReplayAll()
+        a = ovs_quantum_agent.OVSQuantumAgent(self.INT_BRIDGE,
+                                              self.TUN_BRIDGE,
+                                              '10.0.0.1', self.NET_MAPPING,
+                                              'sudo', 2, True)
+        a.phys_brs['net1'] = self.mock_map_tun_bridge
+        a.phys_ofports['net1'] = self.MAP_TUN_OFPORT
+        a.int_ofports['net1'] = self.INT_OFPORT
+
+        a.available_local_vlans = set()
+        a.local_vlan_map[NET_UUID] = LVM_FLAT
+        a.reclaim_local_vlan(NET_UUID, LVM_FLAT)
+        self.assertTrue(LVM_FLAT.vlan in a.available_local_vlans)
+        self.mox.VerifyAll()
+
+    def testReclaimLocalVlanVLAN(self):
+        self.mock_map_tun_bridge.delete_flows(
+            in_port=self.MAP_TUN_OFPORT, dl_vlan=LVM_VLAN.vlan)
+
+        self.mock_int_bridge.delete_flows(
+            dl_vlan=LV_ID, in_port=self.INT_OFPORT)
+
+        self.mox.ReplayAll()
+        a = ovs_quantum_agent.OVSQuantumAgent(self.INT_BRIDGE,
+                                              self.TUN_BRIDGE,
+                                              '10.0.0.1', self.NET_MAPPING,
+                                              'sudo', 2, True)
+        a.phys_brs['net1'] = self.mock_map_tun_bridge
+        a.phys_ofports['net1'] = self.MAP_TUN_OFPORT
+        a.int_ofports['net1'] = self.INT_OFPORT
+
+        a.available_local_vlans = set()
+        a.local_vlan_map[NET_UUID] = LVM_VLAN
+        a.reclaim_local_vlan(NET_UUID, LVM_VLAN)
+        self.assertTrue(LVM_VLAN.vlan in a.available_local_vlans)
+        self.mox.VerifyAll()
+
     def testPortBound(self):
         self.mock_int_bridge.set_db_attribute('Port', VIF_PORT.port_name,
                                               'tag', str(LVM.vlan))
@@ -138,7 +289,7 @@ class TunnelTest(unittest.TestCase):
         self.mox.ReplayAll()
         a = ovs_quantum_agent.OVSQuantumAgent(self.INT_BRIDGE,
                                               self.TUN_BRIDGE,
-                                              '10.0.0.1', {},
+                                              '10.0.0.1', self.NET_MAPPING,
                                               'sudo', 2, True)
         a.local_vlan_map[NET_UUID] = LVM
         a.port_bound(VIF_PORT, NET_UUID, 'gre', None, LS_ID)
@@ -149,7 +300,7 @@ class TunnelTest(unittest.TestCase):
         self.mox.ReplayAll()
         a = ovs_quantum_agent.OVSQuantumAgent(self.INT_BRIDGE,
                                               self.TUN_BRIDGE,
-                                              '10.0.0.1', {},
+                                              '10.0.0.1', self.NET_MAPPING,
                                               'sudo', 2, True)
         a.available_local_vlans = set([LV_ID])
         a.local_vlan_map[NET_UUID] = LVM
@@ -166,9 +317,77 @@ class TunnelTest(unittest.TestCase):
         self.mox.ReplayAll()
         a = ovs_quantum_agent.OVSQuantumAgent(self.INT_BRIDGE,
                                               self.TUN_BRIDGE,
-                                              '10.0.0.1', {},
+                                              '10.0.0.1', self.NET_MAPPING,
                                               'sudo', 2, True)
         a.available_local_vlans = set([LV_ID])
         a.local_vlan_map[NET_UUID] = LVM
         a.port_dead(VIF_PORT)
         self.mox.VerifyAll()
+
+    def testTunnelUpdate(self):
+        self.mock_tun_bridge.add_tunnel_port('gre-1', '10.0.10.1')
+        self.mox.ReplayAll()
+        a = ovs_quantum_agent.OVSQuantumAgent(self.INT_BRIDGE,
+                                              self.TUN_BRIDGE,
+                                              '10.0.0.1', self.NET_MAPPING,
+                                              'sudo', 2, True)
+        a.tunnel_update(
+            mox.MockAnything, tunnel_id='1', tunnel_ip='10.0.10.1')
+        self.mox.VerifyAll()
+
+    def testTunnelUpdateSelf(self):
+        self.mox.ReplayAll()
+        a = ovs_quantum_agent.OVSQuantumAgent(self.INT_BRIDGE,
+                                              self.TUN_BRIDGE,
+                                              '10.0.0.1', self.NET_MAPPING,
+                                              'sudo', 2, True)
+        a.tunnel_update(
+            mox.MockAnything, tunnel_id='1', tunnel_ip='10.0.0.1')
+        self.mox.VerifyAll()
+
+    def testDaemonLoop(self):
+        reply2 = {'current': set(['tap0']),
+                  'added': set([]),
+                  'removed': set([])}
+
+        reply3 = {'current': set(['tap2']),
+                  'added': set([]),
+                  'removed': set([])}
+
+        self.mox.StubOutWithMock(log.ContextAdapter, 'exception')
+        log.ContextAdapter.exception(
+            _("Error in agent event loop")).AndRaise(
+                Exception('Fake exception to get out of the loop'))
+
+        self.mox.StubOutWithMock(
+            ovs_quantum_agent.OVSQuantumAgent, 'update_ports')
+        ovs_quantum_agent.OVSQuantumAgent.update_ports(set()).AndReturn(reply2)
+        ovs_quantum_agent.OVSQuantumAgent.update_ports(
+            set(['tap0'])).AndReturn(reply3)
+        self.mox.StubOutWithMock(
+            ovs_quantum_agent.OVSQuantumAgent, 'process_network_ports')
+        ovs_quantum_agent.OVSQuantumAgent.process_network_ports(
+            {'current': set(['tap0']),
+             'removed': set([]),
+             'added': set([])}).AndReturn(False)
+        ovs_quantum_agent.OVSQuantumAgent.process_network_ports(
+            {'current': set(['tap0']),
+             'removed': set([]),
+             'added': set([])}).AndRaise(
+                 Exception('Fake exception to get out of the loop'))
+        self.mox.ReplayAll()
+        q_agent = ovs_quantum_agent.OVSQuantumAgent(self.INT_BRIDGE,
+                                                    self.TUN_BRIDGE,
+                                                    '10.0.0.1',
+                                                    self.NET_MAPPING,
+                                                    'sudo', 2, True)
+
+        # Hack to test loop
+        # We start method and expect it will raise after 2nd loop
+        # If something goes wrong, mox.VerifyAll() will catch it
+        try:
+            q_agent.daemon_loop()
+        except:
+            pass
+
+        self.mox.VerifyAll()