chain agnostic node plumber

This plumber simply provides chain drivers with the
Service Targets they requested for, without making
any modification depending on the rest of the chain.

Partially implements blueprint node-centric-chain-plugin

Change-Id: I9030b4b43f87dc250e263eeaf58576f1b5bef40a
This commit is contained in:
Ivar Lazzaro
2015-05-11 00:44:19 -07:00
parent 7f90fa8c90
commit 47d7f0a118
9 changed files with 289 additions and 22 deletions

View File

@@ -21,7 +21,7 @@ service_chain_opts = [
"gbpservice.neutron.servicechain.ncp_drivers "
"namespace.")),
cfg.StrOpt('node_plumber',
default='dummy_plumber',
default='agnostic_plumber',
help=_("The plumber used by the Node Composition Plugin "
"for service plumbing. Entrypoint loaded from the "
"gbpservice.neutron.servicechain.ncp_plumbers "

View File

@@ -25,6 +25,11 @@ class NodeCompositionPluginException(exceptions.NeutronException):
pass
class PlumbingException(exceptions.NeutronException):
"""Base for node driver exceptions returned to user."""
pass
class NodeCompositionPluginBadRequest(exceptions.BadRequest,
NodeCompositionPluginException):
"""Base for node driver bad request exceptions returned to user."""
@@ -45,4 +50,10 @@ class NoDriverAvailableForAction(NodeCompositionPluginBadRequest):
class ServiceProfileInUseByAnInstance(NodeCompositionPluginBadRequest):
message = _("Cannot update Service Profile %(profile_id)s because it's "
"used by servicechain instance %(instance_id)s.")
"used by servicechain instance %(instance_id)s.")
class NotAvailablePTGForTargetRequest(PlumbingException):
message = _("PTG of type %(ptg_type)s doesn't exist for service chain "
"instance %(instance)s. However, it is required by the "
"scheduled Node Driver in order to deploy Node %(node)s")

View File

@@ -105,17 +105,41 @@ def get_service_targets(session, policy_target_id=None, relationship=None,
servicechain_instance_id=None, position=None,
servicechain_node_id=None):
with session.begin(subtransactions=True):
query = session.query(ServiceTarget)
if servicechain_instance_id:
query = query.filter_by(
servicechain_instance_id=servicechain_instance_id)
if servicechain_node_id:
query = query.filter_by(
servicechain_node_id=servicechain_node_id)
if policy_target_id:
query = query.filter_by(policy_target_id=policy_target_id)
if position:
query = query.filter_by(position=position)
if relationship:
query = query.filter_by(relationship=relationship)
query = _prepare_service_target_query(
session, policy_target_id=policy_target_id,
relationship=relationship,
servicechain_instance_id=servicechain_instance_id,
position=position, servicechain_node_id=servicechain_node_id)
return query.all()
def get_service_targets_count(session, policy_target_id=None,
relationship=None, servicechain_instance_id=None,
position=None, servicechain_node_id=None):
with session.begin(subtransactions=True):
query = _prepare_service_target_query(
session, policy_target_id=policy_target_id,
relationship=relationship,
servicechain_instance_id=servicechain_instance_id,
position=position, servicechain_node_id=servicechain_node_id)
return query.count()
def _prepare_service_target_query(session, policy_target_id=None,
relationship=None,
servicechain_instance_id=None, position=None,
servicechain_node_id=None):
query = session.query(ServiceTarget)
if servicechain_instance_id:
query = query.filter_by(
servicechain_instance_id=servicechain_instance_id)
if servicechain_node_id:
query = query.filter_by(
servicechain_node_id=servicechain_node_id)
if policy_target_id:
query = query.filter_by(policy_target_id=policy_target_id)
if position:
query = query.filter_by(position=position)
if relationship:
query = query.filter_by(relationship=relationship)
return query

View File

@@ -0,0 +1,38 @@
# 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.common import log
from gbpservice.neutron.services.servicechain.plugins.ncp import plumber_base
class ChainAgnosticPlumber(plumber_base.NodePlumberBase):
""" Chain Agnostic Plumber.
This plumber simply provides node drivers with the Service Targets
they requested for, without making any modification depending on the
rest of the chain.
"""
@log.log
def initialize(self):
pass
@log.log
def plug_services(self, context, deployment):
for part in deployment:
self._create_service_targets(context, part)
@log.log
def unplug_services(self, context, deployment):
for part in deployment:
self._delete_service_targets(context, part)

View File

@@ -13,6 +13,15 @@
import abc
import six
from oslo_log import log as logging
from gbpservice.neutron.extensions import group_policy
from gbpservice.neutron.services.servicechain.plugins.ncp import exceptions
from gbpservice.neutron.services.servicechain.plugins.ncp import model
TARGET_DESCRIPTION = "%s facing Service Target for node %s in instance %s"
LOG = logging.getLogger(__name__)
@six.add_metaclass(abc.ABCMeta)
class NodePlumberBase(object):
@@ -74,5 +83,59 @@ class NodePlumberBase(object):
node_context.current_position
"""
def _create_service_targets(self, context, part):
info = part['plumbing_info']
if not info:
return
part_context = part['context']
provider = part_context.provider
consumer = part_context.consumer
management = part_context.management
self._create_service_target(context, part_context,
info.get('provider', []),
provider, 'provider')
self._create_service_target(context, part_context,
info.get('consumer', []),
consumer, 'consumer')
self._create_service_target(context, part_context,
info.get('management', []),
management, 'management')
def _delete_service_targets(self, context, part):
part_context = part['context']
node = part_context.current_node
instance = part_context.instance
gbp_plugin = part_context.gbp_plugin
pts = model.get_service_targets(
context.session, servicechain_instance_id=instance['id'],
servicechain_node_id=node['id'])
for pt in pts:
try:
gbp_plugin.delete_policy_target(context, pt.policy_target_id)
except group_policy.PolicyTargetNotFound as ex:
LOG.debug(ex.message)
def _create_service_target(self, context, part_context, targets, group,
relationship):
instance = part_context.instance
node = part_context.current_node
gbp_plugin = part_context.gbp_plugin
for target in targets:
if not group:
exceptions.NotAvailablePTGForTargetRequest(
ptg_type=relationship, instance=instance['id'],
node=node['id'])
data = {'policy_target_group_id': group['id'],
'description': TARGET_DESCRIPTION % (relationship,
node['id'],
instance['id']),
'name': '', 'port_id': None}
data.update(target)
pt = gbp_plugin.create_policy_target(context,
{'policy_target': data})
model.set_service_target(part_context, pt['id'], relationship)
def _sort_deployment(self, deployment):
deployment.sort(key=lambda x: x['context'].current_position)