637 lines
29 KiB
Python
637 lines
29 KiB
Python
# 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.
|
|
|
|
import ast
|
|
|
|
from neutron_lib.db import model_base
|
|
from neutron_lib import exceptions as n_exc
|
|
from neutron_lib.plugins import constants as pconst
|
|
from neutron_lib.plugins import directory
|
|
from oslo_log import helpers as log
|
|
from oslo_log import log as logging
|
|
from oslo_serialization import jsonutils
|
|
from oslo_utils import uuidutils
|
|
import sqlalchemy as sa
|
|
from sqlalchemy.ext.orderinglist import ordering_list
|
|
from sqlalchemy import orm
|
|
from sqlalchemy.orm import exc
|
|
|
|
from gbpservice._i18n import _
|
|
from gbpservice.neutron.db import api as db_api
|
|
from gbpservice.neutron.extensions import servicechain as schain
|
|
from gbpservice.neutron.services.servicechain.common import exceptions as s_exc
|
|
|
|
|
|
LOG = logging.getLogger(__name__)
|
|
MAX_IPV4_SUBNET_PREFIX_LENGTH = 31
|
|
MAX_IPV6_SUBNET_PREFIX_LENGTH = 127
|
|
|
|
|
|
class BaseSCResource(model_base.HasId, model_base.HasProject):
|
|
name = sa.Column(sa.String(255))
|
|
description = sa.Column(sa.String(255))
|
|
status = sa.Column(sa.String(length=16), nullable=True)
|
|
status_details = sa.Column(sa.String(length=4096), nullable=True)
|
|
|
|
|
|
class BaseSharedSCResource(BaseSCResource):
|
|
shared = sa.Column(sa.Boolean)
|
|
|
|
|
|
class SpecNodeAssociation(model_base.BASEV2):
|
|
"""Models one to many providing relation between Specs and Nodes."""
|
|
__tablename__ = 'sc_spec_node_associations'
|
|
servicechain_spec_id = sa.Column(
|
|
sa.String(36), sa.ForeignKey('sc_specs.id'), primary_key=True)
|
|
node_id = sa.Column(sa.String(36),
|
|
sa.ForeignKey('sc_nodes.id'),
|
|
primary_key=True)
|
|
position = sa.Column(sa.Integer)
|
|
|
|
|
|
class InstanceSpecAssociation(model_base.BASEV2):
|
|
"""Models one to many providing relation between Instance and Specs."""
|
|
__tablename__ = 'sc_instance_spec_mappings'
|
|
servicechain_instance_id = sa.Column(
|
|
sa.String(36), sa.ForeignKey('sc_instances.id'), primary_key=True)
|
|
servicechain_spec_id = sa.Column(sa.String(36),
|
|
sa.ForeignKey('sc_specs.id'),
|
|
primary_key=True)
|
|
position = sa.Column(sa.Integer)
|
|
|
|
|
|
class ServiceChainNode(model_base.BASEV2, BaseSharedSCResource):
|
|
"""ServiceChain Node"""
|
|
__tablename__ = 'sc_nodes'
|
|
config = sa.Column(sa.TEXT)
|
|
specs = orm.relationship(SpecNodeAssociation,
|
|
backref="nodes",
|
|
cascade='all, delete, delete-orphan')
|
|
service_type = sa.Column(sa.String(50), nullable=True)
|
|
service_profile_id = sa.Column(
|
|
sa.String(36), sa.ForeignKey('service_profiles.id'),
|
|
nullable=True)
|
|
|
|
|
|
class ServiceChainInstance(model_base.BASEV2, BaseSCResource):
|
|
"""Service chain instances"""
|
|
__tablename__ = 'sc_instances'
|
|
config_param_values = sa.Column(sa.String(4096))
|
|
specs = orm.relationship(
|
|
InstanceSpecAssociation,
|
|
backref='instances',
|
|
cascade='all,delete, delete-orphan',
|
|
order_by='InstanceSpecAssociation.position',
|
|
collection_class=ordering_list('position', count_from=1))
|
|
provider_ptg_id = sa.Column(sa.String(36),
|
|
# FixMe(Magesh) Issue with cascade on Delete
|
|
# sa.ForeignKey('gp_policy_target_groups.id'),
|
|
nullable=True)
|
|
consumer_ptg_id = sa.Column(sa.String(36),
|
|
# sa.ForeignKey('gp_policy_target_groups.id'),
|
|
nullable=True)
|
|
management_ptg_id = sa.Column(sa.String(36),
|
|
# sa.ForeignKey('gp_policy_target_groups.id'),
|
|
nullable=True)
|
|
classifier_id = sa.Column(sa.String(36),
|
|
# sa.ForeignKey('gp_policy_classifiers.id'),
|
|
nullable=True)
|
|
|
|
|
|
class ServiceChainSpec(model_base.BASEV2, BaseSharedSCResource):
|
|
""" ServiceChain Spec
|
|
"""
|
|
__tablename__ = 'sc_specs'
|
|
nodes = orm.relationship(
|
|
SpecNodeAssociation,
|
|
backref='specs', cascade='all, delete, delete-orphan',
|
|
order_by='SpecNodeAssociation.position',
|
|
collection_class=ordering_list('position', count_from=1))
|
|
config_param_names = sa.Column(sa.String(4096))
|
|
instances = orm.relationship(InstanceSpecAssociation,
|
|
backref="specs",
|
|
cascade='all, delete, delete-orphan')
|
|
|
|
|
|
class ServiceProfile(model_base.BASEV2, BaseSharedSCResource):
|
|
""" Service Profile
|
|
"""
|
|
__tablename__ = 'service_profiles'
|
|
vendor = sa.Column(sa.String(50))
|
|
# Not using ENUM for less painful upgrades. Validation will happen at the
|
|
# API level
|
|
insertion_mode = sa.Column(sa.String(50))
|
|
service_type = sa.Column(sa.String(50))
|
|
service_flavor = sa.Column(sa.String(1024))
|
|
nodes = orm.relationship(ServiceChainNode, backref="service_profile")
|
|
|
|
|
|
class ServiceChainDbPlugin(schain.ServiceChainPluginBase):
|
|
"""ServiceChain plugin interface implementation using SQLAlchemy models."""
|
|
|
|
# TODO(osms69): native bulk support
|
|
__native_bulk_support = False
|
|
__native_pagination_support = True
|
|
__native_sorting_support = True
|
|
|
|
def __init__(self, *args, **kwargs):
|
|
super(ServiceChainDbPlugin, self).__init__(*args, **kwargs)
|
|
|
|
@property
|
|
def _grouppolicy_plugin(self):
|
|
# REVISIT(Magesh): Need initialization method after all
|
|
# plugins are loaded to grab and store plugin.
|
|
grouppolicy_plugin = directory.get_plugin(pconst.GROUP_POLICY)
|
|
if not grouppolicy_plugin:
|
|
LOG.error("No Grouppolicy service plugin found.")
|
|
raise s_exc.ServiceChainDeploymentError()
|
|
return grouppolicy_plugin
|
|
|
|
# REVISIT: This is temporary, the correct fix is to use the
|
|
# project_id in the context. Moreover, patch.py already patches
|
|
# thi, so it should not be required here.
|
|
def _get_tenant_id_for_create(self, context, resource):
|
|
if context.is_admin and 'tenant_id' in resource:
|
|
tenant_id = resource['tenant_id']
|
|
return tenant_id
|
|
elif ('tenant_id' in resource and
|
|
resource['tenant_id'] != context.tenant_id):
|
|
reason = _('Cannot create resource for another tenant')
|
|
raise n_exc.AdminRequired(reason=reason)
|
|
else:
|
|
tenant_id = context.tenant_id
|
|
return tenant_id
|
|
|
|
def _get_servicechain_node(self, context, node_id):
|
|
try:
|
|
return db_api.get_by_id(context, ServiceChainNode, node_id)
|
|
except exc.NoResultFound:
|
|
raise schain.ServiceChainNodeNotFound(sc_node_id=node_id)
|
|
|
|
def _get_servicechain_spec(self, context, spec_id):
|
|
try:
|
|
return db_api.get_by_id(context, ServiceChainSpec, spec_id)
|
|
except exc.NoResultFound:
|
|
raise schain.ServiceChainSpecNotFound(sc_spec_id=spec_id)
|
|
|
|
def _get_servicechain_instance(self, context, instance_id):
|
|
try:
|
|
return db_api.get_by_id(context, ServiceChainInstance, instance_id)
|
|
except exc.NoResultFound:
|
|
raise schain.ServiceChainInstanceNotFound(
|
|
sc_instance_id=instance_id)
|
|
|
|
def _get_service_profile(self, context, profile_id):
|
|
try:
|
|
return db_api.get_by_id(context, ServiceProfile, profile_id)
|
|
except exc.NoResultFound:
|
|
raise schain.ServiceProfileNotFound(
|
|
profile_id=profile_id)
|
|
|
|
def _populate_common_fields_in_dict(self, db_ref):
|
|
res = {'id': db_ref['id'],
|
|
'tenant_id': db_ref['tenant_id'],
|
|
'name': db_ref['name'],
|
|
'description': db_ref['description'],
|
|
'status': db_ref['status'],
|
|
'status_details': db_ref['status_details'],
|
|
'shared': db_ref.get('shared', False)}
|
|
return res
|
|
|
|
def _make_sc_node_dict(self, sc_node, fields=None):
|
|
res = self._populate_common_fields_in_dict(sc_node)
|
|
res['service_profile_id'] = sc_node['service_profile_id']
|
|
res['service_type'] = sc_node['service_type']
|
|
res['config'] = sc_node['config']
|
|
res['servicechain_specs'] = [sc_spec['servicechain_spec_id']
|
|
for sc_spec in sc_node['specs']]
|
|
return db_api.resource_fields(res, fields)
|
|
|
|
def _make_sc_spec_dict(self, spec, fields=None):
|
|
res = self._populate_common_fields_in_dict(spec)
|
|
res['config_param_names'] = spec.get('config_param_names')
|
|
res['nodes'] = [sc_node['node_id'] for sc_node in spec['nodes']]
|
|
res['instances'] = [x['servicechain_instance_id'] for x in
|
|
spec['instances']]
|
|
return db_api.resource_fields(res, fields)
|
|
|
|
def _make_sc_instance_dict(self, instance, fields=None):
|
|
res = {'id': instance['id'],
|
|
'tenant_id': instance['tenant_id'],
|
|
'name': instance['name'],
|
|
'description': instance['description'],
|
|
'config_param_values': instance['config_param_values'],
|
|
'provider_ptg_id': instance['provider_ptg_id'],
|
|
'consumer_ptg_id': instance['consumer_ptg_id'],
|
|
'management_ptg_id': instance['management_ptg_id'],
|
|
'classifier_id': instance['classifier_id'],
|
|
'status': instance['status'],
|
|
'status_details': instance['status_details']}
|
|
res['servicechain_specs'] = [sc_spec['servicechain_spec_id']
|
|
for sc_spec in instance['specs']]
|
|
return db_api.resource_fields(res, fields)
|
|
|
|
def _make_service_profile_dict(self, profile, fields=None):
|
|
res = self._populate_common_fields_in_dict(profile)
|
|
res['service_type'] = profile['service_type']
|
|
res['service_flavor'] = profile['service_flavor']
|
|
res['vendor'] = profile['vendor']
|
|
res['insertion_mode'] = profile['insertion_mode']
|
|
res['nodes'] = [node['id'] for node in profile['nodes']]
|
|
return db_api.resource_fields(res, fields)
|
|
|
|
@staticmethod
|
|
def validate_service_type(service_type):
|
|
if service_type not in schain.sc_supported_type:
|
|
raise schain.ServiceTypeNotSupported(sc_service_type=service_type)
|
|
|
|
@log.log_method_call
|
|
def create_servicechain_node(self, context, servicechain_node):
|
|
node = servicechain_node['servicechain_node']
|
|
tenant_id = self._get_tenant_id_for_create(context, node)
|
|
with db_api.CONTEXT_WRITER.using(context):
|
|
node_db = ServiceChainNode(
|
|
id=uuidutils.generate_uuid(), tenant_id=tenant_id,
|
|
name=node['name'], description=node['description'],
|
|
service_profile_id=node.get('service_profile_id'),
|
|
service_type=node.get('service_type'),
|
|
config=node['config'], shared=node['shared'],
|
|
status=node.get('status'),
|
|
status_details=node.get('status_details'))
|
|
context.session.add(node_db)
|
|
return self._make_sc_node_dict(node_db)
|
|
|
|
@log.log_method_call
|
|
def update_servicechain_node(self, context, servicechain_node_id,
|
|
servicechain_node, set_params=False):
|
|
node = servicechain_node['servicechain_node']
|
|
with db_api.CONTEXT_WRITER.using(context):
|
|
node_db = self._get_servicechain_node(context,
|
|
servicechain_node_id)
|
|
node_db.update(node)
|
|
# Update the config param names derived for the associated specs
|
|
spec_node_associations = node_db.specs
|
|
for node_spec in spec_node_associations:
|
|
spec_id = node_spec.servicechain_spec_id
|
|
spec_db = self._get_servicechain_spec(context, spec_id)
|
|
self._process_nodes_for_spec(
|
|
context, spec_db, self._make_sc_spec_dict(spec_db),
|
|
set_params=set_params)
|
|
return self._make_sc_node_dict(node_db)
|
|
|
|
@log.log_method_call
|
|
def delete_servicechain_node(self, context, servicechain_node_id):
|
|
with db_api.CONTEXT_WRITER.using(context):
|
|
node_db = self._get_servicechain_node(context,
|
|
servicechain_node_id)
|
|
if node_db.specs:
|
|
raise schain.ServiceChainNodeInUse(
|
|
node_id=servicechain_node_id)
|
|
context.session.delete(node_db)
|
|
|
|
@log.log_method_call
|
|
def get_servicechain_node(self, context, servicechain_node_id,
|
|
fields=None):
|
|
node = self._get_servicechain_node(context, servicechain_node_id)
|
|
return self._make_sc_node_dict(node, fields)
|
|
|
|
@log.log_method_call
|
|
def get_servicechain_nodes(self, context, filters=None, fields=None,
|
|
sorts=None, limit=None, marker=None,
|
|
page_reverse=False):
|
|
plugin = directory.get_plugin()
|
|
marker_obj = db_api.get_marker_obj(plugin, context,
|
|
'servicechain_node', limit,
|
|
marker)
|
|
return db_api.get_collection(context, ServiceChainNode,
|
|
self._make_sc_node_dict,
|
|
filters=filters, fields=fields,
|
|
sorts=sorts, limit=limit,
|
|
marker_obj=marker_obj,
|
|
page_reverse=page_reverse)
|
|
|
|
@log.log_method_call
|
|
def get_servicechain_nodes_count(self, context, filters=None):
|
|
return db_api.get_collection_count(context, ServiceChainNode,
|
|
filters=filters)
|
|
|
|
def _process_nodes_for_spec(self, context, spec_db, spec,
|
|
set_params=True):
|
|
if 'nodes' in spec:
|
|
self._set_nodes_for_spec(context, spec_db, spec['nodes'],
|
|
set_params=set_params)
|
|
del spec['nodes']
|
|
return spec
|
|
|
|
def _set_nodes_for_spec(self, context, spec_db, nodes_id_list,
|
|
set_params=True):
|
|
if not nodes_id_list:
|
|
spec_db.nodes = []
|
|
spec_db.config_param_names = '[]'
|
|
return
|
|
with context.session.begin(subtransactions=True):
|
|
# We will first check if the new list of nodes is valid
|
|
filters = {'id': [n_id for n_id in nodes_id_list]}
|
|
nodes_in_db = db_api.get_collection_query(context,
|
|
ServiceChainNode,
|
|
filters=filters)
|
|
nodes_list = [n_db['id'] for n_db in nodes_in_db]
|
|
for node_id in nodes_id_list:
|
|
if node_id not in nodes_list:
|
|
# If we find an invalid node id in the list we
|
|
# do not perform the update
|
|
raise schain.ServiceChainNodeNotFound(sc_node_id=node_id)
|
|
# New list of nodes is valid so we will first reset the
|
|
# existing list and then add each node in order.
|
|
# Note that the list could be empty in which case we interpret
|
|
# it as clearing existing nodes.
|
|
spec_db.nodes = []
|
|
if set_params:
|
|
spec_db.config_param_names = '[]'
|
|
for node_id in nodes_id_list:
|
|
if set_params:
|
|
sc_node = self.get_servicechain_node(context, node_id)
|
|
node_dict = jsonutils.loads(sc_node['config'])
|
|
config_params = (node_dict.get('parameters') or
|
|
node_dict.get('Parameters'))
|
|
if config_params:
|
|
if not spec_db.config_param_names:
|
|
spec_db.config_param_names = str(
|
|
list(config_params.keys()))
|
|
else:
|
|
config_param_names = ast.literal_eval(
|
|
spec_db.config_param_names)
|
|
config_param_names.extend(
|
|
list(config_params.keys()))
|
|
spec_db.config_param_names = str(
|
|
config_param_names)
|
|
|
|
assoc = SpecNodeAssociation(servicechain_spec_id=spec_db.id,
|
|
node_id=node_id)
|
|
spec_db.nodes.append(assoc)
|
|
|
|
def _process_specs_for_instance(self, context, instance_db, instance):
|
|
if 'servicechain_specs' in instance:
|
|
self._set_specs_for_instance(context, instance_db,
|
|
instance['servicechain_specs'])
|
|
del instance['servicechain_specs']
|
|
return instance
|
|
|
|
def _set_specs_for_instance(self, context, instance_db, spec_id_list):
|
|
if not spec_id_list:
|
|
instance_db.spec_ids = []
|
|
return
|
|
with context.session.begin(subtransactions=True):
|
|
filters = {'id': spec_id_list}
|
|
specs_in_db = db_api.get_collection_query(context,
|
|
ServiceChainSpec,
|
|
filters=filters)
|
|
specs_list = set(spec_db['id'] for spec_db in specs_in_db)
|
|
for spec_id in spec_id_list:
|
|
if spec_id not in specs_list:
|
|
# Do not update if spec ID is invalid
|
|
raise schain.ServiceChainSpecNotFound(sc_spec_id=spec_id)
|
|
# Reset the existing list and then add each spec in order. The list
|
|
# could be empty in which case we clear the existing specs.
|
|
instance_db.specs = []
|
|
for spec_id in spec_id_list:
|
|
assoc = InstanceSpecAssociation(
|
|
servicechain_instance_id=instance_db.id,
|
|
servicechain_spec_id=spec_id)
|
|
instance_db.specs.append(assoc)
|
|
|
|
def _get_instances_from_policy_target(self, context, policy_target):
|
|
with context.session.begin(subtransactions=True):
|
|
ptg_id = policy_target['policy_target_group_id']
|
|
scis_p = self.get_servicechain_instances(
|
|
context, {'provider_ptg_id': [ptg_id]})
|
|
scis_c = self.get_servicechain_instances(
|
|
context, {'consumer_ptg_id': [ptg_id]})
|
|
# Don't return duplicates
|
|
result = []
|
|
seen = set()
|
|
for sci in scis_p + scis_c:
|
|
if sci['id'] not in seen:
|
|
seen.add(sci['id'])
|
|
result.append(sci)
|
|
return result
|
|
|
|
@log.log_method_call
|
|
def create_servicechain_spec(self, context, servicechain_spec,
|
|
set_params=True):
|
|
spec = servicechain_spec['servicechain_spec']
|
|
tenant_id = self._get_tenant_id_for_create(context, spec)
|
|
with db_api.CONTEXT_WRITER.using(context):
|
|
spec_db = ServiceChainSpec(
|
|
id=uuidutils.generate_uuid(),
|
|
tenant_id=tenant_id,
|
|
name=spec['name'],
|
|
description=spec['description'],
|
|
shared=spec['shared'],
|
|
status=spec.get('status'),
|
|
status_details=spec.get('status_details'))
|
|
self._process_nodes_for_spec(context, spec_db, spec,
|
|
set_params=set_params)
|
|
context.session.add(spec_db)
|
|
return self._make_sc_spec_dict(spec_db)
|
|
|
|
@log.log_method_call
|
|
def update_servicechain_spec(self, context, spec_id,
|
|
servicechain_spec, set_params=True):
|
|
spec = servicechain_spec['servicechain_spec']
|
|
with db_api.CONTEXT_WRITER.using(context):
|
|
spec_db = self._get_servicechain_spec(context,
|
|
spec_id)
|
|
spec = self._process_nodes_for_spec(context, spec_db, spec,
|
|
set_params=set_params)
|
|
spec_db.update(spec)
|
|
return self._make_sc_spec_dict(spec_db)
|
|
|
|
@log.log_method_call
|
|
def delete_servicechain_spec(self, context, spec_id):
|
|
policy_actions = self._grouppolicy_plugin.get_policy_actions(
|
|
context, filters={"action_value": [spec_id]})
|
|
if policy_actions:
|
|
raise schain.ServiceChainSpecInUse(spec_id=spec_id)
|
|
with db_api.CONTEXT_WRITER.using(context):
|
|
spec_db = self._get_servicechain_spec(context,
|
|
spec_id)
|
|
if spec_db.instances:
|
|
raise schain.ServiceChainSpecInUse(spec_id=spec_id)
|
|
context.session.delete(spec_db)
|
|
|
|
@log.log_method_call
|
|
def get_servicechain_spec(self, context, spec_id,
|
|
fields=None):
|
|
spec = self._get_servicechain_spec(context, spec_id)
|
|
return self._make_sc_spec_dict(spec, fields)
|
|
|
|
@log.log_method_call
|
|
def get_servicechain_specs(self, context, filters=None, fields=None,
|
|
sorts=None, limit=None, marker=None,
|
|
page_reverse=False):
|
|
plugin = directory.get_plugin()
|
|
marker_obj = db_api.get_marker_obj(plugin, context,
|
|
'servicechain_spec', limit,
|
|
marker)
|
|
return db_api.get_collection(context, ServiceChainSpec,
|
|
self._make_sc_spec_dict,
|
|
filters=filters, fields=fields,
|
|
sorts=sorts, limit=limit,
|
|
marker_obj=marker_obj,
|
|
page_reverse=page_reverse)
|
|
|
|
@log.log_method_call
|
|
def get_servicechain_specs_count(self, context, filters=None):
|
|
return db_api.get_collection_count(context, ServiceChainSpec,
|
|
filters=filters)
|
|
|
|
@log.log_method_call
|
|
def create_servicechain_instance(self, context, servicechain_instance):
|
|
instance = servicechain_instance['servicechain_instance']
|
|
tenant_id = self._get_tenant_id_for_create(context, instance)
|
|
with db_api.CONTEXT_WRITER.using(context):
|
|
if not instance.get('management_ptg_id'):
|
|
management_groups = (
|
|
self._grouppolicy_plugin.get_policy_target_groups(
|
|
context, {'service_management': [True],
|
|
'tenant_id': [instance.get('tenant_id')]}))
|
|
if not management_groups:
|
|
# Fall back on shared service management
|
|
management_groups = (
|
|
self._grouppolicy_plugin.get_policy_target_groups(
|
|
context, {'service_management': [True]}))
|
|
if management_groups:
|
|
instance['management_ptg_id'] = management_groups[0]['id']
|
|
instance_db = ServiceChainInstance(
|
|
id=uuidutils.generate_uuid(),
|
|
tenant_id=tenant_id, name=instance['name'],
|
|
description=instance['description'],
|
|
config_param_values=instance['config_param_values'],
|
|
provider_ptg_id=instance.get('provider_ptg_id'),
|
|
consumer_ptg_id=instance.get('consumer_ptg_id'),
|
|
management_ptg_id=instance.get('management_ptg_id'),
|
|
classifier_id=instance.get('classifier_id'),
|
|
status=instance.get('status'),
|
|
status_details=instance.get('status_details'))
|
|
self._process_specs_for_instance(context, instance_db, instance)
|
|
context.session.add(instance_db)
|
|
return self._make_sc_instance_dict(instance_db)
|
|
|
|
@log.log_method_call
|
|
def update_servicechain_instance(self, context, servicechain_instance_id,
|
|
servicechain_instance):
|
|
instance = servicechain_instance['servicechain_instance']
|
|
with db_api.CONTEXT_WRITER.using(context):
|
|
instance_db = self._get_servicechain_instance(
|
|
context, servicechain_instance_id)
|
|
instance = self._process_specs_for_instance(context, instance_db,
|
|
instance)
|
|
instance_db.update(instance)
|
|
return self._make_sc_instance_dict(instance_db)
|
|
|
|
@log.log_method_call
|
|
def delete_servicechain_instance(self, context, servicechain_instance_id):
|
|
with db_api.CONTEXT_WRITER.using(context):
|
|
instance_db = self._get_servicechain_instance(
|
|
context, servicechain_instance_id)
|
|
context.session.delete(instance_db)
|
|
|
|
@log.log_method_call
|
|
def get_servicechain_instance(self, context, sc_instance_id, fields=None):
|
|
instance_db = self._get_servicechain_instance(context, sc_instance_id)
|
|
return self._make_sc_instance_dict(instance_db, fields)
|
|
|
|
@log.log_method_call
|
|
def get_servicechain_instances(self, context, filters=None, fields=None,
|
|
sorts=None, limit=None, marker=None,
|
|
page_reverse=False):
|
|
plugin = directory.get_plugin()
|
|
marker_obj = db_api.get_marker_obj(plugin, context,
|
|
'servicechain_instance',
|
|
limit, marker)
|
|
return db_api.get_collection(context, ServiceChainInstance,
|
|
self._make_sc_instance_dict,
|
|
filters=filters, fields=fields,
|
|
sorts=sorts, limit=limit,
|
|
marker_obj=marker_obj,
|
|
page_reverse=page_reverse)
|
|
|
|
@log.log_method_call
|
|
def get_servicechain_instances_count(self, context, filters=None):
|
|
return db_api.get_collection_count(context, ServiceChainInstance,
|
|
filters=filters)
|
|
|
|
@log.log_method_call
|
|
def get_service_profiles_count(self, context, filters=None):
|
|
return db_api.get_collection_count(context, ServiceProfile,
|
|
filters=filters)
|
|
|
|
@log.log_method_call
|
|
def create_service_profile(self, context, service_profile):
|
|
profile = service_profile['service_profile']
|
|
tenant_id = self._get_tenant_id_for_create(context, profile)
|
|
with db_api.CONTEXT_WRITER.using(context):
|
|
profile_db = ServiceProfile(
|
|
id=uuidutils.generate_uuid(), tenant_id=tenant_id,
|
|
name=profile['name'], description=profile['description'],
|
|
service_type=profile.get('service_type'),
|
|
insertion_mode=profile.get('insertion_mode'),
|
|
vendor=profile.get('vendor'),
|
|
service_flavor=profile.get('service_flavor'),
|
|
shared=profile.get('shared'),
|
|
status=profile.get('status'),
|
|
status_details=profile.get('status_details'))
|
|
context.session.add(profile_db)
|
|
return self._make_service_profile_dict(profile_db)
|
|
|
|
@log.log_method_call
|
|
def update_service_profile(self, context, service_profile_id,
|
|
service_profile):
|
|
profile = service_profile['service_profile']
|
|
with db_api.CONTEXT_WRITER.using(context):
|
|
profile_db = self._get_service_profile(context,
|
|
service_profile_id)
|
|
profile_db.update(profile)
|
|
return self._make_service_profile_dict(profile_db)
|
|
|
|
@log.log_method_call
|
|
def delete_service_profile(self, context, service_profile_id):
|
|
with db_api.CONTEXT_WRITER.using(context):
|
|
profile_db = self._get_service_profile(context,
|
|
service_profile_id)
|
|
if profile_db.nodes:
|
|
raise schain.ServiceProfileInUse(
|
|
profile_id=service_profile_id)
|
|
context.session.delete(profile_db)
|
|
|
|
@log.log_method_call
|
|
def get_service_profile(self, context, service_profile_id, fields=None):
|
|
profile_db = self._get_service_profile(
|
|
context, service_profile_id)
|
|
return self._make_service_profile_dict(profile_db, fields)
|
|
|
|
@log.log_method_call
|
|
def get_service_profiles(self, context, filters=None, fields=None,
|
|
sorts=None, limit=None, marker=None,
|
|
page_reverse=False):
|
|
plugin = directory.get_plugin()
|
|
marker_obj = db_api.get_marker_obj(plugin, context,
|
|
'service_profile',
|
|
limit, marker)
|
|
return db_api.get_collection(context, ServiceProfile,
|
|
self._make_service_profile_dict,
|
|
filters=filters, fields=fields,
|
|
sorts=sorts, limit=limit,
|
|
marker_obj=marker_obj,
|
|
page_reverse=page_reverse)
|