Teach DHCP Agent about DVR router interfaces
When DVR is enabled and enable_isolated_metadata=True, the DHCP agent should only inject a metadata host route when there is no port with the gateway IP address configured on the subnet. Add a check for DEVICE_OWNER_DVR_INTERFACE when we look at each port's device_owner field, otherwise it will always add this route to the opts file when DVR is enabled. Change-Id: I3ff3bb85105b8215b36535983016d8c0ff3d8cb7 Closes-bug: #1377307
This commit is contained in:
parent
161aa37bca
commit
88d572e4d9
@ -730,7 +730,8 @@ class Dnsmasq(DhcpLocalProcess):
|
||||
subnets = dict((subnet.id, subnet) for subnet in network.subnets)
|
||||
|
||||
for port in network.ports:
|
||||
if port.device_owner != constants.DEVICE_OWNER_ROUTER_INTF:
|
||||
if port.device_owner not in (constants.DEVICE_OWNER_ROUTER_INTF,
|
||||
constants.DEVICE_OWNER_DVR_INTERFACE):
|
||||
continue
|
||||
for alloc in port.fixed_ips:
|
||||
if subnets[alloc.subnet_id].gateway_ip == alloc.ip_address:
|
||||
|
@ -72,6 +72,8 @@ fake_meta_subnet = dhcp.DictModel(dict(id='bbbbbbbb-1111-2222-bbbbbbbbbbbb',
|
||||
|
||||
fake_fixed_ip1 = dhcp.DictModel(dict(id='', subnet_id=fake_subnet1.id,
|
||||
ip_address='172.9.9.9'))
|
||||
fake_fixed_ip2 = dhcp.DictModel(dict(id='', subnet_id=fake_subnet1.id,
|
||||
ip_address='172.9.9.10'))
|
||||
fake_meta_fixed_ip = dhcp.DictModel(dict(id='', subnet=fake_meta_subnet,
|
||||
ip_address='169.254.169.254'))
|
||||
fake_allocation_pool_subnet1 = dhcp.DictModel(dict(id='', start='172.9.9.2',
|
||||
@ -89,7 +91,7 @@ fake_port2 = dhcp.DictModel(dict(id='12345678-1234-aaaa-123456789000',
|
||||
device_owner='',
|
||||
mac_address='aa:bb:cc:dd:ee:99',
|
||||
network_id='12345678-1234-5678-1234567890ab',
|
||||
fixed_ips=[]))
|
||||
fixed_ips=[fake_fixed_ip2]))
|
||||
|
||||
fake_meta_port = dhcp.DictModel(dict(id='12345678-1234-aaaa-1234567890ab',
|
||||
mac_address='aa:bb:cc:dd:ee:ff',
|
||||
@ -98,6 +100,13 @@ fake_meta_port = dhcp.DictModel(dict(id='12345678-1234-aaaa-1234567890ab',
|
||||
device_id='forzanapoli',
|
||||
fixed_ips=[fake_meta_fixed_ip]))
|
||||
|
||||
fake_dist_port = dhcp.DictModel(dict(id='12345678-1234-aaaa-1234567890ab',
|
||||
mac_address='aa:bb:cc:dd:ee:ff',
|
||||
network_id='12345678-1234-5678-1234567890ab',
|
||||
device_owner=const.DEVICE_OWNER_DVR_INTERFACE,
|
||||
device_id='forzanapoli',
|
||||
fixed_ips=[fake_meta_fixed_ip]))
|
||||
|
||||
fake_network = dhcp.NetModel(True, dict(id='12345678-1234-5678-1234567890ab',
|
||||
tenant_id='aaaaaaaa-aaaa-aaaa-aaaaaaaaaaaa',
|
||||
admin_state_up=True,
|
||||
@ -112,6 +121,14 @@ isolated_network = dhcp.NetModel(
|
||||
subnets=[fake_subnet1],
|
||||
ports=[fake_port1]))
|
||||
|
||||
nonisolated_dist_network = dhcp.NetModel(
|
||||
True, dict(
|
||||
id='12345678-1234-5678-1234567890ab',
|
||||
tenant_id='aaaaaaaa-aaaa-aaaa-aaaaaaaaaaaa',
|
||||
admin_state_up=True,
|
||||
subnets=[fake_subnet1],
|
||||
ports=[fake_port1, fake_port2]))
|
||||
|
||||
empty_network = dhcp.NetModel(
|
||||
True, dict(
|
||||
id='12345678-1234-5678-1234567890ab',
|
||||
@ -127,6 +144,13 @@ fake_meta_network = dhcp.NetModel(
|
||||
subnets=[fake_meta_subnet],
|
||||
ports=[fake_meta_port]))
|
||||
|
||||
fake_dist_network = dhcp.NetModel(
|
||||
True, dict(id='12345678-1234-5678-1234567890ab',
|
||||
tenant_id='aaaaaaaa-aaaa-aaaa-aaaaaaaaaaaa',
|
||||
admin_state_up=True,
|
||||
subnets=[fake_meta_subnet],
|
||||
ports=[fake_meta_port, fake_dist_port]))
|
||||
|
||||
fake_down_network = dhcp.NetModel(
|
||||
True, dict(id='12345678-dddd-dddd-1234567890ab',
|
||||
tenant_id='aaaaaaaa-aaaa-aaaa-aaaaaaaaaaaa',
|
||||
@ -540,13 +564,26 @@ class TestDhcpAgentEventHandler(base.BaseTestCase):
|
||||
|
||||
def test_enable_dhcp_helper_enable_metadata_nonisolated_network(self):
|
||||
nonisolated_network = copy.deepcopy(isolated_network)
|
||||
nonisolated_network.ports[0].device_owner = "network:router_interface"
|
||||
nonisolated_network.ports[0].device_owner = (
|
||||
const.DEVICE_OWNER_ROUTER_INTF)
|
||||
nonisolated_network.ports[0].fixed_ips[0].ip_address = '172.9.9.1'
|
||||
|
||||
self._enable_dhcp_helper(nonisolated_network,
|
||||
enable_isolated_metadata=True,
|
||||
is_isolated_network=False)
|
||||
|
||||
def test_enable_dhcp_helper_enable_metadata_nonisolated_dist_network(self):
|
||||
nonisolated_dist_network.ports[0].device_owner = (
|
||||
const.DEVICE_OWNER_ROUTER_INTF)
|
||||
nonisolated_dist_network.ports[0].fixed_ips[0].ip_address = '172.9.9.1'
|
||||
nonisolated_dist_network.ports[1].device_owner = (
|
||||
const.DEVICE_OWNER_DVR_INTERFACE)
|
||||
nonisolated_dist_network.ports[1].fixed_ips[0].ip_address = '172.9.9.1'
|
||||
|
||||
self._enable_dhcp_helper(nonisolated_dist_network,
|
||||
enable_isolated_metadata=True,
|
||||
is_isolated_network=False)
|
||||
|
||||
def test_enable_dhcp_helper_enable_metadata_empty_network(self):
|
||||
self._enable_dhcp_helper(empty_network,
|
||||
enable_isolated_metadata=True,
|
||||
@ -685,7 +722,7 @@ class TestDhcpAgentEventHandler(base.BaseTestCase):
|
||||
mock.call().disable()
|
||||
])
|
||||
|
||||
def test_enable_isolated_metadata_proxy_with_metadata_network(self):
|
||||
def _test_metadata_network(self, network):
|
||||
cfg.CONF.set_override('enable_metadata_network', True)
|
||||
cfg.CONF.set_override('debug', True)
|
||||
cfg.CONF.set_override('verbose', False)
|
||||
@ -695,7 +732,7 @@ class TestDhcpAgentEventHandler(base.BaseTestCase):
|
||||
# Ensure the mock is restored if this test fail
|
||||
try:
|
||||
with mock.patch(class_path) as ip_wrapper:
|
||||
self.dhcp.enable_isolated_metadata_proxy(fake_meta_network)
|
||||
self.dhcp.enable_isolated_metadata_proxy(network)
|
||||
ip_wrapper.assert_has_calls([mock.call(
|
||||
'sudo',
|
||||
'qdhcp-12345678-1234-5678-1234567890ab'),
|
||||
@ -708,11 +745,17 @@ class TestDhcpAgentEventHandler(base.BaseTestCase):
|
||||
mock.ANY,
|
||||
'--debug',
|
||||
('--log-file=neutron-ns-metadata-proxy-%s.log' %
|
||||
fake_meta_network.id)], addl_env=None)
|
||||
network.id)], addl_env=None)
|
||||
])
|
||||
finally:
|
||||
self.external_process_p.start()
|
||||
|
||||
def test_enable_isolated_metadata_proxy_with_metadata_network(self):
|
||||
self._test_metadata_network(fake_meta_network)
|
||||
|
||||
def test_enable_isolated_metadata_proxy_with_dist_network(self):
|
||||
self._test_metadata_network(fake_dist_network)
|
||||
|
||||
def test_network_create_end(self):
|
||||
payload = dict(network=dict(id=fake_network.id))
|
||||
|
||||
|
@ -130,8 +130,9 @@ class FakeRouterPort:
|
||||
'dddddddd-dddd-dddd-dddd-dddddddddddd')]
|
||||
mac_address = '00:00:0f:rr:rr:rr'
|
||||
|
||||
def __init__(self):
|
||||
def __init__(self, dev_owner=constants.DEVICE_OWNER_ROUTER_INTF):
|
||||
self.extra_dhcp_opts = []
|
||||
self.device_owner = dev_owner
|
||||
|
||||
|
||||
class FakePortMultipleAgents1:
|
||||
@ -341,6 +342,13 @@ class FakeV4NetworkNoRouter:
|
||||
ports = [FakePort1()]
|
||||
|
||||
|
||||
class FakeV4NetworkDistRouter:
|
||||
id = 'cccccccc-cccc-cccc-cccc-cccccccccccc'
|
||||
subnets = [FakeV4Subnet()]
|
||||
ports = [FakePort1(),
|
||||
FakeRouterPort(dev_owner=constants.DEVICE_OWNER_DVR_INTERFACE)]
|
||||
|
||||
|
||||
class FakeDualV4Pxe3Ports:
|
||||
id = 'cccccccc-cccc-cccc-cccc-cccccccccccc'
|
||||
subnets = [FakeV4Subnet(), FakeV4SubnetNoDHCP()]
|
||||
@ -962,6 +970,26 @@ tag:tag0,option:router""".lstrip()
|
||||
|
||||
self.safe.assert_called_once_with('/foo/opts', expected)
|
||||
|
||||
def test_output_opts_file_dist_neutron_router_on_subnet(self):
|
||||
expected = (
|
||||
'tag:tag0,option:dns-server,8.8.8.8\n'
|
||||
'tag:tag0,option:classless-static-route,20.0.0.1/24,20.0.0.1,'
|
||||
'0.0.0.0/0,192.168.0.1\n'
|
||||
'tag:tag0,249,20.0.0.1/24,20.0.0.1,0.0.0.0/0,192.168.0.1\n'
|
||||
'tag:tag0,option:router,192.168.0.1').lstrip()
|
||||
|
||||
with mock.patch.object(dhcp.Dnsmasq, 'get_conf_file_name') as conf_fn:
|
||||
conf_fn.return_value = '/foo/opts'
|
||||
dm = dhcp.Dnsmasq(self.conf, FakeV4NetworkDistRouter(),
|
||||
version=dhcp.Dnsmasq.MINIMUM_VERSION)
|
||||
with mock.patch.object(dm, '_make_subnet_interface_ip_map') as ipm:
|
||||
ipm.return_value = {FakeV4Subnet.id: '192.168.0.1'}
|
||||
|
||||
dm._output_opts_file()
|
||||
self.assertTrue(ipm.called)
|
||||
|
||||
self.safe.assert_called_once_with('/foo/opts', expected)
|
||||
|
||||
def test_output_opts_file_pxe_2port_1net(self):
|
||||
expected = (
|
||||
'tag:tag0,option:dns-server,8.8.8.8\n'
|
||||
|
Loading…
Reference in New Issue
Block a user