[AIM] Remove raw_sql RPC implementation

Remove the raw_sql RPC implementation and the unit test variations
that test it. Also, add a few REVISIT comments regarding interactions
between the mechanism and policy drivers.

A follow-on patch will switch to the new RPC implementation as the
default, with the ablity to configure the original implemenation if
needed.

The final patch in the series will remove the original RPC
implementation and all its supporting code that is no longer needed.

Change-Id: Idc6166e19bc1f93b0bd0bbb0e5f70973cdb47a38
This commit is contained in:
Robert Kukura 2019-03-06 16:19:28 -05:00
parent 6b675b6e52
commit 90ce382e96
6 changed files with 185 additions and 802 deletions

View File

@ -53,12 +53,8 @@ apic_opts = [
"plugin, formatted as a dictionary mapping Neutron external "
"network IDs (UUIDs) to ACI external network distinguished "
"names."),
# REVISIT: Eliminate the following two options, leaving a single
# RPC implementation.
cfg.BoolOpt('enable_raw_sql_for_device_rpc',
default=False,
help=("This will use those raw SQL statements to speed "
"up the calculation of the EP file.")),
# REVISIT: Eliminate the following option, leaving a single RPC
# implementation.
cfg.BoolOpt('enable_new_rpc',
default=False,
help=("Enable new RPC handler.")),

View File

@ -235,6 +235,7 @@ class DbMixin(object):
return query(session).params(
network_id=network_id).one_or_none()
# REVISIT: Remove with original RPC implementation.
def _get_network_mapping_bulk(self, session, network_ids):
# REVISIT: This method is not called during any UT, and does
# not appear to be referenced elsewhere in this repository.
@ -259,6 +260,7 @@ class DbMixin(object):
vrf_tenant_name=vrf.tenant_name,
vrf_name=vrf.name).all()
# REVISIT: Remove with original RPC implementation.
def _get_network_mappings_for_bd(self, session, bd):
query = BAKERY(lambda s: s.query(
NetworkMapping))
@ -423,6 +425,7 @@ class DbMixin(object):
except orm.exc.NoResultFound:
return
# REVISIT: This method is only called from unit tests.
def get_ha_port_associations(self):
session = db_api.get_reader_session()
@ -524,6 +527,7 @@ class DbMixin(object):
last_full_update_time=last_full_update_time)
session.add(db_obj)
# REVISIT: Remove with original RPC implementation.
def _delete_vm_name_update(self, session):
with session.begin(subtransactions=True):
db_obj = self._get_vm_name_update(session)

View File

