GBP servicechain instance should be maintained between a pair of PTGs

Change-Id: If30cbd09b1bd9ac2db5df47ac50e395274146dee
Closes-bug: #1387508
This commit is contained in:
Magesh GV
2014-12-08 21:02:02 +05:30
parent 0ff6e01eee
commit b8345171cf
3 changed files with 100 additions and 99 deletions

View File

@@ -13,7 +13,7 @@
# under the License.
#
"""gbp_rule_servicechain_mapping
"""gbp_ptgs_servicechain_mapping
Revision ID: 6d76bcf836a7
Revises: 43443f15fa3f
@@ -31,16 +31,22 @@ import sqlalchemy as sa
def upgrade(active_plugins=None, options=None):
op.create_table(
'gpm_rule_servicechain_mapping',
sa.Column('rule_id', sa.String(length=36), nullable=False),
'gpm_ptgs_servicechain_mapping',
sa.Column('provider_ptg_id', sa.String(length=36), nullable=False),
sa.Column('consumer_ptg_id', sa.String(length=36), nullable=False),
sa.Column('servicechain_instance_id', sa.String(length=36)),
sa.ForeignKeyConstraint(['rule_id'], ['gp_policy_rules.id']),
sa.ForeignKeyConstraint(['provider_ptg_id'],
['gp_policy_target_groups.id'],
ondelete='CASCADE'),
sa.ForeignKeyConstraint(['consumer_ptg_id'],
['gp_policy_target_groups.id'],
ondelete='CASCADE'),
sa.ForeignKeyConstraint(['servicechain_instance_id'],
['sc_instances.id'],
ondelete='CASCADE'),
sa.PrimaryKeyConstraint('rule_id')
sa.PrimaryKeyConstraint('servicechain_instance_id')
)
def downgrade(active_plugins=None, options=None):
op.drop_table('gpm_rule_servicechain_mapping')
op.drop_table('gpm_ptgs_servicechain_mapping')

View File

