]> review.fuel-infra Code Review - openstack-build/neutron-build.git/commitdiff
Setup device alias by device flavor information.
authorJason Zhang <zhesen@nttmcl.com>
Thu, 6 Dec 2012 19:39:34 +0000 (11:39 -0800)
committerJason Zhang <zhesen@nttmcl.com>
Mon, 4 Mar 2013 22:56:21 +0000 (14:56 -0800)
The router interface cannot be deleted since the MetaPlugin
cannot get the flavor information from the port which has
been deleted.
The solution is setting up the alias for each device based
on the flavor information, so the MetaPlugin still can get
the flavor information from the device itself even the
port has been deleted.

Also the router interface cannot be deleted since the
l3_port_check flag is not passed by MetaPlugin.

Fixes: bug #1085276
Change-Id: I670aa45c804e660ee4afb5359e0ab1347f369986

quantum/agent/linux/interface.py
quantum/agent/linux/ip_lib.py
quantum/plugins/metaplugin/meta_quantum_plugin.py
quantum/tests/unit/test_linux_interface.py
quantum/tests/unit/test_linux_ip_lib.py

index 21a251a0d0a3a14461c7105bc48ca6c822c7237b..496f0905450e457a55f3a94087b4f0a62486ae0e 100644 (file)
@@ -265,18 +265,22 @@ class MetaInterfaceDriver(LinuxInterfaceDriver):
                 self.conf.meta_flavor_driver_mappings.split(',')]:
             self.flavor_driver_map[flavor] = self._load_driver(driver_name)
 
-    def _get_driver_by_network_id(self, network_id):
+    def _get_flavor_by_network_id(self, network_id):
         network = self.quantum.show_network(network_id)
-        flavor = network['network'][FLAVOR_NETWORK]
+        return network['network'][FLAVOR_NETWORK]
+
+    def _get_driver_by_network_id(self, network_id):
+        flavor = self._get_flavor_by_network_id(network_id)
         return self.flavor_driver_map[flavor]
 
-    def _get_driver_by_device_name(self, device_name, namespace=None):
-        device = ip_lib.IPDevice(device_name, self.root_helper, namespace)
-        mac_address = device.link.address
-        ports = self.quantum.list_ports(mac_address=mac_address)
-        if not ports.get('ports'):
-            raise Exception(_('No port for this device %s') % device_name)
-        return self._get_driver_by_network_id(ports['ports'][0]['network_id'])
+    def _set_device_plugin_tag(self, network_id, device_name, namespace=None):
+        plugin_tag = self._get_flavor_by_network_id(network_id)
+        device = ip_lib.IPDevice(device_name, self.conf.root_helper, namespace)
+        device.link.set_alias(plugin_tag)
+
+    def _get_device_plugin_tag(self, device_name, namespace=None):
+        device = ip_lib.IPDevice(device_name, self.conf.root_helper, namespace)
+        return device.link.alias
 
     def get_device_name(self, port):
         driver = self._get_driver_by_network_id(port.network_id)
@@ -285,11 +289,14 @@ class MetaInterfaceDriver(LinuxInterfaceDriver):
     def plug(self, network_id, port_id, device_name, mac_address,
              bridge=None, namespace=None, prefix=None):
         driver = self._get_driver_by_network_id(network_id)
-        return driver.plug(network_id, port_id, device_name, mac_address,
-                           bridge=bridge, namespace=namespace, prefix=prefix)
+        ret = driver.plug(network_id, port_id, device_name, mac_address,
+                          bridge=bridge, namespace=namespace, prefix=prefix)
+        self._set_device_plugin_tag(network_id, device_name, namespace)
+        return ret
 
     def unplug(self, device_name, bridge=None, namespace=None, prefix=None):
-        driver = self._get_driver_by_device_name(device_name, namespace=None)
+        plugin_tag = self._get_device_plugin_tag(device_name, namespace)
+        driver = self.flavor_driver_map[plugin_tag]
         return driver.unplug(device_name, bridge, namespace, prefix)
 
     def _load_driver(self, driver_provider):
index 31337087e6043cd9c1086d60f488c0688dfbb1b4..1f618c3f95b794434190aa025de27213978d9f4e 100644 (file)
@@ -189,6 +189,9 @@ class IpLinkCommand(IpDeviceCommandBase):
         self._as_root('set', self.name, 'name', name)
         self._parent.name = name
 
+    def set_alias(self, alias_name):
+        self._as_root('set', self.name, 'alias', alias_name)
+
     def delete(self):
         self._as_root('delete', self.name)
 
@@ -212,6 +215,10 @@ class IpLinkCommand(IpDeviceCommandBase):
     def qlen(self):
         return self.attributes.get('qlen')
 
+    @property
+    def alias(self):
+        return self.attributes.get('alias')
+
     @property
     def attributes(self):
         return self._parse_line(self._run('show', self.name, options='o'))
index 7ec3ffe8f29ffec26f692eb5a30da8720bb3fc9d..3c9cde6e6643db8f4d12fae0fb33ee62a50fca6a 100644 (file)
@@ -258,7 +258,7 @@ class MetaPluginV2(db_base_plugin_v2.QuantumDbPluginV2,
         if l3_port_check:
             self.prevent_l3_port_deletion(context, id)
             self.disassociate_floatingips(context, id)
-        return plugin.delete_port(context, id)
+        return plugin.delete_port(context, id, l3_port_check)
 
     def create_subnet(self, context, subnet):
         s = subnet['subnet']
index 9e3ed5262bfc2a97278e2476f8fd7c3a06589e23..f1c60f23b24404c3857fe370bd5c8a7f1fdc676d 100644 (file)
@@ -380,15 +380,35 @@ class TestMetaInterfaceDriver(TestBase):
             driver,
             interface.OVSInterfaceDriver))
 
