Admin or Provider tenant to own implicit SCIs

Whenever a Redirect action is provided/consumed GBP, the
implicitly created SCI could be owned by different tenants
depending on the actor triggering it.
To make this consistent, this patch proposes to have a single
configurable admin tenant that will own all the chain resources.
When the said tenant is not configured, the provider PTG's
tenant will be used instead.

Change-Id: I4862b87c41b48344a53dbf72c004a8dc18c2aa99
Closes-Bug: 1432816
This commit is contained in:
Sumit Naiksatam 2015-03-20 16:53:11 -07:00 committed by Ivar Lazzaro
parent dab68def4a
commit 3becb34638
27 changed files with 1347 additions and 874 deletions

View File

@ -2,3 +2,14 @@
# DNS nameservers to be used configured in the PTG subnets by this driver.
# dns_nameservers = 8.8.8.7, 8.8.8.8
# Chain owner username. If set, will be used in place of the Neutron service
# admin for retrieving tenant owner information through Keystone.
# chain_owner_user = <username>
# Chain owner password.
# chain_owner_password = <secret>
# Name of the Tenant that will own the service chain instances for this driver.
# Leave empty for provider owned chains.
# chain_owner_tenant_name = <tenant_name>

View File

@ -0,0 +1,15 @@
[simplechain]
# Heat server address to create services specified in the service chain
# heat_uri = http://localhost:8004/v1
# CA file for heatclient to verify server certificates
# heat_ca_certificates_file =
# Boolean to control ignoring SSL errors on the heat url
# heat_api_insecure = False
# Number of attempts to retry for stack deletion
# stack_delete_retries = 5
# Wait time between two successive stack delete retries
# stack_delete_retry_wait = 3

View File

@ -0,0 +1,6 @@
[servicechain]
# An ordered list of service chain drivers entrypoints to be loaded from the
# gbpservice.neutron.servicechain.servicechain_drivers namespace.
# servicechain_drivers=simplechain_driver,oneconvergence_servicechain_driver

View File

@ -12,6 +12,8 @@
import contextlib
from neutron import context as n_ctx
from oslo_config import cfg
from oslo_log import log as logging
from oslo_utils import importutils
from stevedore import driver
@ -44,6 +46,12 @@ def load_plugin(namespace, plugin):
return plugin_class()
def admin_context(context):
admin_context = n_ctx.get_admin_context()
admin_context._session = context.session
return admin_context
class DictClass(dict):
def __getattr__(self, item):
@ -51,3 +59,20 @@ class DictClass(dict):
__setattr__ = dict.__setattr__
__delattr__ = dict.__delattr__
def get_keystone_creds():
keystone_conf = cfg.CONF.keystone_authtoken
user = keystone_conf.admin_user
pw = keystone_conf.admin_password
tenant = keystone_conf.admin_tenant_name
if keystone_conf.get('auth_uri'):
auth_url = keystone_conf.auth_uri.rstrip('/')
if not auth_url.endswith('/v2.0'):
auth_url += '/v2.0'
else:
auth_url = ('%s://%s:%s/v2.0' % (
keystone_conf.auth_protocol,
keystone_conf.auth_host,
keystone_conf.auth_port))
return user, pw, tenant, auth_url + '/'

View File

@ -356,10 +356,9 @@ class LocalAPI(object):
return self._update_resource(self._servicechain_plugin, plugin_context,
'servicechain_instance', sci_id, attrs)
def _delete_servicechain_instance(self, context, sci_id):
def _delete_servicechain_instance(self, plugin_context, sci_id):
try:
self._delete_resource(self._servicechain_plugin,
context._plugin_context,
self._delete_resource(self._servicechain_plugin, plugin_context,
'servicechain_instance', sci_id)
except sc_ext.ServiceChainInstanceNotFound:
# SC could have been already deleted

View File

@ -1355,6 +1355,11 @@ class GroupPolicyDbPlugin(gpolicy.GroupPolicyPluginBase,
marker_obj=marker_obj,
page_reverse=page_reverse)
@log.log
def get_l3_policies_count(self, context, filters=None):
return self._get_collection_count(context, L3Policy,
filters=filters)
@log.log
def create_network_service_policy(self, context, network_service_policy):
nsp = network_service_policy['network_service_policy']

View File

@ -234,6 +234,11 @@ class GroupPolicyMappingDbPlugin(gpdb.GroupPolicyDbPlugin):
context.session.add(pt_db)
return self._make_policy_target_dict(pt_db)
@log.log
def get_policy_targets_count(self, context, filters=None):
return self._get_collection_count(context, PolicyTargetMapping,
filters=filters)
@log.log
def get_policy_targets(self, context, filters=None, fields=None,
sorts=None, limit=None, marker=None,
@ -331,6 +336,11 @@ class GroupPolicyMappingDbPlugin(gpdb.GroupPolicyDbPlugin):
marker_obj=marker_obj,
page_reverse=page_reverse)
@log.log
def get_l2_policies_count(self, context, filters=None):
return self._get_collection_count(context, L2PolicyMapping,
filters=filters)
@log.log
def create_l3_policy(self, context, l3_policy):
l3p = l3_policy['l3_policy']
@ -426,6 +436,10 @@ class GroupPolicyMappingDbPlugin(gpdb.GroupPolicyDbPlugin):
marker_obj=marker_obj,
page_reverse=page_reverse)
def get_external_segments_count(self, context, filters=None):
return self._get_collection_count(context, ExternalSegmentMapping,
filters=filters)
@log.log
def create_nat_pool(self, context, nat_pool):
np = nat_pool['nat_pool']

View File

@ -1 +1 @@
1fadeb573886
c2a9d04c8cef

View File

@ -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.
#
"""Admin owns SCI (admin_owns_sci)
Revision ID: c2a9d04c8cef
"""
# revision identifiers, used by Alembic.
revision = 'c2a9d04c8cef'
down_revision = '1fadeb573886'
from alembic import op
import sqlalchemy as sa
def upgrade():
op.add_column(
'gpm_ptgs_servicechain_mapping',
sa.Column('tenant_id', sa.String(length=255), nullable=True)
)
def downgrade():
op.drop_column('gpm_ptgs_servicechain_mapping', 'tenant_id')

View File

