]> review.fuel-infra Code Review - openstack-build/neutron-build.git/commitdiff
Validate local_ip for linuxbridge-agent
authorNick <skywalker.nick@gmail.com>
Tue, 11 Aug 2015 05:25:10 +0000 (13:25 +0800)
committerNick <skywalker.nick@gmail.com>
Thu, 8 Oct 2015 01:29:50 +0000 (09:29 +0800)
When tunneling is enabled, check the availability
of the IP address in local_ip belonging to the host
interface.

Change-Id: Ic1b893d61d5efef397773cdba3b7418ef70a0417
Closes-Bug: #1483497

neutron/plugins/ml2/drivers/linuxbridge/agent/linuxbridge_neutron_agent.py
neutron/tests/unit/plugins/ml2/drivers/linuxbridge/agent/test_linuxbridge_neutron_agent.py

index 175a81c83f2e9ef9e320cd5b09ede1c5136f95f5..d192bcf5d202ca3414765f809d27a9511920e314 100644 (file)
@@ -87,14 +87,9 @@ class LinuxBridgeManager(object):
         self.local_ip = cfg.CONF.VXLAN.local_ip
         self.vxlan_mode = lconst.VXLAN_NONE
         if cfg.CONF.VXLAN.enable_vxlan:
-            device = self.ip.get_device_by_ip(self.local_ip)
-            if device:
-                self.local_int = device.name
-                self.check_vxlan_support()
-            else:
-                self.local_int = None
-                LOG.warning(_LW('VXLAN is enabled, a valid local_ip '
-                                'must be provided'))
+            device = self.get_local_ip_device(self.local_ip)
+            self.local_int = device.name
+            self.check_vxlan_support()
         # Store network mapping to segments
         self.network_map = {}
 
@@ -114,6 +109,18 @@ class LinuxBridgeManager(object):
                           {'brq': bridge, 'net': physnet})
                 sys.exit(1)
 
+    def get_local_ip_device(self, local_ip):
+        """Return the device with local_ip on the host."""
+        device = self.ip.get_device_by_ip(local_ip)
+        if not device:
+            LOG.error(_LE("Tunneling cannot be enabled without the local_ip "
+                          "bound to an interface on the host. Please "
+                          "configure local_ip %s on the host interface to "
+                          "be used for tunneling and restart the agent."),
+                      local_ip)
+            sys.exit(1)
+        return device
+
     def interface_exists_on_bridge(self, bridge, interface):
         directory = '/sys/class/net/%s/brif' % bridge
         for filename in os.listdir(directory):
index 2ac4b3870ca55c8ff9834bedf2b50456880ba7f5..2105a131dfb96a17ae4ecbd50852cbcfe8f742f3 100644 (file)
@@ -13,6 +13,7 @@
 #    under the License.
 
 import os
+import sys
 
 import mock
 from oslo_config import cfg
@@ -33,6 +34,8 @@ LOCAL_IP = '192.168.0.33'
 DEVICE_1 = 'tapabcdef01-12'
 BRIDGE_MAPPINGS = {'physnet0': 'br-eth2'}
 INTERFACE_MAPPINGS = {'physnet1': 'eth1'}
+FAKE_DEFAULT_DEV = mock.Mock()
+FAKE_DEFAULT_DEV.name = 'eth1'
 
 
 class FakeIpLinkCommand(object):
@@ -53,9 +56,12 @@ class TestLinuxBridge(base.BaseTestCase):
         bridge_mappings = BRIDGE_MAPPINGS
 
         with mock.patch.object(ip_lib.IPWrapper,
-                               'get_device_by_ip', return_value=None),\
+                               'get_device_by_ip', return_value=FAKE_DEFAULT_DEV),\
                 mock.patch.object(ip_lib, 'device_exists',
-                                  return_value=True):
+                                  return_value=True),\
+                mock.patch.object(
+                    linuxbridge_neutron_agent.LinuxBridgeManager,
+                    'check_vxlan_support'):
             self.linux_bridge = linuxbridge_neutron_agent.LinuxBridgeManager(
                 bridge_mappings, interface_mappings)
 
