AIM Policy Driver - Part 3 - Policy Rules

Policy Rule is mapped to an AIM Filter, and the Policy Classifier
is mapped to an AIM FilterEntry.

The older apic_mapping driver has been refactored slightly to create
a new library of functions called apic_mapping_lib that can be used both
from the apic_mapping driver as well as the new aim_mapping driver.

The rollback testing for the aim_driver has been enhanced by adding the
dummy_driver as second policy driver for testing, and having the dummy_driver
raise exception to trigger the rollback. This ensures that the entire code in
the aim_driver is executed before the exception, and hence the complete
rollback is tested.

This also fixes a bug in the _get_status_from_drivers() logic which resulted
in the driver extension attributes being dropped from the result that was
returned. This fix now allows validating the "apic:distinguished_names".

Change-Id: I7da7ecedd33a4c38623c944e366fbc01d216fdfa
This commit is contained in:
Sumit Naiksatam
2016-07-20 00:50:42 -07:00
parent 05c119d3a3
commit 8e463413f3
10 changed files with 680 additions and 199 deletions

View File

@@ -23,6 +23,10 @@ EXTENDED_ATTRIBUTES_2_0 = {
DIST_NAMES: {
'allow_post': False, 'allow_put': False, 'is_visible': True},
},
gp.POLICY_RULES: {
DIST_NAMES: {
'allow_post': False, 'allow_put': False, 'is_visible': True},
},
}

View File

@@ -60,12 +60,23 @@ class APICNameMapper(object):
def mapper(name_type):
"""Wrapper to land all the common operations between mappers."""
def wrap(func):
def inner(inst, session, resource_id, resource_name=None):
def inner(inst, session, resource_id, resource_name=None,
prefix=None):
# REVISIT(Bob): Optional argument for reserving characters in
# the prefix?
saved_name = inst.db.get_apic_name(session,
resource_id,
name_type)
if saved_name:
result = saved_name[0]
# REVISIT(Sumit): Should this name mapper be aware of
# this prefixing logic, or should we instead prepend
# the prefix at the point from where this is being
# invoked. The latter approach has the disadvantage
# of having to replicate the logic in many places.
if prefix:
result = prefix + result
result = truncate(result, MAX_APIC_NAME_LENGTH)
return result
name = ''
try:
@@ -94,6 +105,9 @@ class APICNameMapper(object):
inst.db.add_apic_name(session, resource_id,
name_type, result)
if prefix:
result = prefix + result
result = truncate(result, MAX_APIC_NAME_LENGTH)
return result
return inner
return wrap
@@ -155,10 +169,9 @@ class APICNameMapper(object):
return policy_rule_set['name']
@mapper(NAME_TYPE_POLICY_RULE)
def policy_rule(self, context, policy_rule_id):
policy_rule = context._plugin.get_policy_rule(context._plugin_context,
policy_rule_id)
return policy_rule['name']
def policy_rule(self, context, policy_rule_id,
policy_rule_name=None):
return policy_rule_name
@mapper(NAME_TYPE_EXTERNAL_SEGMENT)
def external_segment(self, context, external_segment_id):

View File

