AIM Policy Driver - Part 2 - Extension Driver
This adds a AIM specific extension to reflect the APIC DN for a GBP resource that maps to an AIM resource. This patch implements this only for the PTG resource. This also sets the status of the PTG based on the AIM EPG status. This also updates the devstack setup to include the aim_mapping GBP policy driver configuration. Change-Id: I30f5e5e63b3b172eb79c8a9934eb662928d13f6c
This commit is contained in:
@@ -11,6 +11,8 @@ function configure_apic_aim {
|
||||
|
||||
# devstack/lib/neutron_plugins/ml2 does not allow overriding
|
||||
# Q_PLUGIN_CLASS in override_defaults, so do it here instread
|
||||
|
||||
# Neutron Configuration for AIM
|
||||
iniset $NEUTRON_CONF DEFAULT core_plugin ml2plus
|
||||
|
||||
iniset /$Q_PLUGIN_CONF_FILE apic_aim_auth auth_plugin v3password
|
||||
@@ -21,6 +23,13 @@ function configure_apic_aim {
|
||||
iniset /$Q_PLUGIN_CONF_FILE apic_aim_auth project_domain_name default
|
||||
iniset /$Q_PLUGIN_CONF_FILE apic_aim_auth project_name admin
|
||||
|
||||
# GBP Configuration for AIM
|
||||
# Policy drivers (REVISIT: chain_mapping might needed to be added later)
|
||||
iniset $NEUTRON_CONF group_policy policy_drivers "aim_mapping"
|
||||
# Extension drivers (REVISIT: proxy_group might needed to be added later)
|
||||
iniset $NEUTRON_CONF group_policy extension_drivers "aim_extension"
|
||||
# Service Chain (REVISIT: not overriding any defaults yet)
|
||||
|
||||
init_aim
|
||||
}
|
||||
|
||||
|
@@ -352,8 +352,7 @@ class GroupPolicyMappingDbPlugin(gpdb.GroupPolicyDbPlugin):
|
||||
return self._get_collection_count(context, PolicyTargetGroupMapping,
|
||||
filters=filters)
|
||||
|
||||
@log.log_method_call
|
||||
def get_policy_target_groups(self, context, filters=None, fields=None,
|
||||
def _get_policy_target_groups(self, context, filters=None, fields=None,
|
||||
sorts=None, limit=None, marker=None,
|
||||
page_reverse=False):
|
||||
marker_obj = self._get_marker_obj(context, 'policy_target_group',
|
||||
@@ -365,6 +364,13 @@ class GroupPolicyMappingDbPlugin(gpdb.GroupPolicyDbPlugin):
|
||||
marker_obj=marker_obj,
|
||||
page_reverse=page_reverse)
|
||||
|
||||
@log.log_method_call
|
||||
def get_policy_target_groups(self, context, filters=None, fields=None,
|
||||
sorts=None, limit=None, marker=None,
|
||||
page_reverse=False):
|
||||
return self._get_policy_target_groups(
|
||||
context, filters, fields, sorts, limit, marker, page_reverse)
|
||||
|
||||
@log.log_method_call
|
||||
def create_l2_policy(self, context, l2_policy):
|
||||
l2p = l2_policy['l2_policy']
|
||||
|
56
gbpservice/neutron/extensions/aim_driver_ext.py
Normal file
56
gbpservice/neutron/extensions/aim_driver_ext.py
Normal file
@@ -0,0 +1,56 @@
|
||||
# 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.
|
||||
|
||||
from neutron.api import extensions
|
||||
|
||||
from gbpservice.neutron.extensions import group_policy as gp
|
||||
|
||||
|
||||
AIM_DRIVER_EXT = 'aim-driver-extensions'
|
||||
DIST_NAMES = 'apic:distinguished_names'
|
||||
|
||||
EXTENDED_ATTRIBUTES_2_0 = {
|
||||
gp.POLICY_TARGET_GROUPS: {
|
||||
DIST_NAMES: {
|
||||
'allow_post': False, 'allow_put': False, 'is_visible': True},
|
||||
},
|
||||
}
|
||||
|
||||
|
||||
class Aim_driver_ext(extensions.ExtensionDescriptor):
|
||||
|
||||
@classmethod
|
||||
def get_name(cls):
|
||||
return "Extensions for AIM driver"
|
||||
|
||||
@classmethod
|
||||
def get_alias(cls):
|
||||
return AIM_DRIVER_EXT
|
||||
|
||||
@classmethod
|
||||
def get_description(cls):
|
||||
return _("Adds AIM driver specific attributes to GBP resources.")
|
||||
|
||||
@classmethod
|
||||
def get_namespace(cls):
|
||||
return ("http://docs.openstack.org/ext/neutron/grouppolicy/"
|
||||
"aim_driver_ext/api/v1.0")
|
||||
|
||||
@classmethod
|
||||
def get_updated(cls):
|
||||
return "2016-07-11T10:00:00-00:00"
|
||||
|
||||
def get_extended_resources(self, version):
|
||||
if version == "2.0":
|
||||
return EXTENDED_ATTRIBUTES_2_0
|
||||
else:
|
||||
return {}
|
@@ -10,11 +10,9 @@
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
from aim import aim_manager
|
||||
from aim.api import resource as aim_resource
|
||||
from aim import context as aim_context
|
||||
from neutron._i18n import _LI
|
||||
from neutron import context as nctx
|
||||
from neutron import manager
|
||||
from oslo_concurrency import lockutils
|
||||
from oslo_log import helpers as log
|
||||
@@ -23,10 +21,15 @@ from oslo_log import log as logging
|
||||
from gbpservice.neutron.extensions import group_policy as gpolicy
|
||||
from gbpservice.neutron.plugins.ml2plus.drivers.apic_aim import (
|
||||
mechanism_driver as aim_md)
|
||||
from gbpservice.neutron.plugins.ml2plus.drivers.apic_aim.extensions import (
|
||||
cisco_apic)
|
||||
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.common import exceptions as gpexc
|
||||
from gbpservice.neutron.services.grouppolicy.drivers import (
|
||||
neutron_resources as nrd)
|
||||
from gbpservice.neutron.services.grouppolicy import plugin as gbp_plugin
|
||||
|
||||
|
||||
LOG = logging.getLogger(__name__)
|
||||
@@ -47,7 +50,6 @@ class AIMMappingDriver(nrd.CommonNeutronBase):
|
||||
def initialize(self):
|
||||
LOG.info(_LI("APIC AIM Policy Driver initializing"))
|
||||
self.db = model.DbModel()
|
||||
self.aim = aim_manager.AimManager()
|
||||
super(AIMMappingDriver, self).initialize()
|
||||
self._apic_aim_mech_driver = None
|
||||
|
||||
@@ -59,97 +61,14 @@ class AIMMappingDriver(nrd.CommonNeutronBase):
|
||||
ml2plus_plugin.mechanism_manager.mech_drivers['apic_aim'].obj)
|
||||
return self._apic_aim_mech_driver
|
||||
|
||||
@property
|
||||
def aim(self):
|
||||
return self.aim_mech_driver.aim
|
||||
|
||||
@property
|
||||
def name_mapper(self):
|
||||
return self.aim_mech_driver.name_mapper
|
||||
|
||||
def _aim_tenant_name(self, context):
|
||||
session = context._plugin_context.session
|
||||
tenant_id = context.current['tenant_id']
|
||||
tenant_name = self.name_mapper.tenant(session, tenant_id)
|
||||
LOG.info(_LI("Mapped tenant_id %(id)s to %(apic_name)s"),
|
||||
{'id': tenant_id, 'apic_name': tenant_name})
|
||||
return tenant_name
|
||||
|
||||
def _aim_endpoint_group(self, context, bd_name=None, bd_tenant_name=None):
|
||||
session = context._plugin_context.session
|
||||
tenant_name = self._aim_tenant_name(context)
|
||||
id = context.current['id']
|
||||
name = context.current['name']
|
||||
epg_name = self.name_mapper.policy_target_group(session, id, name)
|
||||
LOG.info(_LI("Mapped ptg_id %(id)s with name %(name)s to "
|
||||
"%(apic_name)s"),
|
||||
{'id': id, 'name': name, 'apic_name': epg_name})
|
||||
|
||||
epg = aim_resource.EndpointGroup(tenant_name=str(tenant_name),
|
||||
name=str(epg_name),
|
||||
app_profile_name=aim_md.AP_NAME,
|
||||
bd_name=bd_name,
|
||||
bd_tenant_name=bd_tenant_name)
|
||||
return epg
|
||||
|
||||
def _aim_bridge_domain(self, context, network_id, network_name):
|
||||
session = context._plugin_context.session
|
||||
tenant_name = self._aim_tenant_name(context)
|
||||
bd_name = self.name_mapper.network(session, network_id, network_name)
|
||||
LOG.info(_LI("Mapped network_id %(id)s with name %(name)s to "
|
||||
"%(apic_name)s"),
|
||||
{'id': network_id, 'name': network_name,
|
||||
'apic_name': bd_name})
|
||||
|
||||
bd = aim_resource.BridgeDomain(tenant_name=str(tenant_name),
|
||||
name=str(bd_name))
|
||||
return bd
|
||||
|
||||
def _get_l2p_subnets(self, context, l2p_id, clean_session=False):
|
||||
plugin_context = context._plugin_context
|
||||
l2p = context._plugin.get_l2_policy(plugin_context, l2p_id)
|
||||
# REVISIT: The following should be a get_subnets call via local API
|
||||
return self._core_plugin.get_subnets_by_network(
|
||||
plugin_context, l2p['network_id'])
|
||||
|
||||
def _sync_ptg_subnets(self, context, l2p):
|
||||
l2p_subnets = [x['id'] for x in
|
||||
self._get_l2p_subnets(context, l2p['id'])]
|
||||
ptgs = context._plugin.get_policy_target_groups(
|
||||
nctx.get_admin_context(), {'l2_policy_id': [l2p['id']]})
|
||||
for sub in l2p_subnets:
|
||||
# Add to PTG
|
||||
for ptg in ptgs:
|
||||
if sub not in ptg['subnets']:
|
||||
try:
|
||||
(context._plugin.
|
||||
_add_subnet_to_policy_target_group(
|
||||
nctx.get_admin_context(), ptg['id'], sub))
|
||||
except gpolicy.PolicyTargetGroupNotFound as e:
|
||||
LOG.warning(e)
|
||||
|
||||
def _use_implicit_subnet(self, context, force_add=False,
|
||||
clean_session=False):
|
||||
"""Implicit subnet for AIM.
|
||||
|
||||
The first PTG in a L2P will allocate a new subnet from the L3P.
|
||||
Any subsequent PTG in the same L2P will use the same subnet.
|
||||
Additional subnets will be allocated as and when the currently used
|
||||
subnet runs out of IP addresses.
|
||||
"""
|
||||
l2p_id = context.current['l2_policy_id']
|
||||
with lockutils.lock(l2p_id, external=True):
|
||||
subs = self._get_l2p_subnets(context, l2p_id)
|
||||
subs = set([x['id'] for x in subs])
|
||||
added = []
|
||||
if not subs or force_add:
|
||||
l2p = context._plugin.get_l2_policy(context._plugin_context,
|
||||
l2p_id)
|
||||
name = APIC_OWNED + l2p['name']
|
||||
added = super(
|
||||
AIMMappingDriver, self)._use_implicit_subnet(
|
||||
context, subnet_specifics={'name': name},
|
||||
is_proxy=False, clean_session=clean_session)
|
||||
context.add_subnets(subs - set(context.current['subnets']))
|
||||
for subnet in added:
|
||||
self._sync_ptg_subnets(context, l2p)
|
||||
|
||||
@log.log_method_call
|
||||
def ensure_tenant(self, plugin_context, tenant_id):
|
||||
self.aim_mech_driver.ensure_tenant(plugin_context, tenant_id)
|
||||
@@ -183,9 +102,11 @@ class AIMMappingDriver(nrd.CommonNeutronBase):
|
||||
|
||||
bd_name = str(self.name_mapper.network(
|
||||
session, net['id'], net['name']))
|
||||
bd_tenant_name = str(self._aim_tenant_name(context))
|
||||
bd_tenant_name = str(self._aim_tenant_name(
|
||||
session, context.current['tenant_id']))
|
||||
|
||||
epg = self._aim_endpoint_group(context, bd_name, bd_tenant_name)
|
||||
epg = self._aim_endpoint_group(session, context.current, bd_name,
|
||||
bd_tenant_name)
|
||||
self.aim.create(aim_ctx, epg)
|
||||
|
||||
@log.log_method_call
|
||||
@@ -201,12 +122,10 @@ class AIMMappingDriver(nrd.CommonNeutronBase):
|
||||
session = context._plugin_context.session
|
||||
|
||||
aim_ctx = aim_context.AimContext(session)
|
||||
epg = self._aim_endpoint_group(context)
|
||||
epg = self._aim_endpoint_group(session, context.current)
|
||||
self.aim.delete(aim_ctx, epg)
|
||||
self.name_mapper.delete_apic_name(session, context.current['id'])
|
||||
|
||||
# REVISIT(Sumit): Delete app_profile if this is last PTG
|
||||
|
||||
subnet_ids = [assoc['subnet_id'] for assoc in ptg_db['subnets']]
|
||||
|
||||
context._plugin._remove_subnets_from_policy_target_group(
|
||||
@@ -226,12 +145,25 @@ class AIMMappingDriver(nrd.CommonNeutronBase):
|
||||
if not l2p_db['policy_target_groups']:
|
||||
self._cleanup_l2_policy(context, l2p_id, clean_session=False)
|
||||
|
||||
@log.log_method_call
|
||||
def extend_policy_target_group_dict(self, session, result):
|
||||
epg = self._get_aim_endpoint_group(session, result)
|
||||
if epg:
|
||||
result[cisco_apic.DIST_NAMES] = {cisco_apic.EPG: epg.dn}
|
||||
|
||||
@log.log_method_call
|
||||
def get_policy_target_group_status(self, context):
|
||||
session = context._plugin_context.session
|
||||
epg = self._get_aim_endpoint_group(session, context.current)
|
||||
context.current['status'] = self._map_aim_status(session, epg)
|
||||
|
||||
@log.log_method_call
|
||||
def create_policy_target_precommit(self, context):
|
||||
if not context.current['port_id']:
|
||||
ptg = context._plugin.get_policy_target_group(
|
||||
context._plugin_context,
|
||||
context.current['policy_target_group_id'])
|
||||
ptg = self._db_plugin(
|
||||
context._plugin).get_policy_target_group(
|
||||
context._plugin_context,
|
||||
context.current['policy_target_group_id'])
|
||||
subnets = self._get_subnets(
|
||||
context._plugin_context, {'id': ptg['subnets']},
|
||||
clean_session=False)
|
||||
@@ -285,3 +217,123 @@ class AIMMappingDriver(nrd.CommonNeutronBase):
|
||||
# rn = self.mapper.tenant_filter(tenant, pr_id)
|
||||
# tf = aim_resource.TenantFilter(tenant_rn=tenant, rn=rn)
|
||||
# self.aim.delete(aim_context, tf)
|
||||
|
||||
def _aim_tenant_name(self, session, tenant_id):
|
||||
tenant_name = self.name_mapper.tenant(session, tenant_id)
|
||||
LOG.debug("Mapped tenant_id %(id)s to %(apic_name)s",
|
||||
{'id': tenant_id, 'apic_name': tenant_name})
|
||||
return tenant_name
|
||||
|
||||
def _aim_endpoint_group(self, session, ptg, bd_name=None,
|
||||
bd_tenant_name=None):
|
||||
# This returns a new AIM EPG resource
|
||||
tenant_id = ptg['tenant_id']
|
||||
tenant_name = self._aim_tenant_name(session, tenant_id)
|
||||
id = ptg['id']
|
||||
name = ptg['name']
|
||||
epg_name = self.name_mapper.policy_target_group(session, id, name)
|
||||
LOG.debug("Mapped ptg_id %(id)s with name %(name)s to %(apic_name)s",
|
||||
{'id': id, 'name': name, 'apic_name': epg_name})
|
||||
kwargs = {'tenant_name': str(tenant_name),
|
||||
'name': str(epg_name),
|
||||
'app_profile_name': aim_md.AP_NAME}
|
||||
if bd_name:
|
||||
kwargs['bd_name'] = bd_name
|
||||
if bd_tenant_name:
|
||||
kwargs['bd_tenant_name'] = bd_tenant_name
|
||||
|
||||
epg = aim_resource.EndpointGroup(**kwargs)
|
||||
return epg
|
||||
|
||||
def _get_aim_endpoint_group(self, session, ptg):
|
||||
# This gets an EPG from the AIM DB
|
||||
epg = self._aim_endpoint_group(session, ptg)
|
||||
aim_ctx = aim_context.AimContext(session)
|
||||
epg_fetched = self.aim.get(aim_ctx, epg)
|
||||
if not epg_fetched:
|
||||
LOG.debug("No EPG found in AIM DB")
|
||||
else:
|
||||
LOG.debug("Got epg: %s", epg_fetched.__dict__)
|
||||
return epg_fetched
|
||||
|
||||
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)
|
||||
bd_name = self.name_mapper.network(session, network_id, network_name)
|
||||
LOG.info(_LI("Mapped network_id %(id)s with name %(name)s to "
|
||||
"%(apic_name)s"),
|
||||
{'id': network_id, 'name': network_name,
|
||||
'apic_name': bd_name})
|
||||
|
||||
bd = aim_resource.BridgeDomain(tenant_name=str(tenant_name),
|
||||
name=str(bd_name))
|
||||
return bd
|
||||
|
||||
def _get_l2p_subnets(self, context, l2p_id, clean_session=False):
|
||||
plugin_context = context._plugin_context
|
||||
l2p = context._plugin.get_l2_policy(plugin_context, l2p_id)
|
||||
# REVISIT: The following should be a get_subnets call via local API
|
||||
return self._core_plugin.get_subnets_by_network(
|
||||
plugin_context, l2p['network_id'])
|
||||
|
||||
def _sync_ptg_subnets(self, context, l2p):
|
||||
l2p_subnets = [x['id'] for x in
|
||||
self._get_l2p_subnets(context, l2p['id'])]
|
||||
ptgs = context._plugin._get_policy_target_groups(
|
||||
context._plugin_context.elevated(), {'l2_policy_id': [l2p['id']]})
|
||||
for sub in l2p_subnets:
|
||||
# Add to PTG
|
||||
for ptg in ptgs:
|
||||
if sub not in ptg['subnets']:
|
||||
try:
|
||||
(context._plugin.
|
||||
_add_subnet_to_policy_target_group(
|
||||
context._plugin_context.elevated(),
|
||||
ptg['id'], sub))
|
||||
except gpolicy.PolicyTargetGroupNotFound as e:
|
||||
LOG.warning(e)
|
||||
|
||||
def _use_implicit_subnet(self, context, force_add=False,
|
||||
clean_session=False):
|
||||
"""Implicit subnet for AIM.
|
||||
|
||||
The first PTG in a L2P will allocate a new subnet from the L3P.
|
||||
Any subsequent PTG in the same L2P will use the same subnet.
|
||||
Additional subnets will be allocated as and when the currently used
|
||||
subnet runs out of IP addresses.
|
||||
"""
|
||||
l2p_id = context.current['l2_policy_id']
|
||||
with lockutils.lock(l2p_id, external=True):
|
||||
subs = self._get_l2p_subnets(context, l2p_id)
|
||||
subs = set([x['id'] for x in subs])
|
||||
added = []
|
||||
if not subs or force_add:
|
||||
l2p = context._plugin.get_l2_policy(
|
||||
context._plugin_context, l2p_id)
|
||||
name = APIC_OWNED + l2p['name']
|
||||
added = super(
|
||||
AIMMappingDriver, self)._use_implicit_subnet(
|
||||
context, subnet_specifics={'name': name},
|
||||
is_proxy=False, clean_session=clean_session)
|
||||
context.add_subnets(subs - set(context.current['subnets']))
|
||||
for subnet in added:
|
||||
self._sync_ptg_subnets(context, l2p)
|
||||
|
||||
def _map_aim_status(self, session, aim_resource_obj):
|
||||
# Note that this implementation assumes that this driver
|
||||
# is the only policy driver configured, and no merging
|
||||
# with any previous status is required.
|
||||
aim_ctx = aim_context.AimContext(session)
|
||||
aim_status = self.aim.get_status(aim_ctx, aim_resource_obj)
|
||||
if not aim_status:
|
||||
# REVIST(Sumit)
|
||||
return gp_const.STATUS_BUILD
|
||||
if aim_status.is_error():
|
||||
return gp_const.STATUS_ERROR
|
||||
elif aim_status.is_build():
|
||||
return gp_const.STATUS_BUILD
|
||||
else:
|
||||
return gp_const.STATUS_ACTIVE
|
||||
|
||||
def _db_plugin(self, plugin_obj):
|
||||
return super(gbp_plugin.GroupPolicyPlugin, plugin_obj)
|
||||
|
@@ -0,0 +1,49 @@
|
||||
# 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.
|
||||
|
||||
from neutron._i18n import _LI
|
||||
from neutron import manager as n_manager
|
||||
from oslo_log import log as logging
|
||||
|
||||
from gbpservice.neutron.extensions import aim_driver_ext
|
||||
from gbpservice.neutron.services.grouppolicy import (
|
||||
group_policy_driver_api as api)
|
||||
|
||||
LOG = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class AIMExtensionDriver(api.ExtensionDriver):
|
||||
_supported_extension_alias = aim_driver_ext.AIM_DRIVER_EXT
|
||||
_extension_dict = aim_driver_ext.EXTENDED_ATTRIBUTES_2_0
|
||||
|
||||
def __init__(self):
|
||||
LOG.info(_LI("AIM Extension __init__"))
|
||||
self._policy_driver = None
|
||||
|
||||
@property
|
||||
def _pd(self):
|
||||
if not self._policy_driver:
|
||||
gbp_plugin = (n_manager.NeutronManager.get_service_plugins()
|
||||
.get("GROUP_POLICY"))
|
||||
policy_mgr = gbp_plugin.policy_driver_manager
|
||||
self._policy_driver = policy_mgr.policy_drivers['aim_mapping'].obj
|
||||
return self._policy_driver
|
||||
|
||||
def initialize(self):
|
||||
pass
|
||||
|
||||
@property
|
||||
def extension_alias(self):
|
||||
return self._supported_extension_alias
|
||||
|
||||
def extend_policy_target_group_dict(self, session, result):
|
||||
self._pd.extend_policy_target_group_dict(session, result)
|
@@ -13,23 +13,24 @@
|
||||
|
||||
import mock
|
||||
|
||||
from aim import aim_manager
|
||||
from aim.api import resource as aim_resource
|
||||
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
|
||||
from neutron import context as nctx
|
||||
from neutron.db import api as db_api
|
||||
from oslo_log import log as logging
|
||||
import webob.exc
|
||||
|
||||
from gbpservice.neutron.plugins.ml2plus.drivers.apic_aim import (
|
||||
mechanism_driver as aim_md)
|
||||
from gbpservice.neutron.plugins.ml2plus.drivers.apic_aim import apic_mapper
|
||||
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.tests.unit.plugins.ml2plus import (
|
||||
test_apic_aim as test_aim_md)
|
||||
from gbpservice.neutron.tests.unit.services.grouppolicy import (
|
||||
test_extension_driver_api as test_ext_base)
|
||||
from gbpservice.neutron.tests.unit.services.grouppolicy import (
|
||||
test_neutron_resources_driver as test_nr_base)
|
||||
|
||||
@@ -37,7 +38,10 @@ from gbpservice.neutron.tests.unit.services.grouppolicy import (
|
||||
ML2PLUS_PLUGIN = 'gbpservice.neutron.plugins.ml2plus.plugin.Ml2PlusPlugin'
|
||||
|
||||
|
||||
class AIMBaseTestCase(test_nr_base.CommonNeutronBaseTestCase):
|
||||
class AIMBaseTestCase(test_nr_base.CommonNeutronBaseTestCase,
|
||||
test_ext_base.ExtensionDriverTestBase):
|
||||
_extension_drivers = ['aim_extension']
|
||||
_extension_path = None
|
||||
|
||||
def setUp(self, policy_drivers=None, core_plugin=None, ml2_options=None,
|
||||
sc_plugin=None, **kwargs):
|
||||
@@ -65,16 +69,32 @@ class AIMBaseTestCase(test_nr_base.CommonNeutronBaseTestCase):
|
||||
|
||||
engine = db_api.get_engine()
|
||||
aim_model_base.Base.metadata.create_all(engine)
|
||||
self._aim = aim_manager.AimManager()
|
||||
self._aim_mgr = None
|
||||
self._aim_context = aim_context.AimContext(
|
||||
self._neutron_context.session)
|
||||
self._db = model.DbModel()
|
||||
self._name_mapper = apic_mapper.APICNameMapper(self._db, logging)
|
||||
self._name_mapper = None
|
||||
|
||||
def tearDown(self):
|
||||
ksc_client.Client = self.saved_keystone_client
|
||||
super(AIMBaseTestCase, self).tearDown()
|
||||
|
||||
@property
|
||||
def aim_mgr(self):
|
||||
if not self._aim_mgr:
|
||||
self._aim_mgr = (
|
||||
self._gbp_plugin.policy_driver_manager.policy_drivers[
|
||||
'aim_mapping'].obj.aim)
|
||||
return self._aim_mgr
|
||||
|
||||
@property
|
||||
def name_mapper(self):
|
||||
if not self._name_mapper:
|
||||
self._name_mapper = (
|
||||
self._gbp_plugin.policy_driver_manager.policy_drivers[
|
||||
'aim_mapping'].obj.name_mapper)
|
||||
return self._name_mapper
|
||||
|
||||
|
||||
class TestL2Policy(test_nr_base.TestL2Policy, AIMBaseTestCase):
|
||||
|
||||
@@ -83,32 +103,48 @@ class TestL2Policy(test_nr_base.TestL2Policy, AIMBaseTestCase):
|
||||
|
||||
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)
|
||||
if aim_status.is_error():
|
||||
self.assertEqual(gp_const.STATUS_ERROR, gbp_resource['status'])
|
||||
elif aim_status.is_build():
|
||||
self.assertEqual(gp_const.STATUS_BUILD, gbp_resource['status'])
|
||||
else:
|
||||
self.assertEqual(gp_const.STATUS_ACTIVE, gbp_resource['status'])
|
||||
|
||||
def test_policy_target_group_lifecycle_implicit_l2p(self):
|
||||
ptg = self.create_policy_target_group(
|
||||
name="ptg1")['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.show_l2_policy(ptg['l2_policy_id'], expected_res_status=200)
|
||||
req = self.new_show_request('subnets', ptg['subnets'][0], fmt=self.fmt)
|
||||
res = self.deserialize(self.fmt, req.get_response(self.api))
|
||||
self.assertIsNotNone(res['subnet']['id'])
|
||||
ptg_name = ptg['name']
|
||||
aim_epg_name = str(self._name_mapper.policy_target_group(
|
||||
aim_epg_name = str(self.name_mapper.policy_target_group(
|
||||
self._neutron_context.session, ptg_id, ptg_name))
|
||||
aim_tenant_name = str(self._name_mapper.tenant(
|
||||
aim_tenant_name = str(self.name_mapper.tenant(
|
||||
self._neutron_context.session, self._tenant_id))
|
||||
aim_app_profile_name = aim_md.AP_NAME
|
||||
aim_app_profiles = self._aim.find(
|
||||
aim_app_profiles = self.aim_mgr.find(
|
||||
self._aim_context, aim_resource.ApplicationProfile,
|
||||
tenant_name=aim_tenant_name, name=aim_app_profile_name)
|
||||
self.assertEqual(1, len(aim_app_profiles))
|
||||
aim_epgs = self._aim.find(
|
||||
aim_epgs = self.aim_mgr.find(
|
||||
self._aim_context, aim_resource.EndpointGroup, name=aim_epg_name)
|
||||
self.assertEqual(1, len(aim_epgs))
|
||||
self.assertEqual(aim_epg_name, aim_epgs[0].name)
|
||||
self.assertEqual(aim_tenant_name, aim_epgs[0].tenant_name)
|
||||
|
||||
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)
|
||||
|
||||
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
|
||||
@@ -118,7 +154,7 @@ class TestPolicyTargetGroup(AIMBaseTestCase):
|
||||
# Implicitly created L2P should be deleted
|
||||
self.show_l2_policy(ptg['l2_policy_id'], expected_res_status=404)
|
||||
|
||||
aim_epgs = self._aim.find(
|
||||
aim_epgs = self.aim_mgr.find(
|
||||
self._aim_context, aim_resource.EndpointGroup, name=aim_epg_name)
|
||||
self.assertEqual(0, len(aim_epgs))
|
||||
|
||||
@@ -136,21 +172,23 @@ class TestPolicyTargetGroup(AIMBaseTestCase):
|
||||
res = self.deserialize(self.fmt, req.get_response(self.api))
|
||||
self.assertIsNotNone(res['subnet']['id'])
|
||||
ptg_name = ptg['name']
|
||||
aim_epg_name = str(self._name_mapper.policy_target_group(
|
||||
aim_epg_name = str(self.name_mapper.policy_target_group(
|
||||
self._neutron_context.session, ptg_id, ptg_name))
|
||||
aim_tenant_name = str(self._name_mapper.tenant(
|
||||
aim_tenant_name = str(self.name_mapper.tenant(
|
||||
self._neutron_context.session, self._tenant_id))
|
||||
aim_app_profile_name = aim_md.AP_NAME
|
||||
aim_app_profiles = self._aim.find(
|
||||
aim_app_profiles = self.aim_mgr.find(
|
||||
self._aim_context, aim_resource.ApplicationProfile,
|
||||
tenant_name=aim_tenant_name, name=aim_app_profile_name)
|
||||
self.assertEqual(1, len(aim_app_profiles))
|
||||
aim_epgs = self._aim.find(
|
||||
aim_epgs = self.aim_mgr.find(
|
||||
self._aim_context, aim_resource.EndpointGroup, name=aim_epg_name)
|
||||
self.assertEqual(1, len(aim_epgs))
|
||||
self.assertEqual(aim_epg_name, aim_epgs[0].name)
|
||||
self.assertEqual(aim_tenant_name, aim_epgs[0].tenant_name)
|
||||
|
||||
self._test_aim_resource_status(aim_epgs[0], ptg)
|
||||
|
||||
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
|
||||
@@ -160,7 +198,7 @@ class TestPolicyTargetGroup(AIMBaseTestCase):
|
||||
# Explicitly created L2P should not be deleted
|
||||
self.show_l2_policy(ptg['l2_policy_id'], expected_res_status=200)
|
||||
|
||||
aim_epgs = self._aim.find(
|
||||
aim_epgs = self.aim_mgr.find(
|
||||
self._aim_context, aim_resource.EndpointGroup, name=aim_epg_name)
|
||||
self.assertEqual(0, len(aim_epgs))
|
||||
|
||||
@@ -340,7 +378,7 @@ class TestPolicyRule(AIMBaseTestCase):
|
||||
pr_id = pr['id']
|
||||
pr_name = pr['name']
|
||||
rn = self._aim_mapper.tenant_filter(tenant, pr_id, name=pr_name)
|
||||
aim_pr = self._aim.find(
|
||||
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)
|
||||
@@ -349,6 +387,6 @@ class TestPolicyRule(AIMBaseTestCase):
|
||||
self.delete_policy_rule(pr_id, expected_res_status=204)
|
||||
self.show_policy_rule(pr_id, expected_res_status=404)
|
||||
|
||||
aim_pr = self._aim.find(
|
||||
aim_pr = self.aim_mgr.find(
|
||||
self._aim_context, aim_resource.TenantFilter, rn=rn)
|
||||
self.assertEqual(0, len(aim_pr))
|
||||
|
@@ -12,7 +12,7 @@
|
||||
|
||||
import os
|
||||
|
||||
from neutron.common import config # noqa
|
||||
from neutron.common import config as neutron_config # noqa
|
||||
from neutron.db import model_base
|
||||
import sqlalchemy as sa
|
||||
|
||||
@@ -32,14 +32,17 @@ class ExtensionDriverTestBase(test_plugin.GroupPolicyPluginTestCase):
|
||||
_extension_drivers = ['test']
|
||||
_extension_path = os.path.dirname(os.path.abspath(test_ext.__file__))
|
||||
|
||||
def setUp(self):
|
||||
def setUp(self, policy_drivers=None, core_plugin=None,
|
||||
ml2_options=None, sc_plugin=None):
|
||||
config.cfg.CONF.set_override('extension_drivers',
|
||||
self._extension_drivers,
|
||||
group='group_policy')
|
||||
if self._extension_path:
|
||||
config.cfg.CONF.set_override(
|
||||
'api_extensions_path', self._extension_path)
|
||||
super(ExtensionDriverTestBase, self).setUp()
|
||||
super(ExtensionDriverTestBase, self).setUp(
|
||||
core_plugin=core_plugin, ml2_options=ml2_options,
|
||||
sc_plugin=sc_plugin)
|
||||
|
||||
|
||||
class ExtensionDriverTestCase(ExtensionDriverTestBase):
|
||||
|
@@ -48,6 +48,7 @@ neutron.service_plugins =
|
||||
gbpservice.neutron.group_policy.extension_drivers =
|
||||
test = gbpservice.neutron.tests.unit.services.grouppolicy.test_extension_driver_api:TestExtensionDriver
|
||||
proxy_group = gbpservice.neutron.services.grouppolicy.drivers.extensions.proxy_group_driver:ProxyGroupDriver
|
||||
aim_extension = gbpservice.neutron.services.grouppolicy.drivers.extensions.aim_mapping_extension_driver:AIMExtensionDriver
|
||||
gbpservice.neutron.group_policy.policy_drivers =
|
||||
dummy = gbpservice.neutron.services.grouppolicy.drivers.dummy_driver:NoopDriver
|
||||
implicit_policy = gbpservice.neutron.services.grouppolicy.drivers.implicit_policy:ImplicitPolicyDriver
|
||||
|
Reference in New Issue
Block a user