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)
|
subnets = dict((subnet.id, subnet) for subnet in network.subnets)
|
||||||
|
|
||||||
for port in network.ports:
|
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
|
continue
|
||||||
for alloc in port.fixed_ips:
|
for alloc in port.fixed_ips:
|
||||||
if subnets[alloc.subnet_id].gateway_ip == alloc.ip_address:
|
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,
|
fake_fixed_ip1 = dhcp.DictModel(dict(id='', subnet_id=fake_subnet1.id,
|
||||||
ip_address='172.9.9.9'))
|
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,
|
fake_meta_fixed_ip = dhcp.DictModel(dict(id='', subnet=fake_meta_subnet,
|
||||||
ip_address='169.254.169.254'))
|
ip_address='169.254.169.254'))
|
||||||
fake_allocation_pool_subnet1 = dhcp.DictModel(dict(id='', start='172.9.9.2',
|
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='',
|
device_owner='',
|
||||||
mac_address='aa:bb:cc:dd:ee:99',
|
mac_address='aa:bb:cc:dd:ee:99',
|
||||||
network_id='12345678-1234-5678-1234567890ab',
|
network_id='12345678-1234-5678-1234567890ab',
|
||||||
fixed_ips=[]))
|
fixed_ips=[fake_fixed_ip2]))
|
||||||
|
|
||||||
fake_meta_port = dhcp.DictModel(dict(id='12345678-1234-aaaa-1234567890ab',
|
fake_meta_port = dhcp.DictModel(dict(id='12345678-1234-aaaa-1234567890ab',
|
||||||
mac_address='aa:bb:cc:dd:ee:ff',
|
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',
|
device_id='forzanapoli',
|
||||||
fixed_ips=[fake_meta_fixed_ip]))
|
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',
|
fake_network = dhcp.NetModel(True, dict(id='12345678-1234-5678-1234567890ab',
|
||||||
tenant_id='aaaaaaaa-aaaa-aaaa-aaaaaaaaaaaa',
|
tenant_id='aaaaaaaa-aaaa-aaaa-aaaaaaaaaaaa',
|
||||||
admin_state_up=True,
|
admin_state_up=True,
|
||||||
@ -112,6 +121,14 @@ isolated_network = dhcp.NetModel(
|
|||||||
subnets=[fake_subnet1],
|
subnets=[fake_subnet1],
|
||||||
ports=[fake_port1]))
|
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(
|
empty_network = dhcp.NetModel(
|
||||||
True, dict(
|
True, dict(
|
||||||
id='12345678-1234-5678-1234567890ab',
|
id='12345678-1234-5678-1234567890ab',
|
||||||
@ -127,6 +144,13 @@ fake_meta_network = dhcp.NetModel(
|
|||||||
subnets=[fake_meta_subnet],
|
subnets=[fake_meta_subnet],
|
||||||
ports=[fake_meta_port]))
|
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(
|
fake_down_network = dhcp.NetModel(
|
||||||
True, dict(id='12345678-dddd-dddd-1234567890ab',
|
True, dict(id='12345678-dddd-dddd-1234567890ab',
|
||||||
tenant_id='aaaaaaaa-aaaa-aaaa-aaaaaaaaaaaa',
|
tenant_id='aaaaaaaa-aaaa-aaaa-aaaaaaaaaaaa',
|
||||||
@ -540,13 +564,26 @@ class TestDhcpAgentEventHandler(base.BaseTestCase):
|
|||||||
|
|
||||||
def test_enable_dhcp_helper_enable_metadata_nonisolated_network(self):
|
def test_enable_dhcp_helper_enable_metadata_nonisolated_network(self):
|
||||||
nonisolated_network = copy.deepcopy(isolated_network)
|
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'
|
nonisolated_network.ports[0].fixed_ips[0].ip_address = '172.9.9.1'
|
||||||
|
|
||||||
self._enable_dhcp_helper(nonisolated_network,
|
self._enable_dhcp_helper(nonisolated_network,
|
||||||
enable_isolated_metadata=True,
|
enable_isolated_metadata=True,
|
||||||
is_isolated_network=False)
|
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):
|
def test_enable_dhcp_helper_enable_metadata_empty_network(self):
|
||||||
self._enable_dhcp_helper(empty_network,
|
self._enable_dhcp_helper(empty_network,
|
||||||
enable_isolated_metadata=True,
|
enable_isolated_metadata=True,
|
||||||
@ -685,7 +722,7 @@ class TestDhcpAgentEventHandler(base.BaseTestCase):
|
|||||||
mock.call().disable()
|
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('enable_metadata_network', True)
|
||||||
cfg.CONF.set_override('debug', True)
|
cfg.CONF.set_override('debug', True)
|
||||||
cfg.CONF.set_override('verbose', False)
|
cfg.CONF.set_override('verbose', False)
|
||||||
@ -695,7 +732,7 @@ class TestDhcpAgentEventHandler(base.BaseTestCase):
|
|||||||
# Ensure the mock is restored if this test fail
|
# Ensure the mock is restored if this test fail
|
||||||
try:
|
try:
|
||||||
with mock.patch(class_path) as ip_wrapper:
|
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(
|
ip_wrapper.assert_has_calls([mock.call(
|
||||||
'sudo',
|
'sudo',
|
||||||
'qdhcp-12345678-1234-5678-1234567890ab'),
|
'qdhcp-12345678-1234-5678-1234567890ab'),
|
||||||
@ -708,11 +745,17 @@ class TestDhcpAgentEventHandler(base.BaseTestCase):
|
|||||||
mock.ANY,
|
mock.ANY,
|
||||||
'--debug',
|
'--debug',
|
||||||
('--log-file=neutron-ns-metadata-proxy-%s.log' %
|
('--log-file=neutron-ns-metadata-proxy-%s.log' %
|
||||||
fake_meta_network.id)], addl_env=None)
|
network.id)], addl_env=None)
|
||||||
])
|
])
|
||||||
finally:
|
finally:
|
||||||
self.external_process_p.start()
|
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):
|
def test_network_create_end(self):
|
||||||
payload = dict(network=dict(id=fake_network.id))
|
payload = dict(network=dict(id=fake_network.id))
|
||||||
|
|
||||||
|
@ -130,8 +130,9 @@ class FakeRouterPort:
|
|||||||
'dddddddd-dddd-dddd-dddd-dddddddddddd')]
|
'dddddddd-dddd-dddd-dddd-dddddddddddd')]
|
||||||
mac_address = '00:00:0f:rr:rr:rr'
|
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.extra_dhcp_opts = []
|
||||||
|
self.device_owner = dev_owner
|
||||||
|
|
||||||
|
|
||||||
class FakePortMultipleAgents1:
|
class FakePortMultipleAgents1:
|
||||||
@ -341,6 +342,13 @@ class FakeV4NetworkNoRouter:
|
|||||||
ports = [FakePort1()]
|
ports = [FakePort1()]
|
||||||
|
|
||||||
|
|
||||||
|
class FakeV4NetworkDistRouter:
|
||||||
|
id = 'cccccccc-cccc-cccc-cccc-cccccccccccc'
|
||||||
|
subnets = [FakeV4Subnet()]
|
||||||
|
ports = [FakePort1(),
|
||||||
|
FakeRouterPort(dev_owner=constants.DEVICE_OWNER_DVR_INTERFACE)]
|
||||||
|
|
||||||
|
|
||||||
class FakeDualV4Pxe3Ports:
|
class FakeDualV4Pxe3Ports:
|
||||||
id = 'cccccccc-cccc-cccc-cccc-cccccccccccc'
|
id = 'cccccccc-cccc-cccc-cccc-cccccccccccc'
|
||||||
subnets = [FakeV4Subnet(), FakeV4SubnetNoDHCP()]
|
subnets = [FakeV4Subnet(), FakeV4SubnetNoDHCP()]
|
||||||
@ -962,6 +970,26 @@ tag:tag0,option:router""".lstrip()
|
|||||||
|
|
||||||
self.safe.assert_called_once_with('/foo/opts', expected)
|
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):
|
def test_output_opts_file_pxe_2port_1net(self):
|
||||||
expected = (
|
expected = (
|
||||||
'tag:tag0,option:dns-server,8.8.8.8\n'
|
'tag:tag0,option:dns-server,8.8.8.8\n'
|
||||||
|
Loading…
Reference in New Issue
Block a user