@@ -89,16 +89,22 @@ class PolicyRuleSetSGsMapping(model_base.BASEV2):
sa.ForeignKey('securitygroups.id'))
class RuleServiceChainInstanceMapping(model_base.BASEV2):
"""Policy Rule to ServiceChainInstance mapping DB."""
class PtgServiceChainInstanceMapping(model_base.BASEV2):
"""Policy Target Group to ServiceChainInstance mapping DB."""
__tablename__ = 'gpm_rule_servicechain_mapping'
rule_id = sa.Column(sa.String(36),
sa.ForeignKey('gp_policy_rules.id'),
nullable=False, primary_key=True)
__tablename__ = 'gpm_ptgs_servicechain_mapping'
provider_ptg_id = sa.Column(sa.String(36),
sa.ForeignKey('gp_policy_target_groups.id',
ondelete='CASCADE'),
nullable=False)
consumer_ptg_id = sa.Column(sa.String(36),
sa.ForeignKey('gp_policy_target_groups.id',
ondelete='CASCADE'),
nullable=False)
servicechain_instance_id = sa.Column(sa.String(36),
sa.ForeignKey('sc_instances.id',
ondelete='CASCADE'))
ondelete='CASCADE'),
primary_key=True)
class ServicePolicyPTGIpAddressMapping(model_base.BASEV2):
@@ -362,7 +368,15 @@ class ResourceMappingDriver(api.PolicyDriver):
@log.log
def delete_policy_target_group_precommit(self, context):
pass
provider_ptg_chain_map = self._get_ptg_servicechain_mapping(
context._plugin_context.session,
context.current['id'],
None)
consumer_ptg_chain_map = self._get_ptg_servicechain_mapping(
context._plugin_context.session,
None,
context.current['id'],)
context.ptg_chain_map = provider_ptg_chain_map + consumer_ptg_chain_map
@log.log
def delete_policy_target_group_postcommit(self, context):
@@ -883,10 +897,6 @@ class ResourceMappingDriver(api.PolicyDriver):
policy_rule_set = context._plugin.get_policy_rule_set(
context._plugin_context, policy_rule_set_id)
for rule_id in policy_rule_set.get('policy_rules'):
rule_chain_map = self._get_rule_servicechain_mapping(
context._plugin_context.session, rule_id)
if rule_chain_map:
break # Only one redirect action per rule
policy_rule = context._plugin.get_policy_rule(
context._plugin_context, rule_id)
classifier_id = policy_rule.get("policy_classifier_id")
@@ -896,46 +906,29 @@ class ResourceMappingDriver(api.PolicyDriver):
if policy_action['action_type'].upper() == "REDIRECT":
for ptg_consuming_prs in (
ptgs_consuming_policy_rule_set):
ptg_chain_map = self._get_ptg_servicechain_mapping(
context._plugin_context.session,
ptg_providing_prs.policy_target_group_id,
ptg_consuming_prs.policy_target_group_id)
if ptg_chain_map:
break # one chain between a pair of PTGs
sc_instance = self._create_servicechain_instance(
context, policy_action.get("action_value"),
ptg_providing_prs.policy_target_group_id,
ptg_consuming_prs.policy_target_group_id,
classifier_id)
chain_instance_id = sc_instance['id']
self._set_rule_servicechain_instance_mapping(
self._set_ptg_servicechain_instance_mapping(
context._plugin_context.session,
rule_id, chain_instance_id)
ptg_providing_prs.policy_target_group_id,
ptg_consuming_prs.policy_target_group_id,
chain_instance_id)
break
def _cleanup_redirect_action(self, context):
consumed_policy_rule_sets = context.current[
'consumed_policy_rule_sets']
provided_policy_rule_sets = context.current[
'provided_policy_rule_sets']
if not provided_policy_rule_sets and not consumed_policy_rule_sets:
return
policy_rule_sets = provided_policy_rule_sets + (
consumed_policy_rule_sets)
for policy_rule_set_id in policy_rule_sets:
ptgs_consuming_policy_rule_set = (
self._get_ptgs_consuming_policy_rule_set(
context._plugin_context._session, policy_rule_set_id))
ptg_providing_policy_rule_set = (
self._get_ptgs_providing_policy_rule_set(
context._plugin_context._session, policy_rule_set_id))
# Delete the ServiceChain Instance when we do not have either
# the Provider or the consumer PTGs
if not ptgs_consuming_policy_rule_set or (
not ptg_providing_policy_rule_set):
policy_rule_set = context._plugin.get_policy_rule_set(
context._plugin_context, policy_rule_set_id)
for rule_id in policy_rule_set.get('policy_rules'):
chain_id_map = self._get_rule_servicechain_mapping(
context._plugin_context.session, rule_id)
if chain_id_map:
self._delete_servicechain_instance(
context, chain_id_map.servicechain_instance_id)
break # Only one redirect action per rule
for ptg_chain in context.ptg_chain_map:
self._delete_servicechain_instance(
context, ptg_chain.servicechain_instance_id)
# The following methods perform the necessary subset of
# functionality from neutron.api.v2.base.Controller.
@@ -1541,15 +1534,22 @@ class ResourceMappingDriver(api.PolicyDriver):
'consuming_cidrs': self._get_ptg_cidrs(
context, policy_rule_set['consuming_policy_target_groups'])}
def _set_rule_servicechain_instance_mapping(self, session, rule_id,
servicechain_instance_id):
def _set_ptg_servicechain_instance_mapping(self, session, provider_ptg_id,
consumer_ptg_id,
servicechain_instance_id):
with session.begin(subtransactions=True):
mapping = RuleServiceChainInstanceMapping(
rule_id=rule_id,
mapping = PtgServiceChainInstanceMapping(
provider_ptg_id=provider_ptg_id,
consumer_ptg_id=consumer_ptg_id,
servicechain_instance_id=servicechain_instance_id)
session.add(mapping)
def _get_rule_servicechain_mapping(self, session, rule_id):
def _get_ptg_servicechain_mapping(self, session, provider_ptg_id,
consumer_ptg_id):
with session.begin(subtransactions=True):
return (session.query(RuleServiceChainInstanceMapping).
filter_by(rule_id=rule_id).first())
query = session.query(PtgServiceChainInstanceMapping)
if provider_ptg_id:
query = query.filter_by(provider_ptg_id=provider_ptg_id)
if consumer_ptg_id:
query = query.filter_by(consumer_ptg_id=consumer_ptg_id)
return query.all()

View File

@@ -27,10 +27,12 @@ import webob.exc
from gbp.neutron.db import servicechain_db
from gbp.neutron.services.grouppolicy.common import constants as gconst
from gbp.neutron.services.grouppolicy import config
from gbp.neutron.services.grouppolicy.drivers import resource_mapping
from gbp.neutron.services.servicechain import servicechain_plugin
from gbp.neutron.tests.unit.services.grouppolicy import test_grouppolicy_plugin
SERVICECHAIN_NODES = 'servicechain/servicechain_nodes'
SERVICECHAIN_SPECS = 'servicechain/servicechain_specs'
SERVICECHAIN_INSTANCES = 'servicechain/servicechain_instances'
class NoL3NatSGTestPlugin(
test_l3_plugin.TestNoL3NatPlugin,
@@ -858,12 +860,23 @@ class TestPolicyRuleSet(ResourceMappingTestCase):
self.assertEqual(udp_rule['port_range_max'], 150)
def test_redirect_to_chain(self):
data = {'servicechain_node': {'service_type': "LOADBALANCER",
'tenant_id': self._tenant_id,
'config': "{}"}}
scn_req = self.new_create_request(SERVICECHAIN_NODES, data, self.fmt)
node = self.deserialize(self.fmt, scn_req.get_response(self.ext_api))
scn_id = node['servicechain_node']['id']
data = {'servicechain_spec': {'tenant_id': self._tenant_id,
'nodes': [scn_id]}}
scs_req = self.new_create_request(SERVICECHAIN_SPECS, data, self.fmt)
spec = self.deserialize(self.fmt, scs_req.get_response(self.ext_api))
scs_id = spec['servicechain_spec']['id']
classifier = self.create_policy_classifier(
name="class1", protocol="tcp", direction="in", port_range="20:90")
classifier_id = classifier['policy_classifier']['id']
action = self.create_policy_action(
name="action1", action_type=gconst.GP_ACTION_REDIRECT,
action_value=uuidutils.generate_uuid())
action_value=scs_id)
action_id = action['policy_action']['id']
action_id_list = [action_id]
policy_rule = self.create_policy_rule(
@@ -874,47 +887,29 @@ class TestPolicyRuleSet(ResourceMappingTestCase):
policy_rule_set = self.create_policy_rule_set(
name="c1", policy_rules=policy_rule_list)
policy_rule_set_id = policy_rule_set['policy_rule_set']['id']
self.create_policy_target_group(
provider_ptg = self.create_policy_target_group(
name="ptg1", provided_policy_rule_sets={policy_rule_set_id: None})
create_chain_instance = mock.patch.object(
servicechain_plugin.ServiceChainPlugin,
'create_servicechain_instance')
create_chain_instance = create_chain_instance.start()
chain_instance_id = uuidutils.generate_uuid()
create_chain_instance.return_value = {'id': chain_instance_id}
# TODO(Magesh):Add tests which verifies that provide/consumer PTGs
# are set correctly for the SCI
with mock.patch.object(
resource_mapping.ResourceMappingDriver,
'_set_rule_servicechain_instance_mapping') as set_rule:
with mock.patch.object(servicechain_db.ServiceChainDbPlugin,
'get_servicechain_spec') as sc_spec_get:
sc_spec_get.return_value = {'servicechain_spec': {}}
consumer_ptg = self.create_policy_target_group(
name="ptg2",
consumed_policy_rule_sets={policy_rule_set_id: None})
consumer_ptg_id = consumer_ptg['policy_target_group']['id']
set_rule.assert_called_once_with(mock.ANY, policy_rule_id,
chain_instance_id)
with mock.patch.object(servicechain_plugin.ServiceChainPlugin,
'delete_servicechain_instance'):
with mock.patch.object(
resource_mapping.ResourceMappingDriver,
'_get_rule_servicechain_mapping') as get_rule:
r_sc_map = resource_mapping.RuleServiceChainInstanceMapping()
r_sc_map.rule_id = policy_rule_id
r_sc_map.servicechain_instance_id = chain_instance_id
get_rule.return_value = r_sc_map
get_chain_inst = mock.patch.object(
servicechain_db.ServiceChainDbPlugin,
'get_servicechain_instance')
get_chain_inst.start()
get_chain_inst.return_value = {
"servicechain_instance": {'id': chain_instance_id}}
req = self.new_delete_request(
'policy_target_groups', consumer_ptg_id)
res = req.get_response(self.ext_api)
self.assertEqual(res.status_int, webob.exc.HTTPNoContent.code)
provider_ptg_id = provider_ptg['policy_target_group']['id']
consumer_ptg = self.create_policy_target_group(
name="ptg2",
consumed_policy_rule_sets={policy_rule_set_id: None})
consumer_ptg_id = consumer_ptg['policy_target_group']['id']
sc_node_list_req = self.new_list_request(SERVICECHAIN_INSTANCES)
res = sc_node_list_req.get_response(self.ext_api)
sc_instances = self.deserialize(self.fmt, res)
# We should have one service chain instance created now
self.assertEqual(len(sc_instances['servicechain_instances']), 1)
sc_instance = sc_instances['servicechain_instances'][0]
self.assertEqual(sc_instance['provider_ptg_id'], provider_ptg_id)
self.assertEqual(sc_instance['consumer_ptg_id'], consumer_ptg_id)
req = self.new_delete_request(
'policy_target_groups', consumer_ptg_id)
res = req.get_response(self.ext_api)
self.assertEqual(res.status_int, webob.exc.HTTPNoContent.code)
sc_node_list_req = self.new_list_request(SERVICECHAIN_INSTANCES)
res = sc_node_list_req.get_response(self.ext_api)
sc_instances = self.deserialize(self.fmt, res)
self.assertEqual(len(sc_instances['servicechain_instances']), 0)
def test_shared_policy_rule_set_create_negative(self):
self.create_policy_rule_set(shared=True, expected_res_status=400)
@@ -931,4 +926,4 @@ class TestPolicyAction(ResourceMappingTestCase):
shared=True,
action_value=uuid)
self.assertEqual('InvalidSharedResource',
res['NeutronError']['type'])
res['NeutronError']['type'])