@@ -29,10 +29,19 @@ from gbpservice.neutron.services.grouppolicy.common import (
from gbpservice.neutron.services.grouppolicy.common import exceptions as gpexc
from gbpservice.neutron.services.grouppolicy.drivers import (
neutron_resources as nrd)
from gbpservice.neutron.services.grouppolicy.drivers.cisco.apic import (
apic_mapping_lib as alib)
from gbpservice.neutron.services.grouppolicy import plugin as gbp_plugin
LOG = logging.getLogger(__name__)
FORWARD = 'Forward'
REVERSE = 'Reverse'
FILTER_DIRECTIONS = {FORWARD: False, REVERSE: True}
FORWARD_FILTER_ENTRIES = 'Forward-FilterEntries'
REVERSE_FILTER_ENTRIES = 'Reverse-FilterEntries'
# Definitions duplicated from apicapi lib
APIC_OWNED = 'apic_owned_'
@@ -190,33 +199,74 @@ class AIMMappingDriver(nrd.CommonNeutronBase):
@log.log_method_call
def create_policy_rule_precommit(self, context):
pass
# TODO(sumit): uncomment the following when AIM supports TenantFilter
# aim_context = aim_manager.AimContext(context._plugin_context.session)
# tenant = context.current['tenant_id']
# pr_id = context.current['id']
# pr_name = context.current['name']
# rn = self.mapper.tenant_filter(tenant, pr_id, name=pr_name)
# tf = aim_resource.TenantFilter(tenant_rn=tenant, rn=rn)
# self.aim.create(aim_context, tf)
# pr_db = context._plugin_context.session.query(
# gpdb.PolicyRule).get(context.current['id'])
# context._plugin_context.session.expunge(pr_db)
# TODO(sumit): uncomment the following line when the GBP resource
# is appropriately extended to hold AIM references
# pr_db['aim_id'] = rn
# context._plugin_context.session.add(pr_db)
entries = alib.get_filter_entries_for_policy_rule(context)
if entries['forward_rules']:
session = context._plugin_context.session
aim_ctx = aim_context.AimContext(session)
aim_filter = self._aim_filter(session, context.current)
self.aim.create(aim_ctx, aim_filter)
self._create_aim_filter_entries(session, aim_ctx, aim_filter,
entries['forward_rules'])
if entries['reverse_rules']:
# Also create reverse rule
aim_filter = self._aim_filter(session, context.current,
reverse_prefix=True)
self.aim.create(aim_ctx, aim_filter)
self._create_aim_filter_entries(session, aim_ctx, aim_filter,
entries['reverse_rules'])
@log.log_method_call
def update_policy_rule_precommit(self, context):
self.delete_policy_rule_precommit(context)
self.create_policy_rule_precommit(context)
@log.log_method_call
def delete_policy_rule_precommit(self, context):
pass
# TODO(sumit): uncomment the following when AIM supports TenantFilter
# aim_context = aim_manager.AimContext(context._plugin_context.session)
# tenant = context.current['tenant_id']
# pr_id = context.current['id']
# rn = self.mapper.tenant_filter(tenant, pr_id)
# tf = aim_resource.TenantFilter(tenant_rn=tenant, rn=rn)
# self.aim.delete(aim_context, tf)
session = context._plugin_context.session
aim_ctx = aim_context.AimContext(session)
aim_filter = self._aim_filter(session, context.current)
aim_filter_entries = self.aim.find(
aim_ctx, aim_resource.FilterEntry,
tenant_name=aim_filter.tenant_name,
filter_name=aim_filter.name)
for entry in aim_filter_entries:
self.aim.delete(aim_ctx, entry)
self.aim.delete(aim_ctx, aim_filter)
aim_reverse_filter = self._aim_filter(
session, context.current, reverse_prefix=True)
if aim_reverse_filter:
aim_reverse_filter_entries = self.aim.find(
aim_ctx, aim_resource.FilterEntry,
tenant_name=aim_reverse_filter.tenant_name,
filter_name=aim_reverse_filter.name)
for entry in aim_reverse_filter_entries:
self.aim.delete(aim_ctx, entry)
self.aim.delete(aim_ctx, aim_reverse_filter)
self.name_mapper.delete_apic_name(session, context.current['id'])
@log.log_method_call
def extend_policy_rule_dict(self, session, result):
result[cisco_apic.DIST_NAMES] = {}
aim_filter_entries = self._get_aim_filter_entries(session, result)
for k, v in aim_filter_entries.iteritems():
dn_list = []
for entry in v:
dn_list.append(entry.dn)
if k == FORWARD:
result[cisco_apic.DIST_NAMES].update(
{FORWARD_FILTER_ENTRIES: dn_list})
else:
result[cisco_apic.DIST_NAMES].update(
{REVERSE_FILTER_ENTRIES: dn_list})
@log.log_method_call
def get_policy_rule_status(self, context):
session = context._plugin_context.session
aim_filters = self._get_aim_filters(session, context.current)
aim_filter_entries = self._get_aim_filter_entries(session,
context.current)
context.current['status'] = self._merge_aim_status(
session, aim_filters.values() + aim_filter_entries.values())
def _aim_tenant_name(self, session, tenant_id):
tenant_name = self.name_mapper.tenant(session, tenant_id)
@@ -256,6 +306,79 @@ class AIMMappingDriver(nrd.CommonNeutronBase):
LOG.debug("Got epg: %s", epg_fetched.__dict__)
return epg_fetched
def _aim_filter(self, session, pr, reverse_prefix=False):
# This returns a new AIM Filter resource
tenant_id = pr['tenant_id']
tenant_name = self._aim_tenant_name(session, tenant_id)
id = pr['id']
name = pr['name']
if reverse_prefix:
filter_name = self.name_mapper.policy_rule(
session, id, resource_name=name, prefix=alib.REVERSE_PREFIX)
else:
filter_name = self.name_mapper.policy_rule(session, id,
resource_name=name)
LOG.debug("Mapped policy_rule_id %(id)s with name %(name)s to",
"%(apic_name)s",
{'id': id, 'name': name, 'apic_name': filter_name})
kwargs = {'tenant_name': str(tenant_name),
'name': str(filter_name)}
aim_filter = aim_resource.Filter(**kwargs)
return aim_filter
def _aim_filter_entry(self, session, aim_filter, filter_entry_name,
filter_entry_attrs):
# This returns a new AIM FilterEntry resource
tenant_name = aim_filter.tenant_name
filter_name = aim_filter.name
kwargs = {'tenant_name': tenant_name,
'filter_name': filter_name,
'name': filter_entry_name}
kwargs.update(filter_entry_attrs)
aim_filter_entry = aim_resource.FilterEntry(**kwargs)
return aim_filter_entry
def _create_aim_filter_entries(self, session, aim_ctx, aim_filter,
filter_entries):
for k, v in filter_entries.iteritems():
aim_filter_entry = self._aim_filter_entry(
session, aim_filter, k, v)
self.aim.create(aim_ctx, aim_filter_entry)
def _get_aim_filters(self, session, policy_rule):
# This gets the Forward and Reverse Filters from the AIM DB
aim_ctx = aim_context.AimContext(session)
filters = {}
for k, v in FILTER_DIRECTIONS.iteritems():
aim_filter = self._aim_filter(session, policy_rule, v)
aim_filter_fetched = self.aim.get(aim_ctx, aim_filter)
if not aim_filter_fetched:
LOG.debug("No %s Filter found in AIM DB", k)
else:
LOG.debug("Got %s Filter: %s",
(aim_filter_fetched.__dict__, k))
filters[k] = aim_filter_fetched
return filters
def _get_aim_filter_entries(self, session, policy_rule):
# This gets the Forward and Reverse FilterEntries from the AIM DB
aim_ctx = aim_context.AimContext(session)
filters = self._get_aim_filters(session, policy_rule)
filters_entries = {}
for k, v in filters.iteritems():
aim_filter_entries = self.aim.find(
aim_ctx, aim_resource.FilterEntry,
tenant_name=v.tenant_name, filter_name=v.name)
if not aim_filter_entries:
LOG.debug("No %s FilterEntry found in AIM DB", k)
else:
LOG.debug("Got %s FilterEntry: %s",
(aim_filter_entries, k))
filters_entries[k] = aim_filter_entries
return filters_entries
def _aim_bridge_domain(self, session, tenant_id, network_id, network_name):
# This returns a new AIM BD resource
tenant_name = self._aim_tenant_name(session, tenant_id)
@@ -335,5 +458,20 @@ class AIMMappingDriver(nrd.CommonNeutronBase):
else:
return gp_const.STATUS_ACTIVE
def _merge_aim_status(self, session, aim_resource_obj_list):
# Note that this implementation assumes that this driver
# is the only policy driver configured, and no merging
# with any previous status is required.
# When merging states of multiple AIM objects, the status
# priority is ERROR > BUILD > ACTIVE.
merged_status = gp_const.STATUS_ACTIVE
for aim_obj in aim_resource_obj_list:
status = self._map_aim_status(session, aim_obj)
if status != gp_const.STATUS_ACTIVE:
merged_status = status
if merged_status == gp_const.STATUS_ERROR:
break
return merged_status
def _db_plugin(self, plugin_obj):
return super(gbp_plugin.GroupPolicyPlugin, plugin_obj)

View File

@@ -56,6 +56,8 @@ from gbpservice.neutron.services.grouppolicy.common import constants as g_const
from gbpservice.neutron.services.grouppolicy.common import exceptions as gpexc
from gbpservice.neutron.services.grouppolicy.drivers import (
resource_mapping as api)
from gbpservice.neutron.services.grouppolicy.drivers.cisco.apic import (
apic_mapping_lib as alib)
from gbpservice.neutron.services.grouppolicy.drivers.cisco.apic import (
name_manager as name_manager)
from gbpservice.neutron.services.grouppolicy.drivers.cisco.apic import (
@@ -212,7 +214,6 @@ class TenantSpecificNatEpg(model_base.BASEV2):
tenant_id = sa.Column(sa.String(36), primary_key=True)
REVERSE_PREFIX = 'reverse-'
SHADOW_PREFIX = 'Shd-'
AUTO_PREFIX = 'Auto-'
SERVICE_PREFIX = 'Svc-'
@@ -223,13 +224,8 @@ APIC_OWNED = 'apic_owned_'
APIC_OWNED_RES = 'apic_owned_res_'
PROMISCUOUS_TYPES = [n_constants.DEVICE_OWNER_DHCP,
n_constants.DEVICE_OWNER_LOADBALANCER]
ALLOWING_ACTIONS = [g_const.GP_ACTION_ALLOW, g_const.GP_ACTION_REDIRECT]
REVERTIBLE_PROTOCOLS = [n_constants.PROTO_NAME_TCP.lower(),
n_constants.PROTO_NAME_UDP.lower(),
n_constants.PROTO_NAME_ICMP.lower()]
PROXY_PORT_PREFIX = "opflex_proxy:"
EOC_PREFIX = "opflex_eoc:"
ICMP_REPLY_TYPES = ['echo-rep', 'dst-unreach', 'src-quench', 'time-exceeded']
class ApicMappingDriver(api.ResourceMappingDriver,
@@ -750,49 +746,21 @@ class ApicMappingDriver(api.ResourceMappingDriver,
pass
def create_policy_rule_postcommit(self, context, transaction=None):
action = context._plugin.get_policy_action(
context._plugin_context, context.current['policy_actions'][0])
classifier = context._plugin.get_policy_classifier(
context._plugin_context,
context.current['policy_classifier_id'])
if action['action_type'] in ALLOWING_ACTIONS:
port_min, port_max = (
gpdb.GroupPolicyMappingDbPlugin._get_min_max_ports_from_range(
classifier['port_range']))
attrs = {'etherT': 'unspecified'}
if classifier['protocol']:
attrs['etherT'] = 'ip'
attrs['prot'] = classifier['protocol'].lower()
if port_min and port_max:
attrs['dToPort'] = port_max
attrs['dFromPort'] = port_min
entries = alib.get_filter_entries_for_policy_rule(context)
if entries['forward_rules']:
tenant = self._tenant_by_sharing_policy(context.current)
policy_rule = self.name_mapper.policy_rule(context,
context.current)
entries = [attrs]
with self.apic_manager.apic.transaction(transaction) as trs:
self._create_tenant_filter(policy_rule, tenant, entries,
self._create_tenant_filter(policy_rule, tenant,
entries['forward_rules'],
transaction=trs)
# Also create reverse rule
if attrs.get('prot') in REVERTIBLE_PROTOCOLS:
if entries['reverse_rules']:
# Also create reverse rule
policy_rule = self.name_mapper.policy_rule(
context, context.current, prefix=REVERSE_PREFIX)
if attrs.get('dToPort') and attrs.get('dFromPort'):
attrs.pop('dToPort')
attrs.pop('dFromPort')
attrs['sToPort'] = port_max
attrs['sFromPort'] = port_min
if attrs['prot'] == n_constants.PROTO_NAME_TCP.lower():
# Only match on established sessions
attrs['tcpRules'] = 'est'
if attrs['prot'] == n_constants.PROTO_NAME_ICMP.lower():
# create more entries:
entries = []
for reply_type in ICMP_REPLY_TYPES:
entry = copy.deepcopy(attrs)
entry['icmpv4T'] = reply_type
entries.append(entry)
self._create_tenant_filter(policy_rule, tenant, entries,
context, context.current, prefix=alib.REVERSE_PREFIX)
self._create_tenant_filter(policy_rule, tenant,
entries['reverse_rules'],
transaction=trs)
def create_policy_rule_set_precommit(self, context):
@@ -1041,7 +1009,7 @@ class ApicMappingDriver(api.ResourceMappingDriver,
transaction=trs)
# Delete policy reverse rule
policy_rule = self.name_mapper.policy_rule(
context, context.current, prefix=REVERSE_PREFIX)
context, context.current, prefix=alib.REVERSE_PREFIX)
self.apic_manager.delete_tenant_filter(policy_rule, owner=tenant,
transaction=trs)
@@ -1345,8 +1313,8 @@ class ApicMappingDriver(api.ResourceMappingDriver,
c_prot = context.current['protocol']
# TODO(ivar): Optimize by aggregating on PRS ID
if ((o_dir != c_dir) or
((o_prot in REVERTIBLE_PROTOCOLS) !=
(c_prot in REVERTIBLE_PROTOCOLS))):
((o_prot in alib.REVERSIBLE_PROTOCOLS) !=
(c_prot in alib.REVERSIBLE_PROTOCOLS))):
for prs in context._plugin.get_policy_rule_sets(
admin_context,
filters={'id': rule['policy_rule_sets']}):
@@ -1612,7 +1580,7 @@ class ApicMappingDriver(api.ResourceMappingDriver,
rule['policy_classifier_id'])
policy_rule = self.name_mapper.policy_rule(context, rule)
reverse_policy_rule = self.name_mapper.policy_rule(
context, rule, prefix=REVERSE_PREFIX)
context, rule, prefix=alib.REVERSE_PREFIX)
rule_owner = self._tenant_by_sharing_policy(rule)
with self.apic_manager.apic.transaction(transaction) as trs:
if classifier['direction'] in in_dir:
@@ -1623,7 +1591,7 @@ class ApicMappingDriver(api.ResourceMappingDriver,
rule_owner=rule_owner)
if classifier['protocol'] and (
classifier['protocol'].lower() in
REVERTIBLE_PROTOCOLS):
alib.REVERSIBLE_PROTOCOLS):
(self.apic_manager.
manage_contract_subject_out_filter(
contract, contract, reverse_policy_rule,
@@ -1637,7 +1605,7 @@ class ApicMappingDriver(api.ResourceMappingDriver,
rule_owner=rule_owner)
if classifier['protocol'] and (
classifier['protocol'].lower() in
REVERTIBLE_PROTOCOLS):
alib.REVERSIBLE_PROTOCOLS):
(self.apic_manager.
manage_contract_subject_in_filter(
contract, contract, reverse_policy_rule,
@@ -2621,7 +2589,7 @@ class ApicMappingDriver(api.ResourceMappingDriver,
contract, owner=tenant, transaction=trs)
# Create ARP filter/subject
attrs = {'etherT': 'arp'}
attrs = alib.get_arp_filter_entry()
self._associate_service_filter(tenant, contract, 'arp',
'arp', transaction=trs, **attrs)
@@ -2645,61 +2613,40 @@ class ApicMappingDriver(api.ResourceMappingDriver,
tenant, shadow_epg, contract, provider=True,
contract_owner=tenant, transaction=trs)
entries = alib.get_service_contract_filter_entries()
# Create DNS filter/subject
attrs = {'etherT': 'ip',
'prot': 'udp',
'dToPort': 'dns',
'dFromPort': 'dns'}
self._associate_service_filter(tenant, contract, 'dns',
'dns', transaction=trs, **attrs)
attrs = {'etherT': 'ip',
'prot': 'udp',
'sToPort': 'dns',
'sFromPort': 'dns'}
'dns', transaction=trs,
**entries['dns'])
self._associate_service_filter(tenant, contract, 'dns',
'r-dns', transaction=trs, **attrs)
'r-dns', transaction=trs,
**entries['r-dns'])
# Create HTTP filter/subject
attrs = {'etherT': 'ip',
'prot': 'tcp',
'dToPort': 80,
'dFromPort': 80}
self._associate_service_filter(tenant, contract, 'http',
'http', transaction=trs, **attrs)
attrs = {'etherT': 'ip',
'prot': 'tcp',
'sToPort': 80,
'sFromPort': 80}
'http', transaction=trs,
**entries['http'])
self._associate_service_filter(tenant, contract, 'http',
'r-http', transaction=trs, **attrs)
'r-http', transaction=trs,
**entries['r-http'])
attrs = {'etherT': 'ip',
'prot': 'icmp'}
self._associate_service_filter(tenant, contract, 'icmp',
'icmp', transaction=trs, **attrs)
'icmp', transaction=trs,
**entries['icmp'])
# Create DHCP filter/subject
attrs = {'etherT': 'ip',
'prot': 'udp',
'dToPort': 68,
'dFromPort': 68,
'sToPort': 67,
'sFromPort': 67}
self._associate_service_filter(tenant, contract, 'dhcp',
'dhcp', transaction=trs, **attrs)
attrs = {'etherT': 'ip',
'prot': 'udp',
'dToPort': 67,
'dFromPort': 67,
'sToPort': 68,
'sFromPort': 68}
'dhcp', transaction=trs,
**entries['dhcp'])
self._associate_service_filter(tenant, contract, 'dhcp',
'r-dhcp', transaction=trs, **attrs)
'r-dhcp', transaction=trs,
**entries['r-dhcp'])
# Create ARP filter/subject
attrs = {'etherT': 'arp'}
self._associate_service_filter(tenant, contract, 'arp',
'arp', transaction=trs, **attrs)
'arp', transaction=trs,
**entries['arp'])
contract = self.name_mapper.l2_policy(
context, l2p, prefix=IMPLICIT_PREFIX)
@@ -3467,14 +3414,10 @@ class ApicMappingDriver(api.ResourceMappingDriver,
def _create_tenant_filter(self, rule_name, tenant, entries=None,
transaction=None):
entries = entries or []
x = 0
with self.apic_manager.apic.transaction(transaction) as trs:
for entry in entries:
for k, v in entries.iteritems():
self.apic_manager.create_tenant_filter(
rule_name, owner=tenant, transaction=trs,
entry=apic_manager.CP_ENTRY + '-' + str(x), **entry)
x += 1
rule_name, owner=tenant, transaction=trs, entry=k, **v)
def _get_l3p_allocated_subnets(self, context, l3p_id,
clean_session=True):