@ -34,7 +34,6 @@ from gbpservice.neutron.services.grouppolicy.common import (
# The code below is a monkey patch of key Neutron's modules. This is needed for
# the GBP service to be loaded correctly. GBP extensions' path is added
# to Neutron's so that it's found at extension scanning time.
extensions.append_api_extensions_path(gbpservice.neutron.extensions.__path__)
constants.GROUP_POLICY = "GROUP_POLICY"
constants.COMMON_PREFIXES["GROUP_POLICY"] = "/grouppolicy"

View File

@ -11,6 +11,7 @@
# under the License.
from neutron.db import l3_db
from neutron.db import securitygroups_db
# Monkey patch create floatingip to allow subnet_id to be specified.
@ -94,3 +95,37 @@ def get_assoc_data(self, context, fip, floating_network_id):
return fip['port_id'], internal_ip_address, router_id
l3_db.L3_NAT_dbonly_mixin.get_assoc_data = get_assoc_data
# REVISIT(ivar): Neutron adds a tenant filter on SG lookup for a given port,
# this breaks our service chain plumbing model so for now we should monkey
# patch the specific method. A follow up with the Neutron team is needed to
# figure out the reason for this and how to proceed for future releases.
def _get_security_groups_on_port(self, context, port):
"""Check that all security groups on port belong to tenant.
:returns: all security groups IDs on port belonging to tenant.
"""
p = port['port']
if not securitygroups_db.attributes.is_attr_set(
p.get(securitygroups_db.ext_sg.SECURITYGROUPS)):
return
if p.get('device_owner') and p['device_owner'].startswith('network:'):
return
port_sg = p.get(securitygroups_db.ext_sg.SECURITYGROUPS, [])
filters = {'id': port_sg}
valid_groups = set(g['id'] for g in
self.get_security_groups(context, fields=['id'],
filters=filters))
requested_groups = set(port_sg)
port_sg_missing = requested_groups - valid_groups
if port_sg_missing:
raise securitygroups_db.ext_sg.SecurityGroupNotFound(
id=', '.join(port_sg_missing))
return requested_groups
securitygroups_db.SecurityGroupDbMixin._get_security_groups_on_port = (
_get_security_groups_on_port)

View File

@ -13,6 +13,8 @@
import netaddr
import operator
from keystoneclient import exceptions as k_exceptions
from keystoneclient.v2_0 import client as k_client
from neutron.api.v2 import attributes
from neutron.common import constants as const
from neutron.common import exceptions as n_exc
@ -24,6 +26,7 @@ from neutron.extensions import securitygroup as ext_sg
from oslo_config import cfg
from oslo_log import log as logging
from oslo_serialization import jsonutils
from oslo_utils import excutils
import sqlalchemy as sa
from gbpservice.common import utils
@ -40,6 +43,24 @@ from gbpservice.neutron.services.grouppolicy.common import exceptions as exc
LOG = logging.getLogger(__name__)
DEFAULT_SG_PREFIX = 'gbp_%s'
group_policy_opts = [
cfg.StrOpt('chain_owner_user',
help=_("Chain owner username. If set, will be used in "
"place of the Neutron service admin for retrieving "
"tenant owner information through Keystone."),
default=''),
cfg.StrOpt('chain_owner_password',
help=_("Chain owner password."), default='',
secret=True),
cfg.StrOpt('chain_owner_tenant_name',
help=_("Name of the Tenant that will own the service chain "
"instances for this driver. Leave empty for provider "
"owned chains."), default=''),
]
cfg.CONF.register_opts(group_policy_opts, "resource_mapping")
opts = [
cfg.ListOpt('dns_nameservers',
@ -101,7 +122,7 @@ class PolicyRuleSetSGsMapping(model_base.BASEV2):
sa.ForeignKey('securitygroups.id'))
class PtgServiceChainInstanceMapping(model_base.BASEV2):
class PtgServiceChainInstanceMapping(model_base.BASEV2, models_v2.HasTenant):
"""Policy Target Group to ServiceChainInstance mapping DB."""
__tablename__ = 'gpm_ptgs_servicechain_mapping'
@ -173,6 +194,41 @@ class ResourceMappingDriver(api.PolicyDriver, local_api.LocalAPI):
@log.log
def initialize(self):
self._cached_agent_notifier = None
self.chain_owner = ResourceMappingDriver.chain_tenant_id(reraise=True)
@staticmethod
def chain_tenant_id(reraise=False):
keystone = ResourceMappingDriver.chain_tenant_keystone_client()
if keystone:
tenant = cfg.CONF.resource_mapping.chain_owner_tenant_name
try:
# Can it be retrieved directly, without a further keystone
# call?
tenant = keystone.tenants.find(name=tenant)
return tenant.id
except k_exceptions.NotFound:
with excutils.save_and_reraise_exception(reraise=reraise):
LOG.error(_('No tenant with name %s exists.'), tenant)
except k_exceptions.NoUniqueMatch:
with excutils.save_and_reraise_exception(reraise=reraise):
LOG.error(_('Multiple tenants matches found for %s'),
tenant)
@staticmethod
def chain_tenant_keystone_client():
chain_user = cfg.CONF.resource_mapping.chain_owner_user
user, pwd, tenant, auth_url = utils.get_keystone_creds()
user = (chain_user or user)
pwd = (cfg.CONF.resource_mapping.chain_owner_password or
(pwd if not chain_user else ''))
# Tenant must be configured in the resource_mapping section, provider
# owner will be used otherwise.
tenant = cfg.CONF.resource_mapping.chain_owner_tenant_name
if tenant:
return k_client.Client(username=user, password=pwd,
auth_url=auth_url)
def _reject_shared(self, object, type):
if object.get('shared'):
@ -512,7 +568,6 @@ class ResourceMappingDriver(api.PolicyDriver, local_api.LocalAPI):
"network_service_policy_id")
if not network_service_policy_id:
return
nsp = context._plugin.get_network_service_policy(
context._plugin_context, network_service_policy_id)
nsp_params = nsp.get("network_service_params")
@ -937,11 +992,16 @@ class ResourceMappingDriver(api.PolicyDriver, local_api.LocalAPI):
context.original['direction'] != context.current['direction']):
sc_instances = (
self._servicechain_plugin.get_servicechain_instances(
context._plugin_context,
context._plugin_context.elevated(),
filters={'classifier_id': [context.current['id']]}))
for sc_instance in sc_instances:
cmap = self._get_ptg_servicechain_mapping(
context._plugin_context.session,
servicechain_instance_id=sc_instance['id'])
ctx = self._get_chain_admin_context(context._plugin_context,
cmap[0].tenant_id)
self._servicechain_plugin.notify_chain_parameters_updated(
context._plugin_context, sc_instance['id'])
ctx, sc_instance['id'])
@log.log
def delete_policy_classifier_precommit(self, context):
@ -1856,10 +1916,11 @@ class ResourceMappingDriver(api.PolicyDriver, local_api.LocalAPI):
x == context.original['action_value'] else
x for x in old_specs]
self._update_servicechain_instance(
context, servicechain_instance.servicechain_instance_id,
context._plugin_context,
servicechain_instance.servicechain_instance_id,
sc_specs=new_specs)
def _update_servicechain_instance(self, context, sc_instance_id,
def _update_servicechain_instance(self, plugin_context, sc_instance_id,
classifier_id=None, sc_specs=None):
sc_instance_update_data = {}
if sc_specs:
@ -1867,7 +1928,9 @@ class ResourceMappingDriver(api.PolicyDriver, local_api.LocalAPI):
if classifier_id:
sc_instance_update_data.update({'classifier_id': classifier_id})
super(ResourceMappingDriver, self)._update_servicechain_instance(
context._plugin_context, sc_instance_id, sc_instance_update_data)
self._get_chain_admin_context(
plugin_context, instance_id=sc_instance_id),
sc_instance_id, sc_instance_update_data)
def _get_rule_ids_for_actions(self, context, action_id):
policy_rule_qry = context.session.query(
@ -1940,41 +2003,42 @@ class ResourceMappingDriver(api.PolicyDriver, local_api.LocalAPI):
context, ptg_providing_prs, ptg_consuming_prs,
spec_id,
parent_spec_id, classifier_id,
hierarchial_classifier_mismatch)
hierarchial_classifier_mismatch, policy_rule_set)
def _create_or_update_chain(self, context, provider, consumer, spec_id,
parent_spec_id, classifier_id,
hierarchial_classifier_mismatch):
hierarchial_classifier_mismatch, prs_id):
ptg_chain_map = self._get_ptg_servicechain_mapping(
context._plugin_context.session, provider, consumer)
if ptg_chain_map:
if hierarchial_classifier_mismatch or not spec_id:
ctx = self._get_chain_admin_context(
context._plugin_context,
tenant_id=ptg_chain_map[0].tenant_id)
self._delete_servicechain_instance(
context, ptg_chain_map[0].servicechain_instance_id)
ctx, ptg_chain_map[0].servicechain_instance_id)
else:
sc_specs = [spec_id]
if parent_spec_id:
sc_specs.insert(0, parent_spec_id)
# One Chain between a unique pair of provider and consumer
self._update_servicechain_instance(
context,
context._plugin_context,
ptg_chain_map[0].servicechain_instance_id,
classifier_id=classifier_id,
sc_specs=sc_specs)
elif spec_id and not hierarchial_classifier_mismatch:
sc_instance = self._create_servicechain_instance(
context, spec_id,
parent_spec_id, provider,
consumer, classifier_id)
self._set_ptg_servicechain_instance_mapping(
context._plugin_context.session,
provider, consumer,
sc_instance['id'])
self._create_servicechain_instance(context, spec_id,
parent_spec_id, provider,
consumer, classifier_id, prs_id)
def _cleanup_redirect_action(self, context):
for ptg_chain in context.ptg_chain_map:
ctx = self._get_chain_admin_context(context._plugin_context,
tenant_id=ptg_chain.tenant_id)
self._delete_servicechain_instance(
context, ptg_chain.servicechain_instance_id)
ctx, ptg_chain.servicechain_instance_id)
def _restore_ip_to_allocation_pool(self, context, subnet_id, ip_address):
# TODO(Magesh):Pass subnets and loop on subnets. Better to add logic
@ -2026,18 +2090,30 @@ class ResourceMappingDriver(api.PolicyDriver, local_api.LocalAPI):
def _create_servicechain_instance(self, context, servicechain_spec,
parent_servicechain_spec,
provider_ptg_id, consumer_ptg_id,
classifier_id,
classifier_id, policy_rule_set,
config_params=None):
sc_spec = [servicechain_spec]
if parent_servicechain_spec:
sc_spec.insert(0, parent_servicechain_spec)
config_param_values = {}
ptg = context._plugin.get_policy_target_group(
context._plugin_context, provider_ptg_id)
network_service_policy_id = ptg.get("network_service_policy_id")
provider_ptg = context._plugin.get_policy_target_group(
utils.admin_context(context._plugin_context), provider_ptg_id)
p_ctx = self._get_chain_admin_context(
context._plugin_context,
provider_tenant_id=provider_ptg['tenant_id'])
session = context._plugin_context.session
if consumer_ptg_id:
try:
consumer_ptg = context._plugin.get_policy_target_group(
p_ctx, consumer_ptg_id)
except gp_ext.PolicyTargetGroupNotFound:
consumer_ptg = context._plugin.get_external_policy(
p_ctx, consumer_ptg_id)
network_service_policy_id = provider_ptg.get(
"network_service_policy_id")
if network_service_policy_id:
nsp = context._plugin.get_network_service_policy(
context._plugin_context, network_service_policy_id)
p_ctx, network_service_policy_id)
service_params = nsp.get("network_service_params")
for service_parameter in service_params:
param_type = service_parameter.get("type")
@ -2046,7 +2122,7 @@ class ResourceMappingDriver(api.PolicyDriver, local_api.LocalAPI):
key = service_parameter.get("name")
servicepolicy_ptg_ip_map = (
self._get_ptg_policy_ipaddress_mapping(
context._plugin_context.session, provider_ptg_id))
session, provider_ptg_id))
servicepolicy_ip = servicepolicy_ptg_ip_map.get(
"ipaddress")
config_param_values[key] = servicepolicy_ip
@ -2060,8 +2136,11 @@ class ResourceMappingDriver(api.PolicyDriver, local_api.LocalAPI):
for fip_map in fip_maps:
servicepolicy_fip_ids.append(fip_map.floatingip_id)
config_param_values[key] = servicepolicy_fip_ids
attrs = {'tenant_id': context.current['tenant_id'],
'name': 'gbp_' + ptg['name'],
name = 'gbp_%s_%s_%s' % (policy_rule_set['name'], provider_ptg['name'],
consumer_ptg['name'] if consumer_ptg else '')
attrs = {'tenant_id': p_ctx.tenant,
'name': name,
'description': "",
'servicechain_specs': sc_spec,
'provider_ptg_id': provider_ptg_id,
@ -2069,9 +2148,13 @@ class ResourceMappingDriver(api.PolicyDriver, local_api.LocalAPI):
'management_ptg_id': None,
'classifier_id': classifier_id,
'config_param_values': jsonutils.dumps(config_param_values)}
return super(
sc_instance = super(
ResourceMappingDriver, self)._create_servicechain_instance(
context._plugin_context, attrs)
p_ctx, attrs)
self._set_ptg_servicechain_instance_mapping(
session, provider_ptg_id, consumer_ptg_id, sc_instance['id'],
p_ctx.tenant)
return sc_instance
# Do Not Pass floating_ip_address to this method until after Kilo Release
def _create_floatingip(self, plugin_context, tenant_id, ext_net_id,
@ -2540,27 +2623,36 @@ class ResourceMappingDriver(api.PolicyDriver, local_api.LocalAPI):
def _set_ptg_servicechain_instance_mapping(self, session, provider_ptg_id,
consumer_ptg_id,
servicechain_instance_id):
servicechain_instance_id,
provider_tenant_id):
with session.begin(subtransactions=True):
mapping = PtgServiceChainInstanceMapping(
provider_ptg_id=provider_ptg_id,
consumer_ptg_id=consumer_ptg_id,
servicechain_instance_id=servicechain_instance_id)
servicechain_instance_id=servicechain_instance_id,
tenant_id=provider_tenant_id)
session.add(mapping)
def _get_ptg_servicechain_mapping(self, session, provider_ptg_id,
consumer_ptg_id):
def _get_ptg_servicechain_mapping(self, session, provider_ptg_id=None,
consumer_ptg_id=None, tenant_id=None,
servicechain_instance_id=None):
with session.begin(subtransactions=True):
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)
if servicechain_instance_id:
query = query.filter_by(
servicechain_instance_id=servicechain_instance_id)
if tenant_id:
query = query.filter_by(consumer_ptg_id=tenant_id)
all = query.all()
return [utils.DictClass([('provider_ptg_id', x.provider_ptg_id),
('consumer_ptg_id', x.consumer_ptg_id),
('servicechain_instance_id',
x.servicechain_instance_id)])
x.servicechain_instance_id),
('tenant_id', x.tenant_id)])
for x in all]
def _get_ep_cidr_list(self, context, ep):
@ -2737,3 +2829,25 @@ class ResourceMappingDriver(api.PolicyDriver, local_api.LocalAPI):
ptg_subnet_id=",".join(ptg.get('subnets')),
port_subnet_id=port_subnet_id,
policy_target_group_id=ptg_id)
def _get_chain_admin_context(self, plugin_context, tenant_id=None,
provider_tenant_id=None, instance_id=None):
ctx = plugin_context.elevated()
# REVISIT(Ivar): Any particular implication when a provider owned PT
# exist in the consumer PTG? Especially when the consumer PTG belongs
# to another tenant? We may want to consider a strong convention
# for reference plumbers to absolutely avoid this kind of inter tenant
# object creation when the owner is the provider (in which case, the
# context can as well be a normal context without admin capabilities).
ctx.tenant_id = None
if instance_id:
cmap = self._get_ptg_servicechain_mapping(
ctx.session, servicechain_instance_id=instance_id)
if cmap:
ctx.tenant_id = cmap[0].tenant_id
if not ctx.tenant_id:
ctx.tenant_id = tenant_id or self.chain_owner or provider_tenant_id
if self.chain_owner == ctx.tenant_id:
ctx.auth_token = self.chain_tenant_keystone_client().get_token(
self.chain_owner)
return ctx

