Fix lack of routes for neighbour IPv4 subnets
According to [1], when a network contains more that one IPv4 subnet, they are returned in the 'classless-static-routes' DHCP option, regardless of whether DHCP is enabled for them or not. However, the get_active_networks_info() method used for synchronizing networks after the dhcp agent restarts filters subnets with "enable_dhcp=True", which differs from the get_network_info() method. This will block VM access to other VMs in the dhcp disabled subnets, even though they are in the same network. This is visible by looking at the "opts" file before and after a restart. Change the dhcp agent to ask for all subnets in its get_active_networks_info() RPC call by adding an enable_dhcp_filter argument to toggle the behavior, with the default being True to not break backwards compatibility. Based on https://review.openstack.org/#/c/352530/ by Quan Tian. [1] https://review.openstack.org/#/c/125043/ Change-Id: I11ca1d1a603d02587f3b8d4a5a52a96b0587d61f Closes-Bug: #1652654
This commit is contained in:
parent
2b11c8a054
commit
2e34279ec3
@ -186,7 +186,8 @@ class DhcpAgent(manager.Manager):
|
|||||||
known_network_ids = set(self.cache.get_network_ids())
|
known_network_ids = set(self.cache.get_network_ids())
|
||||||
|
|
||||||
try:
|
try:
|
||||||
active_networks = self.plugin_rpc.get_active_networks_info()
|
active_networks = self.plugin_rpc.get_active_networks_info(
|
||||||
|
enable_dhcp_filter=False)
|
||||||
LOG.info('All active networks have been fetched through RPC.')
|
LOG.info('All active networks have been fetched through RPC.')
|
||||||
active_network_ids = set(network.id for network in active_networks)
|
active_network_ids = set(network.id for network in active_networks)
|
||||||
for deleted_id in known_network_ids - active_network_ids:
|
for deleted_id in known_network_ids - active_network_ids:
|
||||||
@ -567,11 +568,11 @@ class DhcpPluginApi(object):
|
|||||||
# can be independently tracked server side.
|
# can be independently tracked server side.
|
||||||
return context.get_admin_context_without_session()
|
return context.get_admin_context_without_session()
|
||||||
|
|
||||||
def get_active_networks_info(self):
|
def get_active_networks_info(self, **kwargs):
|
||||||
"""Make a remote process call to retrieve all network info."""
|
"""Make a remote process call to retrieve all network info."""
|
||||||
cctxt = self.client.prepare(version='1.1')
|
cctxt = self.client.prepare(version='1.1')
|
||||||
networks = cctxt.call(self.context, 'get_active_networks_info',
|
networks = cctxt.call(self.context, 'get_active_networks_info',
|
||||||
host=self.host)
|
host=self.host, **kwargs)
|
||||||
return [dhcp.NetModel(n) for n in networks]
|
return [dhcp.NetModel(n) for n in networks]
|
||||||
|
|
||||||
def get_network_info(self, network_id):
|
def get_network_info(self, network_id):
|
||||||
|
@ -144,6 +144,8 @@ class DhcpRpcCallback(object):
|
|||||||
plugin = directory.get_plugin()
|
plugin = directory.get_plugin()
|
||||||
filters = {'network_id': [network['id'] for network in networks]}
|
filters = {'network_id': [network['id'] for network in networks]}
|
||||||
ports = plugin.get_ports(context, filters=filters)
|
ports = plugin.get_ports(context, filters=filters)
|
||||||
|
# default is to filter subnets based on 'enable_dhcp' flag
|
||||||
|
if kwargs.get('enable_dhcp_filter', True):
|
||||||
filters['enable_dhcp'] = [True]
|
filters['enable_dhcp'] = [True]
|
||||||
# NOTE(kevinbenton): we sort these because the agent builds tags
|
# NOTE(kevinbenton): we sort these because the agent builds tags
|
||||||
# based on position in the list and has to restart the process if
|
# based on position in the list and has to restart the process if
|
||||||
|
@ -97,6 +97,24 @@ class TestDhcpRpcCallback(base.BaseTestCase):
|
|||||||
'ports': []}]
|
'ports': []}]
|
||||||
self.assertEqual(expected, networks)
|
self.assertEqual(expected, networks)
|
||||||
|
|
||||||
|
def _test_get_active_networks_info_enable_dhcp_filter(self,
|
||||||
|
enable_dhcp_filter):
|
||||||
|
plugin_retval = [{'id': 'a'}, {'id': 'b'}]
|
||||||
|
self.plugin.get_networks.return_value = plugin_retval
|
||||||
|
self.callbacks.get_active_networks_info(mock.Mock(), host='host',
|
||||||
|
enable_dhcp_filter=enable_dhcp_filter)
|
||||||
|
filters = {'network_id': ['a', 'b']}
|
||||||
|
if enable_dhcp_filter:
|
||||||
|
filters['enable_dhcp'] = [True]
|
||||||
|
self.plugin.get_subnets.assert_called_once_with(mock.ANY,
|
||||||
|
filters=filters)
|
||||||
|
|
||||||
|
def test_get_active_networks_info_enable_dhcp_filter_false(self):
|
||||||
|
self._test_get_active_networks_info_enable_dhcp_filter(False)
|
||||||
|
|
||||||
|
def test_get_active_networks_info_enable_dhcp_filter_true(self):
|
||||||
|
self._test_get_active_networks_info_enable_dhcp_filter(True)
|
||||||
|
|
||||||
def _test__port_action_with_failures(self, exc=None, action=None):
|
def _test__port_action_with_failures(self, exc=None, action=None):
|
||||||
port = {
|
port = {
|
||||||
'network_id': 'foo_network_id',
|
'network_id': 'foo_network_id',
|
||||||
|
Loading…
Reference in New Issue
Block a user