From: Nick Date: Tue, 11 Aug 2015 05:25:10 +0000 (+0800) Subject: Validate local_ip for linuxbridge-agent X-Git-Url: https://review.fuel-infra.org/gitweb?a=commitdiff_plain;h=0b6cc6e667cbbd9c668bf60aee1220836d06c866;p=openstack-build%2Fneutron-build.git Validate local_ip for linuxbridge-agent 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 --- diff --git a/neutron/plugins/ml2/drivers/linuxbridge/agent/linuxbridge_neutron_agent.py b/neutron/plugins/ml2/drivers/linuxbridge/agent/linuxbridge_neutron_agent.py index 175a81c83..d192bcf5d 100644 --- a/neutron/plugins/ml2/drivers/linuxbridge/agent/linuxbridge_neutron_agent.py +++ b/neutron/plugins/ml2/drivers/linuxbridge/agent/linuxbridge_neutron_agent.py @@ -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): diff --git a/neutron/tests/unit/plugins/ml2/drivers/linuxbridge/agent/test_linuxbridge_neutron_agent.py b/neutron/tests/unit/plugins/ml2/drivers/linuxbridge/agent/test_linuxbridge_neutron_agent.py index 2ac4b3870..2105a131d 100644 --- a/neutron/tests/unit/plugins/ml2/drivers/linuxbridge/agent/test_linuxbridge_neutron_agent.py +++ b/neutron/tests/unit/plugins/ml2/drivers/linuxbridge/agent/test_linuxbridge_neutron_agent.py @@ -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,