View File

@ -131,7 +131,7 @@ class GroupPolicyPlugin(group_policy_mapping_db.GroupPolicyMappingDbPlugin):
for linked in linked_objects:
link_ids.add(linked['id'])
GroupPolicyPlugin._verify_sharing_consistency(
obj, linked, identity, ref_type)
obj, linked, identity, ref_type, context.is_admin)
# Check for missing references
missing = set(ids) - link_ids
if missing:
@ -288,20 +288,22 @@ class GroupPolicyPlugin(group_policy_mapping_db.GroupPolicyMappingDbPlugin):
spec = self.servicechain_plugin.get_servicechain_spec(
context, action['action_value'])
GroupPolicyPlugin._verify_sharing_consistency(
action, spec, 'polocy_action', 'servicechain_spec')
action, spec, 'policy_action', 'servicechain_spec',
context.is_admin)
@staticmethod
def _verify_sharing_consistency(primary, reference, primary_type,
reference_type):
reference_type, is_admin):
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'])
if not is_admin:
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()
@ -484,7 +486,8 @@ class GroupPolicyPlugin(group_policy_mapping_db.GroupPolicyMappingDbPlugin):
policy_target_group = self.get_policy_target_group(
context, policy_target_group_id)
pt_ids = policy_target_group['policy_targets']
for pt in self.get_policy_targets(context, {'id': pt_ids}):
for pt in self.get_policy_targets(context.elevated(),
{'id': pt_ids}):
if pt['port_id'] and self._is_port_bound(pt['port_id']) or (
self._is_service_target(context, pt['id'])):
raise gp_exc.PolicyTargetGroupInUse(

View File

@ -15,6 +15,7 @@ import time
from heatclient import client as heat_client
from heatclient import exc as heat_exc
from keystoneclient.v2_0 import client as keyclient
from neutron.common import log
from neutron.db import model_base
from neutron import manager
@ -416,11 +417,16 @@ class HeatClient:
def __init__(self, context, password=None):
api_version = "1"
endpoint = "%s/%s" % (cfg.CONF.simplechain.heat_uri, context.tenant)
self.tenant = context.tenant
self._keystone = None
endpoint = "%s/%s" % (cfg.CONF.simplechain.heat_uri, self.tenant)
kwargs = {
'token': context.auth_token,
'token': self._get_auth_token(self.tenant),
'username': context.user_name,
'password': password
'password': password,
'cacert': cfg.CONF.simplechain.heat_ca_certificates_file,
'insecure': cfg.CONF.simplechain.heat_api_insecure
}
self.client = heat_client.Client(api_version, endpoint, **kwargs)
self.stacks = self.client.stacks
@ -445,3 +451,25 @@ class HeatClient:
def get(self, stack_id):
return self.stacks.get(stack_id)
@property
def keystone(self):
if not self._keystone:
keystone_conf = cfg.CONF.keystone_authtoken
if keystone_conf.get('auth_uri'):
auth_url = keystone_conf.auth_uri
else:
auth_url = ('%s://%s:%s/v2.0/' % (
keystone_conf.auth_protocol,
keystone_conf.auth_host,
keystone_conf.auth_port))
user = (keystone_conf.get('admin_user') or keystone_conf.username)
pw = (keystone_conf.get('admin_password') or
keystone_conf.password)
self._keystone = keyclient.Client(
username=user, password=pw, auth_url=auth_url,
tenant_id=self.tenant)
return self._keystone
def _get_auth_token(self, tenant):
return self.keystone.get_token(tenant)

View File

@ -10,10 +10,10 @@
# License for the specific language governing permissions and limitations
# under the License.
from neutron import context as n_context
from neutron import manager
from neutron.plugins.common import constants as pconst
from gbpservice.common import utils
from gbpservice.neutron.services.servicechain.plugins.ncp import model
@ -23,26 +23,26 @@ def get_gbp_plugin():
def get_node_driver_context(sc_plugin, context, sc_instance,
current_node, original_node=None,
service_targets=None):
management_group=None, service_targets=None):
admin_context = utils.admin_context(context)
specs = sc_plugin.get_servicechain_specs(
context, filters={'id': sc_instance['servicechain_specs']})
admin_context, filters={'id': sc_instance['servicechain_specs']})
position = _calculate_node_position(specs, current_node['id'])
provider, _ = _get_ptg_or_ep(
context, sc_instance['provider_ptg_id'])
admin_context, sc_instance['provider_ptg_id'])
consumer, is_consumer_external = _get_ptg_or_ep(
context, sc_instance['consumer_ptg_id'])
admin_context, sc_instance['consumer_ptg_id'])
management, _ = _get_ptg_or_ep(context, sc_instance['management_ptg_id'])
classifier = get_gbp_plugin().get_policy_classifier(
context, sc_instance['classifier_id'])
admin_context, sc_instance['classifier_id'])
current_profile = sc_plugin.get_service_profile(
context, current_node['service_profile_id'])
admin_context, current_node['service_profile_id'])
original_profile = sc_plugin.get_service_profile(
context,
admin_context,
original_node['service_profile_id']) if original_node else None
if not service_targets:
service_targets = model.get_service_targets(
context.session, servicechain_instance_id=sc_instance['id'],
admin_context.session, servicechain_instance_id=sc_instance['id'],
position=position, servicechain_node_id=current_node['id'])
return NodeDriverContext(sc_plugin=sc_plugin,
@ -147,7 +147,7 @@ class NodeDriverContext(object):
@property
def admin_context(self):
if not self._admin_context:
self._admin_context = n_context.get_admin_context()
self._admin_context = utils.admin_context(self.plugin_context)
return self._admin_context
@property

View File

@ -283,7 +283,9 @@ class NodeCompositionPlugin(servicechain_db.ServiceChainDbPlugin,
self._update_chains_pt_modified(context, policy_target, 'removed')
def _update_chains_pt_modified(self, context, policy_target, action):
scis = self._get_instances_from_policy_target(context, policy_target)
admin_context = utils.admin_context(context)
scis = self._get_instances_from_policy_target(
admin_context, policy_target)
for sci in scis:
updaters = self._get_scheduled_drivers(context, sci, 'update')
@ -317,6 +319,7 @@ class NodeCompositionPlugin(servicechain_db.ServiceChainDbPlugin,
"failed, %s"), ex.message)
def _get_instance_nodes(self, context, instance):
context = utils.admin_context(context)
if not instance['servicechain_specs']:
return []
specs = self.get_servicechain_spec(
@ -324,6 +327,7 @@ class NodeCompositionPlugin(servicechain_db.ServiceChainDbPlugin,
return self.get_servicechain_nodes(context, {'id': specs['nodes']})
def _get_node_instances(self, context, node):
context = utils.admin_context(context)
specs = self.get_servicechain_specs(
context, {'id': node['servicechain_specs']})
result = []

View File

@ -113,8 +113,8 @@ class NodePlumberBase(object):
for pt in pts:
try:
gbp_plugin.delete_policy_target(context, pt.policy_target_id,
notify_sc=False)
gbp_plugin.delete_policy_target(
context.elevated(), pt.policy_target_id, notify_sc=False)
except group_policy.PolicyTargetNotFound as ex:
LOG.debug(ex.message)
@ -134,7 +134,7 @@ class NodePlumberBase(object):
instance['id']),
'name': '', 'port_id': None}
data.update(target)
pt = gbp_plugin.create_policy_target(context,
pt = gbp_plugin.create_policy_target(context.elevated(),
{'policy_target': data},
notify_sc=False)
model.set_service_target(part_context, pt['id'], relationship)

View File

@ -56,21 +56,14 @@
"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",
"create_service_profile": "",
"create_service_profile:shared": "rule:admin_only",
"get_service_profile": "rule:admin_or_owner or rule:shared_sp",
"update_service_profile:shared": "rule:admin_only"
"get_service_profile": "rule:admin_or_owner or rule:shared_sp"
}

View File

@ -16,8 +16,9 @@ import os
import webob.exc
from neutron.api import extensions
from neutron.api.v2 import attributes as nattr
from neutron import context
from neutron.db import api as db_api
from neutron.db import model_base
from neutron import manager
from neutron.openstack.common import uuidutils
from neutron.plugins.common import constants
@ -27,7 +28,9 @@ from oslo_config import cfg
from oslo_utils import importutils
from gbpservice.neutron.db.grouppolicy import group_policy_db as gpdb
from gbpservice.neutron.db import servicechain_db as svcchain_db
from gbpservice.neutron.extensions import group_policy as gpolicy
from gbpservice.neutron.extensions import servicechain as service_chain
import gbpservice.neutron.tests
from gbpservice.neutron.tests.unit import common as cm
@ -36,6 +39,7 @@ JSON_FORMAT = 'json'
_uuid = uuidutils.generate_uuid
TESTDIR = os.path.dirname(os.path.abspath(gbpservice.neutron.tests.__file__))
ETCDIR = os.path.join(TESTDIR, 'etc')
CHAIN_TENANT_ID = 'chain_owner'
class ApiManagerMixin(object):
@ -123,21 +127,31 @@ class ApiManagerMixin(object):
class GroupPolicyDBTestBase(ApiManagerMixin):
resource_prefix_map = dict(
(k, constants.COMMON_PREFIXES[constants.SERVICECHAIN])
for k in service_chain.RESOURCE_ATTRIBUTE_MAP.keys())
resource_prefix_map.update(dict(
(k, constants.COMMON_PREFIXES[constants.GROUP_POLICY])
for k in gpolicy.RESOURCE_ATTRIBUTE_MAP.keys()
)
))
fmt = JSON_FORMAT
def __getattr__(self, item):
# Verify is an update of a proper GBP object
def _is_sc_resource(plural):
return plural in service_chain.RESOURCE_ATTRIBUTE_MAP
def _is_gbp_resource(plural):
return plural in gpolicy.RESOURCE_ATTRIBUTE_MAP
def _is_valid_resource(plural):
return _is_gbp_resource(plural) or _is_sc_resource(plural)
# Update Method
if item.startswith('update_'):
resource = item[len('update_'):]
plural = cm.get_resource_plural(resource)
if _is_gbp_resource(plural):
if _is_valid_resource(plural):
def update_wrapper(id, **kwargs):
return self._update_resource(id, resource, **kwargs)
return update_wrapper
@ -145,7 +159,7 @@ class GroupPolicyDBTestBase(ApiManagerMixin):
if item.startswith('show_'):
resource = item[len('show_'):]
plural = cm.get_resource_plural(resource)
if _is_gbp_resource(plural):
if _is_valid_resource(plural):
def show_wrapper(id, **kwargs):
return self._show_resource(id, plural, **kwargs)
return show_wrapper
@ -153,7 +167,7 @@ class GroupPolicyDBTestBase(ApiManagerMixin):
if item.startswith('create_'):
resource = item[len('create_'):]
plural = cm.get_resource_plural(resource)
if _is_gbp_resource(plural):
if _is_valid_resource(plural):
def create_wrapper(**kwargs):
return self._create_resource(resource, **kwargs)
return create_wrapper
@ -161,13 +175,51 @@ class GroupPolicyDBTestBase(ApiManagerMixin):
if item.startswith('delete_'):
resource = item[len('delete_'):]
plural = cm.get_resource_plural(resource)
if _is_gbp_resource(plural):
if _is_valid_resource(plural):
def delete_wrapper(id, **kwargs):
return self._delete_resource(id, plural, **kwargs)
return delete_wrapper
raise AttributeError
def _get_resource_plural(self, resource):
if resource.endswith('y'):
resource_plural = resource.replace('y', 'ies')
else:
resource_plural = resource + 's'
return resource_plural
def _test_list_resources(self, resource, items,
neutron_context=None,
query_params=None):
resource_plural = self._get_resource_plural(resource)
res = self._list(resource_plural,
neutron_context=neutron_context,
query_params=query_params)
params = None
if query_params:
params = query_params.split('&')
params = dict((x.split('=')[0], x.split('=')[1].split(','))
for x in params)
count = getattr(self.plugin, 'get_%s_count' % resource_plural)(
neutron_context or context.get_admin_context(), params)
self.assertEqual(len(res[resource_plural]), count)
resource = resource.replace('-', '_')
self.assertEqual(sorted([i['id'] for i in res[resource_plural]]),
sorted([i[resource]['id'] for i in items]))
def _create_profiled_servicechain_node(
self, service_type=constants.LOADBALANCER, shared_profile=False,
profile_tenant_id=None, **kwargs):
prof = self.create_service_profile(
service_type=service_type,
shared=shared_profile,
tenant_id=profile_tenant_id or self._tenant_id)['service_profile']
return self.create_servicechain_node(
service_profile_id=prof['id'], **kwargs)
class GroupPolicyDBTestPlugin(gpdb.GroupPolicyDbPlugin):
@ -178,26 +230,42 @@ DB_GP_PLUGIN_KLASS = (GroupPolicyDBTestPlugin.__module__ + '.' +
GroupPolicyDBTestPlugin.__name__)
class ServiceChainDBTestPlugin(svcchain_db.ServiceChainDbPlugin):
supported_extension_aliases = ['servicechain']
DB_SC_PLUGIN_KLASS = (ServiceChainDBTestPlugin.__module__ + '.' +
ServiceChainDBTestPlugin.__name__)
class GroupPolicyDbTestCase(GroupPolicyDBTestBase,
test_db_base_plugin_v2.NeutronDbPluginV2TestCase):
def setUp(self, core_plugin=None, gp_plugin=None, service_plugins=None,
ext_mgr=None):
if not gp_plugin:
gp_plugin = DB_GP_PLUGIN_KLASS
def setUp(self, core_plugin=None, sc_plugin=None, service_plugins=None,
ext_mgr=None, gp_plugin=None):
sc_plugin = sc_plugin or DB_SC_PLUGIN_KLASS
gp_plugin = gp_plugin or DB_GP_PLUGIN_KLASS
if not service_plugins:
service_plugins = {'gp_plugin_name': gp_plugin}
nattr.PLURALS['nat_pools'] = 'nat_pool'
service_plugins = {
'l3_plugin_name': 'router',
'gp_plugin_name': gp_plugin,
'sc_plugin_name': sc_plugin}
test_policy_file = ETCDIR + "/test-policy.json"
cfg.CONF.set_override('policy_file', test_policy_file)
super(GroupPolicyDbTestCase, self).setUp(
plugin=core_plugin, ext_mgr=ext_mgr,
service_plugins=service_plugins
)
self.plugin = importutils.import_object(gp_plugin)
self._sc_plugin = importutils.import_object(sc_plugin)
if not ext_mgr:
ext_mgr = extensions.PluginAwareExtensionManager.get_instance()
self.ext_api = test_extensions.setup_extensions_middleware(ext_mgr)
test_policy_file = ETCDIR + "/test-policy.json"
cfg.CONF.set_override('policy_file', test_policy_file)
engine = db_api.get_engine()
model_base.BASEV2.metadata.create_all(engine)
plugins = manager.NeutronManager.get_service_plugins()
self._gbp_plugin = plugins.get(constants.GROUP_POLICY)

