From 4f4fef9c2129fba14c38ac0e9414b5bead7d593a Mon Sep 17 00:00:00 2001 From: LipingMao Date: Mon, 31 Mar 2014 05:49:18 +0000 Subject: [PATCH] lbaas on a network without gateway Not only check the gateway_ip in subnet, but also check the host_routes. If there is a default route in host_routes then the next hop of the default route is also a gateway_ip. Closes-Bug: 1300017 DocImpact Change-Id: Id3ae04bfa6cefb1c030857894f0594828b8e856d --- .../drivers/haproxy/namespace_driver.py | 8 ++++ .../drivers/haproxy/test_namespace_driver.py | 37 +++++++++++++++++++ 2 files changed, 45 insertions(+) diff --git a/neutron/services/loadbalancer/drivers/haproxy/namespace_driver.py b/neutron/services/loadbalancer/drivers/haproxy/namespace_driver.py index 6bbe4f6b8..e07f814d4 100644 --- a/neutron/services/loadbalancer/drivers/haproxy/namespace_driver.py +++ b/neutron/services/loadbalancer/drivers/haproxy/namespace_driver.py @@ -257,6 +257,14 @@ class HaproxyNSDriver(agent_device_driver.AgentDeviceDriver): self.vif_driver.init_l3(interface_name, cidrs, namespace=namespace) gw_ip = port['fixed_ips'][0]['subnet'].get('gateway_ip') + + if not gw_ip: + host_routes = port['fixed_ips'][0]['subnet'].get('host_routes', []) + for host_route in host_routes: + if host_route['destination'] == "0.0.0.0/0": + gw_ip = host_route['nexthop'] + break + if gw_ip: cmd = ['route', 'add', 'default', 'gw', gw_ip] ip_wrapper = ip_lib.IPWrapper(self.root_helper, diff --git a/neutron/tests/unit/services/loadbalancer/drivers/haproxy/test_namespace_driver.py b/neutron/tests/unit/services/loadbalancer/drivers/haproxy/test_namespace_driver.py index 6d96bd550..e328212d1 100644 --- a/neutron/tests/unit/services/loadbalancer/drivers/haproxy/test_namespace_driver.py +++ b/neutron/tests/unit/services/loadbalancer/drivers/haproxy/test_namespace_driver.py @@ -322,6 +322,43 @@ class TestHaproxyNSDriver(base.BaseTestCase): self.assertRaises(exceptions.PreexistingDeviceFailure, self.driver._plug, 'test_ns', test_port, False) + def test_plug_gw_in_host_routes(self): + test_port = {'id': 'port_id', + 'network_id': 'net_id', + 'mac_address': 'mac_addr', + 'fixed_ips': [{'ip_address': '10.0.0.2', + 'subnet': {'cidr': '10.0.0.0/24', + 'host_routes': + [{'destination': '0.0.0.0/0', + 'nexthop': '10.0.0.1'}]}}]} + with contextlib.nested( + mock.patch('neutron.agent.linux.ip_lib.device_exists'), + mock.patch('netaddr.IPNetwork'), + mock.patch('neutron.agent.linux.ip_lib.IPWrapper'), + ) as (dev_exists, ip_net, ip_wrap): + self.vif_driver.get_device_name.return_value = 'test_interface' + dev_exists.return_value = False + ip_net.return_value = ip_net + ip_net.prefixlen = 24 + + self.driver._plug('test_ns', test_port) + self.rpc_mock.plug_vip_port.assert_called_once_with( + test_port['id']) + self.assertTrue(dev_exists.called) + self.vif_driver.plug.assert_called_once_with('net_id', 'port_id', + 'test_interface', + 'mac_addr', + namespace='test_ns') + self.vif_driver.init_l3.assert_called_once_with('test_interface', + ['10.0.0.2/24'], + namespace= + 'test_ns') + cmd = ['route', 'add', 'default', 'gw', '10.0.0.1'] + ip_wrap.assert_has_calls([ + mock.call('sudo_test', namespace='test_ns'), + mock.call().netns.execute(cmd, check_exit_code=False), + ]) + def test_unplug(self): self.vif_driver.get_device_name.return_value = 'test_interface' -- 2.45.2