-    def test_get_driver_by_device_name(self):
-        device_address_p = mock.patch(
-            'quantum.agent.linux.ip_lib.IpLinkCommand.address')
-        device_address = device_address_p.start()
-        device_address.return_value = 'aa:bb:cc:dd:ee:ffa'
-
+    def test_set_device_plugin_tag(self):
         meta_interface = interface.MetaInterfaceDriver(self.conf)
-        driver = meta_interface._get_driver_by_device_name('test')
-        self.assertTrue(isinstance(
-            driver,
-            interface.OVSInterfaceDriver))
-        device_address_p.stop()
+        driver = meta_interface._get_driver_by_network_id('test')
+        meta_interface._set_device_plugin_tag(driver,
+                                              'tap0',
+                                              namespace=None)
+        expected = [mock.call('tap0', 'sudo', None),
+                    mock.call().link.set_alias('fake1')]
+        self.ip_dev.assert_has_calls(expected)
+        namespace = '01234567-1234-1234-99'
+        meta_interface._set_device_plugin_tag(driver,
+                                              'tap1',
+                                              namespace=namespace)
+        expected = [mock.call('tap1', 'sudo', '01234567-1234-1234-99'),
+                    mock.call().link.set_alias('fake1')]
+        self.ip_dev.assert_has_calls(expected)
+
+    def test_get_device_plugin_tag(self):
+        meta_interface = interface.MetaInterfaceDriver(self.conf)
+        self.ip_dev().link.alias = 'fake1'
+        plugin_tag0 = meta_interface._get_device_plugin_tag('tap0',
+                                                            namespace=None)
+        expected = [mock.call('tap0', 'sudo', None)]
+        self.ip_dev.assert_has_calls(expected)
+        self.assertEquals('fake1', plugin_tag0)
+        namespace = '01234567-1234-1234-99'
+        expected = [mock.call('tap1', 'sudo', '01234567-1234-1234-99')]
+        plugin_tag1 = meta_interface._get_device_plugin_tag(
+            'tap1',
+            namespace=namespace)
+        self.ip_dev.assert_has_calls(expected)
+        self.assertEquals('fake1', plugin_tag1)
index cc54ff23cdc24c178ec29ee49b060eac281c4764..9d97a3a0920a1b4ed1fa8a3bca89eb9a0bfb1acf 100644 (file)
@@ -30,7 +30,8 @@ LINK_SAMPLE = [
     '1: lo: <LOOPBACK,UP,LOWER_UP> mtu 16436 qdisc noqueue state UNKNOWN \\'
     'link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00',
     '2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc mq state UP '
-    'qlen 1000\    link/ether cc:dd:ee:ff:ab:cd brd ff:ff:ff:ff:ff:ff',
+    'qlen 1000\    link/ether cc:dd:ee:ff:ab:cd brd ff:ff:ff:ff:ff:ff'
+    '\    alias openvswitch',
     '3: br-int: <BROADCAST,MULTICAST> mtu 1500 qdisc noop state DOWN '
     '\    link/ether aa:bb:cc:dd:ee:ff brd ff:ff:ff:ff:ff:ff',
     '4: gw-ddc717df-49: <BROADCAST,MULTICAST> mtu 1500 qdisc noop '
@@ -426,6 +427,10 @@ class TestIpLinkCommand(TestIPCmdBase):
         self._assert_sudo([], ('set', 'eth0', 'name', 'tap1'))
         self.assertEqual(self.parent.name, 'tap1')
 
+    def test_set_alias(self):
+        self.link_cmd.set_alias('openvswitch')
+        self._assert_sudo([], ('set', 'eth0', 'alias', 'openvswitch'))
+
     def test_delete(self):
         self.link_cmd.delete()
         self._assert_sudo([], ('delete', 'eth0'))
@@ -446,6 +451,10 @@ class TestIpLinkCommand(TestIPCmdBase):
         self.parent._execute = mock.Mock(return_value=LINK_SAMPLE[1])
         self.assertEqual(self.link_cmd.qlen, 1000)
 
+    def test_alias_property(self):
+        self.parent._execute = mock.Mock(return_value=LINK_SAMPLE[1])
+        self.assertEqual(self.link_cmd.alias, 'openvswitch')
+
     def test_state_property(self):
         self.parent._execute = mock.Mock(return_value=LINK_SAMPLE[1])
         self.assertEqual(self.link_cmd.state, 'UP')
@@ -456,7 +465,8 @@ class TestIpLinkCommand(TestIPCmdBase):
                     'state': 'UP',
                     'qdisc': 'mq',
                     'brd': 'ff:ff:ff:ff:ff:ff',
-                    'link/ether': 'cc:dd:ee:ff:ab:cd'}
+                    'link/ether': 'cc:dd:ee:ff:ab:cd',
+                    'alias': 'openvswitch'}
         self.parent._execute = mock.Mock(return_value=LINK_SAMPLE[1])
         self.assertEqual(self.link_cmd.attributes, expected)
         self._assert_call('o', ('show', 'eth0'))