View File

@ -210,6 +210,7 @@ class TestMappedGroupResourceAttrs(GroupPolicyMappingDbTestCase):
ports = [port1['port']['id'], port2['port']['id']]
pts = [self.create_policy_target(port_id=ports[0]),
self.create_policy_target(port_id=ports[1])]
self._test_list_resources('policy_target', pts)
self._test_list_resources('policy_target', [pts[0]],
query_params='port_id=' + ports[0])
@ -221,8 +222,10 @@ class TestMappedGroupResourceAttrs(GroupPolicyMappingDbTestCase):
l2_policies = [self.create_l2_policy(network_id=networks[0]),
self.create_l2_policy(network_id=networks[1])]
self._test_list_resources(
'l2_policy', [l2_policies[0]],
query_params='network_id=' + networks[0])
'l2_policy', l2_policies)
self._test_list_resources(
'l2_policy', [l2_policies[0]],
query_params='network_id=' + networks[0])
def test_list_es(self):
with self.subnet(cidr='10.10.1.0/24') as subnet1:
@ -232,5 +235,7 @@ class TestMappedGroupResourceAttrs(GroupPolicyMappingDbTestCase):
self.create_external_segment(subnet_id=subnets[0]),
self.create_external_segment(subnet_id=subnets[1])]
self._test_list_resources(
'external_segment', [external_segments[0]],
query_params='subnet_id=' + subnets[0])
'external_segment', external_segments)
self._test_list_resources(
'external_segment', [external_segments[0]],
query_params='subnet_id=' + subnets[0])

