[APIC AIM] Populate get_gbp_details correctly for certain ports on external network
Network reverse mapping doesn't work for ports on external networks because naming convention followed is opaque to the mechanism driver. Now we deal with reverse mapping exceptions by checking if the network mapping table has an entry for the BD. Change-Id: I5bb2e9f9718cdf312316d34b988ea4db60bcc6d4 Signed-off-by: Amit Bose <amitbose@gmail.com>
This commit is contained in:
parent
a7cf4ee4b5
commit
fa1d544b59
|
@ -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)
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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):
|
||||
|
|
|
@ -2398,6 +2398,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)
|
||||
|
|
|
@ -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})
|
||||
|
|
|
@ -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:',
|
||||
|
|
Loading…
Reference in New Issue