]> review.fuel-infra Code Review - openstack-build/neutron-build.git/commitdiff
Validate interface_mappings on Linux bridge init
authorKevin Benton <blak111@gmail.com>
Thu, 30 Jul 2015 00:28:50 +0000 (17:28 -0700)
committerKevin Benton <blak111@gmail.com>
Wed, 5 Aug 2015 20:41:35 +0000 (13:41 -0700)
Verify that the interfaces actually exist that are defined in
interface_mappings on Linux bridge startup. If they do not, exit
immediately similar to how OVS handles incorrect bridge_mappings.

This prevents an unfriendly exception in the rpc setup routine.

Change-Id: I050b9b66aa0b27f148e67123eedf29fe332e6f65
Closes-Bug: #1470584

neutron/plugins/ml2/drivers/linuxbridge/agent/linuxbridge_neutron_agent.py
neutron/tests/functional/agent/linux/test_ip_lib.py
neutron/tests/functional/agent/test_l2_lb_agent.py [new file with mode: 0644]
neutron/tests/unit/plugins/ml2/drivers/linuxbridge/agent/test_linuxbridge_neutron_agent.py

index b9747a4ec04073945d4667c9f86bc91f806a26ab..4d5c596db13a1159257b360c38a9f46263e838f1 100644 (file)
@@ -77,6 +77,7 @@ class NetworkSegment(object):
 class LinuxBridgeManager(object):
     def __init__(self, interface_mappings):
         self.interface_mappings = interface_mappings
+        self.validate_interface_mappings()
         self.ip = ip_lib.IPWrapper()
         # VXLAN related parameters:
         self.local_ip = cfg.CONF.VXLAN.local_ip
@@ -93,6 +94,14 @@ class LinuxBridgeManager(object):
         # Store network mapping to segments
         self.network_map = {}
 
+    def validate_interface_mappings(self):
+        for physnet, interface in self.interface_mappings.items():
+            if not ip_lib.device_exists(interface):
+                LOG.error(_LE("Interface %(intf)s for physical network %(net)s"
+                              " does not exist. Agent terminated!"),
+                          {'intf': interface, 'net': physnet})
+                sys.exit(1)
+
     def interface_exists_on_bridge(self, bridge, interface):
         directory = '/sys/class/net/%s/brif' % bridge
         for filename in os.listdir(directory):
index 8804599ec5bad97dfca6ff649eef32a01c2337aa..dce36a47fca03925c51098c48c73f8ceebde09e1 100644 (file)
@@ -73,8 +73,9 @@ class IpLibTestFramework(functional_base.BaseSudoTestCase):
         :return: A tuntap ip_lib.IPDevice
         """
         ip = ip_lib.IPWrapper(namespace=attr.namespace)
-        ip.netns.add(attr.namespace)
-        self.addCleanup(ip.netns.delete, attr.namespace)
+        if attr.namespace:
+            ip.netns.add(attr.namespace)
+            self.addCleanup(ip.netns.delete, attr.namespace)
         tap_device = ip.add_tuntap(attr.name)
         self.addCleanup(self._safe_delete_device, tap_device)
         tap_device.link.set_address(attr.mac_address)
diff --git a/neutron/tests/functional/agent/test_l2_lb_agent.py b/neutron/tests/functional/agent/test_l2_lb_agent.py
new file mode 100644 (file)
index 0000000..32ea6c5
--- /dev/null
@@ -0,0 +1,47 @@
+# All Rights Reserved.
+#
+#    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
+from oslo_log import log as logging
+import testtools
+
+from neutron.plugins.ml2.drivers.linuxbridge.agent import \
+    linuxbridge_neutron_agent
+from neutron.tests.functional.agent.linux import test_ip_lib
+
+LOG = logging.getLogger(__name__)
+lba = linuxbridge_neutron_agent
+
+
+class LinuxBridgeAgentTests(test_ip_lib.IpLibTestFramework):
+
+    def setUp(self):
+        super(LinuxBridgeAgentTests, self).setUp()
+        agent_rpc = ('neutron.agent.rpc.PluginApi')
+        mock.patch(agent_rpc).start()
+        mock.patch('neutron.agent.rpc.PluginReportStateAPI').start()
+
+    def test_validate_interface_mappings(self):
+        mappings = {'physnet1': 'int1', 'physnet2': 'int2'}
+        with testtools.ExpectedException(SystemExit):
+            lba.LinuxBridgeManager(mappings)
+        self.manage_device(
+            self.generate_device_details()._replace(namespace=None,
+                                                    name='int1'))
+        with testtools.ExpectedException(SystemExit):
+            lba.LinuxBridgeManager(mappings)
+        self.manage_device(
+            self.generate_device_details()._replace(namespace=None,
+                                                    name='int2'))
+        lba.LinuxBridgeManager(mappings)
index 55b9bd821b4ce6f0ddb41c6652a5733a8e23cb0d..5673958958b11b1a222a53a69ac8c129457c04a1 100644 (file)
@@ -50,7 +50,9 @@ class TestLinuxBridge(base.BaseTestCase):
         interface_mappings = {'physnet1': 'eth1'}
 
         with mock.patch.object(ip_lib.IPWrapper,
-                               'get_device_by_ip', return_value=None):
+                               'get_device_by_ip', return_value=None),\
+                mock.patch.object(ip_lib, 'device_exists',
+                                  return_value=True):
             self.linux_bridge = linuxbridge_neutron_agent.LinuxBridgeManager(
                 interface_mappings)
 
@@ -355,7 +357,9 @@ class TestLinuxBridgeManager(base.BaseTestCase):
         self.interface_mappings = {'physnet1': 'eth1'}
 
         with mock.patch.object(ip_lib.IPWrapper,
-                               'get_device_by_ip', return_value=None):
+                               'get_device_by_ip', return_value=None),\
+                mock.patch.object(ip_lib, 'device_exists',
+                                  return_value=True):
             self.lbm = linuxbridge_neutron_agent.LinuxBridgeManager(
                 self.interface_mappings)
 
@@ -935,7 +939,9 @@ class TestLinuxBridgeRpcCallbacks(base.BaseTestCase):
                 self.agent_id = 1
                 with mock.patch.object(
                         ip_lib.IPWrapper,
-                        'get_device_by_ip', return_value=None):
+                        'get_device_by_ip', return_value=None),\
+                    mock.patch.object(ip_lib, 'device_exists',
+                                      return_value=True):
                     self.br_mgr = (linuxbridge_neutron_agent.
                                    LinuxBridgeManager({'physnet1': 'eth1'}))