Merge "AIM Policy Driver - Part 2 - Extension Driver" into stable/mitaka
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