Merge "[DVR] Send allowed address pairs info to the L3 agents" into stable/victoria
This commit is contained in:
commit
d63396fddd
|
@ -327,6 +327,13 @@ class DvrLocalRouter(dvr_router_base.DvrRouterBase):
|
||||||
'add',
|
'add',
|
||||||
device=device,
|
device=device,
|
||||||
device_exists=device_exists)
|
device_exists=device_exists)
|
||||||
|
for allowed_address_pair in p.get('allowed_address_pairs', []):
|
||||||
|
self._update_arp_entry(allowed_address_pair['ip_address'],
|
||||||
|
allowed_address_pair['mac_address'],
|
||||||
|
subnet_id,
|
||||||
|
'add',
|
||||||
|
device=device,
|
||||||
|
device_exists=device_exists)
|
||||||
self._process_arp_cache_for_internal_port(subnet_id)
|
self._process_arp_cache_for_internal_port(subnet_id)
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
|
|
|
@ -12,6 +12,7 @@
|
||||||
# License for the specific language governing permissions and limitations
|
# License for the specific language governing permissions and limitations
|
||||||
# under the License.
|
# under the License.
|
||||||
#
|
#
|
||||||
|
import collections
|
||||||
|
|
||||||
from neutron_lib.api.definitions import allowedaddresspairs as addr_apidef
|
from neutron_lib.api.definitions import allowedaddresspairs as addr_apidef
|
||||||
from neutron_lib.api.definitions import port as port_def
|
from neutron_lib.api.definitions import port as port_def
|
||||||
|
@ -65,6 +66,17 @@ class AllowedAddressPairsMixin(object):
|
||||||
return [self._make_allowed_address_pairs_dict(pair.db_obj)
|
return [self._make_allowed_address_pairs_dict(pair.db_obj)
|
||||||
for pair in pairs]
|
for pair in pairs]
|
||||||
|
|
||||||
|
def get_allowed_address_pairs_for_ports(self, context, port_ids):
|
||||||
|
pairs = (
|
||||||
|
obj_addr_pair.AllowedAddressPair.
|
||||||
|
get_allowed_address_pairs_for_ports(
|
||||||
|
context, port_ids=port_ids))
|
||||||
|
result = collections.defaultdict(list)
|
||||||
|
for pair in pairs:
|
||||||
|
result[pair.port_id].append(
|
||||||
|
self._make_allowed_address_pairs_dict(pair.db_obj))
|
||||||
|
return result
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
@resource_extend.extends([port_def.COLLECTION_NAME])
|
@resource_extend.extends([port_def.COLLECTION_NAME])
|
||||||
def _extend_port_dict_allowed_address_pairs(port_res, port_db):
|
def _extend_port_dict_allowed_address_pairs(port_res, port_db):
|
||||||
|
|
|
@ -1331,11 +1331,23 @@ class L3_NAT_with_dvr_db_mixin(_DVRAgentInterfaceMixin,
|
||||||
def get_ports_under_dvr_connected_subnet(self, context, subnet_id):
|
def get_ports_under_dvr_connected_subnet(self, context, subnet_id):
|
||||||
query = dvr_mac_db.get_ports_query_by_subnet_and_ip(context, subnet_id)
|
query = dvr_mac_db.get_ports_query_by_subnet_and_ip(context, subnet_id)
|
||||||
ports = [p for p in query.all() if is_port_bound(p)]
|
ports = [p for p in query.all() if is_port_bound(p)]
|
||||||
return [
|
# TODO(slaweq): if there would be way to pass to neutron-lib only
|
||||||
|
# list of extensions which actually should be processed, than setting
|
||||||
|
# process_extensions=True below could avoid that second loop and
|
||||||
|
# getting allowed_address_pairs for each of the ports
|
||||||
|
ports_list = [
|
||||||
self.l3plugin._core_plugin._make_port_dict(
|
self.l3plugin._core_plugin._make_port_dict(
|
||||||
port, process_extensions=False)
|
port, process_extensions=False)
|
||||||
for port in ports
|
for port in ports
|
||||||
]
|
]
|
||||||
|
ports_ids = [p['id'] for p in ports_list]
|
||||||
|
allowed_address_pairs = (
|
||||||
|
self._core_plugin.get_allowed_address_pairs_for_ports(
|
||||||
|
context, ports_ids))
|
||||||
|
for port in ports_list:
|
||||||
|
port['allowed_address_pairs'] = allowed_address_pairs.get(
|
||||||
|
port['id'], [])
|
||||||
|
return ports_list
|
||||||
|
|
||||||
|
|
||||||
def is_distributed_router(router):
|
def is_distributed_router(router):
|
||||||
|
|
|
@ -10,6 +10,7 @@
|
||||||
# License for the specific language governing permissions and limitations
|
# License for the specific language governing permissions and limitations
|
||||||
# under the License.
|
# under the License.
|
||||||
|
|
||||||
|
from neutron_lib.db import api as db_api
|
||||||
from neutron_lib.objects import common_types
|
from neutron_lib.objects import common_types
|
||||||
from neutron_lib.utils import net as net_utils
|
from neutron_lib.utils import net as net_utils
|
||||||
|
|
||||||
|
@ -61,3 +62,12 @@ class AllowedAddressPair(base.NeutronDbObject):
|
||||||
fields['mac_address'] = net_utils.AuthenticEUI(
|
fields['mac_address'] = net_utils.AuthenticEUI(
|
||||||
fields['mac_address'])
|
fields['mac_address'])
|
||||||
return fields
|
return fields
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def get_allowed_address_pairs_for_ports(cls, context, port_ids):
|
||||||
|
with db_api.CONTEXT_READER.using(context):
|
||||||
|
query = context.session.query(models.AllowedAddressPair).filter(
|
||||||
|
models.AllowedAddressPair.port_id.in_(port_ids))
|
||||||
|
pairs = [cls._load_object(context, db_obj)
|
||||||
|
for db_obj in query.all()]
|
||||||
|
return pairs
|
||||||
|
|
|
@ -1005,21 +1005,25 @@ class TestDvrRouter(DvrRouterTestFramework, framework.L3AgentTestFramework):
|
||||||
# cache is properly populated.
|
# cache is properly populated.
|
||||||
self.agent.conf.agent_mode = 'dvr_snat'
|
self.agent.conf.agent_mode = 'dvr_snat'
|
||||||
router_info = self.generate_dvr_router_info(enable_snat=True)
|
router_info = self.generate_dvr_router_info(enable_snat=True)
|
||||||
expected_neighbor = '35.4.1.10'
|
expected_neighbors = ['35.4.1.10', '10.0.0.10']
|
||||||
port_data = {
|
port_data = {
|
||||||
'fixed_ips': [{'ip_address': expected_neighbor}],
|
'fixed_ips': [{'ip_address': expected_neighbors[0]}],
|
||||||
'mac_address': 'fa:3e:aa:bb:cc:dd',
|
'mac_address': 'fa:3e:aa:bb:cc:dd',
|
||||||
'device_owner': DEVICE_OWNER_COMPUTE
|
'device_owner': DEVICE_OWNER_COMPUTE,
|
||||||
|
'allowed_address_pairs': [
|
||||||
|
{'ip_address': expected_neighbors[1],
|
||||||
|
'mac_address': 'fa:3e:aa:bb:cc:dd'}]
|
||||||
}
|
}
|
||||||
self.agent.plugin_rpc.get_ports_by_subnet.return_value = [port_data]
|
self.agent.plugin_rpc.get_ports_by_subnet.return_value = [port_data]
|
||||||
router1 = self.manage_router(self.agent, router_info)
|
router1 = self.manage_router(self.agent, router_info)
|
||||||
internal_device = router1.get_internal_device_name(
|
internal_device = router1.get_internal_device_name(
|
||||||
router_info['_interfaces'][0]['id'])
|
router_info['_interfaces'][0]['id'])
|
||||||
neighbor = ip_lib.dump_neigh_entries(4, internal_device,
|
for expected_neighbor in expected_neighbors:
|
||||||
router1.ns_name,
|
neighbor = ip_lib.dump_neigh_entries(4, internal_device,
|
||||||
dst=expected_neighbor)
|
router1.ns_name,
|
||||||
self.assertNotEqual([], neighbor)
|
dst=expected_neighbor)
|
||||||
self.assertEqual(expected_neighbor, neighbor[0]['dst'])
|
self.assertNotEqual([], neighbor)
|
||||||
|
self.assertEqual(expected_neighbor, neighbor[0]['dst'])
|
||||||
|
|
||||||
def _assert_rfp_fpr_mtu(self, router, expected_mtu=1500):
|
def _assert_rfp_fpr_mtu(self, router, expected_mtu=1500):
|
||||||
dev_mtu = self.get_device_mtu(
|
dev_mtu = self.get_device_mtu(
|
||||||
|
|
|
@ -532,7 +532,10 @@ class TestDvrRouterOperations(base.BaseTestCase):
|
||||||
'device_owner': lib_constants.DEVICE_OWNER_DHCP,
|
'device_owner': lib_constants.DEVICE_OWNER_DHCP,
|
||||||
'fixed_ips': [{'ip_address': '1.2.3.4',
|
'fixed_ips': [{'ip_address': '1.2.3.4',
|
||||||
'prefixlen': 24,
|
'prefixlen': 24,
|
||||||
'subnet_id': subnet_id}]},
|
'subnet_id': subnet_id}],
|
||||||
|
'allowed_address_pairs': [
|
||||||
|
{'ip_address': '10.20.30.40',
|
||||||
|
'mac_address': '00:11:22:33:44:55'}]},
|
||||||
{'mac_address': '11:22:33:44:55:66',
|
{'mac_address': '11:22:33:44:55:66',
|
||||||
'device_owner': lib_constants.DEVICE_OWNER_LOADBALANCER,
|
'device_owner': lib_constants.DEVICE_OWNER_LOADBALANCER,
|
||||||
'fixed_ips': [{'ip_address': '1.2.3.5',
|
'fixed_ips': [{'ip_address': '1.2.3.5',
|
||||||
|
@ -554,8 +557,9 @@ class TestDvrRouterOperations(base.BaseTestCase):
|
||||||
'_process_arp_cache_for_internal_port') as parp:
|
'_process_arp_cache_for_internal_port') as parp:
|
||||||
ri._set_subnet_arp_info(subnet_id)
|
ri._set_subnet_arp_info(subnet_id)
|
||||||
self.assertEqual(1, parp.call_count)
|
self.assertEqual(1, parp.call_count)
|
||||||
self.mock_ip_dev.neigh.add.assert_called_once_with(
|
self.mock_ip_dev.neigh.add.assert_has_calls([
|
||||||
'1.2.3.4', '00:11:22:33:44:55')
|
mock.call('1.2.3.4', '00:11:22:33:44:55'),
|
||||||
|
mock.call('10.20.30.40', '00:11:22:33:44:55')])
|
||||||
|
|
||||||
# Test negative case
|
# Test negative case
|
||||||
router['distributed'] = False
|
router['distributed'] = False
|
||||||
|
|
|
@ -1392,6 +1392,8 @@ class L3DvrTestCase(test_db_base_plugin_v2.NeutronDbPluginV2TestCase):
|
||||||
router = self._create_router(router_dict)
|
router = self._create_router(router_dict)
|
||||||
with self.network() as network,\
|
with self.network() as network,\
|
||||||
self.subnet(network=network) as subnet:
|
self.subnet(network=network) as subnet:
|
||||||
|
self.mixin._core_plugin.get_allowed_address_pairs_for_ports = (
|
||||||
|
mock.Mock())
|
||||||
fake_bound_ports_ids = []
|
fake_bound_ports_ids = []
|
||||||
|
|
||||||
def fake_is_port_bound(port):
|
def fake_is_port_bound(port):
|
||||||
|
@ -1413,6 +1415,8 @@ class L3DvrTestCase(test_db_base_plugin_v2.NeutronDbPluginV2TestCase):
|
||||||
self.ctx, subnet['subnet']['id'])
|
self.ctx, subnet['subnet']['id'])
|
||||||
dvr_subnet_ports_ids = [p['id'] for p in dvr_subnet_ports]
|
dvr_subnet_ports_ids = [p['id'] for p in dvr_subnet_ports]
|
||||||
self.assertItemsEqual(fake_bound_ports_ids, dvr_subnet_ports_ids)
|
self.assertItemsEqual(fake_bound_ports_ids, dvr_subnet_ports_ids)
|
||||||
|
(self.mixin._core_plugin.get_allowed_address_pairs_for_ports.
|
||||||
|
assert_called_once_with(self.ctx, dvr_subnet_ports_ids))
|
||||||
|
|
||||||
@mock.patch.object(plugin_utils, 'can_port_be_bound_to_virtual_bridge',
|
@mock.patch.object(plugin_utils, 'can_port_be_bound_to_virtual_bridge',
|
||||||
return_value=True)
|
return_value=True)
|
||||||
|
|
Loading…
Reference in New Issue