View File

@@ -0,0 +1,136 @@
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
import copy
from neutron.common import constants as n_constants
from gbpservice.neutron.db.grouppolicy import group_policy_mapping_db as gpdb
from gbpservice.neutron.services.grouppolicy.common import constants as g_const
ALLOWING_ACTIONS = [g_const.GP_ACTION_ALLOW, g_const.GP_ACTION_REDIRECT]
REVERSE_PREFIX = 'reverse-'
REVERSIBLE_PROTOCOLS = [n_constants.PROTO_NAME_TCP.lower(),
n_constants.PROTO_NAME_UDP.lower(),
n_constants.PROTO_NAME_ICMP.lower()]
ICMP_REPLY_TYPES = ['echo-rep', 'dst-unreach', 'src-quench', 'time-exceeded']
CP_ENTRY = 'os-entry'
def get_filter_entries_for_policy_rule(context):
# forward_rules and reverse_rules is each a dict of filter_entries
# with each entry in the dict having the filter_entry name as the
# key and the filter_entry attributes as the value
entries = {'forward_rules': None, 'reverse_rules': None}
action = context._plugin.get_policy_action(
context._plugin_context, context.current['policy_actions'][0])
classifier = context._plugin.get_policy_classifier(
context._plugin_context,
context.current['policy_classifier_id'])
x = 0
if action['action_type'] in ALLOWING_ACTIONS:
port_min, port_max = (
gpdb.GroupPolicyMappingDbPlugin._get_min_max_ports_from_range(
classifier['port_range']))
f_attrs = {'etherT': 'unspecified'}
if classifier['protocol']:
f_attrs['etherT'] = 'ip'
f_attrs['prot'] = classifier['protocol'].lower()
if port_min and port_max:
f_attrs['dToPort'] = port_max
f_attrs['dFromPort'] = port_min
entries['forward_rules'] = {_get_filter_entry_name(x): f_attrs}
# Also create reverse rule
if f_attrs.get('prot') in REVERSIBLE_PROTOCOLS:
r_entries = {}
r_attrs = copy.deepcopy(f_attrs)
if r_attrs.get('dToPort') and r_attrs.get('dFromPort'):
r_attrs.pop('dToPort')
r_attrs.pop('dFromPort')
r_attrs['sToPort'] = port_max
r_attrs['sFromPort'] = port_min
if r_attrs['prot'] == n_constants.PROTO_NAME_TCP.lower():
# Only match on established sessions
r_attrs['tcpRules'] = 'est'
r_entries[_get_filter_entry_name(x)] = r_attrs
if r_attrs['prot'] == n_constants.PROTO_NAME_ICMP.lower():
r_entries = {}
# create more entries:
for reply_type in ICMP_REPLY_TYPES:
x += 1
r_entry = copy.deepcopy(r_attrs)
r_entry['icmpv4T'] = reply_type
r_entries[_get_filter_entry_name(x)] = r_entry
entries['reverse_rules'] = r_entries
return entries
def get_arp_filter_entry():
return {'etherT': 'arp'}
def get_service_contract_filter_entries():
entries = {}
# DNS
dns_attrs = {'etherT': 'ip',
'prot': 'udp',
'dToPort': 'dns',
'dFromPort': 'dns'}
entries['dns'] = dns_attrs
r_dns_attrs = {'etherT': 'ip',
'prot': 'udp',
'sToPort': 'dns',
'sFromPort': 'dns'}
entries['r-dns'] = r_dns_attrs
# HTTP
http_attrs = {'etherT': 'ip',
'prot': 'tcp',
'dToPort': 80,
'dFromPort': 80}
entries['http'] = http_attrs
r_http_attrs = {'etherT': 'ip',
'prot': 'tcp',
'sToPort': 80,
'sFromPort': 80}
entries['r-http'] = r_http_attrs
icmp_attrs = {'etherT': 'ip',
'prot': 'icmp'}
entries['icmp'] = icmp_attrs
# DHCP
dhcp_attrs = {'etherT': 'ip',
'prot': 'udp',
'dToPort': 68,
'dFromPort': 68,
'sToPort': 67,
'sFromPort': 67}
entries['dhcp'] = dhcp_attrs
r_dhcp_attrs = {'etherT': 'ip',
'prot': 'udp',
'dToPort': 67,
'dFromPort': 67,
'sToPort': 68,
'sFromPort': 68}
entries['r-dhcp'] = r_dhcp_attrs
# ARP
arp_attrs = get_arp_filter_entry()
entries['arp'] = arp_attrs
return entries
def _get_filter_entry_name(entry_number):
return CP_ENTRY + '-' + str(entry_number)