View File

@ -13,19 +13,11 @@
import webob.exc
from neutron.api import extensions
from neutron import context
from neutron.db import api as db_api
from neutron.db import model_base
from neutron.openstack.common import uuidutils
from neutron.plugins.common import constants
from neutron.tests.unit.api import test_extensions
from neutron.tests.unit.db import test_db_base_plugin_v2
from oslo_config import cfg
from oslo_utils import importutils
from gbpservice.neutron.db import servicechain_db as svcchain_db
from gbpservice.neutron.extensions import group_policy as gpolicy
from gbpservice.neutron.extensions import servicechain as service_chain
from gbpservice.neutron.tests.unit import common as cm
from gbpservice.neutron.tests.unit.db.grouppolicy import test_group_policy_db
@ -33,135 +25,20 @@ from gbpservice.neutron.tests.unit.db.grouppolicy import test_group_policy_db
JSON_FORMAT = 'json'
class ServiceChainDBTestBase(test_group_policy_db.ApiManagerMixin):
resource_prefix_map = dict(
(k, constants.COMMON_PREFIXES[constants.SERVICECHAIN])
for k in service_chain.RESOURCE_ATTRIBUTE_MAP.keys())
resource_prefix_map.update(dict(
(k, constants.COMMON_PREFIXES[constants.GROUP_POLICY])
for k in gpolicy.RESOURCE_ATTRIBUTE_MAP.keys()
))
fmt = JSON_FORMAT
def __getattr__(self, item):
# Verify is an update of a proper GBP object
def _is_sc_resource(plural):
return plural in service_chain.RESOURCE_ATTRIBUTE_MAP
def _is_gbp_resource(plural):
return plural in gpolicy.RESOURCE_ATTRIBUTE_MAP
def _is_valid_resource(plural):
return _is_gbp_resource(plural) or _is_sc_resource(plural)
# Update Method
if item.startswith('update_'):
resource = item[len('update_'):]
plural = cm.get_resource_plural(resource)
if _is_valid_resource(plural):
def update_wrapper(id, **kwargs):
return self._update_resource(id, resource, **kwargs)
return update_wrapper
# Show Method
if item.startswith('show_'):
resource = item[len('show_'):]
plural = cm.get_resource_plural(resource)
if _is_valid_resource(plural):
def show_wrapper(id, **kwargs):
return self._show_resource(id, plural, **kwargs)
return show_wrapper
# Create Method
if item.startswith('create_'):
resource = item[len('create_'):]
plural = cm.get_resource_plural(resource)
if _is_valid_resource(plural):
def create_wrapper(**kwargs):
return self._create_resource(resource, **kwargs)
return create_wrapper
# Delete Method
if item.startswith('delete_'):
resource = item[len('delete_'):]
plural = cm.get_resource_plural(resource)
if _is_valid_resource(plural):
def delete_wrapper(id, **kwargs):
return self._delete_resource(id, plural, **kwargs)
return delete_wrapper
raise AttributeError
def _get_resource_plural(self, resource):
if resource.endswith('y'):
resource_plural = resource.replace('y', 'ies')
else:
resource_plural = resource + 's'
return resource_plural
def _test_list_resources(self, resource, items,
neutron_context=None,
query_params=None):
resource_plural = self._get_resource_plural(resource)
res = self._list(resource_plural,
neutron_context=neutron_context,
query_params=query_params)
params = query_params.split('&')
params = dict((x.split('=')[0], x.split('=')[1].split(','))
for x in params)
count = getattr(self.plugin, 'get_%s_count' % resource_plural)(
neutron_context or context.get_admin_context(), params)
self.assertEqual(len(res[resource_plural]), count)
resource = resource.replace('-', '_')
self.assertEqual(sorted([i['id'] for i in res[resource_plural]]),
sorted([i[resource]['id'] for i in items]))
def _create_profiled_servicechain_node(
self, service_type=constants.LOADBALANCER, shared_profile=False,
profile_tenant_id=None, **kwargs):
prof = self.create_service_profile(
service_type=service_type,
shared=shared_profile,
tenant_id=profile_tenant_id or self._tenant_id)['service_profile']
return self.create_servicechain_node(
service_profile_id=prof['id'], **kwargs)
class ServiceChainDBTestPlugin(svcchain_db.ServiceChainDbPlugin):
supported_extension_aliases = ['servicechain']
DB_GP_PLUGIN_KLASS = (ServiceChainDBTestPlugin.__module__ + '.' +
ServiceChainDBTestPlugin.__name__)
GP_PLUGIN_KLASS = (
"gbpservice.neutron.services.grouppolicy.plugin.GroupPolicyPlugin")
class ServiceChainDbTestCase(ServiceChainDBTestBase,
test_db_base_plugin_v2.NeutronDbPluginV2TestCase):
class ServiceChainDbTestCase(test_group_policy_db.GroupPolicyDbTestCase):
def setUp(self, core_plugin=None, sc_plugin=None, service_plugins=None,
ext_mgr=None, gp_plugin=None):
if not sc_plugin:
sc_plugin = DB_GP_PLUGIN_KLASS
if not service_plugins:
service_plugins = {
'l3_plugin_name': 'router',
'gp_plugin_name': gp_plugin or GP_PLUGIN_KLASS,
'sc_plugin_name': sc_plugin}
super(ServiceChainDbTestCase, self).setUp(
plugin=core_plugin, ext_mgr=ext_mgr,
service_plugins=service_plugins
)
self.plugin = importutils.import_object(sc_plugin)
if not ext_mgr:
ext_mgr = extensions.PluginAwareExtensionManager.get_instance()
self.ext_api = test_extensions.setup_extensions_middleware(ext_mgr)
engine = db_api.get_engine()
model_base.BASEV2.metadata.create_all(engine)
gp_plugin=gp_plugin or GP_PLUGIN_KLASS, core_plugin=core_plugin,
sc_plugin=sc_plugin, service_plugins=service_plugins,
ext_mgr=ext_mgr)
self.plugin = self._sc_plugin
class TestServiceChainResources(ServiceChainDbTestCase):