@@ -108,10 +114,14 @@ class TestLinuxBridgeAgent(base.BaseTestCase):
         self.get_mac = self.get_mac_p.start()
         self.get_mac.return_value = '00:00:00:00:00:01'
         with mock.patch.object(ip_lib.IPWrapper,
-                               'get_device_by_ip', return_value=None):
+                               'get_device_by_ip',
+                               return_value=FAKE_DEFAULT_DEV):
             self.agent = linuxbridge_neutron_agent.LinuxBridgeNeutronAgentRPC(
                 {}, {}, 0, cfg.CONF.AGENT.quitting_rpc_timeout)
-            with mock.patch.object(self.agent, "daemon_loop"):
+            with mock.patch.object(self.agent, "daemon_loop"),\
+                    mock.patch.object(
+                        linuxbridge_neutron_agent.LinuxBridgeManager,
+                        'check_vxlan_support'):
                 self.agent.start()
 
     def test_treat_devices_removed_with_existed_device(self):
@@ -363,12 +373,34 @@ class TestLinuxBridgeManager(base.BaseTestCase):
         self.bridge_mappings = BRIDGE_MAPPINGS
 
         with mock.patch.object(ip_lib.IPWrapper,
-                               'get_device_by_ip', return_value=None),\
+                               'get_device_by_ip',
+                               return_value=FAKE_DEFAULT_DEV),\
                 mock.patch.object(ip_lib, 'device_exists',
-                                  return_value=True):
+                                  return_value=True),\
+                mock.patch.object(
+                    linuxbridge_neutron_agent.LinuxBridgeManager,
+                    'check_vxlan_support'):
             self.lbm = linuxbridge_neutron_agent.LinuxBridgeManager(
                 self.bridge_mappings, self.interface_mappings)
 
+    def test_local_ip_validation_with_valid_ip(self):
+        with mock.patch.object(ip_lib.IPWrapper,
+                               'get_device_by_ip',
+                               return_value=FAKE_DEFAULT_DEV):
+            result = self.lbm.get_local_ip_device(LOCAL_IP)
+            self.assertEqual(FAKE_DEFAULT_DEV, result)
+
+    def test_local_ip_validation_with_invalid_ip(self):
+        with mock.patch.object(ip_lib.IPWrapper,
+                               'get_device_by_ip',
+                               return_value=None),\
+                mock.patch.object(sys, 'exit') as exit,\
+                mock.patch.object(linuxbridge_neutron_agent.LOG,
+                                  'error') as log:
+            self.lbm.get_local_ip_device(LOCAL_IP)
+            self.assertEqual(1, log.call_count)
+            exit.assert_called_once_with(1)
+
     def test_interface_exists_on_bridge(self):
         with mock.patch.object(os, 'listdir') as listdir_fn:
             listdir_fn.return_value = ["abc"]
@@ -844,7 +876,11 @@ class TestLinuxBridgeManager(base.BaseTestCase):
         bridge_mappings = {}
         interface_mappings = {}
         with mock.patch.object(ip_lib.IPWrapper,
-                               'get_device_by_ip', return_value=None):
+                               'get_device_by_ip',
+                               return_value=FAKE_DEFAULT_DEV),\
+                mock.patch.object(
+                    linuxbridge_neutron_agent.LinuxBridgeManager,
+                    'check_vxlan_support'):
             lbm = linuxbridge_neutron_agent.LinuxBridgeManager(
                 bridge_mappings, interface_mappings)
 
@@ -1047,9 +1083,12 @@ class TestLinuxBridgeRpcCallbacks(base.BaseTestCase):
                 self.agent_id = 1
                 with mock.patch.object(
                         ip_lib.IPWrapper,
-                        'get_device_by_ip', return_value=None),\
-                    mock.patch.object(ip_lib, 'device_exists',
-                                      return_value=True):
+                        'get_device_by_ip', return_value=FAKE_DEFAULT_DEV),\
+                        mock.patch.object(ip_lib, 'device_exists',
+                                          return_value=True),\
+                        mock.patch.object(
+                            linuxbridge_neutron_agent.LinuxBridgeManager,
+                            'check_vxlan_support'):
                     self.br_mgr = (
                         linuxbridge_neutron_agent.LinuxBridgeManager(
                                    BRIDGE_MAPPINGS,