View File

@@ -47,3 +47,6 @@ class AIMExtensionDriver(api.ExtensionDriver):
def extend_policy_target_group_dict(self, session, result):
self._pd.extend_policy_target_group_dict(session, result)
def extend_policy_rule_dict(self, session, result):
self._pd.extend_policy_rule_dict(session, result)

View File

@@ -343,7 +343,6 @@ class GroupPolicyPlugin(group_policy_mapping_db.GroupPolicyMappingDbPlugin):
def _get_status_from_drivers(self, context, context_name, resource_name,
resource_id, resource):
result = resource
status = resource['status']
status_details = resource['status_details']
policy_context = getattr(p_context, context_name)(
@@ -360,10 +359,12 @@ class GroupPolicyPlugin(group_policy_mapping_db.GroupPolicyMappingDbPlugin):
updated_status_details}}
session = context.session
with session.begin(subtransactions=True):
result = getattr(super(GroupPolicyPlugin, self),
"update_" + resource_name)(
context, _resource['id'], new_status)
return result
getattr(super(GroupPolicyPlugin, self),
"update_" + resource_name)(
context, _resource['id'], new_status)
resource['status'] = updated_status
resource['status_details'] = updated_status_details
return resource
def _get_resource(self, context, resource_name, resource_id,
gbp_context_name, fields=None):
@@ -412,7 +413,7 @@ class GroupPolicyPlugin(group_policy_mapping_db.GroupPolicyMappingDbPlugin):
result)
new_filtered_results.append(result)
new_filtered_results = new_filtered_results or filtered_results
return [self._fields(result, fields) for result in
return [self._fields(nfresult, fields) for nfresult in
new_filtered_results]
@resource_registry.tracked_resources(

View File

@@ -14,6 +14,7 @@
import mock
from aim.api import resource as aim_resource
from aim.api import status as aim_status
from aim import context as aim_context
from aim.db import model_base as aim_model_base
from keystoneclient.v3 import client as ksc_client
@@ -27,6 +28,8 @@ from gbpservice.neutron.plugins.ml2plus.drivers.apic_aim import model
from gbpservice.neutron.services.grouppolicy.common import (
constants as gp_const)
from gbpservice.neutron.services.grouppolicy import config
from gbpservice.neutron.services.grouppolicy.drivers.cisco.apic import (
apic_mapping_lib as alib)
from gbpservice.neutron.tests.unit.plugins.ml2plus import (
test_apic_aim as test_aim_md)
from gbpservice.neutron.tests.unit.services.grouppolicy import (
@@ -46,7 +49,12 @@ class AIMBaseTestCase(test_nr_base.CommonNeutronBaseTestCase,
def setUp(self, policy_drivers=None, core_plugin=None, ml2_options=None,
sc_plugin=None, **kwargs):
core_plugin = core_plugin or ML2PLUS_PLUGIN
policy_drivers = policy_drivers or ['aim_mapping']
# The dummy driver configured here is meant to be the second driver
# invoked and helps in rollback testing. We mock the dummy driver
# methods to raise an exception and validate that DB operations
# performed up until that point (including those in the aim_mapping)
# driver are rolled back.
policy_drivers = policy_drivers or ['aim_mapping', 'dummy']
ml2_opts = ml2_options or {'mechanism_drivers': ['logger', 'apic_aim'],
'extension_drivers': ['apic_aim'],
'type_drivers': ['opflex', 'local', 'vlan'],
@@ -95,14 +103,6 @@ class AIMBaseTestCase(test_nr_base.CommonNeutronBaseTestCase,
'aim_mapping'].obj.name_mapper)
return self._name_mapper
class TestL2Policy(test_nr_base.TestL2Policy, AIMBaseTestCase):
pass
class TestPolicyTargetGroup(AIMBaseTestCase):
def _test_aim_resource_status(self, aim_resource_obj, gbp_resource):
aim_status = self.aim_mgr.get_status(self._aim_context,
aim_resource_obj)
@@ -113,6 +113,14 @@ class TestPolicyTargetGroup(AIMBaseTestCase):
else:
self.assertEqual(gp_const.STATUS_ACTIVE, gbp_resource['status'])
class TestL2Policy(test_nr_base.TestL2Policy, AIMBaseTestCase):
pass
class TestPolicyTargetGroup(AIMBaseTestCase):
def test_policy_target_group_lifecycle_implicit_l2p(self):
ptg = self.create_policy_target_group(
name="ptg1")['policy_target_group']
@@ -140,11 +148,15 @@ class TestPolicyTargetGroup(AIMBaseTestCase):
self.assertEqual(aim_epg_name, aim_epgs[0].name)
self.assertEqual(aim_tenant_name, aim_epgs[0].tenant_name)
self.assertEqual(aim_epgs[0].dn,
ptg['apic:distinguished_names']['EndpointGroup'])
self._test_aim_resource_status(aim_epgs[0], ptg)
self.assertEqual(aim_epgs[0].dn,
ptg_show['apic:distinguished_names']['EndpointGroup'])
self._test_aim_resource_status(aim_epgs[0], ptg_show)
# TODO(Sumit): Test update
self.delete_policy_target_group(ptg_id, expected_res_status=204)
self.show_policy_target_group(ptg_id, expected_res_status=404)
# Implicitly created subnet should be deleted
@@ -165,7 +177,8 @@ class TestPolicyTargetGroup(AIMBaseTestCase):
ptg = self.create_policy_target_group(
name="ptg1", l2_policy_id=l2p_id)['policy_target_group']
ptg_id = ptg['id']
self.show_policy_target_group(ptg_id, expected_res_status=200)
ptg_show = self.show_policy_target_group(
ptg_id, expected_res_status=200)['policy_target_group']
self.assertEqual(l2p_id, ptg['l2_policy_id'])
self.show_l2_policy(ptg['l2_policy_id'], expected_res_status=200)
req = self.new_show_request('subnets', ptg['subnets'][0], fmt=self.fmt)
@@ -187,7 +200,13 @@ class TestPolicyTargetGroup(AIMBaseTestCase):
self.assertEqual(aim_epg_name, aim_epgs[0].name)
self.assertEqual(aim_tenant_name, aim_epgs[0].tenant_name)
self.assertEqual(aim_epgs[0].dn,
ptg['apic:distinguished_names']['EndpointGroup'])
self._test_aim_resource_status(aim_epgs[0], ptg)
self.assertEqual(aim_epgs[0].dn,
ptg_show['apic:distinguished_names']['EndpointGroup'])
# TODO(Sumit): Test update
self.delete_policy_target_group(ptg_id, expected_res_status=204)
self.show_policy_target_group(ptg_id, expected_res_status=404)
@@ -226,11 +245,11 @@ class TestPolicyTargetGroup(AIMBaseTestCase):
class TestPolicyTargetGroupRollback(AIMBaseTestCase):
def test_policy_target_group_create_fail(self):
# REVISIT(Sumit): This exception should be raised from the deepest
# point. Currently this is the deepest point.
orig_func = self._gbp_plugin.policy_driver_manager.policy_drivers[
'dummy'].obj.create_policy_target_group_precommit
self._gbp_plugin.policy_driver_manager.policy_drivers[
'aim_mapping'].obj._validate_and_add_subnet = mock.Mock(
side_effect=Exception)
'dummy'].obj.create_policy_target_group_precommit = (
mock.Mock(side_effect=Exception))
self.create_policy_target_group(name="ptg1", expected_res_status=500)
self.assertEqual([], self._plugin.get_subnets(self._context))
self.assertEqual([], self._plugin.get_networks(self._context))
@@ -238,12 +257,15 @@ class TestPolicyTargetGroupRollback(AIMBaseTestCase):
self._context))
self.assertEqual([], self._gbp_plugin.get_l2_policies(self._context))
self.assertEqual([], self._gbp_plugin.get_l3_policies(self._context))
# restore mock
self._gbp_plugin.policy_driver_manager.policy_drivers[
'dummy'].obj.create_policy_target_group_precommit = orig_func
def test_policy_target_group_update_fail(self):
# REVISIT(Sumit): This exception should be raised from the deepest
# point. Currently this is the deepest point.
orig_func = self._gbp_plugin.policy_driver_manager.policy_drivers[
'dummy'].obj.update_policy_target_group_precommit
self._gbp_plugin.policy_driver_manager.policy_drivers[
'aim_mapping'].obj.update_policy_target_group_precommit = (
'dummy'].obj.update_policy_target_group_precommit = (
mock.Mock(side_effect=Exception))
ptg = self.create_policy_target_group(name="ptg1")
ptg_id = ptg['policy_target_group']['id']
@@ -253,12 +275,15 @@ class TestPolicyTargetGroupRollback(AIMBaseTestCase):
expected_res_status=200)
self.assertEqual(ptg['policy_target_group']['name'],
new_ptg['policy_target_group']['name'])
# restore mock
self._gbp_plugin.policy_driver_manager.policy_drivers[
'dummy'].obj.update_policy_target_group_precommit = orig_func
def test_policy_target_group_delete_fail(self):
# REVISIT(Sumit): This exception should be raised from the deepest
# point. Currently this is the deepest point.
orig_func = self._gbp_plugin.policy_driver_manager.policy_drivers[
'dummy'].obj.delete_l3_policy_precommit
self._gbp_plugin.policy_driver_manager.policy_drivers[
'aim_mapping'].obj.delete_l3_policy_precommit = mock.Mock(
'dummy'].obj.delete_l3_policy_precommit = mock.Mock(
side_effect=Exception)
ptg = self.create_policy_target_group(name="ptg1")
ptg_id = ptg['policy_target_group']['id']
@@ -273,6 +298,9 @@ class TestPolicyTargetGroupRollback(AIMBaseTestCase):
self.show_policy_target_group(ptg_id, expected_res_status=200)
self.show_l2_policy(l2p_id, expected_res_status=200)
self.show_l3_policy(l3p_id, expected_res_status=200)
# restore mock
self._gbp_plugin.policy_driver_manager.policy_drivers[
'dummy'].obj.delete_l3_policy_precommit = orig_func
class TestPolicyTarget(AIMBaseTestCase):
@@ -305,10 +333,10 @@ class TestPolicyTarget(AIMBaseTestCase):
class TestPolicyTargetRollback(AIMBaseTestCase):
def test_policy_target_create_fail(self):
# REVISIT(Sumit): This exception should be raised from the deepest
# point. Currently this is the deepest point.
orig_func = self._gbp_plugin.policy_driver_manager.policy_drivers[
'dummy'].obj.create_policy_target_precommit
self._gbp_plugin.policy_driver_manager.policy_drivers[
'aim_mapping'].obj._mark_port_owned = mock.Mock(
'dummy'].obj.create_policy_target_precommit = mock.Mock(
side_effect=Exception)
ptg_id = self.create_policy_target_group(
name="ptg1")['policy_target_group']['id']
@@ -318,12 +346,15 @@ class TestPolicyTargetRollback(AIMBaseTestCase):
self.assertEqual([],
self._gbp_plugin.get_policy_targets(self._context))
self.assertEqual([], self._plugin.get_ports(self._context))
# restore mock
self._gbp_plugin.policy_driver_manager.policy_drivers[
'dummy'].obj.create_policy_target_precommit = orig_func
def test_policy_target_update_fail(self):
# REVISIT(Sumit): This exception should be raised from the deepest
# point. Currently this is the deepest point.
orig_func = self._gbp_plugin.policy_driver_manager.policy_drivers[
'dummy'].obj.update_policy_target_precommit
self._gbp_plugin.policy_driver_manager.policy_drivers[
'aim_mapping'].obj.update_policy_target_precommit = mock.Mock(
'dummy'].obj.update_policy_target_precommit = mock.Mock(
side_effect=Exception)
ptg = self.create_policy_target_group(
name="ptg1")['policy_target_group']
@@ -335,10 +366,16 @@ class TestPolicyTargetRollback(AIMBaseTestCase):
name="new name")
new_pt = self.show_policy_target(pt_id, expected_res_status=200)
self.assertEqual(pt['name'], new_pt['policy_target']['name'])
# restore mock
self._gbp_plugin.policy_driver_manager.policy_drivers[
'dummy'].obj.update_policy_target_precommit = orig_func
def test_policy_target_delete_fail(self):
# REVISIT(Sumit): This exception should be raised from the deepest
# point. Currently this is the deepest point.
orig_func = self._gbp_plugin.policy_driver_manager.policy_drivers[
'dummy'].obj.delete_policy_target_precommit
self._gbp_plugin.policy_driver_manager.policy_drivers[
'dummy'].obj.delete_policy_target_precommit = mock.Mock(
side_effect=Exception)
self._gbp_plugin.policy_driver_manager.policy_drivers[
'aim_mapping'].obj._delete_port = mock.Mock(
side_effect=Exception)
@@ -356,12 +393,97 @@ class TestPolicyTargetRollback(AIMBaseTestCase):
req = self.new_show_request('ports', port_id, fmt=self.fmt)
res = self.deserialize(self.fmt, req.get_response(self.api))
self.assertIsNotNone(res['port']['id'])
# restore mock
self._gbp_plugin.policy_driver_manager.policy_drivers[
'dummy'].obj.update_policy_target_precommit = orig_func
class TestPolicyRule(AIMBaseTestCase):
class TestAIMStatus(AIMBaseTestCase):
def _test_policy_rule_lifecycle(self):
# TODO(Sumit): Enable this test when the AIM driver is ready
def test_status_merging(self):
aim_driver = self._gbp_plugin.policy_driver_manager.policy_drivers[
'aim_mapping'].obj
def mock_get_aim_status(aim_context, aim_resource):
astatus = aim_status.AciStatus()
if aim_resource['status'] == '':
return
elif aim_resource['status'] == 'build':
astatus.sync_status = aim_status.AciStatus.SYNC_PENDING
elif aim_resource['status'] == 'error':
astatus.sync_status = aim_status.AciStatus.SYNC_FAILED
else:
astatus.sync_status = aim_status.AciStatus.SYNCED
return astatus
orig_get_status = self.aim_mgr.get_status
self.aim_mgr.get_status = mock_get_aim_status
aim_active = {'status': 'active'}
aim_objs_active = [aim_active, aim_active, aim_active]
mstatus = aim_driver._merge_aim_status(self._neutron_context.session,
aim_objs_active)
self.assertEqual(gp_const.STATUS_ACTIVE, mstatus)
aim_build = {'status': 'build'}
aim_none = {'status': ''}
aim_objs_build = [aim_active, aim_active, aim_build]
mstatus = aim_driver._merge_aim_status(self._neutron_context.session,
aim_objs_build)
self.assertEqual(gp_const.STATUS_BUILD, mstatus)
aim_objs_build = [aim_active, aim_active, aim_none]
mstatus = aim_driver._merge_aim_status(self._neutron_context.session,
aim_objs_build)
self.assertEqual(gp_const.STATUS_BUILD, mstatus)
aim_error = {'status': 'error'}
aim_objs_error = [aim_active, aim_build, aim_error]
mstatus = aim_driver._merge_aim_status(self._neutron_context.session,
aim_objs_error)
self.assertEqual(gp_const.STATUS_ERROR, mstatus)
self.aim_mgr.get_status = orig_get_status
class TestPolicyRuleBase(AIMBaseTestCase):
def _test_policy_rule_create_update_result(self, aim_tenant_name,
aim_filter_name,
aim_reverse_filter_name,
policy_rule):
filter_entries = []
aim_obj_list = []
for filter_name in [aim_filter_name, aim_reverse_filter_name]:
aim_filters = self.aim_mgr.find(
self._aim_context, aim_resource.Filter, name=filter_name)
aim_obj_list.append(aim_filters[0])
self.assertEqual(1, len(aim_filters))
self.assertEqual(filter_name, aim_filters[0].name)
self.assertEqual(aim_tenant_name, aim_filters[0].tenant_name)
aim_filter_entries = self.aim_mgr.find(
self._aim_context, aim_resource.FilterEntry,
tenant_name=aim_filters[0].tenant_name,
filter_name=aim_filters[0].name)
self.assertEqual(1, len(aim_filter_entries))
self.assertEqual('os-entry-0', aim_filter_entries[0].name)
filter_entries.append(aim_filter_entries[0])
aim_obj_list.append(filter_entries)
prule = policy_rule
self.assertEqual(
filter_entries[0].dn,
prule['apic:distinguished_names']['Forward-FilterEntries'][0])
self.assertEqual(
filter_entries[1].dn,
prule['apic:distinguished_names']['Reverse-FilterEntries'][0])
merged_status = self._gbp_plugin.policy_driver_manager.policy_drivers[
'aim_mapping'].obj._merge_aim_status(self._neutron_context.session,
aim_obj_list)
self.assertEqual(merged_status, prule['status'])
class TestPolicyRule(TestPolicyRuleBase):
def test_policy_rule_lifecycle(self):
action1 = self.create_policy_action(
action_type='redirect')['policy_action']
classifier = self.create_policy_classifier(
@@ -372,21 +494,134 @@ class TestPolicyRule(AIMBaseTestCase):
name="pr1", policy_classifier_id=classifier['id'],
policy_actions=[action1['id']])['policy_rule']
pr_id = pr['id']
pr_name = pr['name']
self.show_policy_rule(pr_id, expected_res_status=200)
tenant = pr['tenant_id']
pr_id = pr['id']
pr_name = pr['name']
rn = self._aim_mapper.tenant_filter(tenant, pr_id, name=pr_name)
aim_pr = self.aim_mgr.find(
self._aim_context, aim_resource.TenantFilter, rn=rn)
self.assertEqual(1, len(aim_pr))
self.assertEqual(rn, aim_pr[0].rn)
self.assertEqual(tenant, aim_pr[0].tenant_rn)
aim_filter_name = str(self.name_mapper.policy_rule(
self._neutron_context.session, pr_id, pr_name))
aim_reverse_filter_name = str(self.name_mapper.policy_rule(
self._neutron_context.session, pr_id, pr_name,
prefix=alib.REVERSE_PREFIX))
aim_tenant_name = str(self.name_mapper.tenant(
self._neutron_context.session, self._tenant_id))
self._test_policy_rule_create_update_result(
aim_tenant_name, aim_filter_name, aim_reverse_filter_name, pr)
pr_name = 'new name'
new_pr = self.update_policy_rule(pr_id, expected_res_status=200,
name=pr_name)['policy_rule']
aim_filter_name = str(self.name_mapper.policy_rule(
self._neutron_context.session, pr_id, pr_name))
aim_reverse_filter_name = str(self.name_mapper.policy_rule(
self._neutron_context.session, pr_id, pr_name,
prefix=alib.REVERSE_PREFIX))
self._test_policy_rule_create_update_result(
aim_tenant_name, aim_filter_name, aim_reverse_filter_name, new_pr)
self.delete_policy_rule(pr_id, expected_res_status=204)
self.show_policy_rule(pr_id, expected_res_status=404)
aim_pr = self.aim_mgr.find(
self._aim_context, aim_resource.TenantFilter, rn=rn)
self.assertEqual(0, len(aim_pr))
for filter_name in [aim_filter_name, aim_reverse_filter_name]:
aim_filters = self.aim_mgr.find(
self._aim_context, aim_resource.Filter, name=filter_name)
self.assertEqual(0, len(aim_filters))
class TestPolicyRuleRollback(TestPolicyRuleBase):
def test_policy_rule_create_fail(self):
orig_func = self._gbp_plugin.policy_driver_manager.policy_drivers[
'dummy'].obj.create_policy_rule_precommit
self._gbp_plugin.policy_driver_manager.policy_drivers[
'dummy'].obj.create_policy_rule_precommit = mock.Mock(
side_effect=Exception)
action1 = self.create_policy_action(
action_type='redirect')['policy_action']
classifier = self.create_policy_classifier(
protocol='TCP', port_range="22",
direction='bi')['policy_classifier']
self.create_policy_rule(
name="pr1", policy_classifier_id=classifier['id'],
policy_actions=[action1['id']], expected_res_status=500)
self.assertEqual([],
self._gbp_plugin.get_policy_rules(self._context))
aim_filters = self.aim_mgr.find(
self._aim_context, aim_resource.Filter)
self.assertEqual(0, len(aim_filters))
aim_filter_entries = self.aim_mgr.find(
self._aim_context, aim_resource.FilterEntry)
self.assertEqual(0, len(aim_filter_entries))
# restore mock
self._gbp_plugin.policy_driver_manager.policy_drivers[
'dummy'].obj.create_policy_rule_precommit = orig_func
def test_policy_rule_update_fail(self):
orig_func = self._gbp_plugin.policy_driver_manager.policy_drivers[
'dummy'].obj.update_policy_rule_precommit
self._gbp_plugin.policy_driver_manager.policy_drivers[
'dummy'].obj.update_policy_rule_precommit = mock.Mock(
side_effect=Exception)
action1 = self.create_policy_action(
action_type='redirect')['policy_action']
classifier = self.create_policy_classifier(
protocol='TCP', port_range="22",
direction='bi')['policy_classifier']
pr = self.create_policy_rule(
name="pr1", policy_classifier_id=classifier['id'],
policy_actions=[action1['id']])['policy_rule']
aim_filter_name = str(self.name_mapper.policy_rule(
self._neutron_context.session, pr['id'], pr['name']))
aim_reverse_filter_name = str(self.name_mapper.policy_rule(
self._neutron_context.session, pr['id'], pr['name'],
prefix=alib.REVERSE_PREFIX))
self.update_policy_rule(pr['id'], expected_res_status=500,
name='new name')
aim_filters = self.aim_mgr.find(
self._aim_context, aim_resource.Filter, name=aim_filter_name)
self.assertEqual(1, len(aim_filters))
aim_filters = self.aim_mgr.find(
self._aim_context, aim_resource.Filter,
name=aim_reverse_filter_name)
self.assertEqual(1, len(aim_filters))
# restore mock
self._gbp_plugin.policy_driver_manager.policy_drivers[
'dummy'].obj.create_policy_rule_precommit = orig_func
def test_policy_rule_delete_fail(self):
orig_func = self._gbp_plugin.policy_driver_manager.policy_drivers[
'dummy'].obj.delete_policy_rule_precommit
self._gbp_plugin.policy_driver_manager.policy_drivers[
'dummy'].obj.delete_policy_rule_precommit = mock.Mock(
side_effect=Exception)
action1 = self.create_policy_action(
action_type='redirect')['policy_action']
classifier = self.create_policy_classifier(
protocol='TCP', port_range="22",
direction='bi')['policy_classifier']
pr = self.create_policy_rule(
name="pr1", policy_classifier_id=classifier['id'],
policy_actions=[action1['id']])['policy_rule']
pr_id = pr['id']
pr_name = pr['name']
self.delete_policy_rule(pr_id, expected_res_status=500)
aim_filter_name = str(self.name_mapper.policy_rule(
self._neutron_context.session, pr_id, pr_name))
aim_reverse_filter_name = str(self.name_mapper.policy_rule(
self._neutron_context.session, pr_id, pr_name,
prefix=alib.REVERSE_PREFIX))
aim_tenant_name = str(self.name_mapper.tenant(
self._neutron_context.session, self._tenant_id))
self._test_policy_rule_create_update_result(
aim_tenant_name, aim_filter_name, aim_reverse_filter_name, pr)
# restore mock
self._gbp_plugin.policy_driver_manager.policy_drivers[
'dummy'].obj.delete_policy_rule_precommit = orig_func

