Merge "Prevent deletion of in use ServiceChain Resources"

This commit is contained in:
Jenkins 2015-02-09 20:10:34 +00:00 committed by Gerrit Code Review
commit fc4daaf5d0
3 changed files with 90 additions and 2 deletions

View File

@ -20,11 +20,14 @@ from neutron.common import log
from neutron.db import common_db_mixin
from neutron.db import model_base
from neutron.db import models_v2
from neutron import manager
from neutron.openstack.common import jsonutils
from neutron.openstack.common import log as logging
from neutron.openstack.common import uuidutils
from neutron.plugins.common import constants as pconst
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
@ -121,6 +124,17 @@ class ServiceChainDbPlugin(schain.ServiceChainPluginBase,
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.
plugins = manager.NeutronManager.get_service_plugins()
grouppolicy_plugin = plugins.get(pconst.GROUP_POLICY)
if not grouppolicy_plugin:
LOG.error(_("No Grouppolicy service plugin found."))
raise s_exc.ServiceChainDeploymentError()
return grouppolicy_plugin
def _get_servicechain_node(self, context, node_id):
try:
return self._get_by_id(context, ServiceChainNode, node_id)
@ -205,6 +219,9 @@ class ServiceChainDbPlugin(schain.ServiceChainPluginBase,
with context.session.begin(subtransactions=True):
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
@ -331,9 +348,15 @@ class ServiceChainDbPlugin(schain.ServiceChainPluginBase,
@log.log
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 context.session.begin(subtransactions=True):
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

View File

@ -49,6 +49,16 @@ class ServiceChainInstanceNotFound(nexc.NotFound):
message = _("ServiceChainInstance %(sc_instance_id)s could not be found")
class ServiceChainNodeInUse(nexc.InUse):
message = _("Unable to complete operation, ServiceChainNode "
"%(node_id)s is in use")
class ServiceChainSpecInUse(nexc.InUse):
message = _("Unable to complete operation, ServiceChainSpec "
"%(spec_id)s is in use")
class ServiceTypeNotFound(nexc.NotFound):
message = _("ServiceType %(service_type_id) could not be found")

View File

@ -206,6 +206,9 @@ class ServiceChainDBTestPlugin(svcchain_db.ServiceChainDbPlugin):
DB_GP_PLUGIN_KLASS = (ServiceChainDBTestPlugin.__module__ + '.' +
ServiceChainDBTestPlugin.__name__)
GP_PLUGIN_KLASS = (
"gbpservice.neutron.services.grouppolicy.plugin.GroupPolicyPlugin")
class ServiceChainDbTestCase(ServiceChainDBTestBase,
test_db_plugin.NeutronDbPluginV2TestCase):
@ -218,7 +221,8 @@ class ServiceChainDbTestCase(ServiceChainDBTestBase,
sc_plugin = DB_GP_PLUGIN_KLASS
self.plugin = importutils.import_object(sc_plugin)
if not service_plugins:
service_plugins = {'sc_plugin_name': sc_plugin}
service_plugins = {'gp_plugin_name': GP_PLUGIN_KLASS,
'sc_plugin_name': sc_plugin}
super(ServiceChainDbTestCase, self).setUp(
plugin=core_plugin, ext_mgr=ext_mgr,
@ -290,9 +294,20 @@ class TestServiceChainResources(ServiceChainDbTestCase):
scn = self.create_servicechain_node()
scn_id = scn['servicechain_node']['id']
scs = self.create_servicechain_spec(nodes=[scn_id])
scs_id = scs['servicechain_spec']['id']
# Deleting Service Chain Node in use by a Spec should fail
self.assertRaises(service_chain.ServiceChainNodeInUse,
self.plugin.delete_servicechain_node, ctx, scn_id)
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)
# 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.assertRaises(service_chain.ServiceChainNodeNotFound,
self.plugin.get_servicechain_node,
@ -394,6 +409,46 @@ class TestServiceChainResources(ServiceChainDbTestCase):
self.assertRaises(service_chain.ServiceChainSpecNotFound,
self.plugin.get_servicechain_spec, ctx, scs_id)
def test_delete_spec_in_use_by_policy_action_rejected(self):
ctx = context.get_admin_context()
scs_id = self.create_servicechain_spec()['servicechain_spec']['id']
data = {'policy_action': {'action_type': 'redirect',
'tenant_id': self._tenant_id,
'action_value': scs_id}}
pa_req = self.new_create_request('grouppolicy/policy_actions',
data, self.fmt)
res = pa_req.get_response(self.ext_api)
if res.status_int >= webob.exc.HTTPClientError.code:
raise webob.exc.HTTPClientError(code=res.status_int)
self.assertRaises(service_chain.ServiceChainSpecInUse,
self.plugin.delete_servicechain_spec, ctx, scs_id)
def test_delete_spec_in_use_by_instance_rejected(self):
ctx = context.get_admin_context()
scs_id = self.create_servicechain_spec()['servicechain_spec']['id']
sci = self.create_servicechain_instance(servicechain_specs=[scs_id])
sci_id = sci['servicechain_instance']['id']
# Deleting the Spec used by Instance should not be allowed
self.assertRaises(service_chain.ServiceChainSpecInUse,
self.plugin.delete_servicechain_spec, ctx, scs_id)
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.assertRaises(service_chain.ServiceChainInstanceNotFound,
self.plugin.get_servicechain_instance,
ctx, sci_id)
# Deleting the spec should succeed after the instance is deleted
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.assertRaises(service_chain.ServiceChainSpecNotFound,
self.plugin.get_servicechain_spec, ctx, scs_id)
def test_create_and_show_servicechain_instance(self):
scs_id = self.create_servicechain_spec()['servicechain_spec']['id']
policy_target_group_id = uuidutils.generate_uuid()