Merge "[APIC AIM] Populate get_gbp_details correctly for certain ports on external network"

This commit is contained in:
Zuul 2018-02-14 15:54:11 +00:00 committed by Gerrit Code Review
commit a93caeb49a
6 changed files with 110 additions and 16 deletions

View File

@ -107,6 +107,5 @@ class APICNameMapper(object):
if self._map(session, "", type_tag, prefix) == name[:pos]:
return name[pos:]
elif enforce:
LOG.error("Attempted to reverse-map invalid APIC name '%s'",
name)
raise exceptions.InternalError()
msg = _("Attempted to reverse-map invalid APIC name '%s'") % name
raise exceptions.InternalError(details=msg)

View File

@ -119,6 +119,12 @@ class DbMixin(object):
vrf_name=vrf.name).
all())
def _get_network_mappings_for_bd(self, session, bd):
return (session.query(NetworkMapping).
filter_by(bd_tenant_name=bd.tenant_name,
bd_name=bd.name).
all())
def _is_vrf_used_by_networks(self, session, vrf):
return (session.query(NetworkMapping.network_id).
filter_by(vrf_tenant_name=vrf.tenant_name,

View File

@ -17,7 +17,11 @@ from neutron_lib import exceptions
class InternalError(exceptions.NeutronException):
message = _("Internal mechanism driver error - see error log for details.")
message = _("Internal mechanism driver error - %(details)s.")
def __init__(self, **kwargs):
kwargs.setdefault('details', _("See error log for details"))
super(InternalError, self).__init__(**kwargs)
class UnsupportedRoutingTopology(exceptions.BadRequest):

View File

@ -2400,6 +2400,11 @@ class ApicMechanismDriver(api_plus.MechanismDriver,
mapping = self._get_network_mapping(session, network['id'])
return mapping and self._get_network_vrf(mapping)
# Used by policy driver.
def get_network_ids_for_bd(self, session, bd):
mapping = self._get_network_mappings_for_bd(session, bd)
return [m.network_id for m in mapping]
def get_aim_domains(self, aim_ctx):
vmms = [{'name': x.name, 'type': x.type}
for x in self.aim.find(aim_ctx, aim_resource.VMMDomain)

View File

@ -38,6 +38,8 @@ from gbpservice.neutron.extensions import cisco_apic
from gbpservice.neutron.extensions import cisco_apic_gbp as aim_ext
from gbpservice.neutron.extensions import cisco_apic_l3
from gbpservice.neutron.extensions import group_policy as gpolicy
from gbpservice.neutron.plugins.ml2plus.drivers.apic_aim import (
exceptions as md_exc)
from gbpservice.neutron.plugins.ml2plus.drivers.apic_aim import (
mechanism_driver as md)
from gbpservice.neutron.plugins.ml2plus.drivers.apic_aim import apic_mapper
@ -1904,14 +1906,26 @@ class AIMMappingDriver(nrd.CommonNeutronBase, aim_rpc.AIMMappingRPCMixin):
other_vrfs = self.aim.find(aim_ctx, aim_resource.VRF,
name=vrf_name)
bd_tenants = set([x.tenant_name for x in bds])
vrf_tenants = set([x.tenant_name for x in other_vrfs])
vrf_tenants = set([x.tenant_name for x in other_vrfs
if x.tenant_name != vrf_tenant_name])
valid_tenants = bd_tenants - vrf_tenants
# Only keep BDs that don't have a VRF with that name
# already
bds = [x for x in bds if x.tenant_name in valid_tenants]
# Retrieve subnets from BDs
net_ids = [self.name_mapper.reverse_network(session, bd.name)
for bd in bds]
net_ids = []
for bd in bds:
try:
net_ids.append(self.name_mapper.reverse_network(
session, bd.name))
except md_exc.InternalError as aie:
# Check if BD maps to an external network
ext_ids = self.aim_mech_driver.get_network_ids_for_bd(
session, bd)
if not ext_ids:
LOG.error("%s", aie)
raise
net_ids.extend(ext_ids)
if net_ids:
subnets = self._get_subnets(plugin_context,
{'network_id': net_ids})

View File

@ -210,13 +210,13 @@ class AIMBaseTestCase(test_nr_base.CommonNeutronBaseTestCase,
net = self._make_network(self.fmt, name, True,
arg_list=extn_attr,
**kwargs)['network']
self._make_subnet(
subnet = self._make_subnet(
self.fmt, {'network': net}, '100.100.0.1',
'100.100.0.0/16')['subnet']
router = self._make_router(
self.fmt, router_tenant or net['tenant_id'], 'router1',
external_gateway_info={'network_id': net['id']})['router']
return net, router
return net, router, subnet
def _bind_port_to_host(self, port_id, host):
data = {'port': {'binding:host_id': host,
@ -2941,13 +2941,14 @@ class TestPolicyTarget(AIMBaseTestCase,
def _verify_gbp_details_assertions(self, mapping, req_mapping, port_id,
expected_epg_name, expected_epg_tenant,
subnet, default_route=None):
subnet, default_route=None,
map_tenant_name=True):
self.assertEqual(mapping, req_mapping['gbp_details'])
self.assertEqual(port_id, mapping['port_id'])
self.assertEqual(expected_epg_name, mapping['endpoint_group_name'])
self.assertEqual(
self.name_mapper.project(None, expected_epg_tenant),
mapping['ptg_tenant'])
exp_tenant = (self.name_mapper.project(None, expected_epg_tenant)
if map_tenant_name else expected_epg_tenant)
self.assertEqual(exp_tenant, mapping['ptg_tenant'])
self.assertEqual('someid', mapping['vm-name'])
self.assertTrue(mapping['enable_dhcp_optimization'])
self.assertFalse(mapping['enable_metadata_optimization'])
@ -3151,9 +3152,9 @@ class TestPolicyTarget(AIMBaseTestCase,
name='as2', address_scope_id=address_scope['id'],
tenant_id=self._tenant_id)
ext_net1, router1 = self._setup_external_network(
ext_net1, router1, _ = self._setup_external_network(
'l1', dn='uni/tn-t1/out-l1/instP-n1')
ext_net2, router2 = self._setup_external_network(
ext_net2, router2, _ = self._setup_external_network(
'l2', dn='uni/tn-t1/out-l2/instP-n2')
ext_net2_sub2 = self._make_subnet(
self.fmt, {'network': ext_net2}, '200.200.0.1',
@ -3270,6 +3271,71 @@ class TestPolicyTarget(AIMBaseTestCase,
def test_get_gbp_details_no_pt_no_as_unrouted(self):
self._do_test_gbp_details_no_pt(use_as=False, routed=False)
def test_gbp_details_ext_net_no_pt(self):
# Test ports created on Neutron external networks
ext_net1, _, sn1 = self._setup_external_network(
'l1', dn='uni/tn-common/out-l1/instP-n1')
sn1 = {'subnet': sn1}
ext_net2, _, sn2 = self._setup_external_network(
'l2', dn='uni/tn-t1/out-l2/instP-n2')
sn2 = {'subnet': sn2}
with self.port(subnet=sn1) as port:
port_id = port['port']['id']
self._bind_port_to_host(port_id, 'h1')
sn1_1 = self._make_subnet(self.fmt, {'network': ext_net1},
'200.200.0.1', '200.200.0.0/16')
mapping = self.driver.get_gbp_details(
self._neutron_admin_context, device='tap%s' % port_id,
host='h1')
req_mapping = self.driver.request_endpoint_details(
self._neutron_admin_context,
request={'device': 'tap%s' % port_id,
'timestamp': 0, 'request_id': 'request_id'},
host='h1')
self._verify_gbp_details_assertions(
mapping, req_mapping, port_id, "EXT-l1", "common", sn1,
map_tenant_name=False)
vrf_id = '%s %s' % ("common", "openstack_EXT-l1")
vrf_mapping = self.driver.get_vrf_details(
self._neutron_admin_context, vrf_id=vrf_id)
supernet = [sn1['subnet']['cidr'], sn1_1['subnet']['cidr']]
self._verify_vrf_details_assertions(
mapping, "openstack_EXT-l1", vrf_id, supernet, "common")
self._verify_vrf_details_assertions(
vrf_mapping, "openstack_EXT-l1", vrf_id, supernet, "common")
with self.port(subnet=sn2) as port:
port_id = port['port']['id']
self._bind_port_to_host(port_id, 'h1')
sn2_1 = self._make_subnet(self.fmt, {'network': ext_net2},
'250.250.0.1', '250.250.0.0/16')
mapping = self.driver.get_gbp_details(
self._neutron_admin_context, device='tap%s' % port_id,
host='h1')
req_mapping = self.driver.request_endpoint_details(
nctx.get_admin_context(),
request={'device': 'tap%s' % port_id,
'timestamp': 0, 'request_id': 'request_id'},
host='h1')
self._verify_gbp_details_assertions(
mapping, req_mapping, port_id, "EXT-l2", "t1", sn2,
map_tenant_name=False)
vrf_id = '%s %s' % ("t1", "EXT-l2")
vrf_mapping = self.driver.get_vrf_details(
self._neutron_admin_context, vrf_id=vrf_id)
supernet = [sn2['subnet']['cidr'], sn2_1['subnet']['cidr']]
self._verify_vrf_details_assertions(
mapping, "EXT-l2", vrf_id, supernet, "t1")
self._verify_vrf_details_assertions(
vrf_mapping, "EXT-l2", vrf_id, supernet, "t1")
def test_ip_address_owner_update(self):
l3p = self.create_l3_policy(name='myl3')['l3_policy']
l2p = self.create_l2_policy(name='myl2',
@ -5174,7 +5240,7 @@ class TestNeutronPortOperation(AIMBaseTestCase):
# set allowed-address as fixed-IP of ports p3 and p4, which also have
# floating-IPs. Verify that FIP is "stolen" by p1 and p2
net_ext, rtr = self._setup_external_network(
net_ext, rtr, _ = self._setup_external_network(
'l1', dn='uni/tn-t1/out-l1/instP-n1')
p3 = self._make_port(self.fmt, net['network']['id'],
device_owner='compute:',