View File

@@ -41,6 +41,8 @@ from gbpservice.neutron.services.grouppolicy import (
from gbpservice.neutron.services.grouppolicy import config
from gbpservice.neutron.services.grouppolicy.drivers.cisco.apic import (
apic_mapping as amap)
from gbpservice.neutron.services.grouppolicy.drivers.cisco.apic import (
apic_mapping_lib as alib)
from gbpservice.neutron.services.l3_router import l3_apic
from gbpservice.neutron.tests.unit.services.grouppolicy import (
test_resource_mapping as test_rmd)
@@ -3369,7 +3371,7 @@ class TestPolicyRuleSet(ApicMappingTestCase):
owner=ctr['tenant_id'], transaction=mock.ANY,
unset=False, rule_owner=rule_owner),
mock.call(ctr['id'], ctr['id'],
amap.REVERSE_PREFIX + rules[out]['id'],
alib.REVERSE_PREFIX + rules[out]['id'],
owner=ctr['tenant_id'], transaction=mock.ANY,
unset=False, rule_owner=rule_owner)]
self._check_call_list(
@@ -3381,7 +3383,7 @@ class TestPolicyRuleSet(ApicMappingTestCase):
owner=ctr['tenant_id'], transaction=mock.ANY,
unset=False, rule_owner=rule_owner),
mock.call(ctr['id'], ctr['id'],
amap.REVERSE_PREFIX + rules[in_d]['id'],
alib.REVERSE_PREFIX + rules[in_d]['id'],
owner=ctr['tenant_id'], transaction=mock.ANY,
unset=False, rule_owner=rule_owner)]
self._check_call_list(
@@ -3401,11 +3403,11 @@ class TestPolicyRuleSet(ApicMappingTestCase):
transaction=mock.ANY, unset=False,
rule_owner=rule_owner)
mgr.manage_contract_subject_in_filter.call_happened_with(
ctr['id'], ctr['id'], amap.REVERSE_PREFIX + rules[bi]['id'],
ctr['id'], ctr['id'], alib.REVERSE_PREFIX + rules[bi]['id'],
owner=ctr['tenant_id'], transaction=mock.ANY, unset=False,
rule_owner=rule_owner)
mgr.manage_contract_subject_out_filter.call_happened_with(
ctr['id'], ctr['id'], amap.REVERSE_PREFIX + rules[bi]['id'],
ctr['id'], ctr['id'], alib.REVERSE_PREFIX + rules[bi]['id'],
owner=ctr['tenant_id'], transaction=mock.ANY, unset=False,
rule_owner=rule_owner)
@@ -3524,13 +3526,13 @@ class TestPolicyRule(ApicMappingTestCase):
mock.call(pr['id'], owner=tenant, entry='os-entry-0', etherT='ip',
prot='tcp', dToPort=88, dFromPort=88,
transaction=mock.ANY),
mock.call(amap.REVERSE_PREFIX + pr['id'], owner=tenant,
mock.call(alib.REVERSE_PREFIX + pr['id'], owner=tenant,
entry='os-entry-0', etherT='ip', prot='tcp', sToPort=88,
sFromPort=88, tcpRules='est', transaction=mock.ANY),
mock.call(pr1['id'], owner=tenant, entry='os-entry-0',
etherT='ip', prot='udp', dToPort=53, dFromPort=53,
transaction=mock.ANY),
mock.call(amap.REVERSE_PREFIX + pr1['id'], owner=tenant,
mock.call(alib.REVERSE_PREFIX + pr1['id'], owner=tenant,
entry='os-entry-0', etherT='ip', prot='udp', sToPort=53,
sFromPort=53, transaction=mock.ANY),
mock.call(pr2['id'], owner=tenant, entry='os-entry-0',
@@ -3561,7 +3563,7 @@ class TestPolicyRule(ApicMappingTestCase):
mgr = self.driver.apic_manager
expected_calls = [
mock.call(pr['id'], owner=tenant, transaction=mock.ANY),
mock.call(amap.REVERSE_PREFIX + pr['id'], owner=tenant,
mock.call(alib.REVERSE_PREFIX + pr['id'], owner=tenant,
transaction=mock.ANY)]
self._check_call_list(
expected_calls, mgr.delete_tenant_filter.call_args_list)
@@ -3570,7 +3572,7 @@ class TestPolicyRule(ApicMappingTestCase):
self.delete_policy_rule(pr1['id'], expected_res_status=204)
expected_calls = [
mock.call(pr1['id'], owner=tenant, transaction=mock.ANY),
mock.call(amap.REVERSE_PREFIX + pr1['id'], owner=tenant,
mock.call(alib.REVERSE_PREFIX + pr1['id'], owner=tenant,
transaction=mock.ANY)]
self._check_call_list(
expected_calls, mgr.delete_tenant_filter.call_args_list)
@@ -3611,10 +3613,10 @@ class TestPolicyRule(ApicMappingTestCase):
entry='os-entry-0', transaction=mock.ANY),
mock.call(pr2['id'], owner='test-tenant', etherT='ip', prot='udp',
entry='os-entry-0', transaction=mock.ANY),
mock.call(amap.REVERSE_PREFIX + pr1['id'], owner='common',
mock.call(alib.REVERSE_PREFIX + pr1['id'], owner='common',
etherT='ip', prot='udp', entry='os-entry-0',
transaction=mock.ANY),
mock.call(amap.REVERSE_PREFIX + pr2['id'], owner='test-tenant',
mock.call(alib.REVERSE_PREFIX + pr2['id'], owner='test-tenant',
etherT='ip', prot='udp', entry='os-entry-0',
transaction=mock.ANY)]
self._check_call_list(
@@ -3622,9 +3624,9 @@ class TestPolicyRule(ApicMappingTestCase):
expected_calls = [
mock.call(pr1['id'], owner='common', transaction=mock.ANY),
mock.call(pr2['id'], owner='test-tenant', transaction=mock.ANY),
mock.call(amap.REVERSE_PREFIX + pr1['id'], owner='common',
mock.call(alib.REVERSE_PREFIX + pr1['id'], owner='common',
transaction=mock.ANY),
mock.call(amap.REVERSE_PREFIX + pr2['id'], owner='test-tenant',
mock.call(alib.REVERSE_PREFIX + pr2['id'], owner='test-tenant',
transaction=mock.ANY)]
self._check_call_list(
expected_calls, mgr.delete_tenant_filter.call_args_list)
@@ -3645,9 +3647,9 @@ class TestPolicyRule(ApicMappingTestCase):
expected_calls = [
mock.call(pr1['id'], owner='common', transaction=mock.ANY),
mock.call(pr2['id'], owner='test-tenant', transaction=mock.ANY),
mock.call(amap.REVERSE_PREFIX + pr1['id'], owner='common',
mock.call(alib.REVERSE_PREFIX + pr1['id'], owner='common',
transaction=mock.ANY),
mock.call(amap.REVERSE_PREFIX + pr2['id'], owner='test-tenant',
mock.call(alib.REVERSE_PREFIX + pr2['id'], owner='test-tenant',
transaction=mock.ANY)]
self._check_call_list(
expected_calls, mgr.delete_tenant_filter.call_args_list)
@@ -3663,9 +3665,9 @@ class TestPolicyRule(ApicMappingTestCase):
expected_calls = [
mock.call(pr1['id'], owner='common', transaction=mock.ANY),
mock.call(pr2['id'], owner='test-tenant', transaction=mock.ANY),
mock.call(amap.REVERSE_PREFIX + pr1['id'], owner='common',
mock.call(alib.REVERSE_PREFIX + pr1['id'], owner='common',
transaction=mock.ANY),
mock.call(amap.REVERSE_PREFIX + pr2['id'], owner='test-tenant',
mock.call(alib.REVERSE_PREFIX + pr2['id'], owner='test-tenant',
transaction=mock.ANY)]
self._check_call_list(
expected_calls, mgr.delete_tenant_filter.call_args_list)
@@ -3674,10 +3676,10 @@ class TestPolicyRule(ApicMappingTestCase):
entry='os-entry-0', transaction=mock.ANY),
mock.call(pr2['id'], owner='test-tenant', etherT='ip', prot='tcp',
entry='os-entry-0', transaction=mock.ANY),
mock.call(amap.REVERSE_PREFIX + pr1['id'], owner='common',
mock.call(alib.REVERSE_PREFIX + pr1['id'], owner='common',
etherT='ip', prot='tcp', tcpRules='est',
entry='os-entry-0', transaction=mock.ANY),
mock.call(amap.REVERSE_PREFIX + pr2['id'], owner='test-tenant',
mock.call(alib.REVERSE_PREFIX + pr2['id'], owner='test-tenant',
etherT='ip', prot='tcp', tcpRules='est',
entry='os-entry-0', transaction=mock.ANY)]
self._check_call_list(
@@ -3706,13 +3708,13 @@ class TestPolicyRule(ApicMappingTestCase):
mgr.manage_contract_subject_in_filter.call_args_list)
# SET Reverse PR1 and PR2 OUT
expected_calls = [
mock.call(prs1['id'], prs1['id'], amap.REVERSE_PREFIX + pr1['id'],
mock.call(prs1['id'], prs1['id'], alib.REVERSE_PREFIX + pr1['id'],
owner='test-tenant', transaction=mock.ANY, unset=False,
rule_owner='common'),
mock.call(prs2['id'], prs2['id'], amap.REVERSE_PREFIX + pr1['id'],
mock.call(prs2['id'], prs2['id'], alib.REVERSE_PREFIX + pr1['id'],
owner='test-tenant', transaction=mock.ANY, unset=False,
rule_owner='common'),
mock.call(prs2['id'], prs2['id'], amap.REVERSE_PREFIX + pr2['id'],
mock.call(prs2['id'], prs2['id'], alib.REVERSE_PREFIX + pr2['id'],
owner='test-tenant', transaction=mock.ANY, unset=False,
rule_owner='test-tenant')
]
@@ -3728,23 +3730,23 @@ class TestPolicyRule(ApicMappingTestCase):
expected_calls = [
mock.call(pr['id'], owner=tenant, entry='os-entry-0', etherT='ip',
prot='icmp', transaction=mock.ANY),
mock.call(amap.REVERSE_PREFIX + pr['id'], owner=tenant,
mock.call(alib.REVERSE_PREFIX + pr['id'], owner=tenant,
entry=mock.ANY, etherT='ip', icmpv4T='echo-rep',
prot='icmp', transaction=mock.ANY),
mock.call(amap.REVERSE_PREFIX + pr['id'], owner=tenant,
mock.call(alib.REVERSE_PREFIX + pr['id'], owner=tenant,
entry=mock.ANY, etherT='ip', icmpv4T='dst-unreach',
prot='icmp', transaction=mock.ANY),
mock.call(amap.REVERSE_PREFIX + pr['id'], owner=tenant,
mock.call(alib.REVERSE_PREFIX + pr['id'], owner=tenant,
entry=mock.ANY, etherT='ip', icmpv4T='src-quench',
prot='icmp', transaction=mock.ANY),
mock.call(amap.REVERSE_PREFIX + pr['id'], owner=tenant,
mock.call(alib.REVERSE_PREFIX + pr['id'], owner=tenant,
entry=mock.ANY, etherT='ip', icmpv4T='time-exceeded',
prot='icmp', transaction=mock.ANY)]
# verify that entry is always different
found = set()
for call in mgr.create_tenant_filter.call_args_list:
# Only for reverse filters
if call[0][0].startswith(amap.REVERSE_PREFIX):
if call[0][0].startswith(alib.REVERSE_PREFIX):
self.assertFalse(call[1]['entry'] in found)
found.add(call[1]['entry'])

View File

@@ -104,14 +104,17 @@ class TestL2PolicyRollback(CommonNeutronBaseTestCase):
'GROUP_POLICY'].policy_driver_manager.policy_drivers['dummy'].obj
def test_l2_policy_create_fail(self):
orig_func = self.dummy_driver.create_l2_policy_precommit
self.dummy_driver.create_l2_policy_precommit = mock.Mock(
side_effect=Exception)
self.create_l2_policy(name="l2p1", expected_res_status=500)
self.assertEqual([], self._plugin.get_networks(self._context))
self.assertEqual([], self._gbp_plugin.get_l2_policies(self._context))
self.assertEqual([], self._gbp_plugin.get_l3_policies(self._context))
self.dummy_driver.create_l2_policy_precommit = orig_func
def test_l2_policy_update_fail(self):
orig_func = self.dummy_driver.update_l2_policy_precommit
self.dummy_driver.update_l2_policy_precommit = mock.Mock(
side_effect=Exception)
l2p = self.create_l2_policy(name="l2p1")
@@ -121,8 +124,10 @@ class TestL2PolicyRollback(CommonNeutronBaseTestCase):
new_l2p = self.show_l2_policy(l2p_id, expected_res_status=200)
self.assertEqual(l2p['l2_policy']['name'],
new_l2p['l2_policy']['name'])
self.dummy_driver.update_l2_policy_precommit = orig_func
def test_l2_policy_delete_fail(self):
orig_func = self.dummy_driver.delete_l2_policy_precommit
self.dummy_driver.delete_l2_policy_precommit = mock.Mock(
side_effect=Exception)
l2p = self.create_l2_policy(name="l2p1")
@@ -135,3 +140,4 @@ class TestL2PolicyRollback(CommonNeutronBaseTestCase):
self.assertIsNotNone(res['network']['id'])
self.show_l3_policy(l3p_id, expected_res_status=200)
self.show_l2_policy(l2p_id, expected_res_status=200)
self.dummy_driver.delete_l2_policy_precommit = orig_func