@ -240,10 +240,8 @@ class ApicMechanismDriver(api_plus.MechanismDriver,
self.enable_iptables_firewall = (cfg.CONF.ml2_apic_aim.
enable_iptables_firewall)
self.l3_domain_dn = cfg.CONF.ml2_apic_aim.l3_domain_dn
# REVISIT: Eliminate the following two variables, leaving a
# single RPC implementation.
self.enable_raw_sql_for_device_rpc = (cfg.CONF.ml2_apic_aim.
enable_raw_sql_for_device_rpc)
# REVISIT: Eliminate the following property, leaving a single
# RPC implementation.
self.enable_new_rpc = cfg.CONF.ml2_apic_aim.enable_new_rpc
self.apic_nova_vm_name_cache_update_interval = (cfg.CONF.ml2_apic_aim.
apic_nova_vm_name_cache_update_interval)
@ -2680,9 +2678,8 @@ class ApicMechanismDriver(api_plus.MechanismDriver,
return vrfs.values()
# Used by policy driver.
def _get_address_scope_ids_for_vrf(self, session, vrf, mappings=None):
mappings = mappings or self._get_address_scope_mappings_for_vrf(
session, vrf)
def _get_address_scope_ids_for_vrf(self, session, vrf):
mappings = self._get_address_scope_mappings_for_vrf(session, vrf)
return [mapping.scope_id for mapping in mappings]
def _get_network_ids_for_vrf(self, session, vrf):
@ -3237,12 +3234,12 @@ class ApicMechanismDriver(api_plus.MechanismDriver,
mapping = self._get_network_mapping(session, network['id'])
return mapping and self._get_network_epg(mapping)
# Used by policy driver.
# REVISIT: Remove with original RPC implementation.
def get_vrf_for_network(self, session, network):
mapping = self._get_network_mapping(session, network['id'])
return mapping and self._get_network_vrf(mapping)
# Used by policy driver.
# REVISIT: Remove with original RPC implementation.
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]
@ -3487,6 +3484,7 @@ class ApicMechanismDriver(api_plus.MechanismDriver,
[plugin_context, port])
def _notify_port_update_for_fip(self, plugin_context, port_id):
# REVISIT: Replace get_port() call with joins in query below.
port = self.plugin.get_port(plugin_context.elevated(), port_id)
ports_to_notify = [port_id]
fixed_ips = [x['ip_address'] for x in port['fixed_ips']]
@ -3533,61 +3531,34 @@ class ApicMechanismDriver(api_plus.MechanismDriver,
'prefixlen': <prefix_length_of_subnet>}
"""
session = plugin_context.session
if self.enable_raw_sql_for_device_rpc:
snat_port_query = ("SELECT id FROM ports "
"WHERE network_id = '" + ext_network['id'] + "' "
"AND device_id = '" + host_or_vrf + "' AND "
"device_owner = '" + aim_cst.DEVICE_OWNER_SNAT_PORT +
"'")
snat_port = session.execute(snat_port_query).first()
if snat_port:
snat_port = dict(snat_port)
ip_query = ("SELECT ip_address, subnet_id FROM "
"ipallocations WHERE "
"port_id = '" + snat_port['id'] + "'")
ip_result = session.execute(ip_query)
snat_port['fixed_ips'] = []
for ip in ip_result:
snat_port['fixed_ips'].append(
{'ip_address': ip['ip_address'],
'subnet_id': ip['subnet_id']})
else:
query = BAKERY(lambda s: s.query(
models_v2.Port))
query += lambda q: q.filter(
models_v2.Port.network_id == sa.bindparam('network_id'),
models_v2.Port.device_id == sa.bindparam('device_id'),
models_v2.Port.device_owner == aim_cst.DEVICE_OWNER_SNAT_PORT)
snat_port = query(session).params(
network_id=ext_network['id'],
device_id=host_or_vrf).first()
query = BAKERY(lambda s: s.query(
models_v2.Port))
query += lambda q: q.filter(
models_v2.Port.network_id == sa.bindparam('network_id'),
models_v2.Port.device_id == sa.bindparam('device_id'),
models_v2.Port.device_owner == aim_cst.DEVICE_OWNER_SNAT_PORT)
snat_port = query(session).params(
network_id=ext_network['id'],
device_id=host_or_vrf).first()
snat_ip = None
if not snat_port or snat_port['fixed_ips'] is None:
if not snat_port or snat_port.fixed_ips is None:
# allocate SNAT port
if self.enable_raw_sql_for_device_rpc:
snat_subnet_query = ("SELECT id, cidr, gateway_ip FROM "
"subnets JOIN "
"apic_aim_subnet_extensions AS "
"subnet_ext_1 ON "
"id = subnet_ext_1.subnet_id "
"WHERE network_id = '" +
ext_network['id'] + "' AND "
"subnet_ext_1.snat_host_pool = 1")
snat_subnets = session.execute(snat_subnet_query)
snat_subnets = list(snat_subnets)
else:
extn_db_sn = extension_db.SubnetExtensionDb
query = BAKERY(lambda s: s.query(
models_v2.Subnet))
query += lambda q: q.join(
extn_db_sn,
extn_db_sn.subnet_id == models_v2.Subnet.id)
query += lambda q: q.filter(
models_v2.Subnet.network_id == sa.bindparam('network_id'))
query += lambda q: q.filter(
extn_db_sn.snat_host_pool.is_(True))
snat_subnets = query(session).params(
network_id=ext_network['id']).all()
extn_db_sn = extension_db.SubnetExtensionDb
query = BAKERY(lambda s: s.query(
models_v2.Subnet))
query += lambda q: q.join(
extn_db_sn,
extn_db_sn.subnet_id == models_v2.Subnet.id)
query += lambda q: q.filter(
models_v2.Subnet.network_id == sa.bindparam('network_id'))
query += lambda q: q.filter(
extn_db_sn.snat_host_pool.is_(True))
snat_subnets = query(session).params(
network_id=ext_network['id']).all()
if not snat_subnets:
LOG.info('No subnet in external network %s is marked as '
'SNAT-pool',
@ -3613,20 +3584,15 @@ class ApicMechanismDriver(api_plus.MechanismDriver,
'for SNAT IP allocation',
snat_subnet['id'])
else:
snat_ip = snat_port['fixed_ips'][0]['ip_address']
if self.enable_raw_sql_for_device_rpc:
snat_subnet_query = ("SELECT cidr, gateway_ip FROM subnets "
"WHERE id = '" +
snat_port['fixed_ips'][0]['subnet_id'] +
"'")
snat_subnet = session.execute(snat_subnet_query).first()
else:
query = BAKERY(lambda s: s.query(
models_v2.Subnet))
query += lambda q: q.filter(
models_v2.Subnet.id == sa.bindparam('subnet_id'))
snat_subnet = query(session).params(
subnet_id=snat_port.fixed_ips[0].subnet_id).one()
snat_ip = snat_port.fixed_ips[0]['ip_address']
query = BAKERY(lambda s: s.query(
models_v2.Subnet))
query += lambda q: q.filter(
models_v2.Subnet.id == sa.bindparam('subnet_id'))
snat_subnet = query(session).params(
subnet_id=snat_port.fixed_ips[0].subnet_id).one()
if snat_ip:
return {'host_snat_ip': snat_ip,
'gateway_ip': snat_subnet['gateway_ip'],
@ -3680,6 +3646,7 @@ class ApicMechanismDriver(api_plus.MechanismDriver,
'%(ex)s',
{'port': p, 'ex': ne})
# Called by l3_plugin.
def check_floatingip_external_address(self, context, floatingip):
session = context.session
if floatingip.get('subnet_id'):
@ -3704,6 +3671,7 @@ class ApicMechanismDriver(api_plus.MechanismDriver,
if floatingip['floating_ip_address'] in cidrs:
raise exceptions.SnatPoolCannotBeUsedForFloatingIp()
# Called by l3_plugin.
def get_subnets_for_fip(self, context, floatingip):
session = context.session
extn_db_sn = extension_db.SubnetExtensionDb
@ -4314,6 +4282,7 @@ class ApicMechanismDriver(api_plus.MechanismDriver,
return [p[0] for p in port_ids]
# REVISIT: Remove with original RPC implementation.
def _get_port_network_id(self, plugin_context, port_id):
port = self.plugin.get_port(plugin_context, port_id)
return port['network_id']
@ -4332,14 +4301,17 @@ class ApicMechanismDriver(api_plus.MechanismDriver,
return aim_resource.L3Outside(
tenant_name=aim_ext_net.tenant_name, name=aim_ext_net.l3out_name)
# Called by sfc_driver.
def _get_bd_by_network_id(self, session, network_id):
net_mapping = self._get_network_mapping(session, network_id)
return self._get_network_bd(net_mapping)
# Called by sfc_driver and its unit tests.
def _get_epg_by_network_id(self, session, network_id):
net_mapping = self._get_network_mapping(session, network_id)
return self._get_network_epg(net_mapping)
# Called by sfc_driver.
def _get_vrf_by_network(self, session, network):
vrf_dn = network.get(cisco_apic.DIST_NAMES, {}).get(cisco_apic.VRF)
if vrf_dn:
@ -4356,6 +4328,7 @@ class ApicMechanismDriver(api_plus.MechanismDriver,
net_mapping = self._get_network_mapping(session, network['id'])
return self._get_network_vrf(net_mapping)
# Called by sfc_driver.
def _get_port_static_path_info(self, plugin_context, port):
port_id = port['id']
path = encap = host = None
@ -4386,6 +4359,7 @@ class ApicMechanismDriver(api_plus.MechanismDriver,
path = host_links[0].path
return path, encap, host
# Called by sfc_driver.
def _get_port_unique_domain(self, plugin_context, port):
"""Get port domain

View File

@ -79,9 +79,11 @@ AUTO_PTG_ID_PREFIX = AUTO_PTG_PREFIX + '%s'
# Definitions duplicated from apicapi lib
APIC_OWNED = 'apic_owned_'
# REVISIT: Remove with original RPC implementation.
PROMISCUOUS_TYPES = [n_constants.DEVICE_OWNER_DHCP,
n_constants.DEVICE_OWNER_LOADBALANCER]
# TODO(ivar): define a proper promiscuous API
# REVISIT: Remove with original RPC implementation.
PROMISCUOUS_SUFFIX = 'promiscuous'
CONTRACTS = 'contracts'
@ -1038,6 +1040,10 @@ class AIMMappingDriver(nrd.CommonNeutronBase, aim_rpc.AIMMappingRPCMixin):
np_db.update({'subnet_id': None})
self._delete_subnet_on_nat_pool_delete(context)
# REVISIT: Called by mechanism driver during port
# binding. Consider replacing with a more general hook for the PD
# to participate in port binding. Or consider removing/replacing
# this feature, since VM names should not effect behavior.
def check_allow_vm_names(self, context, port):
ok_to_bind = True
ptg, pt = self._port_id_to_ptg(context._plugin_context, port['id'])
@ -1064,6 +1070,9 @@ class AIMMappingDriver(nrd.CommonNeutronBase, aim_rpc.AIMMappingRPCMixin):
'vm': vm.name})
return ok_to_bind
# REVISIT: Called by mechanism driver when disassociating a
# domain. Consider a more general way for neutron ports to be
# bound using a non-default EPG.
def get_ptg_port_ids(self, context, ptg):
pts = self.gbp_plugin.get_policy_targets(
context, {'id': ptg['policy_targets']})
@ -1149,6 +1158,7 @@ class AIMMappingDriver(nrd.CommonNeutronBase, aim_rpc.AIMMappingRPCMixin):
return self._get_aim_application_profile_from_db(
context._plugin_context.session, ap)
# REVISIT: Remove with original RPC implementation.
def _get_aim_application_profile(self, session, apg):
# This gets an AP from the AIM DB
ap = self._aim_application_profile(session, apg)
@ -1198,6 +1208,9 @@ class AIMMappingDriver(nrd.CommonNeutronBase, aim_rpc.AIMMappingRPCMixin):
context._plugin_context.session)
self.aim.delete(aim_ctx, ap)
# REVISIT: Called by mechanism driver when associating or
# disassociating a domain. Consider a more general way for neutron
# ports to be bound using a non-default EPG.
def _aim_endpoint_group(self, session, ptg, bd_name=None,
bd_tenant_name=None,
provided_contracts=None,
@ -1441,6 +1454,7 @@ class AIMMappingDriver(nrd.CommonNeutronBase, aim_rpc.AIMMappingRPCMixin):
aim_contract, in_filters, out_filters, bi_filters)
self.aim.create(aim_ctx, aim_contract_subject, overwrite=True)
# REVISIT: Remove with original RPC implementation.
def _get_aim_contract(self, session, policy_rule_set):
# This gets a Contract from the AIM DB
aim_ctx = aim_context.AimContext(session)
@ -1767,11 +1781,9 @@ class AIMMappingDriver(nrd.CommonNeutronBase, aim_rpc.AIMMappingRPCMixin):
session = context._plugin_context.session
return aim_context.AimContext(session)
def _is_port_promiscuous(self, plugin_context, port, details=None):
if details and 'pt' in details['_cache']:
pt = details['_cache']['pt']
else:
pt = self._port_id_to_pt(plugin_context, port['id'])
# REVISIT: Remove with original RPC implementation.
def _is_port_promiscuous(self, plugin_context, port):
pt = self._port_id_to_pt(plugin_context, port['id'])
if (pt and pt.get('cluster_id') and
pt.get('cluster_id') != pt['id']):
master = self._get_policy_target(plugin_context, pt['cluster_id'])
@ -1785,24 +1797,25 @@ class AIMMappingDriver(nrd.CommonNeutronBase, aim_rpc.AIMMappingRPCMixin):
return True
return False
# REVISIT: Remove with original RPC implementation.
def _is_dhcp_optimized(self, plugin_context, port):
return self.aim_mech_driver.enable_dhcp_opt
# REVISIT: Remove with original RPC implementation.
def _is_metadata_optimized(self, plugin_context, port):
return self.aim_mech_driver.enable_metadata_opt
# REVISIT: Remove with original RPC implementation.
def _set_dhcp_lease_time(self, details):
if self.aim_mech_driver.apic_optimized_dhcp_lease_time > 0:
details['dhcp_lease_time'] = (
self.aim_mech_driver.apic_optimized_dhcp_lease_time)
def _get_port_epg(self, plugin_context, port, details=None):
if details and 'pt' in details['_cache']:
pt = details['_cache']['pt']
ptg = self._pt_to_ptg(plugin_context, pt)
else:
ptg, pt = self._port_id_to_ptg(plugin_context, port['id'])
# REVISIT: Called by mechanism driver when binding a port using
# DVS. Consider a more general way for neutron ports to be bound
# using a non-default EPG.
def _get_port_epg(self, plugin_context, port):
ptg, pt = self._port_id_to_ptg(plugin_context, port['id'])
if ptg:
# TODO(Kent): optimize this also for GBP workflow?
return self._get_aim_endpoint_group(plugin_context.session, ptg)
@ -1818,34 +1831,26 @@ class AIMMappingDriver(nrd.CommonNeutronBase, aim_rpc.AIMMappingRPCMixin):
"port %s", port['id'])
return epg
def _get_subnet_details(self, plugin_context, port, details):
# REVISIT: Remove with original RPC implementation.
def _get_subnet_details(self, plugin_context, port):
# L2P might not exist for a pure Neutron port
if 'l2p' in details['_cache']:
l2p = details['_cache']['l2p']
else:
l2p = self._network_id_to_l2p(plugin_context, port['network_id'])
l2p = self._network_id_to_l2p(plugin_context, port['network_id'])
# TODO(ivar): support shadow network
# if not l2p and self._ptg_needs_shadow_network(context, ptg):
# l2p = self._get_l2_policy(context._plugin_context,
# ptg['l2_policy_id'])
if 'subnets' in details['_cache']:
subnets = details['_cache']['subnets']
else:
subnets = self._get_subnets(
plugin_context,
filters={'id': [ip['subnet_id'] for ip in port['fixed_ips']]})
subnets = self._get_subnets(
plugin_context,
filters={'id': [ip['subnet_id'] for ip in port['fixed_ips']]})
for subnet in subnets:
dhcp_ports = {}
subnet_dhcp_ips = set()
if 'dhcp_ports' in details['_cache']:
dhcp_ports_list = details['_cache']['dhcp_ports']
else:
dhcp_ports_list = self._get_ports(
for dhcp_port in self._get_ports(
plugin_context,
filters={'network_id': [subnet['network_id']],
'device_owner': [n_constants.DEVICE_OWNER_DHCP]})
for dhcp_port in dhcp_ports_list:
filters={
'network_id': [subnet['network_id']],
'device_owner': [n_constants.DEVICE_OWNER_DHCP]}):
dhcp_ips = set([x['ip_address'] for x in dhcp_port['fixed_ips']
if x['subnet_id'] == subnet['id']])
dhcp_ports.setdefault(dhcp_port['mac_address'], list(dhcp_ips))
@ -1894,21 +1899,21 @@ class AIMMappingDriver(nrd.CommonNeutronBase, aim_rpc.AIMMappingRPCMixin):
subnet['dhcp_server_ports'] = dhcp_ports
return subnets
# REVISIT: Remove with original RPC implementation.
def _get_nova_vm_name(self, context, port):
return self.aim_mech_driver._get_vm_name(context.session,
port['device_id'])
# REVISIT: Remove with original RPC implementation.
def _send_port_update_notification(self, plugin_context, port):
self.aim_mech_driver._notify_port_update(plugin_context, port)
def _get_aap_details(self, plugin_context, port, details):
# REVISIT: Remove with original RPC implementation.
def _get_aap_details(self, plugin_context, port):
aaps = port['allowed_address_pairs']
# Set the correct address ownership for this port
if 'owned_addresses' in details['_cache']:
owned_addresses = details['_cache']['owned_addresses']
else:
owned_addresses = self._get_owned_addresses(
plugin_context, port['id'])
owned_addresses = self._get_owned_addresses(
plugin_context, port['id'])
extra_aaps = []
for allowed in aaps:
cidr = netaddr.IPNetwork(allowed['ip_address'])
@ -1932,20 +1937,17 @@ class AIMMappingDriver(nrd.CommonNeutronBase, aim_rpc.AIMMappingRPCMixin):
aaps.extend(extra_aaps)
return aaps
def _get_port_vrf(self, plugin_context, port, details):
# REVISIT: Remove with original RPC implementation.
def _get_port_vrf(self, plugin_context, port):
net_db = self._core_plugin._get_network(plugin_context,
port['network_id'])
return self.aim_mech_driver.get_vrf_for_network(
plugin_context.session, net_db)
def _get_vrf_subnets(self, plugin_context, vrf_tenant_name, vrf_name,
details):
# REVISIT: Remove with original RPC implementation.
def _get_vrf_subnets(self, plugin_context, vrf_tenant_name, vrf_name):
session = plugin_context.session
result = []
if 'address_scope' in details['_cache']:
mappings = details['_cache']['address_scope']
else:
mappings = None
# get all subnets of the specified VRF
with session.begin(subtransactions=True):
# Find VRF's address_scope first
@ -1953,19 +1955,14 @@ class AIMMappingDriver(nrd.CommonNeutronBase, aim_rpc.AIMMappingRPCMixin):
self.aim_mech_driver._get_address_scope_ids_for_vrf(
session,
aim_resource.VRF(tenant_name=vrf_tenant_name,
name=vrf_name),
mappings))
name=vrf_name)))
if address_scope_ids:
if 'subnetpools' in details['_cache']:
subnetpools = details['_cache']['subnetpools']
else:
for address_scope_id in address_scope_ids:
subnetpools = self._get_subnetpools(
plugin_context,
filters={'address_scope_id': address_scope_ids})
for pool in subnetpools:
result.extend(pool['prefixes'])
elif 'vrf_subnets' in details['_cache']:
result = details['_cache']['vrf_subnets']
filters={'address_scope_id': [address_scope_id]})
for pool in subnetpools:
result.extend(pool['prefixes'])
else:
aim_ctx = aim_context.AimContext(db_session=session)
if vrf_tenant_name != md.COMMON_TENANT_NAME:
@ -1992,6 +1989,7 @@ class AIMMappingDriver(nrd.CommonNeutronBase, aim_rpc.AIMMappingRPCMixin):
result = [x['cidr'] for x in subnets]
return result
# REVISIT: Remove with original RPC implementation.
def _get_net_ids_from_bds(self, session, bds):
net_ids = []
for bd in bds:
@ -2009,15 +2007,14 @@ class AIMMappingDriver(nrd.CommonNeutronBase, aim_rpc.AIMMappingRPCMixin):
# especially true for VRFs in the common tenant.
return net_ids
def _get_segmentation_labels(self, plugin_context, port, details):
if self.apic_segmentation_label_driver:
if 'pt' in details['_cache']:
pt = details['_cache']['pt']
else:
pt = self._port_id_to_pt(plugin_context, port['id'])
if pt and 'segmentation_labels' in pt:
return pt['segmentation_labels']
# REVISIT: Remove with original RPC implementation.
def _get_segmentation_labels(self, plugin_context, port):
pt = self._port_id_to_pt(plugin_context, port['id'])
if self.apic_segmentation_label_driver and pt and (
'segmentation_labels' in pt):
return pt['segmentation_labels']
# REVISIT: Remove with original RPC implementation.
def _get_nat_details(self, plugin_context, port, host, details):
""" Add information about IP mapping for DNAT/SNAT """
@ -2029,63 +2026,50 @@ class AIMMappingDriver(nrd.CommonNeutronBase, aim_rpc.AIMMappingRPCMixin):
# Handle them depending on whether there is a FIP on that
# network.
ext_nets = []
if 'ext_nets' in details['_cache']:
ext_nets = details['_cache']['ext_nets']
else:
port_sn = set([x['subnet_id'] for x in port['fixed_ips']])
router_intf_ports = self._get_ports(
port_sn = set([x['subnet_id'] for x in port['fixed_ips']])
router_intf_ports = self._get_ports(
plugin_context,
filters={'device_owner': [n_constants.DEVICE_OWNER_ROUTER_INTF],
'fixed_ips': {'subnet_id': port_sn}})
if router_intf_ports:
routers = self._get_routers(
plugin_context,
filters={'device_owner':
[n_constants.DEVICE_OWNER_ROUTER_INTF],
'fixed_ips': {'subnet_id': port_sn}})
if router_intf_ports:
routers = self._get_routers(
plugin_context,
filters={'id': [x['device_id']
for x in router_intf_ports]})
ext_nets = self._get_networks(
plugin_context,
filters={'id': [r['external_gateway_info']['network_id']
for r in routers
if r.get('external_gateway_info')]})
filters={'id': [x['device_id']
for x in router_intf_ports]})
ext_nets = self._get_networks(
plugin_context,
filters={'id': [r['external_gateway_info']['network_id']
for r in routers
if r.get('external_gateway_info')]})
if not ext_nets:
return fips, ipms, host_snat_ips
# Handle FIPs of owned addresses - find other ports in the
# network whose address is owned by this port.
# If those ports have FIPs, then steal them.
if 'fips' in details['_cache']:
fips = details['_cache']['fips']
else:
fips_filter = [port['id']]
active_addrs = [a['ip_address']
for a in details['allowed_address_pairs']
if a.get('active')]
if active_addrs:
others = self._get_ports(
plugin_context,
filters={'network_id': [port['network_id']],
'fixed_ips': {'ip_address': active_addrs}})
fips_filter.extend([p['id'] for p in others
if p['id'] != port['id']])
fips = self._get_fips(plugin_context,
filters={'port_id': fips_filter})
fips_filter = [port['id']]
active_addrs = [a['ip_address']
for a in details['allowed_address_pairs']
if a.get('active')]
if active_addrs:
others = self._get_ports(
plugin_context,
filters={'network_id': [port['network_id']],
'fixed_ips': {'ip_address': active_addrs}})
fips_filter.extend([p['id'] for p in others
if p['id'] != port['id']])
fips = self._get_fips(plugin_context,
filters={'port_id': fips_filter})
for ext_net in ext_nets:
if 'ext_nets' in details['_cache']:
dn = ext_net.external_network_dn
ext_net_epg_dn = self.aim_mech_driver._get_network_epg(
ext_net).dn
nat_type = ext_net.nat_type
else:
dn = ext_net.get(cisco_apic.DIST_NAMES, {}).get(
cisco_apic.EXTERNAL_NETWORK)
ext_net_epg_dn = ext_net.get(cisco_apic.DIST_NAMES, {}).get(
cisco_apic.EPG)
nat_type = ext_net.get(cisco_apic.NAT_TYPE)
dn = ext_net.get(cisco_apic.DIST_NAMES, {}).get(
cisco_apic.EXTERNAL_NETWORK)
ext_net_epg_dn = ext_net.get(cisco_apic.DIST_NAMES, {}).get(
cisco_apic.EPG)
if not dn or not ext_net_epg_dn:
continue
if 'distributed' != nat_type:
if 'distributed' != ext_net.get(cisco_apic.NAT_TYPE):
continue
# TODO(amitbose) Handle per-tenant NAT EPG
@ -2361,6 +2345,7 @@ class AIMMappingDriver(nrd.CommonNeutronBase, aim_rpc.AIMMappingRPCMixin):
else:
return False
# REVISIT: Remove with original RPC implementation.
def _get_bd_by_dn(self, context, bd_dn):
aim_context = self._get_aim_context(context)
bd = self.aim.get(
@ -2469,7 +2454,8 @@ class AIMMappingDriver(nrd.CommonNeutronBase, aim_rpc.AIMMappingRPCMixin):
query(context._plugin_context.session).params(
pr_ids=pr_ids).all())]
def _get_port_mtu(self, context, port, details):
# REVISIT: Remove with original RPC implementation.
def _get_port_mtu(self, context, port):
if self.advertise_mtu:
for dhcp_opt in port.get('extra_dhcp_opts'):
if (dhcp_opt.get('opt_name') == 'interface-mtu' or
@ -2479,22 +2465,18 @@ class AIMMappingDriver(nrd.CommonNeutronBase, aim_rpc.AIMMappingRPCMixin):
return int(dhcp_opt['opt_value'])
except ValueError:
continue
if 'network' in details['_cache']:
network = details['_cache']['network']
else:
network = self._get_network(context, port['network_id'])
network = self._get_network(context, port['network_id'])
return network.get('mtu')
return None
# REVISIT: Remove with original RPC implementation.
def _get_dns_domain(self, context, port):
network = self._get_network(context, port['network_id'])
return network.get('dns_domain')
def _get_nested_domain(self, context, port, details):
if 'network' in details['_cache']:
network = details['_cache']['network']
else:
network = self._get_network(context, port['network_id'])
# REVISIT: Remove with original RPC implementation.
def _get_nested_domain(self, context, port):
network = self._get_network(context, port['network_id'])
return (network.get('apic:nested_domain_name'),
network.get('apic:nested_domain_type'),
network.get('apic:nested_domain_infra_vlan'),

View File

@ -33,8 +33,6 @@ from gbpservice.neutron.db.grouppolicy.extensions import (
from gbpservice.neutron.db.grouppolicy import group_policy_mapping_db as gpmdb
from gbpservice.neutron.plugins.ml2plus.drivers.apic_aim import (
constants as md_const)
from gbpservice.neutron.plugins.ml2plus.drivers.apic_aim import (
mechanism_driver as md)
LOG = log.getLogger(__name__)
@ -63,6 +61,9 @@ class AIMMappingRPCMixin(object):
that each module has over the network abstraction.
"""
# REVISIT: Remove original RPC implementation - everything in this
# class before the query_endpoint_rpc_info method.
def setup_opflex_rpc_listeners(self):
self.notifier = o_rpc.AgentNotifierApi(topics.AGENT)
LOG.debug("Set up Opflex RPC listeners.")
@ -78,9 +79,7 @@ class AIMMappingRPCMixin(object):
def _retrieve_vrf_details(self, context, **kwargs):
with context.session.begin(subtransactions=True):
details = {'l3_policy_id': kwargs['vrf_id']}
details['_cache'] = {}
self._add_vrf_details(context, details['l3_policy_id'], details)
details.pop('_cache', None)
return details
def _get_vrf_details(self, context, **kwargs):
@ -220,12 +219,6 @@ class AIMMappingRPCMixin(object):
# - self._get_dns_domain(context, port)
@db_api.retry_if_session_inactive()
def _get_gbp_details(self, context, request, host):
if self.aim_mech_driver.enable_raw_sql_for_device_rpc:
return self._get_gbp_details_new(context, request, host)
else:
return self._get_gbp_details_old(context, request, host)
def _get_gbp_details_old(self, context, request, host):
with context.session.begin(subtransactions=True):
device = request.get('device')
@ -270,8 +263,7 @@ class AIMMappingRPCMixin(object):
self._set_nova_vm_name(context, port, details)
details['_cache'] = {}
mtu = self._get_port_mtu(context, port, details)
mtu = self._get_port_mtu(context, port)
if mtu:
details['interface_mtu'] = mtu
details['dns_domain'] = self._get_dns_domain(context, port)
@ -283,7 +275,7 @@ class AIMMappingRPCMixin(object):
# be used for such caching.
if port.get('security_groups'):
self._add_security_group_details(context, port, details)
vrf = self._get_port_vrf(context, port, details)
vrf = self._get_port_vrf(context, port)
details['l3_policy_id'] = '%s %s' % (vrf.tenant_name, vrf.name)
self._add_subnet_details(context, port, details)
self._add_allowed_address_pairs_details(context, port, details)
@ -293,465 +285,6 @@ class AIMMappingRPCMixin(object):
self._add_segmentation_label_details(context, port, details)
self._set_dhcp_lease_time(details)
self._add_nested_domain_details(context, port, details)
details.pop('_cache', None)
LOG.debug("Details for port %s : %s", port['id'], details)
return details
def _compose_in_filter_str(self, obj_list):
in_str = str(tuple(obj_list))
# Remove the ',' at the end otherwise MySQL will complain
if in_str[-1] == ')' and in_str[-2] == ',':
in_str = in_str[0:-2] + in_str[-1]
return in_str
def _build_up_details_cache(self, session, details, port, network):
ha_addr_query = ("SELECT ha_ip_address FROM "
"apic_ml2_ha_ipaddress_to_port_owner WHERE "
"apic_ml2_ha_ipaddress_to_port_owner.port_id = '"
+ port['id'] + "'")
ha_addr_result = session.execute(ha_addr_query)
owned_addresses = sorted([x[0] for x in ha_addr_result])
details['_cache']['owned_addresses'] = owned_addresses
if port.get('security_groups'):
# Remove the encoding presentation of the string
# otherwise MySQL will complain
sg_list = [str(r) for r in port['security_groups']]
in_str = self._compose_in_filter_str(sg_list)
sg_query = ("SELECT id, project_id FROM securitygroups WHERE "
"id in " + in_str)
details['_cache']['security_groups'] = list(
session.execute(sg_query))
# Get the subnet info
subnets = []
subnet_ids = [str(ip['subnet_id']) for ip in port['fixed_ips']]
if subnet_ids:
subnet_in_str = self._compose_in_filter_str(subnet_ids)
subnet_query = ("SELECT * FROM subnets WHERE "
"id in " + subnet_in_str)
subnet_result = session.execute(subnet_query)
# Build up the ORM relationship manually
for subnet in subnet_result:
subnet_dict = dict(subnet)
dns_query = ("SELECT address FROM dnsnameservers WHERE "
"subnet_id = '" + subnet['id'] + "'")
dns_result = session.execute(dns_query)
subnet_dict['dns_nameservers'] = []
for dns in dns_result:
subnet_dict['dns_nameservers'].append(dns['address'])
route_query = ("SELECT destination, nexthop FROM "
"subnetroutes WHERE "
"subnet_id = '" + subnet['id'] + "'")
route_result = session.execute(route_query)
subnet_dict['host_routes'] = []
for route in route_result:
subnet_dict['host_routes'].append(
{'destination': route['destination'],
'nexthop': route['nexthop']})
subnets.append(subnet_dict)
else:
LOG.error("subnet_ids is empty. fixed_ips: %s, "
"port: %s", port['fixed_ips'], port['id'])
details['_cache']['subnets'] = subnets
# Get DHCP ports
dhcp_query = ("SELECT id, mac_address FROM ports WHERE "
"ports.network_id = '" + network['id'] + "'" + " AND "
"ports.device_owner = 'network:dhcp'")
dhcp_result = session.execute(dhcp_query)
# Build up the ORM relationship manually
dhcp_ports = []
for dhcp_port in dhcp_result:
dhcp_port_dict = dict(dhcp_port)
ip_query = ("SELECT ip_address, subnet_id FROM "
"ipallocations WHERE "
"port_id = '" + dhcp_port['id'] + "'")
ip_result = session.execute(ip_query)
dhcp_port_dict['fixed_ips'] = []
for ip in ip_result:
dhcp_port_dict['fixed_ips'].append(
{'ip_address': ip['ip_address'],
'subnet_id': ip['subnet_id']})
dhcp_ports.append(dhcp_port_dict)
details['_cache']['dhcp_ports'] = dhcp_ports
# Get address_scope, subnetpools and vrf_subnets
address_scope_query = (
"SELECT scope_id FROM apic_aim_address_scope_mappings WHERE "
"vrf_name = '" + network['vrf_name'] + "'" + " AND "
"vrf_tenant_name = '" + network['vrf_tenant_name'] + "'")
as_result = session.execute(address_scope_query)
subnetpools = []
if as_result.rowcount > 0 or as_result.rowcount == -1:
subnetpools_query = (
"SELECT subnetpools.id as id FROM subnetpools JOIN "
"address_scopes AS address_scopes_1 ON "
"address_scopes_1.id = subnetpools.address_scope_id JOIN "
"apic_aim_address_scope_mappings AS aim_as_mappings_1 ON "
"aim_as_mappings_1.scope_id = address_scopes_1.id WHERE "
"vrf_name = '" + network['vrf_name'] + "'" + " AND "
"vrf_tenant_name = '" + network['vrf_tenant_name'] +
"'")
subnetpools_res = session.execute(subnetpools_query)
# Build up the ORM relationship manually
for subnetpool in subnetpools_res:
subnetpool_dict = dict(subnetpool)
prefix_query = (
"SELECT cidr FROM subnetpoolprefixes WHERE "
"subnetpool_id = '" + subnetpool['id'] + "'")
prefix_result = session.execute(prefix_query)
subnetpool_dict['prefixes'] = []
for prefix in prefix_result:
subnetpool_dict['prefixes'].append(prefix['cidr'])
subnetpools.append(subnetpool_dict)
# Unfortunately, there is no relationship in the ORM between
# a VRF and BridgeDomainin -- the BDs reference the VRF by name,
# which doesn't include the ACI tenant. When the VRF lives in the
# common tenant, the only way we can deduce the BDs belonging to
# it is by eliminating all the BDs that are not in the common
# tenant, and have a VRF with the same name in their tenant.
vrf_subnets = []
if as_result.rowcount == 0 or as_result.rowcount == -1:
if network['vrf_tenant_name'] == md.COMMON_TENANT_NAME:
all_vrfs_bds_query = (
"SELECT name, tenant_name FROM aim_bridge_domains "
"WHERE vrf_name = '" + network['vrf_name'] + "'")
all_vrfs_bds_result = list(
session.execute(all_vrfs_bds_query))
all_vrfs_query = (
"SELECT tenant_name FROM aim_vrfs WHERE "
"name = '" + network['vrf_name'] + "'")
all_vrfs_result = session.execute(all_vrfs_query)
bd_tenants = set(
[x.tenant_name for x in all_vrfs_bds_result])
vrf_tenants = set(
[x.tenant_name for x in all_vrfs_result
if x.tenant_name != md.COMMON_TENANT_NAME])
valid_tenants = bd_tenants - vrf_tenants
aim_bd_result = [x for x in all_vrfs_bds_result
if x.tenant_name in valid_tenants]
else:
aim_bd_query = (
"SELECT name, tenant_name FROM aim_bridge_domains "
"WHERE vrf_name = '" + network['vrf_name'] + "'" +
" AND tenant_name = '" +
network['vrf_tenant_name'] + "'")
aim_bd_result = session.execute(aim_bd_query)
net_ids = self._get_net_ids_from_bds(session,
aim_bd_result)
if net_ids:
net_id_list = [str(r) for r in net_ids]
in_str = self._compose_in_filter_str(net_id_list)
vrf_subnet_query = ("SELECT cidr FROM subnets WHERE "
"network_id in " + in_str)
vrf_subnet_result = session.execute(vrf_subnet_query)
vrf_subnets = [x['cidr'] for x in vrf_subnet_result]
details['_cache']['address_scope'] = list(as_result)
details['_cache']['subnetpools'] = subnetpools
details['_cache']['vrf_subnets'] = vrf_subnets
# Get all the router interface ports that are on the same
# subnets as the fixed IPs for the port resource. Then
# use the router IDs from those ports to look for the
# external networks connected to those routers
if subnet_ids:
router_ports_query = (
"SELECT device_id FROM ports JOIN "
"ipallocations AS ipallocations_1 ON "
"ipallocations_1.port_id = ports.id WHERE "
"device_owner = 'network:router_interface' AND "
"ipallocations_1.subnet_id in " + subnet_in_str)
router_ports_result = session.execute(router_ports_query)
routers = [str(p.device_id) for p in router_ports_result]
else:
routers = []
ext_nets = []
if routers:
in_str = self._compose_in_filter_str(routers)
ext_net_query = (
"SELECT externalnetworks.network_id as id, "
"networks_1.project_id as tenant_id,"
"net_map_1.epg_name, net_map_1.epg_tenant_name, "
"net_map_1.epg_app_profile_name, net_ext_1.nat_type, "
"net_ext_1.external_network_dn FROM "
"externalnetworks JOIN networks AS networks_1 ON "
"networks_1.id = externalnetworks.network_id JOIN "
"apic_aim_network_mappings AS net_map_1 ON "
"net_map_1.network_id = externalnetworks.network_id JOIN "
"apic_aim_network_extensions AS net_ext_1 ON "
"net_ext_1.network_id = externalnetworks.network_id JOIN "
"ports AS ports_1 ON "
"ports_1.network_id = externalnetworks.network_id JOIN "
"routerports AS routerports_1 ON "
"routerports_1.port_id = ports_1.id WHERE "
"routerports_1.router_id in " + in_str)
ext_nets = session.execute(ext_net_query)
ext_nets = list(ext_nets)
details['_cache']['ext_nets'] = ext_nets
# For nested domain
nested_allowed_vlans_query = (
"SELECT vlan FROM "
"apic_aim_network_nested_domain_allowed_vlans WHERE "
"network_id = '" + network['id'] + "'")
nested_allowed_vlans_result = session.execute(
nested_allowed_vlans_query)
network['apic:nested_domain_allowed_vlans'] = []
for allowed_vlan in nested_allowed_vlans_result:
network['apic:nested_domain_allowed_vlans'].append(
allowed_vlan.vlan)
details['_cache']['network'] = network
# For PT
pt_query = (
"SELECT id, policy_target_group_id, cluster_id FROM "
"gp_policy_targets WHERE "
"port_id = '" + port['id'] + "'")
pt = session.execute(pt_query).first()
if pt:
pt = dict(pt)
segmentation_label_query = (
"SELECT segmentation_label FROM "
"gp_apic_mapping_segmentation_labels WHERE "
"policy_target_id = '" + pt['id'] + "'")
st_label_result = session.execute(segmentation_label_query)
pt['segmentation_labels'] = [x['segmentation_label']
for x in st_label_result]
group_default_gw_query = (
"SELECT group_default_gateway FROM "
"gp_proxy_gateway_mappings WHERE "
"policy_target_id = '" + pt['id'] + "'")
group_default_gw = session.execute(group_default_gw_query).first()
if group_default_gw:
pt['group_default_gateway'] = group_default_gw[
'group_default_gateway']
details['_cache']['pt'] = pt
# For L2P
l2p_query = (
"SELECT inject_default_route FROM "
"gp_l2_policies WHERE "
"network_id = '" + network['id'] + "'")
l2p = session.execute(l2p_query).first()
details['_cache']['l2p'] = l2p
def _get_gbp_details_new(self, context, request, host):
with context.session.begin(subtransactions=True):
device = request.get('device')
core_plugin = self._core_plugin
port_id = core_plugin._device_to_port_id(context, device)
port_query = ("SELECT project_id, id, name, network_id, "
"mac_address, admin_state_up, device_id, "
"device_owner, port_security_enabled, host, "
"vif_type, vif_details FROM "
"ports JOIN portsecuritybindings AS "
"portsecuritybindings_1 ON "
"ports.id = portsecuritybindings_1.port_id JOIN "
"ml2_port_bindings AS ml2_port_bindings_1 ON "
"ports.id = ml2_port_bindings_1.port_id "
"WHERE ports.id = '" + port_id + "'")
port_result = context.session.execute(port_query)
# in UT env., sqlite doesn't implement rowcount so the value
# is always -1
if port_result.rowcount != 1 and port_result.rowcount != -1:
LOG.warning("Can't find the matching port DB record for "
"this port ID: %(port_id)s",
{'port_id': port_id})
return {'device': request.get('device')}
port = port_result.first()
# Build up the ORM relationship manually
port = dict(port)
binding_level_query = ("SELECT segment_id FROM "
"ml2_port_binding_levels WHERE "
"port_id = '" + port_id + "' AND "
"host = '" + port['host'] + "'")
binding_levels = context.session.execute(binding_level_query)
port['binding_levels'] = []
for binding_level in binding_levels:
port['binding_levels'].append(
{'segment_id': binding_level['segment_id']})
ip_query = ("SELECT ip_address, subnet_id FROM "
"ipallocations WHERE "
"port_id = '" + port_id + "'")
ip_result = context.session.execute(ip_query)
port['fixed_ips'] = []
for ip in ip_result:
port['fixed_ips'].append(
{'ip_address': ip['ip_address'],
'subnet_id': ip['subnet_id']})
if not port['fixed_ips']:
LOG.error("fixed_ips is empty "
"for port: %s", port_id)
sg_query = ("SELECT security_group_id FROM "
"securitygroupportbindings WHERE "
"port_id = '" + port_id + "'")
sg_result = context.session.execute(sg_query)
port['security_groups'] = []
for sg in sg_result:
port['security_groups'].append(sg.security_group_id)
aap_query = ("SELECT mac_address, ip_address FROM "
"allowedaddresspairs WHERE "
"port_id = '" + port_id + "'")
aap_result = context.session.execute(aap_query)
port['allowed_address_pairs'] = []
for aap in aap_result:
port['allowed_address_pairs'].append(
{'ip_address': aap['ip_address'],
'mac_address': aap['mac_address']})
dhcp_opt_query = ("SELECT opt_name, opt_value FROM "
"extradhcpopts WHERE "
"port_id = '" + port_id + "'")
dhcp_opt_result = context.session.execute(dhcp_opt_query)
port['extra_dhcp_opts'] = []
for opt in dhcp_opt_result:
port['extra_dhcp_opts'].append(
{'opt_name': opt['opt_name'],
'opt_value': opt['opt_value']})
net_id = port['network_id']
net_query = ("SELECT id, epg_name, epg_app_profile_name, "
"epg_tenant_name, vrf_name, vrf_tenant_name, mtu, "
"nested_domain_name as 'apic:nested_domain_name', "
"nested_domain_type as 'apic:nested_domain_type', "
"nested_domain_infra_vlan as "
"'apic:nested_domain_infra_vlan', "
"nested_domain_service_vlan as "
"'apic:nested_domain_service_vlan', "
"nested_domain_node_network_vlan as "
"'apic:nested_domain_node_network_vlan', "
"dns_domain, port_security_enabled FROM "
"apic_aim_network_mappings JOIN "
"networks AS net_1 ON net_1.id = "
"apic_aim_network_mappings.network_id JOIN "
"apic_aim_network_extensions AS net_ext_1 ON "
"net_ext_1.network_id = "
"apic_aim_network_mappings.network_id "
"LEFT OUTER JOIN networksecuritybindings AS "
"networksecuritybindings_1 ON net_ext_1.network_id "
"= networksecuritybindings_1.network_id "
"LEFT OUTER JOIN networkdnsdomains AS "
"networkdnsdomains_1 ON net_ext_1.network_id = "
"networkdnsdomains_1.network_id WHERE "
"apic_aim_network_mappings.network_id = '"
+ net_id + "'")
net_result = context.session.execute(net_query)
if net_result.rowcount != 1 and net_result.rowcount != -1:
LOG.warning("Can't find the matching network DB record for "
"this network ID: %(net_id)s",
{'net_id': net_id})
return {'device': request.get('device')}
net_record = net_result.first()
network = dict(net_record)
# NOTE(ivar): removed the PROXY_PORT_PREFIX hack.
# This was needed to support network services without hotplug.
details = {'device': request.get('device'),
'enable_dhcp_optimization': self._is_dhcp_optimized(
context, port),
'enable_metadata_optimization': (
self._is_metadata_optimized(context, port)),
'port_id': port_id,
'mac_address': port['mac_address'],
'app_profile_name': network['epg_app_profile_name'],
'tenant_id': port['project_id'],
'host': port['host'],
# TODO(ivar): scope names, possibly through AIM or the
# name mapper
'ptg_tenant': network['epg_tenant_name'],
'endpoint_group_name': network['epg_name'],
'extra_ips': [],
'floating_ip': [],
'ip_mapping': [],
# Put per mac-address extra info
'extra_details': {}}
self._set_nova_vm_name(context, port, details)
details['_cache'] = {}
self._build_up_details_cache(
context.session, details, port, network)
# EPG name is different for GBP workflow
if details['_cache']['pt']:
epg = self._get_port_epg(context, port, details)
details['endpoint_group_name'] = epg.name
details['promiscuous_mode'] = self._is_port_promiscuous(
context, port, details)
mtu = self._get_port_mtu(context, port, details)
if mtu:
details['interface_mtu'] = mtu
details['dns_domain'] = network['dns_domain']
if port.get('security_groups'):
self._add_security_group_details(context, port, details)
self._add_subnet_details(context, port, details)
self._add_allowed_address_pairs_details(context, port, details)
details['l3_policy_id'] = '%s %s' % (
network['vrf_tenant_name'], network['vrf_name'])
self._add_vrf_details(context, details['l3_policy_id'], details)
# Handle FIPs of owned addresses - find other ports in the
# network whose address is owned by this port.
# If those ports have FIPs, then steal them.
fips_filter = [str(port_id)]
active_addrs = details['_cache']['owned_addresses']
if active_addrs:
in_str = self._compose_in_filter_str(active_addrs)
ports_query = (
"SELECT DISTINCT id FROM ports JOIN "
"ipallocations AS ipallocations_1 ON "
"ipallocations_1.port_id = ports.id WHERE "
"ports.network_id = '" + net_id + "' AND "
"ipallocations_1.ip_address in " + in_str)
ports_result = context.session.execute(ports_query)
fips_filter.extend([str(p['id']) for p in ports_result])
in_str = self._compose_in_filter_str(fips_filter)
fips_query = (
"SELECT id, project_id, fixed_ip_address, "
"floating_ip_address, floating_network_id, "
"fixed_port_id as port_id FROM floatingips WHERE "
"floatingips.fixed_port_id in " + in_str)
fips_result = context.session.execute(fips_query)
fips = []
for fip in fips_result:
fip_dict = dict(fip)
fips.append(fip_dict)
details['_cache']['fips'] = fips
self._add_nat_details(context, port, host, details)
self._add_extra_details(context, port, details)
self._add_segmentation_label_details(context, port, details)
self._set_dhcp_lease_time(details)
self._add_nested_domain_details(context, port, details)
details.pop('_cache', None)
# Get the neutron_details
segments_query = (
"SELECT id, network_type, physical_network FROM "
"networksegments WHERE "
"network_id = '" + net_id + "'")
segments = context.session.execute(segments_query)
bottom_segment = {}
if port['binding_levels']:
for segment in segments:
bottom_segment = dict(segment)
if (segment['id'] ==
port['binding_levels'][-1]['segment_id']):
break
neutron_details = {'admin_state_up': port['admin_state_up'],
'device_owner': port['device_owner'],
'fixed_ips': port['fixed_ips'],
'network_id': net_id,
'port_id': port_id,
'network_type':
bottom_segment.get('network_type'),
'physical_network':
bottom_segment.get('physical_network')}
context.neutron_details = neutron_details
LOG.debug("Details for port %s : %s", port['id'], details)
return details
@ -780,9 +313,7 @@ class AIMMappingRPCMixin(object):
return
details['security_group'] = []
if 'security_groups' in details['_cache']:
port_sgs = details['_cache']['security_groups']
else:
if port['security_groups']:
query = BAKERY(lambda s: s.query(
sg_models.SecurityGroup.id,
sg_models.SecurityGroup.tenant_id))
@ -791,33 +322,26 @@ class AIMMappingRPCMixin(object):
sa.bindparam('sg_ids', expanding=True)))
port_sgs = query(context.session).params(
sg_ids=port['security_groups']).all()
previous_sg_id = None
previous_tenant_id = None
for sg_id, tenant_id in port_sgs:
# This is to work around an UT sqlite bug that duplicate SG
# entries will be returned somehow if we query it with a SELECT
# statement directly
if sg_id == previous_sg_id and tenant_id == previous_tenant_id:
continue
tenant_aname = self.aim_mech_driver.name_mapper.project(
context.session, tenant_id)
details['security_group'].append(
{'policy-space': tenant_aname,
'name': sg_id})
previous_sg_id = sg_id
previous_tenant_id = tenant_id
for sg_id, tenant_id in port_sgs:
tenant_aname = self.aim_mech_driver.name_mapper.project(
context.session, tenant_id)
details['security_group'].append(
{'policy-space': tenant_aname,
'name': sg_id})
# Always include this SG which has the default arp & dhcp rules
details['security_group'].append(
{'policy-space': 'common',
'name': self.aim_mech_driver._default_sg_name})
# Child class needs to support:
# - self._get_subnet_details(context, port, details)
# - self._get_subnet_details(context, port)
def _add_subnet_details(self, context, port, details):
# This method needs to define requirements for this Mixin's child
# classes in order to fill the following result parameters:
# - subnets;
details['subnets'] = self._get_subnet_details(context, port, details)
details['subnets'] = self._get_subnet_details(context, port)
def _add_nat_details(self, context, port, host, details):
# This method needs to define requirements for this Mixin's child
@ -830,18 +354,17 @@ class AIMMappingRPCMixin(object):
context, port, host, details)
# Child class needs to support:
# - self._get_aap_details(context, port, details)
# - self._get_aap_details(context, port)
def _add_allowed_address_pairs_details(self, context, port, details):
# This method needs to define requirements for this Mixin's child
# classes in order to fill the following result parameters:
# - allowed_address_pairs
# This should take care of realizing whether a given address is
# active in the specific port
details['allowed_address_pairs'] = self._get_aap_details(context, port,
details)
details['allowed_address_pairs'] = self._get_aap_details(context, port)
# Child class needs to support:
# - self._get_vrf_subnets(context, vrf_tenant_name, vrf_name, details):
# - self._get_vrf_subnets(context, vrf_tenant_name, vrf_name):
# Subnets managed by the specific VRF.
def _add_vrf_details(self, context, vrf_id, details):
# This method needs to define requirements for this Mixin's child
@ -854,7 +377,7 @@ class AIMMappingRPCMixin(object):
details['vrf_tenant'] = tenant_name
details['vrf_name'] = name
details['vrf_subnets'] = self._get_vrf_subnets(context, tenant_name,
name, details)
name)
# Child class needs to support:
# - self._get_nested_domain(context, port)
@ -873,10 +396,10 @@ class AIMMappingRPCMixin(object):
details['nested_domain_node_network_vlan'],
details['nested_domain_allowed_vlans'],
details['nested_host_vlan']) = (
self._get_nested_domain(context, port, details))
self._get_nested_domain(context, port))
# Child class needs to support:
# - self._get_segmentation_labels(context, port, details)
# - self._get_segmentation_labels(context, port)
def _add_segmentation_label_details(self, context, port, details):
# This method needs to define requirements for this Mixin's child
# classes in order to fill the following result parameters:
@ -884,7 +407,7 @@ class AIMMappingRPCMixin(object):
# apic_segmentation_label is a GBP driver extension configured
# for the aim_mapping driver
details['segmentation_labels'] = self._get_segmentation_labels(
context, port, details)
context, port)
def _add_extra_details(self, context, port, details):
# TODO(ivar): Extra details depend on HA and SC implementation

View File

@ -1632,14 +1632,12 @@ class TestL2PolicyBase(test_nr_base.TestL2Policy, AIMBaseTestCase):
net = self.deserialize(self.fmt, req.get_response(self.api))['network']
self.assertIsNotNone(net['id'])
self.assertEqual(l2p['shared'], net['shared'])
bd = self.driver._get_bd_by_dn(
self._context, net[DN][BD])
bd = aim_resource.BridgeDomain.from_dn(net[DN][BD])
self.assertEqual(
self.name_mapper.project(None, expected_tenant), bd.tenant_name)
def _validate_epg_tenant(self, ptg, expected_tenant):
epg = self.driver._get_epg_by_dn(
self._context, ptg[DN][EPG])
epg = aim_resource.EndpointGroup.from_dn(ptg[DN][EPG])
self.assertEqual(
self.name_mapper.project(None, expected_tenant), epg.tenant_name)
@ -2632,7 +2630,7 @@ class TestGbpDetailsForML2(AIMBaseTestCase,
# REVISIT: Once the new RPC handler implementation in the apic_aim
# mechanism driver is complete and tested, move this unit test
# class to test_apic_aim (or a new module) and remove the
# enable_raw_sql and enable_new_rpc flags.
# enable_new_rpc flag.
def setUp(self, *args, **kwargs):
super(TestGbpDetailsForML2, self).setUp(*args, **kwargs)
@ -2727,10 +2725,7 @@ class TestGbpDetailsForML2(AIMBaseTestCase,
mapping['host_snat_ips'][0])
def _do_test_get_gbp_details(self, pre_vrf=None,
enable_raw_sql=False,
enable_new_rpc=False):
self.driver.aim_mech_driver.enable_raw_sql_for_device_rpc = (
enable_raw_sql)
self.driver.aim_mech_driver.enable_new_rpc = enable_new_rpc
self.driver.aim_mech_driver.apic_optimized_dhcp_lease_time = 100
ext_net1, rtr1, ext_net1_sub = self._setup_external_network(
@ -2906,9 +2901,6 @@ class TestGbpDetailsForML2(AIMBaseTestCase,
def test_get_gbp_details(self):
self._do_test_get_gbp_details()
def test_get_gbp_details_with_raw_sql(self):
self._do_test_get_gbp_details(enable_raw_sql=True)
def test_get_gbp_details_with_new_rpc(self):
self._do_test_get_gbp_details(enable_new_rpc=True)
@ -2919,14 +2911,6 @@ class TestGbpDetailsForML2(AIMBaseTestCase,
monitored=True))
self._do_test_get_gbp_details(pre_vrf=vrf)
def test_get_gbp_details_pre_existing_vrf_with_raw_sql(self):
aim_ctx = aim_context.AimContext(self.db_session)
vrf = self.aim_mgr.create(
aim_ctx, aim_resource.VRF(tenant_name='common', name='ctx1',
monitored=True))
self._do_test_get_gbp_details(pre_vrf=vrf,
enable_raw_sql=True)
def test_get_gbp_details_pre_existing_vrf_with_new_rpc(self):
aim_ctx = aim_context.AimContext(self.db_session)
vrf = self.aim_mgr.create(
@ -3372,10 +3356,7 @@ class TestPolicyTarget(AIMBaseTestCase,
'prefixlen': int(prefix)},
mapping['host_snat_ips'][0])
def _do_test_get_gbp_details(self, pre_vrf=None, enable_raw_sql=False,
enable_new_rpc=False):
self.driver.aim_mech_driver.enable_raw_sql_for_device_rpc = (
enable_raw_sql)
def _do_test_get_gbp_details(self, pre_vrf=None, enable_new_rpc=False):
self.driver.aim_mech_driver.enable_new_rpc = enable_new_rpc
self.driver.aim_mech_driver.apic_optimized_dhcp_lease_time = 100
es1, es1_sub = self._setup_external_segment(
@ -3505,10 +3486,7 @@ class TestPolicyTarget(AIMBaseTestCase,
self.assertEqual(2000, mapping['interface_mtu'])
def _do_test_gbp_details_no_pt(self, use_as=True, routed=True,
pre_vrf=None, enable_raw_sql=False,
enable_new_rpc=False):
self.driver.aim_mech_driver.enable_raw_sql_for_device_rpc = (
enable_raw_sql)
pre_vrf=None, enable_new_rpc=False):
self.driver.aim_mech_driver.enable_new_rpc = enable_new_rpc
# Create port and bind it
address_scope = self._make_address_scope_for_vrf(
@ -3627,9 +3605,6 @@ class TestPolicyTarget(AIMBaseTestCase,
def test_get_gbp_details(self):
self._do_test_get_gbp_details()
def test_get_gbp_details_with_raw_sql(self):
self._do_test_get_gbp_details(enable_raw_sql=True)
def test_get_gbp_details_with_new_rpc(self):
self._do_test_get_gbp_details(enable_new_rpc=True)
@ -3640,13 +3615,6 @@ class TestPolicyTarget(AIMBaseTestCase,
monitored=True))
self._do_test_get_gbp_details(pre_vrf=vrf)
def test_get_gbp_details_pre_existing_vrf_with_raw_sql(self):
aim_ctx = aim_context.AimContext(self.db_session)
vrf = self.aim_mgr.create(
aim_ctx, aim_resource.VRF(tenant_name='common', name='ctx1',
monitored=True))
self._do_test_get_gbp_details(pre_vrf=vrf, enable_raw_sql=True)
def test_get_gbp_details_pre_existing_vrf_with_new_rpc(self):
aim_ctx = aim_context.AimContext(self.db_session)
vrf = self.aim_mgr.create(
@ -3659,11 +3627,6 @@ class TestPolicyTarget(AIMBaseTestCase,
# RPC perspective
self._do_test_gbp_details_no_pt()
def test_get_gbp_details_no_pt_with_raw_sql(self):
# Test that traditional Neutron ports behave correctly from the
# RPC perspective
self._do_test_gbp_details_no_pt(enable_raw_sql=True)
def test_get_gbp_details_no_pt_with_new_rpc(self):
# Test that traditional Neutron ports behave correctly from the
# RPC perspective
@ -3676,13 +3639,6 @@ class TestPolicyTarget(AIMBaseTestCase,
monitored=True))
self._do_test_gbp_details_no_pt(pre_vrf=vrf)
def test_get_gbp_details_no_pt_pre_existing_vrf_with_raw_sql(self):
aim_ctx = aim_context.AimContext(self.db_session)
vrf = self.aim_mgr.create(
aim_ctx, aim_resource.VRF(tenant_name='common', name='ctx1',
monitored=True))
self._do_test_gbp_details_no_pt(pre_vrf=vrf, enable_raw_sql=True)
def test_get_gbp_details_no_pt_pre_existing_vrf_with_new_rpc(self):
aim_ctx = aim_context.AimContext(self.db_session)
vrf = self.aim_mgr.create(
@ -3693,27 +3649,17 @@ class TestPolicyTarget(AIMBaseTestCase,
def test_get_gbp_details_no_pt_no_as(self):
self._do_test_gbp_details_no_pt(use_as=False)
def test_get_gbp_details_no_pt_no_as_with_raw_sql(self):
self._do_test_gbp_details_no_pt(use_as=False, enable_raw_sql=True)
def test_get_gbp_details_no_pt_no_as_with_new_rpc(self):
self._do_test_gbp_details_no_pt(use_as=False, enable_new_rpc=True)
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_get_gbp_details_no_pt_no_as_unrouted_with_raw_sql(self):
self._do_test_gbp_details_no_pt(use_as=False, routed=False,
enable_raw_sql=True)
def test_get_gbp_details_no_pt_no_as_unrouted_with_new_rpc(self):
self._do_test_gbp_details_no_pt(use_as=False, routed=False,
enable_new_rpc=True)
def _test_gbp_details_ext_net_no_pt(self, enable_raw_sql=False,
enable_new_rpc=False):
self.driver.aim_mech_driver.enable_raw_sql_for_device_rpc = (
enable_raw_sql)
def _test_gbp_details_ext_net_no_pt(self, enable_new_rpc=False):
self.driver.aim_mech_driver.enable_new_rpc = enable_new_rpc
# Test ports created on Neutron external networks
ext_net1, _, sn1 = self._setup_external_network(
@ -3796,9 +3742,6 @@ class TestPolicyTarget(AIMBaseTestCase,
def test_gbp_details_ext_net_no_pt(self):
self._test_gbp_details_ext_net_no_pt()
def test_gbp_details_ext_net_no_pt_with_raw_sql(self):
self._test_gbp_details_ext_net_no_pt(enable_raw_sql=True)
def test_gbp_details_ext_net_no_pt_with_new_rpc(self):
self._test_gbp_details_ext_net_no_pt(enable_new_rpc=True)
@ -5754,13 +5697,6 @@ class TestNestedDomain(AIMBaseTestCase):
self.assertIsNone(details['nested_host_vlan'])
class TestNestedDomainWithRawSql(TestNestedDomain):
def setUp(self, **kwargs):
super(TestNestedDomainWithRawSql, self).setUp(**kwargs)
self.driver.aim_mech_driver.enable_raw_sql_for_device_rpc = True
class TestNestedDomainWithNewRpc(TestNestedDomain):
def setUp(self, **kwargs):
@ -6108,24 +6044,6 @@ class TestNeutronPortOperation(AIMBaseTestCase):
self.assertEqual('h1', details.get('host', 'h1'))
# REVISIT: This test class is disabled because two of its tests fail
# with the following SQL error:
#
# OperationalError: (sqlite3.OperationalError) near "'1.2.3.250'":
# syntax error [SQL: u"SELECT DISTINCT id FROM ports JOIN
# ipallocations AS ipallocations_1 ON ipallocations_1.port_id =
# ports.id WHERE ports.network_id =
# 'e7b26ed0-9b92-47b5-a5ca-fd9b19dd4bc2' AND
# ipallocations_1.ip_address in (u'1.2.3.250')"] (Background on this
# error at: http://sqlalche.me/e/e3q8)
#
# class TestNeutronPortOperationWithRawSql(TestNeutronPortOperation):
#
# def setUp(self, **kwargs):
# super(TestNeutronPortOperationWithRawSql, self).setUp(**kwargs)
# self.driver.aim_mech_driver.enable_raw_sql_for_device_rpc = True
class TestNeutronPortOperationWithNewRpc(TestNeutronPortOperation):
def setUp(self, **kwargs):
@ -6209,13 +6127,6 @@ class TestVlanAwareVM(AIMBaseTestCase):
self._do_test_gbp_details_no_pt()
class TestVlanAwareVMWithRawSql(TestVlanAwareVM):
def setUp(self, **kwargs):
super(TestVlanAwareVMWithRawSql, self).setUp(**kwargs)
self.driver.aim_mech_driver.enable_raw_sql_for_device_rpc = True
class TestVlanAwareVMWithNewRpc(TestVlanAwareVM):
def setUp(self, **kwargs):
@ -6280,13 +6191,6 @@ class TestL2PolicyRouteInjection(AIMBaseTestCase):
self._test_route_injection(False)
class TestL2PolicyRouteInjectionWithRawSql(TestL2PolicyRouteInjection):
def setUp(self, **kwargs):
super(TestL2PolicyRouteInjectionWithRawSql, self).setUp(**kwargs)
self.driver.aim_mech_driver.enable_raw_sql_for_device_rpc = True
class TestL2PolicyRouteInjectionWithNewRpc(TestL2PolicyRouteInjection):
def setUp(self, **kwargs):