]> review.fuel-infra Code Review - openstack-build/neutron-build.git/commitdiff
Part of the patch set that enables VM's to use libvirts bridge type.
authorGary Kotton <gkotton@redhat.com>
Thu, 25 Oct 2012 03:22:03 +0000 (03:22 +0000)
committerGary Kotton <gkotton@redhat.com>
Sat, 10 Nov 2012 23:30:42 +0000 (23:30 +0000)
Fixes bug 1078210

The bridge will be created by Nova and not by the agent. This is the first
part for the blueprint vif-plugin-improvements

This patch supports Nova managing bridges too.

In addition to this it cleans gateway code no longer used.

Change-Id: Ia621ba5edd12d8eb7ea412a2993fea43189bd511

quantum/plugins/linuxbridge/agent/linuxbridge_quantum_agent.py
quantum/tests/unit/linuxbridge/test_lb_quantum_agent.py [new file with mode: 0644]

index 1d3fb55fac3b7f7e9232b35f32ad2aaf6cf5d138..89ad6941ed91d867cd9bd6d9b13e07ed70b1a28c 100755 (executable)
@@ -47,7 +47,6 @@ from quantum.plugins.linuxbridge.common import constants as lconst
 LOG = logging.getLogger(__name__)
 
 BRIDGE_NAME_PREFIX = "brq"
-GATEWAY_INTERFACE_PREFIX = "gw-"
 TAP_INTERFACE_PREFIX = "tap"
 BRIDGE_FS = "/sys/devices/virtual/net/"
 BRIDGE_NAME_PLACEHOLDER = "bridge_name"
@@ -141,12 +140,6 @@ class LinuxBridge:
         except RuntimeError:
             return self._get_prefixed_ip_link_devices(TAP_INTERFACE_PREFIX)
 
-    def get_all_gateway_devices(self):
-        try:
-            return self._get_prefixed_tap_devices(GATEWAY_INTERFACE_PREFIX)
-        except RuntimeError:
-            return self._get_prefixed_ip_link_devices(GATEWAY_INTERFACE_PREFIX)
-
     def get_bridge_for_tap_device(self, tap_device_name):
         bridges = self.get_all_quantum_bridges()
         for bridge in bridges:
@@ -275,72 +268,64 @@ class LinuxBridge:
                           bridge_name, e)
                 return
 
+    def ensure_physical_in_bridge(self, network_id,
+                                  physical_network,
+                                  vlan_id):
+        physical_interface = self.interface_mappings.get(physical_network)
+        if not physical_interface:
+            LOG.error("No mapping for physical network %s" %
+                      physical_network)
+            return False
+
+        if int(vlan_id) == lconst.FLAT_VLAN_ID:
+            self.ensure_flat_bridge(network_id, physical_interface)
+        else:
+            self.ensure_vlan_bridge(network_id, physical_interface,
+                                    vlan_id)
+        return True
+
     def add_tap_interface(self, network_id, physical_network, vlan_id,
                           tap_device_name):
         """
         If a VIF has been plugged into a network, this function will
         add the corresponding tap device to the relevant bridge
         """
-        if not tap_device_name:
-            return False
-
         if not self.device_exists(tap_device_name):
-            LOG.debug("Tap device: %s does not exist on this host, skipped" %
-                      tap_device_name)
+            LOG.debug(_("Tap device: %s does not exist on "
+                        "this host, skipped" % tap_device_name))
             return False
 
-        current_bridge_name = self.get_bridge_for_tap_device(tap_device_name)
         bridge_name = self.get_bridge_name(network_id)
-        if bridge_name == current_bridge_name:
-            return False
-        LOG.debug("Adding device %s to bridge %s" % (tap_device_name,
-                                                     bridge_name))
-        if current_bridge_name:
-            if utils.execute(['brctl', 'delif', current_bridge_name,
-                              tap_device_name], root_helper=self.root_helper):
-                return False
-
         if int(vlan_id) == lconst.LOCAL_VLAN_ID:
             self.ensure_local_bridge(network_id)
         else:
-            physical_interface = self.interface_mappings.get(physical_network)
-            if not physical_interface:
-                LOG.error("No mapping for physical network %s" %
-                          physical_network)
+            result = self.ensure_physical_in_bridge(network_id,
+                                                    physical_network,
+                                                    vlan_id)
+            if not result:
                 return False
 