View File

@ -148,16 +148,6 @@ class ApicMappingTestCase(
self.driver.apic_manager.ext_net_dict.update(
self._build_external_dict(x[0], x[1]))
def _check_call_list(self, expected, observed):
for call in expected:
self.assertTrue(call in observed,
msg='Call not found, expected:\n%s\nobserved:'
'\n%s' % (str(call), str(observed)))
observed.remove(call)
self.assertFalse(
len(observed),
msg='There are more calls than expected: %s' % str(observed))
def _create_simple_policy_rule(self, direction='bi', protocol='tcp',
port_range=80, shared=False,
action_type='allow', action_value=None):

View File

@ -853,8 +853,8 @@ class TestNatPool(GroupPolicyPluginTestCase):
class TestPolicyTarget(GroupPolicyPluginTestCase):
def _test_cross_tenant_fails(self, is_admin=False):
status = {False: 404, True: 400}
def _test_cross_tenant(self, is_admin=False):
status = {False: 404, True: 201}
ptg = self.create_policy_target_group(
expected_res_status=201, tenant_id='tenant',
is_admin_context=is_admin)['policy_target_group']
@ -865,9 +865,6 @@ class TestPolicyTarget(GroupPolicyPluginTestCase):
if not is_admin:
self.assertEqual(
'GbpResourceNotFound', res['NeutronError']['type'])
else:
self.assertEqual(
'InvalidCrossTenantReference', res['NeutronError']['type'])
# Create EP without PTG
pt = self.create_policy_target(
@ -875,28 +872,25 @@ class TestPolicyTarget(GroupPolicyPluginTestCase):
is_admin_context=is_admin)['policy_target']
# Update PT fails
res = self.update_policy_target(pt['id'],
expected_res_status=status[is_admin],
tenant_id='another',
policy_target_group_id=ptg['id'],
is_admin_context=is_admin)
res = self.update_policy_target(
pt['id'], tenant_id='another', policy_target_group_id=ptg['id'],
expected_res_status=status[is_admin] if not is_admin else 200,
is_admin_context=is_admin)
if not is_admin:
self.assertEqual(
'GbpResourceNotFound', res['NeutronError']['type'])
else:
self.assertEqual(
'InvalidCrossTenantReference', res['NeutronError']['type'])
def test_cross_tenant_fails(self):
self._test_cross_tenant_fails()
self._test_cross_tenant()
def test_cross_tenant_fails_admin(self):
self._test_cross_tenant_fails(True)
def test_cross_tenant_admin(self):
self._test_cross_tenant(True)
class TestPolicyAction(GroupPolicyPluginTestCase):
def test_redirect_value_fails(self):
def test_redirect_value(self):
scs_id = self._create_servicechain_spec(
node_types=['FIREWALL_TRANSPARENT'])
res = self.create_policy_action(action_type='redirect',
@ -913,9 +907,7 @@ class TestPolicyAction(GroupPolicyPluginTestCase):
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'])
expected_res_status=201, is_admin_context=True)
res = self.create_policy_action(
action_type='redirect', action_value=scs_id,
@ -929,7 +921,7 @@ class TestPolicyAction(GroupPolicyPluginTestCase):
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']
expected_res_status=201)
data = {'servicechain_spec': {'shared': False}}
scs_req = self.new_update_request(
SERVICECHAIN_SPECS, data, scs_id, self.fmt)

View File

@ -172,6 +172,17 @@ class TestPolicyRuleSet(OneConvergenceGBPDriverTestCase,
pass
class TestServiceChain(OneConvergenceGBPDriverTestCase,
test_resource_mapping.TestServiceChain):
pass
class TestServiceChainAdminOwner(
OneConvergenceGBPDriverTestCase,
test_resource_mapping.TestServiceChainAdminOwner):
pass
class TestPolicyAction(OneConvergenceGBPDriverTestCase,
test_resource_mapping.TestPolicyAction):
pass

View File

@ -47,6 +47,7 @@ CORE_PLUGIN = ('gbpservice.neutron.tests.unit.services.grouppolicy.'
GP_PLUGIN_KLASS = (
"gbpservice.neutron.services.grouppolicy.plugin.GroupPolicyPlugin"
)
CHAIN_TENANT_ID = 'sci_owner'
class NodeCompositionPluginTestCase(
@ -155,7 +156,8 @@ class NodeCompositionPluginTestCase(
provider = self.create_policy_target_group()['policy_target_group']
consumer = self.create_policy_target_group()['policy_target_group']
management = self.create_policy_target_group(
service_management=True)['policy_target_group']
service_management=True,
is_admin_context=True)['policy_target_group']
classifier = self.create_policy_classifier()['policy_classifier']
instance = self.create_servicechain_instance(
@ -600,7 +602,7 @@ class NodeCompositionPluginTestCase(
self.create_policy_target_group(
provided_policy_rule_sets={prs['id']: ''})
self.create_policy_target_group(
consumed_policy_rule_sets={prs['id']: ''})['policy_target_group']
consumed_policy_rule_sets={prs['id']: ''})
instances = self._list('servicechain_instances')[
'servicechain_instances']
self.assertEqual(1, len(instances))
@ -679,6 +681,9 @@ class AgnosticChainPlumberTestCase(NodeCompositionPluginTestCase):
self.driver.get_plumbing_info = mock.Mock()
self.driver.get_plumbing_info.return_value = {}
def _assert_service_target_tenant(self, policy_target, provider):
self.assertEqual(provider['tenant_id'], policy_target['tenant_id'])
def _create_simple_chain(self):
node = self._create_profiled_servicechain_node(
service_type="LOADBALANCER",
@ -718,9 +723,11 @@ class AgnosticChainPlumberTestCase(NodeCompositionPluginTestCase):
for target in targets:
self.assertEqual(node['id'], target.servicechain_node_id)
pt = self.show_policy_target(
target.policy_target_id)['policy_target']
target.policy_target_id,
is_admin_context=True)['policy_target']
self.assertEqual(prov_cons[target.relationship]['id'],
pt['policy_target_group_id'])
self._assert_service_target_tenant(pt, provider)
self.assertNotEqual(old_relationship, target.relationship)
old_relationship = target.relationship
@ -731,7 +738,8 @@ class AgnosticChainPlumberTestCase(NodeCompositionPluginTestCase):
self.assertEqual(0, len(new_targets))
for target in targets:
self.show_policy_target(
target.policy_target_id, expected_res_status=404)
target.policy_target_id, is_admin_context=True,
expected_res_status=404)
def test_pt_override(self):
context = n_context.get_admin_context()
@ -742,7 +750,8 @@ class AgnosticChainPlumberTestCase(NodeCompositionPluginTestCase):
targets = model.get_service_targets(context.session)
self.assertEqual(1, len(targets))
pt = self.show_policy_target(
targets[0].policy_target_id)['policy_target']
targets[0].policy_target_id,
is_admin_context=True)['policy_target']
self.assertEqual(test_name, pt['name'])
def test_ptg_delete(self):
@ -839,3 +848,29 @@ class TestQuotasForServiceChain(test_base.ServiceChainPluginTestCase):
self.assertRaises(webob.exc.HTTPClientError,
self.create_policy_target_group,
consumed_policy_rule_sets={prs['id']: ''})
class AgnosticChainPlumberAdminOwner(AgnosticChainPlumberTestCase):
def setUp(self):
mock.patch('gbpservice.neutron.services.grouppolicy.drivers.'
'resource_mapping.ResourceMappingDriver.'
'chain_tenant_keystone_client').start()
res = mock.patch('gbpservice.neutron.services.grouppolicy.drivers.'
'resource_mapping.ResourceMappingDriver.'
'chain_tenant_id').start()
res.return_value = CHAIN_TENANT_ID
super(AgnosticChainPlumberAdminOwner, self).setUp()
def _assert_service_target_tenant(self, policy_target, provider):
self.assertEqual(CHAIN_TENANT_ID, policy_target['tenant_id'])
def test_update_service_chain(self):
# This directly updates the SCI, which requires the right tenant to be
# done
pass
def test_instance_update(self):
# This directly updates the SCI, which requires the right tenant to be
# done
pass

View File

@ -64,6 +64,10 @@ class SimpleChainDriverTestCase(
STACK_DELETE_RETRY_WAIT,
group='simplechain')
super(SimpleChainDriverTestCase, self).setUp()
key_client = mock.patch(
'gbpservice.neutron.services.servicechain.plugins.msc.drivers.'
'simplechain_driver.HeatClient._get_auth_token').start()
key_client.return_value = 'mysplendidtoken'
class TestServiceChainInstance(SimpleChainDriverTestCase):