[aim-mapping] intra-ptg-allow ext attr for PTG
This attribute maps to the policy_enforcement_pref attribute of the AIM EPG, and is used to turn ON or OFF the intra-PTG traffic. It's True by default, implying all PTs in a PTG are allowed to communicate with each other. When set to False, there is no direct connectivity between the PTs of that PTG. Change-Id: I82094cbc1faaed879bfb75518df0f558f0bdad1c Closes-bug: #1648019
This commit is contained in:
parent
259053e740
commit
1f17e4f65a
|
@ -0,0 +1,43 @@
|
|||
# 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.db import model_base
|
||||
import sqlalchemy as sa
|
||||
|
||||
|
||||
class ApicIntraPtgDB(model_base.BASEV2):
|
||||
__tablename__ = 'gp_apic_intra_ptg'
|
||||
policy_target_group_id = sa.Column(
|
||||
sa.String(36), sa.ForeignKey('gp_policy_target_groups.id',
|
||||
ondelete='CASCADE'), primary_key=True)
|
||||
intra_ptg_allow = sa.Column(sa.Boolean, default=True, nullable=False)
|
||||
|
||||
|
||||
class ApicIntraPtgDBMixin(object):
|
||||
|
||||
def get_intra_ptg_allow(self, session, policy_target_group_id):
|
||||
row = (session.query(ApicIntraPtgDB).filter_by(
|
||||
policy_target_group_id=policy_target_group_id).one())
|
||||
return row['intra_ptg_allow']
|
||||
|
||||
def set_intra_ptg_allow(self, session, policy_target_group_id,
|
||||
intra_ptg_allow=True):
|
||||
with session.begin(subtransactions=True):
|
||||
row = (session.query(ApicIntraPtgDB).filter_by(
|
||||
policy_target_group_id=policy_target_group_id).first())
|
||||
if not row:
|
||||
row = ApicIntraPtgDB(
|
||||
policy_target_group_id=policy_target_group_id,
|
||||
intra_ptg_allow=intra_ptg_allow)
|
||||
session.add(row)
|
||||
else:
|
||||
row.update({'intra_ptg_allow': intra_ptg_allow})
|
|
@ -1 +1 @@
|
|||
4af01d620224
|
||||
fce38a8588a2
|
||||
|
|
|
@ -0,0 +1,45 @@
|
|||
# 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.
|
||||
|
||||
"""intra_ptg_allow
|
||||
|
||||
Revision ID: fce38a8588a2
|
||||
Revises: 4af01d620224
|
||||
Create Date: 2016-12-06 17:01:30.735865
|
||||
|
||||
"""
|
||||
|
||||
# revision identifiers, used by Alembic.
|
||||
revision = 'fce38a8588a2'
|
||||
down_revision = '4af01d620224'
|
||||
|
||||
from alembic import op
|
||||
import sqlalchemy as sa
|
||||
|
||||
|
||||
def upgrade():
|
||||
|
||||
op.create_table(
|
||||
'gp_apic_intra_ptg',
|
||||
sa.Column('policy_target_group_id', sa.String(length=36),
|
||||
nullable=False),
|
||||
sa.Column('intra_ptg_allow', sa.Boolean,
|
||||
server_default=sa.sql.true(), nullable=False),
|
||||
sa.ForeignKeyConstraint(
|
||||
['policy_target_group_id'], ['gp_policy_target_groups.id'],
|
||||
name='gp_apic_intra_ptg_fk_ptgid', ondelete='CASCADE'),
|
||||
sa.PrimaryKeyConstraint('policy_target_group_id')
|
||||
)
|
||||
|
||||
|
||||
def downgrade():
|
||||
pass
|
|
@ -11,6 +11,7 @@
|
|||
# under the License.
|
||||
|
||||
from neutron.api import extensions
|
||||
from neutron.api.v2 import attributes as attr
|
||||
|
||||
from gbpservice.neutron.extensions import cisco_apic
|
||||
from gbpservice.neutron.extensions import group_policy as gp
|
||||
|
@ -26,6 +27,9 @@ EXTENDED_ATTRIBUTES_2_0 = {
|
|||
gp.POLICY_TARGET_GROUPS: {
|
||||
cisco_apic.DIST_NAMES: {
|
||||
'allow_post': False, 'allow_put': False, 'is_visible': True},
|
||||
'intra_ptg_allow': {
|
||||
'allow_post': True, 'allow_put': True, 'default': True,
|
||||
'convert_to': attr.convert_to_boolean, 'is_visible': True},
|
||||
},
|
||||
gp.POLICY_RULES: {
|
||||
cisco_apic.DIST_NAMES: {
|
||||
|
|
|
@ -72,6 +72,8 @@ CONTRACTS = 'contracts'
|
|||
CONTRACT_SUBJECTS = 'contract_subjects'
|
||||
FILTERS = 'filters'
|
||||
FILTER_ENTRIES = 'filter_entries'
|
||||
ENFORCED = aim_resource.EndpointGroup.POLICY_ENFORCED
|
||||
UNENFORCED = aim_resource.EndpointGroup.POLICY_UNENFORCED
|
||||
|
||||
# REVISIT: Auto-PTG is currently config driven to align with the
|
||||
# config driven behavior of the older driver but is slated for
|
||||
|
@ -405,6 +407,7 @@ class AIMMappingDriver(nrd.CommonNeutronBase, aim_rpc.AIMMappingRPCMixin):
|
|||
self._configure_contracts_for_default_epg(
|
||||
context, l2p, default_epg_dn)
|
||||
if self.create_auto_ptg:
|
||||
default_epg = self._get_epg_by_dn(context, default_epg_dn)
|
||||
desc = "System created auto PTG for L2P: %s" % l2p['id']
|
||||
data = {
|
||||
"id": self._get_auto_ptg_id(l2p['id']),
|
||||
|
@ -417,6 +420,8 @@ class AIMMappingDriver(nrd.CommonNeutronBase, aim_rpc.AIMMappingRPCMixin):
|
|||
"network_service_policy_id": None,
|
||||
"service_management": False,
|
||||
"shared": l2p['shared'],
|
||||
"intra_ptg_allow":
|
||||
self._map_policy_enforcement_pref(default_epg),
|
||||
}
|
||||
self._create_policy_target_group(
|
||||
context._plugin_context, data, clean_session=False)
|
||||
|
@ -523,10 +528,14 @@ class AIMMappingDriver(nrd.CommonNeutronBase, aim_rpc.AIMMappingRPCMixin):
|
|||
session, context.current['provided_policy_rule_sets'])
|
||||
consumed_contracts = self._get_aim_contract_names(
|
||||
session, context.current['consumed_policy_rule_sets'])
|
||||
|
||||
aim_epg = self._aim_endpoint_group(
|
||||
session, context.current, bd_name, bd_tenant_name,
|
||||
provided_contracts=provided_contracts,
|
||||
consumed_contracts=consumed_contracts)
|
||||
consumed_contracts=consumed_contracts,
|
||||
policy_enforcement_pref=
|
||||
self._get_policy_enforcement_pref(context.current))
|
||||
|
||||
session = context._plugin_context.session
|
||||
aim_ctx = aim_context.AimContext(session)
|
||||
vmms, phys = self.aim_mech_driver.get_aim_domains(aim_ctx)
|
||||
|
@ -553,6 +562,8 @@ class AIMMappingDriver(nrd.CommonNeutronBase, aim_rpc.AIMMappingRPCMixin):
|
|||
if not self._is_auto_ptg(context.current):
|
||||
aim_epg.display_name = (
|
||||
self.aim_display_name(context.current['name']))
|
||||
aim_epg.policy_enforcement_pref = (
|
||||
self._get_policy_enforcement_pref(context.current))
|
||||
aim_epg.provided_contract_names = (
|
||||
list((set(aim_epg.provided_contract_names) -
|
||||
set(old_provided_contracts)) |
|
||||
|
@ -861,7 +872,8 @@ class AIMMappingDriver(nrd.CommonNeutronBase, aim_rpc.AIMMappingRPCMixin):
|
|||
def _aim_endpoint_group(self, session, ptg, bd_name=None,
|
||||
bd_tenant_name=None,
|
||||
provided_contracts=None,
|
||||
consumed_contracts=None):
|
||||
consumed_contracts=None,
|
||||
policy_enforcement_pref=UNENFORCED):
|
||||
# This returns a new AIM EPG resource
|
||||
# TODO(Sumit): Use _aim_resource_by_name
|
||||
tenant_id = ptg['tenant_id']
|
||||
|
@ -876,7 +888,8 @@ class AIMMappingDriver(nrd.CommonNeutronBase, aim_rpc.AIMMappingRPCMixin):
|
|||
kwargs = {'tenant_name': str(tenant_name),
|
||||
'name': str(epg_name),
|
||||
'display_name': display_name,
|
||||
'app_profile_name': self.aim_mech_driver.ap_name}
|
||||
'app_profile_name': self.aim_mech_driver.ap_name,
|
||||
'policy_enforcement_pref': policy_enforcement_pref}
|
||||
if bd_name:
|
||||
kwargs['bd_name'] = bd_name
|
||||
if bd_tenant_name:
|
||||
|
@ -1922,6 +1935,25 @@ class AIMMappingDriver(nrd.CommonNeutronBase, aim_rpc.AIMMappingRPCMixin):
|
|||
def _is_auto_ptg(self, ptg):
|
||||
return ptg['id'].startswith(AUTO_PTG_PREFIX)
|
||||
|
||||
def _get_policy_enforcement_pref(self, ptg):
|
||||
if ptg.get('intra_ptg_allow'):
|
||||
policy_enforcement_pref = UNENFORCED
|
||||
else:
|
||||
policy_enforcement_pref = ENFORCED
|
||||
return policy_enforcement_pref
|
||||
|
||||
def _map_policy_enforcement_pref(self, epg):
|
||||
if epg.policy_enforcement_pref == UNENFORCED:
|
||||
return True
|
||||
else:
|
||||
return False
|
||||
|
||||
def _get_epg_by_dn(self, context, epg_dn):
|
||||
aim_context = self._get_aim_context(context)
|
||||
epg = self.aim.get(
|
||||
aim_context, aim_resource.EndpointGroup.from_dn(epg_dn))
|
||||
return epg
|
||||
|
||||
def _get_epg_name_from_dn(self, context, epg_dn):
|
||||
aim_context = self._get_aim_context(context)
|
||||
default_epg_name = self.aim.get(
|
||||
|
|
|
@ -14,14 +14,19 @@ from neutron._i18n import _LI
|
|||
from neutron import manager as n_manager
|
||||
from oslo_log import log as logging
|
||||
|
||||
from gbpservice.neutron.db.grouppolicy.extensions import (
|
||||
apic_intra_ptg_db as db)
|
||||
from gbpservice.neutron.db.grouppolicy import group_policy_db as gp_db
|
||||
from gbpservice.neutron.extensions import cisco_apic_gbp
|
||||
from gbpservice.neutron.extensions import group_policy as gpolicy
|
||||
from gbpservice.neutron.services.grouppolicy import (
|
||||
group_policy_driver_api as api)
|
||||
|
||||
LOG = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class AIMExtensionDriver(api.ExtensionDriver):
|
||||
class AIMExtensionDriver(api.ExtensionDriver,
|
||||
db.ApicIntraPtgDBMixin):
|
||||
_supported_extension_alias = cisco_apic_gbp.ALIAS
|
||||
_extension_dict = cisco_apic_gbp.EXTENDED_ATTRIBUTES_2_0
|
||||
|
||||
|
@ -45,7 +50,25 @@ class AIMExtensionDriver(api.ExtensionDriver):
|
|||
def extension_alias(self):
|
||||
return self._supported_extension_alias
|
||||
|
||||
def process_create_policy_target_group(self, session, data, result):
|
||||
ptg = data['policy_target_group']
|
||||
if 'intra_ptg_allow' in ptg:
|
||||
ptg_db = (session.query(gp_db.PolicyTargetGroup)
|
||||
.filter_by(id=result['id']).one())
|
||||
if not ptg_db:
|
||||
raise gpolicy.PolicyTargetGroupNotFound(
|
||||
policy_target_group_id=result['id'])
|
||||
self.set_intra_ptg_allow(
|
||||
session, policy_target_group_id=result['id'],
|
||||
intra_ptg_allow=ptg['intra_ptg_allow'])
|
||||
result['intra_ptg_allow'] = ptg['intra_ptg_allow']
|
||||
|
||||
def process_update_policy_target_group(self, session, data, result):
|
||||
self.process_create_policy_target_group(session, data, result)
|
||||
|
||||
def extend_policy_target_group_dict(self, session, result):
|
||||
result['intra_ptg_allow'] = self.get_intra_ptg_allow(
|
||||
session, policy_target_group_id=result['id'])
|
||||
self._pd.extend_policy_target_group_dict(session, result)
|
||||
|
||||
def extend_policy_rule_dict(self, session, result):
|
||||
|
|
|
@ -1220,6 +1220,21 @@ class TestL2PolicyWithAutoPTG(TestL2PolicyBase):
|
|||
self.assertEqual(l3p['subnetpools_v4'][0],
|
||||
subnet['subnetpool_id'])
|
||||
|
||||
auto_ptg_id = self.driver._get_auto_ptg_id(ptg['l2_policy_id'])
|
||||
aim_epg_name = self.driver.apic_epg_name_for_policy_target_group(
|
||||
self._neutron_context.session, auto_ptg_id)
|
||||
aim_epg = self.aim_mgr.find(
|
||||
self._aim_context, aim_resource.EndpointGroup,
|
||||
name=aim_epg_name)[0]
|
||||
auto_ptg = self.show_policy_target_group(
|
||||
auto_ptg_id, expected_res_status=200)['policy_target_group']
|
||||
if aim_epg.policy_enforcement_pref == (
|
||||
aim_resource.EndpointGroup.POLICY_UNENFORCED):
|
||||
self.assertTrue(auto_ptg['intra_ptg_allow'])
|
||||
elif aim_epg.policy_enforcement_pref == (
|
||||
aim_resource.EndpointGroup.POLICY_ENFORCED):
|
||||
self.assertFalse(ptg['intra_ptg_allow'])
|
||||
|
||||
self.delete_policy_target_group(ptg_id, expected_res_status=204)
|
||||
self.show_policy_target_group(ptg_id, expected_res_status=404)
|
||||
self.show_l2_policy(ptg['l2_policy_id'], expected_res_status=404)
|
||||
|
@ -1559,6 +1574,25 @@ class TestPolicyTargetGroup(AIMBaseTestCase):
|
|||
self.assertIn(subnet_id, info['subnet_ids'])
|
||||
self.delete_policy_target_group(ptg_id, expected_res_status=204)
|
||||
|
||||
def test_policy_target_group_intra_ptg_allow(self):
|
||||
ptg = self.create_policy_target_group(
|
||||
intra_ptg_allow=False)['policy_target_group']
|
||||
self.assertFalse(ptg['intra_ptg_allow'])
|
||||
aim_epg_name = self.driver.apic_epg_name_for_policy_target_group(
|
||||
self._neutron_context.session, ptg['id'])
|
||||
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_resource.EndpointGroup.POLICY_ENFORCED,
|
||||
aim_epgs[0].policy_enforcement_pref)
|
||||
ptg = self.update_policy_target_group(
|
||||
ptg['id'], intra_ptg_allow=True)['policy_target_group']
|
||||
self.assertTrue(ptg['intra_ptg_allow'])
|
||||
aim_epgs = self.aim_mgr.find(
|
||||
self._aim_context, aim_resource.EndpointGroup, name=aim_epg_name)
|
||||
self.assertEqual(aim_resource.EndpointGroup.POLICY_UNENFORCED,
|
||||
aim_epgs[0].policy_enforcement_pref)
|
||||
|
||||
|
||||
# TODO(Sumit): Add tests here which tests different scenarios for subnet
|
||||
# allocation for PTGs
|
||||
|
|
Loading…
Reference in New Issue