-            if int(vlan_id) == lconst.FLAT_VLAN_ID:
-                self.ensure_flat_bridge(network_id, physical_interface)
-            else:
-                self.ensure_vlan_bridge(network_id, physical_interface,
-                                        vlan_id)
-
-        if utils.execute(['brctl', 'addif', bridge_name, tap_device_name],
-                         root_helper=self.root_helper):
-            return False
-
-        LOG.debug("Done adding device %s to bridge %s" % (tap_device_name,
-                                                          bridge_name))
+        # Check if device needs to be added to bridge
+        tap_device_in_bridge = self.get_bridge_for_tap_device(tap_device_name)
+        if not tap_device_in_bridge:
+            msg = _("Adding device %(tap_device_name)s to bridge "
+                    "%(bridge_name)s") % locals()
+            LOG.debug(msg)
+            if utils.execute(['brctl', 'addif', bridge_name, tap_device_name],
+                             root_helper=self.root_helper):
+                return False
+        else:
+            msg = _("%(tap_device_name)s already exists on bridge "
+                    "%(bridge_name)s") % locals()
+            LOG.debug(msg)
         return True
 
     def add_interface(self, network_id, physical_network, vlan_id,
-                      interface_id):
-        if not interface_id:
-            """
-            Since the VIF id is null, no VIF is plugged into this port
-            no more processing is required
-            """
-            return False
-
-        if interface_id.startswith(GATEWAY_INTERFACE_PREFIX):
-            return self.add_tap_interface(network_id,
-                                          physical_network, vlan_id,
-                                          interface_id)
-        else:
-            tap_device_name = self.get_tap_device_name(interface_id)
-            return self.add_tap_interface(network_id,
-                                          physical_network, vlan_id,
-                                          tap_device_name)
+                      port_id):
+        tap_device_name = self.get_tap_device_name(port_id)
+        return self.add_tap_interface(network_id,
+                                      physical_network, vlan_id,
+                                      tap_device_name)
 
     def delete_vlan_bridge(self, bridge_name):
         if self.device_exists(bridge_name):
@@ -487,12 +472,6 @@ class LinuxBridgeQuantumAgentRPC:
     def setup_linux_bridge(self, interface_mappings):
         self.linux_br = LinuxBridge(interface_mappings, self.root_helper)
 
-    def process_port_binding(self, network_id, interface_id,
-                             physical_network, vlan_id):
-        return self.linux_br.add_interface(network_id,
-                                           physical_network, vlan_id,
-                                           interface_id)
-
     def remove_port_binding(self, network_id, interface_id):
         bridge_name = self.linux_br.get_bridge_name(network_id)
         tap_device_name = self.linux_br.get_tap_device_name(interface_id)
@@ -535,7 +514,7 @@ class LinuxBridgeQuantumAgentRPC:
     def treat_devices_added(self, devices):
         resync = False
         for device in devices:
-            LOG.info("Port %s added", device)
+            LOG.debug("Port %s added", device)
             try:
                 details = self.plugin_rpc.get_device_details(self.context,
                                                              device,
@@ -548,15 +527,15 @@ class LinuxBridgeQuantumAgentRPC:
                 LOG.info("Port %s updated. Details: %s", device, details)
                 if details['admin_state_up']:
                     # create the networking for the port
-                    self.process_port_binding(details['network_id'],
-                                              details['port_id'],
-                                              details['physical_network'],
-                                              details['vlan_id'])
+                    self.linux_br.add_interface(details['network_id'],
+                                                details['physical_network'],
+                                                details['vlan_id'],
+                                                details['port_id'])
                 else:
                     self.remove_port_binding(details['network_id'],
                                              details['port_id'])
             else:
-                LOG.debug("Device %s not defined on plugin", device)
+                LOG.info("Device %s not defined on plugin", device)
         return resync
 
     def treat_devices_removed(self, devices):
diff --git a/quantum/tests/unit/linuxbridge/test_lb_quantum_agent.py b/quantum/tests/unit/linuxbridge/test_lb_quantum_agent.py
new file mode 100644 (file)
index 0000000..30e37cb
--- /dev/null
@@ -0,0 +1,54 @@
+# vim: tabstop=4 shiftwidth=4 softtabstop=4
+
+# Copyright (c) 2012 OpenStack, LLC.
+#
+#    Licensed under the Apache License, Version 2.0 (the "License"); you may
+#    not use this file except in compliance with the License. You may obtain
+#    a copy of the License at
+#
+#         http://www.apache.org/licenses/LICENSE-2.0
+#
+#    Unless required by applicable law or agreed to in writing, software
+#    distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+#    WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+#    License for the specific language governing permissions and limitations
+#    under the License.
+
+import mock
+import unittest2 as unittest
+
+from quantum.openstack.common import cfg
+from quantum.plugins.linuxbridge.agent import linuxbridge_quantum_agent
+from quantum.plugins.linuxbridge.common import config
+from quantum.plugins.linuxbridge.common import constants as lconst
+
+
+class TestLinuxBridge(unittest.TestCase):
+
+    def setUp(self):
+        self.addCleanup(cfg.CONF.reset)
+        interface_mappings = {'physnet1': 'eth1'}
+        root_helper = cfg.CONF.AGENT.root_helper
+
+        self.linux_bridge = linuxbridge_quantum_agent.LinuxBridge(
+            interface_mappings, root_helper)
+
+    def test_ensure_physical_in_bridge_invalid(self):
+        result = self.linux_bridge.ensure_physical_in_bridge('network_id',
+                                                             'physnetx',
+                                                             7)
+        self.assertFalse(result)
+
+    def test_ensure_physical_in_bridge_flat(self):
+        with mock.patch.object(self.linux_bridge,
+                               'ensure_flat_bridge') as flat_bridge_func:
+            result = self.linux_bridge.ensure_physical_in_bridge(
+                'network_id', 'physnet1', lconst.FLAT_VLAN_ID)
+        self.assertTrue(flat_bridge_func.called)
+
+    def test_ensure_physical_in_bridge_vlan(self):
+        with mock.patch.object(self.linux_bridge,
+                               'ensure_vlan_bridge') as vlan_bridge_func:
+            result = self.linux_bridge.ensure_physical_in_bridge(
+                'network_id', 'physnet1', 7)
+        self.assertTrue(vlan_bridge_func.called)