Share service chain constructs
Adding 'shared' attribute to the following service chain objects: - Service Chain Node; - Service Chain Spec. As a side effect, REDIRECT rules can now be shared with a shared SCS value. implements blueprint share-servicechain-objects Change-Id: If6cd4072271fdbe9f213aa2922cb918547340cd3
This commit is contained in:
parent
c66404c4b6
commit
c9bfb7b116
|
@ -4,60 +4,87 @@
|
|||
"admin_only": "rule:context_is_admin",
|
||||
"regular_user": "",
|
||||
"default": "rule:admin_or_owner",
|
||||
"gbp_shared": "field:policy_target_groups:shared=True",
|
||||
"shared_ptg": "field:policy_target_groups:shared=True",
|
||||
"shared_pt": "field:policy_targets:shared=True",
|
||||
"shared_prs": "field:policy_rule_sets:shared=True",
|
||||
"shared_l3p": "field:l3_policies:shared=True",
|
||||
"shared_l2p": "field:l2_policies:shared=True",
|
||||
"shared_es": "field:external_segments:shared=True",
|
||||
"shared_ep": "field:external_policies:shared=True",
|
||||
"shared_pc": "field:policy_classifiers:shared=True",
|
||||
"shared_pa": "field:policy_actions:shared=True",
|
||||
"shared_pr": "field:policy_rules:shared=True",
|
||||
"shared_np": "field:nat_pools:shared=True",
|
||||
"shared_nsp": "field:network_service_policies:shared=True",
|
||||
"shared_scn": "field:servicechain_nodes:shared=True",
|
||||
"shared_scs": "field:servicechain_specs:shared=True",
|
||||
|
||||
"create_policy_target_group": "",
|
||||
"create_policy_target_group:shared": "rule:admin_only",
|
||||
"get_policy_target_group": "rule:admin_or_owner or rule:gbp_shared",
|
||||
"get_policy_target_group": "rule:admin_or_owner or rule:shared_ptg",
|
||||
"update_policy_target_group:shared": "rule:admin_only",
|
||||
|
||||
"create_l2_policy": "",
|
||||
"create_l2_policy:shared": "rule:admin_only",
|
||||
"get_l2_policy": "rule:admin_or_owner or rule:gbp_shared",
|
||||
"get_l2_policy": "rule:admin_or_owner or rule:shared_l2p",
|
||||
"update_l2_policy:shared": "rule:admin_only",
|
||||
|
||||
"create_l3_policy": "",
|
||||
"create_l3_policy:shared": "rule:admin_only",
|
||||
"get_l3_policy": "rule:admin_or_owner or rule:gbp_shared",
|
||||
"get_l3_policy": "rule:admin_or_owner or rule:shared_l3p",
|
||||
"update_l3_policy:shared": "rule:admin_only",
|
||||
|
||||
"create_policy_classifier": "",
|
||||
"create_policy_classifier:shared": "rule:admin_only",
|
||||
"get_policy_classifier": "rule:admin_or_owner or rule:gbp_shared",
|
||||
"get_policy_classifier": "rule:admin_or_owner or rule:shared_pc",
|
||||
"update_policy_classifier:shared": "rule:admin_only",
|
||||
|
||||
"create_policy_action": "",
|
||||
"create_policy_action:shared": "rule:admin_only",
|
||||
"get_policy_action": "rule:admin_or_owner or rule:gbp_shared",
|
||||
"get_policy_action": "rule:admin_or_owner or rule:shared_pa",
|
||||
"update_policy_action:shared": "rule:admin_only",
|
||||
|
||||
"create_policy_rule": "",
|
||||
"create_policy_rule:shared": "rule:admin_only",
|
||||
"get_policy_rule": "rule:admin_or_owner or rule:gbp_shared",
|
||||
"get_policy_rule": "rule:admin_or_owner or rule:shared_pr",
|
||||
"update_policy_rule:shared": "rule:admin_only",
|
||||
|
||||
"create_policy_rule_set": "",
|
||||
"create_policy_rule_set:shared": "rule:admin_only",
|
||||
"get_policy_rule_set": "rule:admin_or_owner or rule:gbp_shared",
|
||||
"get_policy_rule_set": "rule:admin_or_owner or rule:shared_prs",
|
||||
"update_policy_rule_set:shared": "rule:admin_only",
|
||||
|
||||
"create_network_service_policy": "",
|
||||
"create_network_service_policy:shared": "rule:admin_only",
|
||||
"get_network_service_policy": "rule:admin_or_owner or rule:gbp_shared",
|
||||
"get_network_service_policy": "rule:admin_or_owner or rule:shared_nsp",
|
||||
"update_network_service_policy:shared": "rule:admin_only",
|
||||
|
||||
"create_external_segment": "",
|
||||
"create_external_segment:shared": "rule:admin_only",
|
||||
"get_external_segment": "rule:admin_or_owner or rule:gbp_shared",
|
||||
"get_external_segment": "rule:admin_or_owner or rule:shared_es",
|
||||
"update_external_segment:shared": "rule:admin_only",
|
||||
|
||||
"create_external_policy": "",
|
||||
"create_external_policy:shared": "rule:admin_only",
|
||||
"get_external_policy": "rule:admin_or_owner or rule:gbp_shared",
|
||||
"get_external_policy": "rule:admin_or_owner or rule:shared_ep",
|
||||
"update_external_policy:shared": "rule:admin_only",
|
||||
|
||||
"create_nat_pool": "",
|
||||
"create_nat_pool:shared": "rule:admin_only",
|
||||
"get_nat_pool": "rule:admin_or_owner or rule:gbp_shared",
|
||||
"update_nat_pool:shared": "rule:admin_only"
|
||||
"get_nat_pool": "rule:admin_or_owner or rule:shared_np",
|
||||
"update_nat_pool:shared": "rule:admin_only",
|
||||
|
||||
"create_servicechain_node": "",
|
||||
"create_servicechain_node:shared": "rule:admin_only",
|
||||
"get_servicechain_node": "rule:admin_or_owner or rule:shared_scn",
|
||||
"update_servicechain_node:shared": "rule:admin_only",
|
||||
|
||||
"create_servicechain_spec": "",
|
||||
"create_servicechain_spec:shared": "rule:admin_only",
|
||||
"get_servicechain_spec": "rule:admin_or_owner or rule:shared_scs",
|
||||
"update_servicechain_spec:shared": "rule:admin_only",
|
||||
|
||||
"create_servicechain_instance": "",
|
||||
"get_servicechain_instance": "rule:admin_or_owner",
|
||||
"update_servicechain_instance:shared": "rule:admin_only"
|
||||
}
|
||||
|
|
|
@ -883,6 +883,8 @@ class GroupPolicyDbPlugin(gpolicy.GroupPolicyPluginBase,
|
|||
'action_type': pa['action_type'],
|
||||
'action_value': pa['action_value'],
|
||||
'shared': pa.get('shared', False), }
|
||||
res['policy_rules'] = [pr['policy_rule_id'] for
|
||||
pr in pa['policy_rules']]
|
||||
return self._fields(res, fields)
|
||||
|
||||
def _make_policy_rule_dict(self, pr, fields=None):
|
||||
|
|
|
@ -0,0 +1,40 @@
|
|||
# Copyright 2014 OpenStack Foundation
|
||||
#
|
||||
# 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.
|
||||
#
|
||||
|
||||
# revision identifiers, used by Alembic.
|
||||
revision = '3791adbf0045'
|
||||
down_revision = '2f3834ea746b'
|
||||
|
||||
|
||||
from alembic import op
|
||||
import sqlalchemy as sa
|
||||
|
||||
|
||||
def upgrade():
|
||||
|
||||
op.add_column(
|
||||
'sc_nodes',
|
||||
sa.Column('shared', sa.Boolean)
|
||||
)
|
||||
|
||||
op.add_column(
|
||||
'sc_specs',
|
||||
sa.Column('shared', sa.Boolean)
|
||||
)
|
||||
|
||||
|
||||
def downgrade():
|
||||
op.drop_column('sc_nodes', 'shared')
|
||||
op.drop_column('sc_specs', 'shared')
|
|
@ -1 +1 @@
|
|||
2f3834ea746b
|
||||
3791adbf0045
|
|
@ -68,6 +68,7 @@ class ServiceChainNode(model_base.BASEV2, models_v2.HasId,
|
|||
specs = orm.relationship(SpecNodeAssociation,
|
||||
backref="nodes",
|
||||
cascade='all, delete, delete-orphan')
|
||||
shared = sa.Column(sa.Boolean)
|
||||
|
||||
|
||||
class ServiceChainInstance(model_base.BASEV2, models_v2.HasId,
|
||||
|
@ -111,6 +112,7 @@ class ServiceChainSpec(model_base.BASEV2, models_v2.HasId,
|
|||
instances = orm.relationship(InstanceSpecAssociation,
|
||||
backref="specs",
|
||||
cascade='all, delete, delete-orphan')
|
||||
shared = sa.Column(sa.Boolean)
|
||||
|
||||
|
||||
class ServiceChainDbPlugin(schain.ServiceChainPluginBase,
|
||||
|
@ -161,7 +163,10 @@ class ServiceChainDbPlugin(schain.ServiceChainPluginBase,
|
|||
'name': sc_node['name'],
|
||||
'description': sc_node['description'],
|
||||
'service_type': sc_node['service_type'],
|
||||
'config': sc_node['config']}
|
||||
'config': sc_node['config'],
|
||||
'shared': sc_node['shared']}
|
||||
res['servicechain_specs'] = [sc_spec['servicechain_spec_id']
|
||||
for sc_spec in sc_node['specs']]
|
||||
return self._fields(res, fields)
|
||||
|
||||
def _make_sc_spec_dict(self, spec, fields=None):
|
||||
|
@ -169,7 +174,8 @@ class ServiceChainDbPlugin(schain.ServiceChainPluginBase,
|
|||
'tenant_id': spec['tenant_id'],
|
||||
'name': spec['name'],
|
||||
'description': spec['description'],
|
||||
'config_param_names': spec.get('config_param_names')}
|
||||
'config_param_names': spec.get('config_param_names'),
|
||||
'shared': spec['shared']}
|
||||
res['nodes'] = [sc_node['node_id'] for sc_node in spec['nodes']]
|
||||
return self._fields(res, fields)
|
||||
|
||||
|
@ -201,7 +207,8 @@ class ServiceChainDbPlugin(schain.ServiceChainPluginBase,
|
|||
name=node['name'],
|
||||
description=node['description'],
|
||||
service_type=node['service_type'],
|
||||
config=node['config'])
|
||||
config=node['config'],
|
||||
shared=node['shared'])
|
||||
context.session.add(node_db)
|
||||
return self._make_sc_node_dict(node_db)
|
||||
|
||||
|
@ -331,7 +338,8 @@ class ServiceChainDbPlugin(schain.ServiceChainPluginBase,
|
|||
spec_db = ServiceChainSpec(id=uuidutils.generate_uuid(),
|
||||
tenant_id=tenant_id,
|
||||
name=spec['name'],
|
||||
description=spec['description'])
|
||||
description=spec['description'],
|
||||
shared=spec['shared'])
|
||||
self._process_nodes_for_spec(context, spec_db, spec)
|
||||
context.session.add(spec_db)
|
||||
return self._make_sc_spec_dict(spec_db)
|
||||
|
|
|
@ -115,6 +115,10 @@ RESOURCE_ATTRIBUTE_MAP = {
|
|||
'config': {'allow_post': True, 'allow_put': False,
|
||||
'validate': {'type:string': None},
|
||||
'required': True, 'is_visible': True},
|
||||
attr.SHARED: {'allow_post': True, 'allow_put': True,
|
||||
'default': False, 'convert_to': attr.convert_to_boolean,
|
||||
'is_visible': True, 'required_by_policy': True,
|
||||
'enforce_policy': True},
|
||||
},
|
||||
SERVICECHAIN_SPECS: {
|
||||
'id': {'allow_post': False, 'allow_put': False,
|
||||
|
@ -137,6 +141,10 @@ RESOURCE_ATTRIBUTE_MAP = {
|
|||
'config_param_names': {'allow_post': False, 'allow_put': False,
|
||||
'validate': {'type:string_list': None},
|
||||
'default': [], 'is_visible': True},
|
||||
attr.SHARED: {'allow_post': True, 'allow_put': True,
|
||||
'default': False, 'convert_to': attr.convert_to_boolean,
|
||||
'is_visible': True, 'required_by_policy': True,
|
||||
'enforce_policy': True},
|
||||
},
|
||||
SERVICECHAIN_INSTANCES: {
|
||||
'id': {'allow_post': False, 'allow_put': False,
|
||||
|
|
|
@ -77,9 +77,8 @@ class PolicyTargetGroupContext(GroupPolicyContext,
|
|||
|
||||
def set_l2_policy_id(self, l2_policy_id):
|
||||
self._plugin._validate_shared_create(
|
||||
self._plugin_context,
|
||||
self._policy_target_group,
|
||||
'policy_target_group')
|
||||
self._plugin, self._plugin_context, self._policy_target_group,
|
||||
'policy_target_group')
|
||||
self._plugin._set_l2_policy_for_policy_target_group(
|
||||
self._plugin_context, self._policy_target_group['id'],
|
||||
l2_policy_id)
|
||||
|
@ -115,9 +114,7 @@ class L2PolicyContext(GroupPolicyContext, api.L2PolicyContext):
|
|||
|
||||
def set_l3_policy_id(self, l3_policy_id):
|
||||
self._plugin._validate_shared_create(
|
||||
self._plugin_context,
|
||||
self._l2_policy,
|
||||
'l2_policy')
|
||||
self._plugin, self._plugin_context, self._l2_policy, 'l2_policy')
|
||||
self._plugin._set_l3_policy_for_l2_policy(
|
||||
self._plugin_context, self._l2_policy['id'], l3_policy_id)
|
||||
self._l2_policy['l3_policy_id'] = l3_policy_id
|
||||
|
|
|
@ -14,6 +14,8 @@ import netaddr
|
|||
|
||||
from neutron.api.v2 import attributes as nattr
|
||||
from neutron.common import log
|
||||
from neutron import manager as n_manager
|
||||
from neutron.plugins.common import constants as pconst
|
||||
from oslo_log import log as logging
|
||||
from oslo_utils import excutils
|
||||
|
||||
|
@ -26,6 +28,7 @@ from gbpservice.neutron.services.grouppolicy import (
|
|||
group_policy_context as p_context)
|
||||
from gbpservice.neutron.services.grouppolicy import (
|
||||
policy_driver_manager as manager)
|
||||
from gbpservice.neutron.services.grouppolicy.common import constants as gp_cts
|
||||
from gbpservice.neutron.services.grouppolicy.common import exceptions as gp_exc
|
||||
|
||||
|
||||
|
@ -50,6 +53,17 @@ class GroupPolicyPlugin(group_policy_mapping_db.GroupPolicyMappingDbPlugin):
|
|||
self._aliases = aliases
|
||||
return self._aliases
|
||||
|
||||
@property
|
||||
def servicechain_plugin(self):
|
||||
# REVISIT(rkukura): Need initialization method after all
|
||||
# plugins are loaded to grab and store plugin.
|
||||
plugins = n_manager.NeutronManager.get_service_plugins()
|
||||
servicechain_plugin = plugins.get(pconst.SERVICECHAIN)
|
||||
if not servicechain_plugin:
|
||||
LOG.error(_("No Servicechain service plugin found."))
|
||||
raise gp_exc.GroupPolicyDeploymentError()
|
||||
return servicechain_plugin
|
||||
|
||||
# Shared attribute validation rules:
|
||||
# - A shared resource cannot use/link a non-shared resource
|
||||
# - A shared resource cannot be reverted to non-shared if used/linked by
|
||||
|
@ -96,6 +110,7 @@ class GroupPolicyPlugin(group_policy_mapping_db.GroupPolicyMappingDbPlugin):
|
|||
self._plurals = dict((nattr.PLURALS[k], k) for k in nattr.PLURALS)
|
||||
return self._plurals
|
||||
|
||||
@staticmethod
|
||||
def _validate_shared_create(self, context, obj, identity):
|
||||
# REVISIT(ivar): only validate new references
|
||||
links = self.usage_graph.get(identity, {})
|
||||
|
@ -111,21 +126,15 @@ class GroupPolicyPlugin(group_policy_mapping_db.GroupPolicyMappingDbPlugin):
|
|||
link_ids = set()
|
||||
for linked in linked_objects:
|
||||
link_ids.add(linked['id'])
|
||||
if not linked.get('shared'):
|
||||
if obj.get('shared'):
|
||||
raise gp_exc.SharedResourceReferenceError(
|
||||
res_type=identity, res_id=obj['id'],
|
||||
ref_type=ref_type, ref_id=linked['id'])
|
||||
if obj.get('tenant_id') != linked.get('tenant_id'):
|
||||
raise gp_exc.InvalidCrossTenantReference(
|
||||
res_type=identity, res_id=obj['id'],
|
||||
ref_type=ref_type, ref_id=linked['id'])
|
||||
GroupPolicyPlugin._verify_sharing_consistency(
|
||||
obj, linked, identity, ref_type)
|
||||
# Check for missing references
|
||||
missing = set(ids) - link_ids
|
||||
if missing:
|
||||
raise gpex.GbpResourceNotFound(identity=ref_type,
|
||||
id=str(missing))
|
||||
|
||||
@staticmethod
|
||||
def _validate_shared_update(self, context, original, updated, identity):
|
||||
# Need admin context to check sharing constraints
|
||||
|
||||
|
@ -133,13 +142,14 @@ class GroupPolicyPlugin(group_policy_mapping_db.GroupPolicyMappingDbPlugin):
|
|||
# it is referring to might. For this reson we run the reference
|
||||
# validation every time a shared resource is updated
|
||||
# TODO(ivar): run only when relevant updates happen
|
||||
self._validate_shared_create(context, updated, identity)
|
||||
self._validate_shared_create(self, context, updated, identity)
|
||||
if updated.get('shared') != original.get('shared'):
|
||||
context = context.elevated()
|
||||
getattr(self, '_validate_%s_unshare' % identity)(context, updated)
|
||||
|
||||
def _check_shared_or_different_tenant(self, context, obj,
|
||||
method, attr, value=None):
|
||||
@staticmethod
|
||||
def _check_shared_or_different_tenant(context, obj, method, attr,
|
||||
value=None):
|
||||
tenant_id = obj['tenant_id']
|
||||
refs = method(context, filters={attr: value or [obj['id']]})
|
||||
for ref in refs:
|
||||
|
@ -267,6 +277,28 @@ class GroupPolicyPlugin(group_policy_mapping_db.GroupPolicyMappingDbPlugin):
|
|||
ip=addr, es_id=es['id'], l3p_id=current['id'],
|
||||
es_cidr=es['cidr'])
|
||||
|
||||
def _validate_action_value(self, context, action):
|
||||
if action.get('action_type') == gp_cts.GP_ACTION_REDIRECT:
|
||||
if action.get('action_value'):
|
||||
# Verify sc spec existence and visibility
|
||||
spec = self.servicechain_plugin.get_servicechain_spec(
|
||||
context, action['action_value'])
|
||||
GroupPolicyPlugin._verify_sharing_consistency(
|
||||
action, spec, 'polocy_action', 'servicechain_spec')
|
||||
|
||||
@staticmethod
|
||||
def _verify_sharing_consistency(primary, reference, primary_type,
|
||||
reference_type):
|
||||
if not reference.get('shared'):
|
||||
if primary.get('shared'):
|
||||
raise gp_exc.SharedResourceReferenceError(
|
||||
res_type=primary_type, res_id=primary['id'],
|
||||
ref_type=reference_type, ref_id=reference['id'])
|
||||
if primary.get('tenant_id') != reference.get('tenant_id'):
|
||||
raise gp_exc.InvalidCrossTenantReference(
|
||||
res_type=primary_type, res_id=primary['id'],
|
||||
ref_type=reference_type, ref_id=reference['id'])
|
||||
|
||||
def __init__(self):
|
||||
self.extension_manager = ext_manager.ExtensionManager()
|
||||
self.policy_driver_manager = manager.PolicyDriverManager()
|
||||
|
@ -282,7 +314,8 @@ class GroupPolicyPlugin(group_policy_mapping_db.GroupPolicyMappingDbPlugin):
|
|||
self).create_policy_target(context, policy_target)
|
||||
self.extension_manager.process_create_policy_target(
|
||||
session, policy_target, result)
|
||||
self._validate_shared_create(context, result, 'policy_target')
|
||||
self._validate_shared_create(
|
||||
self, context, result, 'policy_target')
|
||||
policy_context = p_context.PolicyTargetContext(self, context,
|
||||
result)
|
||||
self.policy_driver_manager.create_policy_target_precommit(
|
||||
|
@ -311,7 +344,7 @@ class GroupPolicyPlugin(group_policy_mapping_db.GroupPolicyMappingDbPlugin):
|
|||
context, policy_target_id, policy_target)
|
||||
self.extension_manager.process_update_policy_target(
|
||||
session, policy_target, updated_policy_target)
|
||||
self._validate_shared_update(context, original_policy_target,
|
||||
self._validate_shared_update(self, context, original_policy_target,
|
||||
updated_policy_target,
|
||||
'policy_target')
|
||||
policy_context = p_context.PolicyTargetContext(
|
||||
|
@ -373,7 +406,7 @@ class GroupPolicyPlugin(group_policy_mapping_db.GroupPolicyMappingDbPlugin):
|
|||
context, policy_target_group)
|
||||
self.extension_manager.process_create_policy_target_group(
|
||||
session, policy_target_group, result)
|
||||
self._validate_shared_create(context, result,
|
||||
self._validate_shared_create(self, context, result,
|
||||
'policy_target_group')
|
||||
policy_context = p_context.PolicyTargetGroupContext(
|
||||
self, context, result)
|
||||
|
@ -404,9 +437,9 @@ class GroupPolicyPlugin(group_policy_mapping_db.GroupPolicyMappingDbPlugin):
|
|||
context, policy_target_group_id, policy_target_group)
|
||||
self.extension_manager.process_update_policy_target_group(
|
||||
session, policy_target_group, updated_policy_target_group)
|
||||
self._validate_shared_update(context, original_policy_target_group,
|
||||
updated_policy_target_group,
|
||||
'policy_target_group')
|
||||
self._validate_shared_update(
|
||||
self, context, original_policy_target_group,
|
||||
updated_policy_target_group, 'policy_target_group')
|
||||
policy_context = p_context.PolicyTargetGroupContext(
|
||||
self, context, updated_policy_target_group,
|
||||
original_policy_target_group=original_policy_target_group)
|
||||
|
@ -482,7 +515,7 @@ class GroupPolicyPlugin(group_policy_mapping_db.GroupPolicyMappingDbPlugin):
|
|||
self).create_l2_policy(context, l2_policy)
|
||||
self.extension_manager.process_create_l2_policy(
|
||||
session, l2_policy, result)
|
||||
self._validate_shared_create(context, result, 'l2_policy')
|
||||
self._validate_shared_create(self, context, result, 'l2_policy')
|
||||
policy_context = p_context.L2PolicyContext(self, context, result)
|
||||
self.policy_driver_manager.create_l2_policy_precommit(
|
||||
policy_context)
|
||||
|
@ -508,7 +541,7 @@ class GroupPolicyPlugin(group_policy_mapping_db.GroupPolicyMappingDbPlugin):
|
|||
context, l2_policy_id, l2_policy)
|
||||
self.extension_manager.process_update_l2_policy(
|
||||
session, l2_policy, updated_l2_policy)
|
||||
self._validate_shared_update(context, original_l2_policy,
|
||||
self._validate_shared_update(self, context, original_l2_policy,
|
||||
updated_l2_policy, 'l2_policy')
|
||||
policy_context = p_context.L2PolicyContext(
|
||||
self, context, updated_l2_policy,
|
||||
|
@ -569,7 +602,7 @@ class GroupPolicyPlugin(group_policy_mapping_db.GroupPolicyMappingDbPlugin):
|
|||
context, network_service_policy)
|
||||
self.extension_manager.process_create_network_service_policy(
|
||||
session, network_service_policy, result)
|
||||
self._validate_shared_create(context, result,
|
||||
self._validate_shared_create(self, context, result,
|
||||
'network_service_policy')
|
||||
policy_context = p_context.NetworkServicePolicyContext(
|
||||
self, context, result)
|
||||
|
@ -604,7 +637,7 @@ class GroupPolicyPlugin(group_policy_mapping_db.GroupPolicyMappingDbPlugin):
|
|||
session, network_service_policy,
|
||||
updated_network_service_policy)
|
||||
self._validate_shared_update(
|
||||
context, original_network_service_policy,
|
||||
self, context, original_network_service_policy,
|
||||
updated_network_service_policy, 'network_service_policy')
|
||||
policy_context = p_context.NetworkServicePolicyContext(
|
||||
self, context, updated_network_service_policy,
|
||||
|
@ -670,7 +703,7 @@ class GroupPolicyPlugin(group_policy_mapping_db.GroupPolicyMappingDbPlugin):
|
|||
self).create_l3_policy(context, l3_policy)
|
||||
self.extension_manager.process_create_l3_policy(
|
||||
session, l3_policy, result)
|
||||
self._validate_shared_create(context, result, 'l3_policy')
|
||||
self._validate_shared_create(self, context, result, 'l3_policy')
|
||||
self._validate_l3p_es(context, result)
|
||||
policy_context = p_context.L3PolicyContext(self, context,
|
||||
result)
|
||||
|
@ -698,7 +731,7 @@ class GroupPolicyPlugin(group_policy_mapping_db.GroupPolicyMappingDbPlugin):
|
|||
context, l3_policy_id, l3_policy)
|
||||
self.extension_manager.process_update_l3_policy(
|
||||
session, l3_policy, updated_l3_policy)
|
||||
self._validate_shared_update(context, original_l3_policy,
|
||||
self._validate_shared_update(self, context, original_l3_policy,
|
||||
updated_l3_policy, 'l3_policy')
|
||||
self._validate_l3p_es(context, updated_l3_policy,
|
||||
original_l3_policy)
|
||||
|
@ -766,7 +799,8 @@ class GroupPolicyPlugin(group_policy_mapping_db.GroupPolicyMappingDbPlugin):
|
|||
context, policy_classifier)
|
||||
self.extension_manager.process_create_policy_classifier(
|
||||
session, policy_classifier, result)
|
||||
self._validate_shared_create(context, result, 'policy_classifier')
|
||||
self._validate_shared_create(
|
||||
self, context, result, 'policy_classifier')
|
||||
policy_context = p_context.PolicyClassifierContext(self, context,
|
||||
result)
|
||||
self.policy_driver_manager.create_policy_classifier_precommit(
|
||||
|
@ -795,9 +829,9 @@ class GroupPolicyPlugin(group_policy_mapping_db.GroupPolicyMappingDbPlugin):
|
|||
context, id, policy_classifier)
|
||||
self.extension_manager.process_update_policy_classifier(
|
||||
session, policy_classifier, updated_policy_classifier)
|
||||
self._validate_shared_update(context, original_policy_classifier,
|
||||
updated_policy_classifier,
|
||||
'policy_classifier')
|
||||
self._validate_shared_update(
|
||||
self, context, original_policy_classifier,
|
||||
updated_policy_classifier, 'policy_classifier')
|
||||
policy_context = p_context.PolicyClassifierContext(
|
||||
self, context, updated_policy_classifier,
|
||||
original_policy_classifier=original_policy_classifier)
|
||||
|
@ -858,7 +892,9 @@ class GroupPolicyPlugin(group_policy_mapping_db.GroupPolicyMappingDbPlugin):
|
|||
self).create_policy_action(context, policy_action)
|
||||
self.extension_manager.process_create_policy_action(
|
||||
session, policy_action, result)
|
||||
self._validate_shared_create(context, result, 'policy_action')
|
||||
self._validate_shared_create(self, context, result,
|
||||
'policy_action')
|
||||
self._validate_action_value(context, result)
|
||||
policy_context = p_context.PolicyActionContext(self, context,
|
||||
result)
|
||||
self.policy_driver_manager.create_policy_action_precommit(
|
||||
|
@ -887,9 +923,10 @@ class GroupPolicyPlugin(group_policy_mapping_db.GroupPolicyMappingDbPlugin):
|
|||
policy_action)
|
||||
self.extension_manager.process_update_policy_action(
|
||||
session, policy_action, updated_policy_action)
|
||||
self._validate_shared_update(context, original_policy_action,
|
||||
self._validate_shared_update(self, context, original_policy_action,
|
||||
updated_policy_action,
|
||||
'policy_action')
|
||||
self._validate_action_value(context, updated_policy_action)
|
||||
policy_context = p_context.PolicyActionContext(
|
||||
self, context, updated_policy_action,
|
||||
original_policy_action=original_policy_action)
|
||||
|
@ -948,7 +985,7 @@ class GroupPolicyPlugin(group_policy_mapping_db.GroupPolicyMappingDbPlugin):
|
|||
context, policy_rule)
|
||||
self.extension_manager.process_create_policy_rule(
|
||||
session, policy_rule, result)
|
||||
self._validate_shared_create(context, result, 'policy_rule')
|
||||
self._validate_shared_create(self, context, result, 'policy_rule')
|
||||
policy_context = p_context.PolicyRuleContext(self, context,
|
||||
result)
|
||||
self.policy_driver_manager.create_policy_rule_precommit(
|
||||
|
@ -977,7 +1014,7 @@ class GroupPolicyPlugin(group_policy_mapping_db.GroupPolicyMappingDbPlugin):
|
|||
context, id, policy_rule)
|
||||
self.extension_manager.process_update_policy_rule(
|
||||
session, policy_rule, updated_policy_rule)
|
||||
self._validate_shared_update(context, original_policy_rule,
|
||||
self._validate_shared_update(self, context, original_policy_rule,
|
||||
updated_policy_rule, 'policy_rule')
|
||||
policy_context = p_context.PolicyRuleContext(
|
||||
self, context, updated_policy_rule,
|
||||
|
@ -1038,7 +1075,8 @@ class GroupPolicyPlugin(group_policy_mapping_db.GroupPolicyMappingDbPlugin):
|
|||
context, policy_rule_set)
|
||||
self.extension_manager.process_create_policy_rule_set(
|
||||
session, policy_rule_set, result)
|
||||
self._validate_shared_create(context, result, 'policy_rule_set')
|
||||
self._validate_shared_create(
|
||||
self, context, result, 'policy_rule_set')
|
||||
policy_context = p_context.PolicyRuleSetContext(
|
||||
self, context, result)
|
||||
self.policy_driver_manager.create_policy_rule_set_precommit(
|
||||
|
@ -1067,9 +1105,9 @@ class GroupPolicyPlugin(group_policy_mapping_db.GroupPolicyMappingDbPlugin):
|
|||
context, id, policy_rule_set)
|
||||
self.extension_manager.process_update_policy_rule_set(
|
||||
session, policy_rule_set, updated_policy_rule_set)
|
||||
self._validate_shared_update(context, original_policy_rule_set,
|
||||
updated_policy_rule_set,
|
||||
'policy_rule_set')
|
||||
self._validate_shared_update(
|
||||
self, context, original_policy_rule_set,
|
||||
updated_policy_rule_set, 'policy_rule_set')
|
||||
policy_context = p_context.PolicyRuleSetContext(
|
||||
self, context, updated_policy_rule_set,
|
||||
original_policy_rule_set=original_policy_rule_set)
|
||||
|
@ -1128,7 +1166,7 @@ class GroupPolicyPlugin(group_policy_mapping_db.GroupPolicyMappingDbPlugin):
|
|||
external_segment)
|
||||
self.extension_manager.process_create_external_segment(
|
||||
session, external_segment, result)
|
||||
self._validate_shared_create(context, result,
|
||||
self._validate_shared_create(self, context, result,
|
||||
'external_segment')
|
||||
self._validate_routes(context, result)
|
||||
policy_context = p_context.ExternalSegmentContext(
|
||||
|
@ -1163,7 +1201,7 @@ class GroupPolicyPlugin(group_policy_mapping_db.GroupPolicyMappingDbPlugin):
|
|||
self.extension_manager.process_update_external_segment(
|
||||
session, external_segment, updated_external_segment)
|
||||
self._validate_shared_update(
|
||||
context, original_external_segment,
|
||||
self, context, original_external_segment,
|
||||
updated_external_segment, 'external_segment')
|
||||
self._validate_routes(context, updated_external_segment,
|
||||
original_external_segment)
|
||||
|
@ -1231,7 +1269,7 @@ class GroupPolicyPlugin(group_policy_mapping_db.GroupPolicyMappingDbPlugin):
|
|||
context, external_policy)
|
||||
self.extension_manager.process_create_external_policy(
|
||||
session, external_policy, result)
|
||||
self._validate_shared_create(context, result,
|
||||
self._validate_shared_create(self, context, result,
|
||||
'external_policy')
|
||||
policy_context = p_context.ExternalPolicyContext(
|
||||
self, context, result)
|
||||
|
@ -1265,7 +1303,7 @@ class GroupPolicyPlugin(group_policy_mapping_db.GroupPolicyMappingDbPlugin):
|
|||
self.extension_manager.process_update_external_policy(
|
||||
session, external_policy, updated_external_policy)
|
||||
self._validate_shared_update(
|
||||
context, original_external_policy,
|
||||
self, context, original_external_policy,
|
||||
updated_external_policy, 'external_policy')
|
||||
policy_context = p_context.ExternalPolicyContext(
|
||||
self, context, updated_external_policy,
|
||||
|
@ -1327,7 +1365,7 @@ class GroupPolicyPlugin(group_policy_mapping_db.GroupPolicyMappingDbPlugin):
|
|||
context, nat_pool)
|
||||
self.extension_manager.process_create_nat_pool(session, nat_pool,
|
||||
result)
|
||||
self._validate_shared_create(context, result, 'nat_pool')
|
||||
self._validate_shared_create(self, context, result, 'nat_pool')
|
||||
policy_context = p_context.NatPoolContext(self, context, result)
|
||||
(self.policy_driver_manager.
|
||||
create_nat_pool_precommit(policy_context))
|
||||
|
@ -1354,7 +1392,7 @@ class GroupPolicyPlugin(group_policy_mapping_db.GroupPolicyMappingDbPlugin):
|
|||
nat_pool)
|
||||
self.extension_manager.process_update_nat_pool(
|
||||
session, nat_pool, updated_nat_pool)
|
||||
self._validate_shared_update(context, original_nat_pool,
|
||||
self._validate_shared_update(self, context, original_nat_pool,
|
||||
updated_nat_pool, 'nat_pool')
|
||||
policy_context = p_context.NatPoolContext(
|
||||
self, context, updated_nat_pool, original_nat_pool)
|
||||
|
|
|
@ -19,12 +19,14 @@ from gbpservice.neutron.services.servicechain.plugins.msc import (
|
|||
context as servicechain_context)
|
||||
from gbpservice.neutron.services.servicechain.plugins.msc import (
|
||||
driver_manager as manager)
|
||||
from gbpservice.neutron.services.servicechain.plugins import sharing
|
||||
|
||||
|
||||
LOG = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class ServiceChainPlugin(servicechain_db.ServiceChainDbPlugin):
|
||||
class ServiceChainPlugin(servicechain_db.ServiceChainDbPlugin,
|
||||
sharing.SharingMixin):
|
||||
|
||||
"""Implementation of the Service Chain Plugin.
|
||||
|
||||
|
@ -42,6 +44,7 @@ class ServiceChainPlugin(servicechain_db.ServiceChainDbPlugin):
|
|||
with session.begin(subtransactions=True):
|
||||
result = super(ServiceChainPlugin, self).create_servicechain_node(
|
||||
context, servicechain_node)
|
||||
self._validate_shared_create(context, result, 'servicechain_node')
|
||||
sc_context = servicechain_context.ServiceChainNodeContext(
|
||||
self, context, result)
|
||||
self.driver_manager.create_servicechain_node_precommit(
|
||||
|
@ -70,6 +73,8 @@ class ServiceChainPlugin(servicechain_db.ServiceChainDbPlugin):
|
|||
self).update_servicechain_node(
|
||||
context, servicechain_node_id,
|
||||
servicechain_node)
|
||||
self._validate_shared_update(context, original_sc_node,
|
||||
updated_sc_node, 'servicechain_node')
|
||||
sc_context = servicechain_context.ServiceChainNodeContext(
|
||||
self, context, updated_sc_node,
|
||||
original_sc_node=original_sc_node)
|
||||
|
@ -107,6 +112,7 @@ class ServiceChainPlugin(servicechain_db.ServiceChainDbPlugin):
|
|||
with session.begin(subtransactions=True):
|
||||
result = super(ServiceChainPlugin, self).create_servicechain_spec(
|
||||
context, servicechain_spec)
|
||||
self._validate_shared_create(context, result, 'servicechain_spec')
|
||||
sc_context = servicechain_context.ServiceChainSpecContext(
|
||||
self, context, result)
|
||||
self.driver_manager.create_servicechain_spec_precommit(
|
||||
|
@ -134,6 +140,8 @@ class ServiceChainPlugin(servicechain_db.ServiceChainDbPlugin):
|
|||
self).update_servicechain_spec(
|
||||
context, servicechain_spec_id,
|
||||
servicechain_spec)
|
||||
self._validate_shared_update(context, original_sc_spec,
|
||||
updated_sc_spec, 'servicechain_spec')
|
||||
sc_context = servicechain_context.ServiceChainSpecContext(
|
||||
self, context, updated_sc_spec,
|
||||
original_sc_spec=original_sc_spec)
|
||||
|
|
|
@ -0,0 +1,74 @@
|
|||
# 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.v2 import attributes as nattr
|
||||
from neutron import manager as n_manager
|
||||
from neutron.plugins.common import constants as pconst
|
||||
from oslo_log import log as logging
|
||||
|
||||
from gbpservice.neutron.services.grouppolicy.common import exceptions as gp_exc
|
||||
from gbpservice.neutron.services.grouppolicy import plugin as gbp_plugin
|
||||
|
||||
|
||||
LOG = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class SharingMixin(object):
|
||||
|
||||
"""Implementation of the Service Chain Plugin sharing rules.
|
||||
|
||||
"""
|
||||
|
||||
usage_graph = {'servicechain_spec': {'nodes':
|
||||
'servicechain_node'},
|
||||
'servicechain_node': {},
|
||||
'servicechain_instance': {}}
|
||||
_plurals = None
|
||||
|
||||
@property
|
||||
def plurals(self):
|
||||
if not self._plurals:
|
||||
self._plurals = dict((nattr.PLURALS[k], k) for k in nattr.PLURALS)
|
||||
return self._plurals
|
||||
|
||||
@property
|
||||
def gbp_plugin(self):
|
||||
# REVISIT(rkukura): Need initialization method after all
|
||||
# plugins are loaded to grab and store plugin.
|
||||
plugins = n_manager.NeutronManager.get_service_plugins()
|
||||
gbp_plugin = plugins.get(pconst.GROUP_POLICY)
|
||||
if not gbp_plugin:
|
||||
LOG.error(_("No group policy service plugin found."))
|
||||
raise gp_exc.GroupPolicyDeploymentError()
|
||||
return gbp_plugin
|
||||
|
||||
def _validate_shared_create(self, context, obj, identity):
|
||||
return gbp_plugin.GroupPolicyPlugin._validate_shared_create(
|
||||
self, context, obj, identity)
|
||||
|
||||
def _validate_shared_update(self, context, original, updated, identity):
|
||||
self._validate_shared_create(context, updated, identity)
|
||||
if updated.get('shared') != original.get('shared'):
|
||||
context = context.elevated()
|
||||
getattr(self, '_validate_%s_unshare' % identity)(context, updated)
|
||||
|
||||
def _validate_servicechain_node_unshare(self, context, obj):
|
||||
# Verify not pointed by shared SCS
|
||||
gbp_plugin.GroupPolicyPlugin._check_shared_or_different_tenant(
|
||||
context, obj, self.get_servicechain_specs, 'id',
|
||||
obj['servicechain_specs'])
|
||||
|
||||
def _validate_servicechain_spec_unshare(self, context, obj):
|
||||
# Verify not pointed by shared policy actions
|
||||
gbp_plugin.GroupPolicyPlugin._check_shared_or_different_tenant(
|
||||
context, obj, self.gbp_plugin.get_policy_actions, 'action_value',
|
||||
[obj['id']])
|
|
@ -5,48 +5,65 @@
|
|||
"admin_only": "rule:context_is_admin",
|
||||
"regular_user": "",
|
||||
"default": "rule:admin_or_owner",
|
||||
"gbp_shared": "field:policy_target_groups:shared=True",
|
||||
"shared_ptg": "field:policy_target_groups:shared=True",
|
||||
"shared_pt": "field:policy_targets:shared=True",
|
||||
"shared_prs": "field:policy_rule_sets:shared=True",
|
||||
"shared_l3p": "field:l3_policies:shared=True",
|
||||
"shared_l2p": "field:l2_policies:shared=True",
|
||||
"shared_es": "field:external_segments:shared=True",
|
||||
"shared_ep": "field:external_policies:shared=True",
|
||||
"shared_pc": "field:policy_classifiers:shared=True",
|
||||
"shared_pa": "field:policy_actions:shared=True",
|
||||
"shared_pr": "field:policy_rules:shared=True",
|
||||
"shared_np": "field:nat_pools:shared=True",
|
||||
"shared_nsp": "field:network_service_policies:shared=True",
|
||||
"shared_scn": "field:servicechain_nodes:shared=True",
|
||||
"shared_scs": "field:servicechain_specs:shared=True",
|
||||
|
||||
"create_policy_target_group": "",
|
||||
"get_policy_target_group": "rule:admin_or_owner or rule:gbp_shared",
|
||||
"get_policy_target_group": "rule:admin_or_owner or rule:shared_ptg",
|
||||
|
||||
"gbp_l2p_shared": "field:l2_policies:shared=True",
|
||||
"create_l2_policy": "",
|
||||
"get_l2_policy": "rule:admin_or_owner or rule:gbp_l2p_shared",
|
||||
"get_l2_policy": "rule:admin_or_owner or rule:shared_l2p",
|
||||
|
||||
"gbp_l3p_shared": "field:l3_policies:shared=True",
|
||||
"create_l3_policy": "",
|
||||
"get_l3_policy": "rule:admin_or_owner or rule:gbp_l3p_shared",
|
||||
"get_l3_policy": "rule:admin_or_owner or rule:shared_l3p",
|
||||
|
||||
"gbp_policy_classifier_shared": "field:policy_classifiers:shared=True",
|
||||
"create_policy_classifier": "",
|
||||
"get_policy_classifier": "rule:admin_or_owner or rule:gbp_policy_classifier_shared",
|
||||
"get_policy_classifier": "rule:admin_or_owner or rule:shared_pc",
|
||||
|
||||
"gbp_policy_action_shared": "field:policy_actions:shared=True",
|
||||
"create_policy_action": "",
|
||||
"get_policy_action": "rule:admin_or_owner or rule:gbp_policy_action_shared",
|
||||
"get_policy_action": "rule:admin_or_owner or rule:shared_pa",
|
||||
|
||||
"gbp_policy_rule_shared": "field:policy_rules:shared=True",
|
||||
"create_policy_rule": "",
|
||||
"get_policy_rule": "rule:admin_or_owner or rule:gbp_policy_rule_shared",
|
||||
"get_policy_rule": "rule:admin_or_owner or rule:shared_pr",
|
||||
|
||||
"gbp_policy_rule_set_shared": "field:policy_rule_sets:shared=True",
|
||||
"create_policy_rule_set": "",
|
||||
"get_policy_rule_set": "rule:admin_or_owner or rule:gbp_policy_rule_set_shared",
|
||||
"get_policy_rule_set": "rule:admin_or_owner or rule:shared_prs",
|
||||
|
||||
"gbp_nsp_shared": "field:network_service_policies:shared=True",
|
||||
"create_network_service_policy": "",
|
||||
"get_network_service_policy": "rule:admin_or_owner or rule:gbp_nsp_shared",
|
||||
"get_network_service_policy": "rule:admin_or_owner or rule:shared_nsp",
|
||||
|
||||
"gbp_external_segment_shared": "field:external_segments:shared=True",
|
||||
"create_external_segment": "",
|
||||
"get_external_segment": "rule:admin_or_owner or rule:gbp_external_segment_shared",
|
||||
"get_external_segment": "rule:admin_or_owner or rule:shared_es",
|
||||
|
||||
"gbp_external_policy_shared": "field:external_policies:shared=True",
|
||||
"create_external_policy": "",
|
||||
"get_external_policy": "rule:admin_or_owner or rule:gbp_external_policy_shared",
|
||||
"get_external_policy": "rule:admin_or_owner or rule:shared_ep",
|
||||
|
||||
"gbp_nat_pool_shared": "field:nat_pools:shared=True",
|
||||
"create_nat_pool": "",
|
||||
"get_nat_pool": "rule:admin_or_owner or rule:gbp_nat_pool_shared"
|
||||
"get_nat_pool": "rule:admin_or_owner or rule:shared_np",
|
||||
|
||||
"create_servicechain_node": "",
|
||||
"create_servicechain_node:shared": "rule:admin_only",
|
||||
"get_servicechain_node": "rule:admin_or_owner or rule:shared_scn",
|
||||
"update_servicechain_node:shared": "rule:admin_only",
|
||||
|
||||
"create_servicechain_spec": "",
|
||||
"create_servicechain_spec:shared": "rule:admin_only",
|
||||
"get_servicechain_spec": "rule:admin_or_owner or rule:shared_scs",
|
||||
"update_servicechain_spec:shared": "rule:admin_only",
|
||||
|
||||
"create_servicechain_instance": "",
|
||||
"get_servicechain_instance": "rule:admin_or_owner",
|
||||
"update_servicechain_instance:shared": "rule:admin_only"
|
||||
}
|
||||
|
|
|
@ -58,23 +58,24 @@ class ServiceChainDBTestBase(object):
|
|||
def _get_test_servicechain_node_attrs(self, name='scn1',
|
||||
description='test scn',
|
||||
service_type=constants.FIREWALL,
|
||||
config="{}"):
|
||||
config="{}", shared=False):
|
||||
attrs = {'name': name, 'description': description,
|
||||
'service_type': service_type,
|
||||
'config': config,
|
||||
'tenant_id': self._tenant_id}
|
||||
'tenant_id': self._tenant_id,
|
||||
'shared': shared}
|
||||
|
||||
return attrs
|
||||
|
||||
def _get_test_servicechain_spec_attrs(self, name='scs1',
|
||||
description='test scs',
|
||||
nodes=None):
|
||||
nodes=None, shared=False):
|
||||
node_ids = []
|
||||
if nodes:
|
||||
node_ids = [node_id for node_id in nodes]
|
||||
attrs = {'name': name, 'description': description,
|
||||
'tenant_id': self._tenant_id,
|
||||
'nodes': node_ids}
|
||||
'nodes': node_ids, 'shared': shared}
|
||||
|
||||
return attrs
|
||||
|
||||
|
@ -98,7 +99,7 @@ class ServiceChainDBTestBase(object):
|
|||
def create_servicechain_node(self, service_type=constants.FIREWALL,
|
||||
config="{}", expected_res_status=None,
|
||||
**kwargs):
|
||||
defaults = {'name': 'scn1', 'description': 'test scn'}
|
||||
defaults = {'name': 'scn1', 'description': 'test scn', 'shared': False}
|
||||
defaults.update(kwargs)
|
||||
|
||||
data = {'servicechain_node': {'service_type': service_type,
|
||||
|
@ -120,7 +121,7 @@ class ServiceChainDBTestBase(object):
|
|||
|
||||
def create_servicechain_spec(self, nodes=None, expected_res_status=None,
|
||||
**kwargs):
|
||||
defaults = {'name': 'scs1', 'description': 'test scs'}
|
||||
defaults = {'name': 'scs1', 'description': 'test scs', 'shared': False}
|
||||
defaults.update(kwargs)
|
||||
|
||||
data = {'servicechain_spec': {'tenant_id': self._tenant_id,
|
||||
|
@ -131,7 +132,7 @@ class ServiceChainDBTestBase(object):
|
|||
scs_res = scs_req.get_response(self.ext_api)
|
||||
|
||||
if expected_res_status:
|
||||
self.assertEqual(scs_res.status_int, expected_res_status)
|
||||
self.assertEqual(expected_res_status, scs_res.status_int)
|
||||
elif scs_res.status_int >= webob.exc.HTTPClientError.code:
|
||||
raise webob.exc.HTTPClientError(code=scs_res.status_int)
|
||||
|
||||
|
@ -150,7 +151,7 @@ class ServiceChainDBTestBase(object):
|
|||
spec1,
|
||||
self.fmt)
|
||||
spec_res = spec_req.get_response(self.ext_api)
|
||||
self.assertEqual(spec_res.status_int, webob.exc.HTTPCreated.code)
|
||||
self.assertEqual(webob.exc.HTTPCreated.code, spec_res.status_int)
|
||||
res = self.deserialize(self.fmt, spec_res)
|
||||
self.assertIn('servicechain_spec', res)
|
||||
self.assertEqual([scn_id], res['servicechain_spec']['nodes'])
|
||||
|
@ -161,13 +162,14 @@ class ServiceChainDBTestBase(object):
|
|||
spec2,
|
||||
self.fmt)
|
||||
spec_res = spec_req.get_response(self.ext_api)
|
||||
self.assertEqual(spec_res.status_int, webob.exc.HTTPCreated.code)
|
||||
self.assertEqual(webob.exc.HTTPCreated.code, spec_res.status_int)
|
||||
res = self.deserialize(self.fmt, spec_res)
|
||||
self.assertIn('servicechain_spec', res)
|
||||
self.assertEqual([scn_id], res['servicechain_spec']['nodes'])
|
||||
|
||||
def create_servicechain_instance(self, servicechain_specs=[],
|
||||
config_param_values="{}",
|
||||
config_param_values=
|
||||
'{"key": "value"}',
|
||||
provider_ptg_id=None,
|
||||
consumer_ptg_id=None,
|
||||
classifier_id=None,
|
||||
|
@ -188,7 +190,7 @@ class ServiceChainDBTestBase(object):
|
|||
sci_res = sci_req.get_response(self.ext_api)
|
||||
|
||||
if expected_res_status:
|
||||
self.assertEqual(sci_res.status_int, expected_res_status)
|
||||
self.assertEqual(expected_res_status, sci_res.status_int)
|
||||
elif sci_res.status_int >= webob.exc.HTTPClientError.code:
|
||||
raise webob.exc.HTTPClientError(code=sci_res.status_int)
|
||||
|
||||
|
@ -240,17 +242,17 @@ class TestServiceChainResources(ServiceChainDbTestCase):
|
|||
req.get_response(self.ext_api))
|
||||
|
||||
for k, v in attrs.iteritems():
|
||||
self.assertEqual(res[resource][k], v)
|
||||
self.assertEqual(v, res[resource][k])
|
||||
|
||||
def test_create_and_show_servicechain_node(self):
|
||||
attrs = self._get_test_servicechain_node_attrs(
|
||||
service_type=constants.LOADBALANCER, config="config1")
|
||||
service_type=constants.LOADBALANCER)
|
||||
|
||||
scn = self.create_servicechain_node(
|
||||
service_type=constants.LOADBALANCER, config="config1")
|
||||
service_type=constants.LOADBALANCER)
|
||||
|
||||
for k, v in attrs.iteritems():
|
||||
self.assertEqual(scn['servicechain_node'][k], v)
|
||||
self.assertEqual(v, scn['servicechain_node'][k])
|
||||
|
||||
self._test_show_resource('servicechain_node',
|
||||
scn['servicechain_node']['id'],
|
||||
|
@ -278,7 +280,7 @@ class TestServiceChainResources(ServiceChainDbTestCase):
|
|||
res = self.deserialize(self.fmt, req.get_response(self.ext_api))
|
||||
|
||||
for k, v in attrs.iteritems():
|
||||
self.assertEqual(res['servicechain_node'][k], v)
|
||||
self.assertEqual(v, res['servicechain_node'][k])
|
||||
|
||||
self._test_show_resource('servicechain_node',
|
||||
scn['servicechain_node']['id'],
|
||||
|
@ -304,7 +306,7 @@ class TestServiceChainResources(ServiceChainDbTestCase):
|
|||
# After deleting the Service Chain Spec, node delete should succeed
|
||||
req = self.new_delete_request('servicechain_nodes', scn_id)
|
||||
res = req.get_response(self.ext_api)
|
||||
self.assertEqual(res.status_int, webob.exc.HTTPNoContent.code)
|
||||
self.assertEqual(webob.exc.HTTPNoContent.code, res.status_int)
|
||||
self.assertRaises(service_chain.ServiceChainNodeNotFound,
|
||||
self.plugin.get_servicechain_node,
|
||||
ctx, scn_id)
|
||||
|
@ -319,7 +321,7 @@ class TestServiceChainResources(ServiceChainDbTestCase):
|
|||
scs = self.create_servicechain_spec(name=name, nodes=[scn_id])
|
||||
|
||||
for k, v in attrs.iteritems():
|
||||
self.assertEqual(scs['servicechain_spec'][k], v)
|
||||
self.assertEqual(v, scs['servicechain_spec'][k])
|
||||
|
||||
self._test_show_resource('servicechain_spec',
|
||||
scs['servicechain_spec']['id'],
|
||||
|
@ -336,7 +338,7 @@ class TestServiceChainResources(ServiceChainDbTestCase):
|
|||
scs = self.create_servicechain_spec(
|
||||
name=name, nodes=[scn1_id, scn2_id])
|
||||
for k, v in attrs.iteritems():
|
||||
self.assertEqual(scs['servicechain_spec'][k], v)
|
||||
self.assertEqual(v, scs['servicechain_spec'][k])
|
||||
|
||||
def test_list_servicechain_specs(self):
|
||||
scs = [self.create_servicechain_spec(name='scs1', description='scs'),
|
||||
|
@ -351,27 +353,25 @@ class TestServiceChainResources(ServiceChainDbTestCase):
|
|||
nodes_list = [scn1_id, scn2_id]
|
||||
scs = self.create_servicechain_spec(name='scs1',
|
||||
nodes=nodes_list)
|
||||
self.assertEqual(scs['servicechain_spec']['nodes'], nodes_list)
|
||||
self.assertEqual(nodes_list, scs['servicechain_spec']['nodes'])
|
||||
res = self._list('servicechain_specs')
|
||||
self.assertEqual(len(res['servicechain_specs']), 1)
|
||||
self.assertEqual(res['servicechain_specs'][0]['nodes'],
|
||||
nodes_list)
|
||||
self.assertEqual(1, len(res['servicechain_specs']))
|
||||
self.assertEqual(nodes_list, res['servicechain_specs'][0]['nodes'])
|
||||
|
||||
# Delete the service chain spec and create another with nodes in
|
||||
# reverse order and verify that that proper ordering is maintained
|
||||
req = self.new_delete_request('servicechain_specs',
|
||||
scs['servicechain_spec']['id'])
|
||||
res = req.get_response(self.ext_api)
|
||||
self.assertEqual(res.status_int, webob.exc.HTTPNoContent.code)
|
||||
self.assertEqual(webob.exc.HTTPNoContent.code, res.status_int)
|
||||
|
||||
nodes_list.reverse()
|
||||
scs = self.create_servicechain_spec(name='scs1',
|
||||
nodes=nodes_list)
|
||||
self.assertEqual(scs['servicechain_spec']['nodes'], nodes_list)
|
||||
res = self._list('servicechain_specs')
|
||||
self.assertEqual(len(res['servicechain_specs']), 1)
|
||||
self.assertEqual(res['servicechain_specs'][0]['nodes'],
|
||||
nodes_list)
|
||||
self.assertEqual(1, len(res['servicechain_specs']))
|
||||
self.assertEqual(nodes_list, res['servicechain_specs'][0]['nodes'])
|
||||
|
||||
def test_update_servicechain_spec(self):
|
||||
name = "new_servicechain_spec1"
|
||||
|
@ -388,7 +388,7 @@ class TestServiceChainResources(ServiceChainDbTestCase):
|
|||
res = self.deserialize(self.fmt, req.get_response(self.ext_api))
|
||||
|
||||
for k, v in attrs.iteritems():
|
||||
self.assertEqual(res['servicechain_spec'][k], v)
|
||||
self.assertEqual(v, res['servicechain_spec'][k])
|
||||
|
||||
self._test_show_resource('servicechain_spec',
|
||||
scs['servicechain_spec']['id'], attrs)
|
||||
|
@ -401,7 +401,7 @@ class TestServiceChainResources(ServiceChainDbTestCase):
|
|||
|
||||
req = self.new_delete_request('servicechain_specs', scs_id)
|
||||
res = req.get_response(self.ext_api)
|
||||
self.assertEqual(res.status_int, webob.exc.HTTPNoContent.code)
|
||||
self.assertEqual(webob.exc.HTTPNoContent.code, res.status_int)
|
||||
self.assertRaises(service_chain.ServiceChainSpecNotFound,
|
||||
self.plugin.get_servicechain_spec, ctx, scs_id)
|
||||
|
||||
|
@ -464,7 +464,7 @@ class TestServiceChainResources(ServiceChainDbTestCase):
|
|||
classifier_id=classifier_id,
|
||||
config_param_values=config_param_values)
|
||||
for k, v in attrs.iteritems():
|
||||
self.assertEqual(sci['servicechain_instance'][k], v)
|
||||
self.assertEqual(v, sci['servicechain_instance'][k])
|
||||
|
||||
self._test_show_resource('servicechain_instance',
|
||||
sci['servicechain_instance']['id'],
|
||||
|
@ -488,29 +488,30 @@ class TestServiceChainResources(ServiceChainDbTestCase):
|
|||
specs_list = [scs1_id, scs2_id]
|
||||
sci = self.create_servicechain_instance(name='sci1',
|
||||
servicechain_specs=specs_list)
|
||||
self.assertEqual(sci['servicechain_instance']['servicechain_specs'],
|
||||
specs_list)
|
||||
self.assertEqual(specs_list,
|
||||
sci['servicechain_instance']['servicechain_specs'])
|
||||
res = self._list('servicechain_instances')
|
||||
self.assertEqual(len(res['servicechain_instances']), 1)
|
||||
self.assertEqual(1, len(res['servicechain_instances']))
|
||||
result_instance = res['servicechain_instances'][0]
|
||||
self.assertEqual(result_instance['servicechain_specs'], specs_list)
|
||||
self.assertEqual(specs_list, result_instance['servicechain_specs'])
|
||||
|
||||
# Delete the service chain instance and create another with specs in
|
||||
# reverse order and verify that that proper ordering is maintained
|
||||
req = self.new_delete_request('servicechain_instances',
|
||||
sci['servicechain_instance']['id'])
|
||||
res = req.get_response(self.ext_api)
|
||||
self.assertEqual(res.status_int, webob.exc.HTTPNoContent.code)
|
||||
self.assertEqual(webob.exc.HTTPNoContent.code, res.status_int)
|
||||
|
||||
specs_list.reverse()
|
||||
sci = self.create_servicechain_instance(name='sci1',
|
||||
servicechain_specs=specs_list)
|
||||
self.assertEqual(sci['servicechain_instance']['servicechain_specs'],
|
||||
specs_list)
|
||||
self.assertEqual(specs_list,
|
||||
sci['servicechain_instance']['servicechain_specs'])
|
||||
res = self._list('servicechain_instances')
|
||||
self.assertEqual(len(res['servicechain_instances']), 1)
|
||||
self.assertEqual(1, len(res['servicechain_instances']))
|
||||
result_instance = res['servicechain_instances'][0]
|
||||
self.assertEqual(result_instance['servicechain_specs'], specs_list)
|
||||
self.assertEqual(specs_list,
|
||||
result_instance['servicechain_specs'])
|
||||
|
||||
def test_update_servicechain_instance(self):
|
||||
name = "new_servicechain_instance"
|
||||
|
@ -537,7 +538,7 @@ class TestServiceChainResources(ServiceChainDbTestCase):
|
|||
sci['servicechain_instance']['id'])
|
||||
res = self.deserialize(self.fmt, req.get_response(self.ext_api))
|
||||
for k, v in attrs.iteritems():
|
||||
self.assertEqual(res['servicechain_instance'][k], v)
|
||||
self.assertEqual(v, res['servicechain_instance'][k])
|
||||
|
||||
self._test_show_resource('servicechain_instance',
|
||||
sci['servicechain_instance']['id'], attrs)
|
||||
|
@ -553,7 +554,7 @@ class TestServiceChainResources(ServiceChainDbTestCase):
|
|||
|
||||
req = self.new_delete_request('servicechain_instances', sci_id)
|
||||
res = req.get_response(self.ext_api)
|
||||
self.assertEqual(res.status_int, webob.exc.HTTPNoContent.code)
|
||||
self.assertEqual(webob.exc.HTTPNoContent.code, res.status_int)
|
||||
self.assertRaises(service_chain.ServiceChainInstanceNotFound,
|
||||
self.plugin.get_servicechain_instance,
|
||||
ctx, sci_id)
|
||||
|
|
|
@ -29,6 +29,8 @@ cfg.CONF.import_opt('policy_drivers',
|
|||
GP_PLUGIN_KLASS = (
|
||||
"gbpservice.neutron.services.grouppolicy.plugin.GroupPolicyPlugin"
|
||||
)
|
||||
SERVICECHAIN_SPECS = 'servicechain/servicechain_specs'
|
||||
SERVICECHAIN_NODES = 'servicechain/servicechain_nodes'
|
||||
|
||||
|
||||
class FakeDriver(object):
|
||||
|
@ -47,6 +49,8 @@ class GroupPolicyPluginTestCase(tgpmdb.GroupPolicyMappingDbTestCase):
|
|||
gp_plugin = GP_PLUGIN_KLASS
|
||||
super(GroupPolicyPluginTestCase, self).setUp(core_plugin=core_plugin,
|
||||
gp_plugin=gp_plugin)
|
||||
cfg.CONF.set_override('servicechain_drivers', ['dummy'],
|
||||
group='servicechain')
|
||||
|
||||
def test_reverse_on_delete(self):
|
||||
manager = self.plugin.policy_driver_manager
|
||||
|
@ -105,6 +109,38 @@ class GroupPolicyPluginTestCase(tgpmdb.GroupPolicyMappingDbTestCase):
|
|||
external_segment_id=es['external_segment']['id'],
|
||||
**kwargs)['nat_pool']
|
||||
|
||||
def _create_servicechain_spec(self, node_types=None, shared=False):
|
||||
node_types = node_types or []
|
||||
if not node_types:
|
||||
node_types = ['LOADBALANCER']
|
||||
node_ids = []
|
||||
for node_type in node_types:
|
||||
node_ids.append(self._create_servicechain_node(node_type,
|
||||
shared=shared))
|
||||
data = {'servicechain_spec': {'tenant_id': self._tenant_id if not
|
||||
shared else 'another-tenant',
|
||||
'nodes': node_ids,
|
||||
'shared': shared}}
|
||||
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']
|
||||
return scs_id
|
||||
|
||||
def _create_servicechain_node(self, node_type="LOADBALANCER",
|
||||
shared=False):
|
||||
config = "{}"
|
||||
data = {'servicechain_node': {'service_type': node_type,
|
||||
'tenant_id': self._tenant_id if not
|
||||
shared else 'another-tenant',
|
||||
'config': config,
|
||||
'shared': shared}}
|
||||
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']
|
||||
return scn_id
|
||||
|
||||
|
||||
class TestL3Policy(GroupPolicyPluginTestCase):
|
||||
|
||||
|
@ -806,6 +842,57 @@ class TestPolicyTarget(GroupPolicyPluginTestCase):
|
|||
self._test_cross_tenant_fails(True)
|
||||
|
||||
|
||||
class TestPolicyAction(GroupPolicyPluginTestCase):
|
||||
|
||||
def test_redirect_value_fails(self):
|
||||
scs_id = self._create_servicechain_spec(
|
||||
node_types=['FIREWALL_TRANSPARENT'])
|
||||
res = self.create_policy_action(action_type='redirect',
|
||||
action_value=scs_id, shared=True,
|
||||
expected_res_status=400)
|
||||
self.assertEqual(
|
||||
'SharedResourceReferenceError', res['NeutronError']['type'])
|
||||
|
||||
res = self.create_policy_action(
|
||||
action_type='redirect', action_value=scs_id, tenant_id='different',
|
||||
expected_res_status=404)
|
||||
self.assertEqual(
|
||||
'ServiceChainSpecNotFound', res['NeutronError']['type'])
|
||||
|
||||
res = self.create_policy_action(
|
||||
action_type='redirect', action_value=scs_id, tenant_id='different',
|
||||
expected_res_status=400, is_admin_context=True)
|
||||
self.assertEqual(
|
||||
'InvalidCrossTenantReference', res['NeutronError']['type'])
|
||||
|
||||
res = self.create_policy_action(
|
||||
action_type='redirect', action_value=scs_id,
|
||||
expected_res_status=201)['policy_action']
|
||||
res = self.update_policy_action(
|
||||
res['id'], shared=True, expected_res_status=400)
|
||||
self.assertEqual(
|
||||
'SharedResourceReferenceError', res['NeutronError']['type'])
|
||||
|
||||
scs_id = self._create_servicechain_spec(
|
||||
node_types=['FIREWALL_TRANSPARENT'], shared=True)
|
||||
self.create_policy_action(
|
||||
action_type='redirect', action_value=scs_id, shared=True,
|
||||
expected_res_status=201)['policy_action']
|
||||
data = {'servicechain_spec': {'shared': False}}
|
||||
scs_req = self.new_update_request(
|
||||
SERVICECHAIN_SPECS, data, scs_id, self.fmt)
|
||||
res = self.deserialize(
|
||||
self.fmt, scs_req.get_response(self.ext_api))
|
||||
self.assertEqual(
|
||||
'InvalidSharedAttributeUpdate', res['NeutronError']['type'])
|
||||
|
||||
def test_redirect_shared_create(self):
|
||||
scs_id = self._create_servicechain_spec(
|
||||
node_types=['FIREWALL_TRANSPARENT'], shared=True)
|
||||
self.create_policy_action(action_type='redirect', action_value=scs_id,
|
||||
shared=True, expected_res_status=201)
|
||||
|
||||
|
||||
class TestGroupPolicyPluginGroupResources(
|
||||
GroupPolicyPluginTestCase, tgpdb.TestGroupResources):
|
||||
|
||||
|
|
|
@ -66,7 +66,8 @@ class ServiceChainExtensionTestCase(test_extensions_base.ExtensionTestCase):
|
|||
return {
|
||||
'name': '',
|
||||
'description': '',
|
||||
'config': ''
|
||||
'config': '',
|
||||
'shared': False
|
||||
}
|
||||
|
||||
def _get_create_servicechain_node_attrs(self):
|
||||
|
@ -75,7 +76,8 @@ class ServiceChainExtensionTestCase(test_extensions_base.ExtensionTestCase):
|
|||
'service_type': 'FIREWALL',
|
||||
'tenant_id': _uuid(),
|
||||
'description': 'test servicechain node',
|
||||
'config': 'test_config'
|
||||
'config': 'test_config',
|
||||
'shared': True
|
||||
}
|
||||
|
||||
def _get_update_servicechain_node_attrs(self):
|
||||
|
@ -185,7 +187,8 @@ class ServiceChainExtensionTestCase(test_extensions_base.ExtensionTestCase):
|
|||
return {
|
||||
'name': '',
|
||||
'description': '',
|
||||
'nodes': []
|
||||
'nodes': [],
|
||||
'shared': False,
|
||||
}
|
||||
|
||||
def _get_create_servicechain_spec_attrs(self):
|
||||
|
@ -193,7 +196,8 @@ class ServiceChainExtensionTestCase(test_extensions_base.ExtensionTestCase):
|
|||
'name': 'servicechainspec1',
|
||||
'nodes': [_uuid(), _uuid()],
|
||||
'tenant_id': _uuid(),
|
||||
'description': 'test servicechain spec'
|
||||
'description': 'test servicechain spec',
|
||||
'shared': True
|
||||
}
|
||||
|
||||
def _get_update_servicechain_spec_attrs(self):
|
||||
|
|
Loading…
Reference in New Issue