by pass to run workflow if there is no tasks at all
When system errors, for example, we failed to create the member vnf of a ns, the workflow tasks to delete the ns will be empty. This patch is to deal with this error situation. in this case, the workflow execution is passed by, and the NS object is deleted. Change-Id: Ib714ab0dcc38859314239facc3f18bfcc18c0682 Closes-bug: 1670921
This commit is contained in:
parent
8d6d76ff98
commit
e22bb960f1
|
@ -309,7 +309,7 @@ class NSPluginDb(network_service.NSPluginBase, db_base.CommonDbMixin):
|
|||
self._model_query(context, NS).
|
||||
filter(NS.id == ns_id).
|
||||
filter(NS.status == constants.PENDING_DELETE))
|
||||
if mistral_obj.state == 'ERROR':
|
||||
if mistral_obj and mistral_obj.state == 'ERROR':
|
||||
query.update({'status': constants.ERROR})
|
||||
self._cos_db_plg.create_event(
|
||||
context, res_id=ns_id,
|
||||
|
|
|
@ -221,6 +221,11 @@ class NSDInUse(exceptions.InUse):
|
|||
class NSInUse(exceptions.InUse):
|
||||
message = _('NS %(ns_id)s is still in use')
|
||||
|
||||
|
||||
class NoTasksException(exceptions.TackerException):
|
||||
message = _('No tasks to run for %(action)s on %(resource)s')
|
||||
|
||||
|
||||
RESOURCE_ATTRIBUTE_MAP = {
|
||||
|
||||
'vims': {
|
||||
|
|
|
@ -485,6 +485,8 @@ class OpenStack_Driver(abstract_vim_driver.VimAbstractDriver,
|
|||
mistral_client = self.get_mistral_client(auth_dict)
|
||||
wg = workflow_generator.WorkflowGenerator(resource, action)
|
||||
wg.task(**kwargs)
|
||||
if not wg.get_tasks():
|
||||
raise nfvo.NoTasksException(resource=resource, action=action)
|
||||
definition_yaml = yaml.safe_dump(wg.definition)
|
||||
workflow = mistral_client.workflows.create(definition_yaml)
|
||||
return {'id': workflow[0].id, 'input': wg.get_input_dict()}
|
||||
|
|
|
@ -55,6 +55,9 @@ class WorkflowGenerator(object):
|
|||
def _get_description(self):
|
||||
pass
|
||||
|
||||
def get_tasks(self):
|
||||
return self.definition[self.wf_identifier]['tasks']
|
||||
|
||||
def _add_create_vnf_tasks(self, ns):
|
||||
vnfds = ns['vnfd_details']
|
||||
task_dict = dict()
|
||||
|
|
|
@ -582,12 +582,15 @@ class NfvoPlugin(nfvo_db.NfvoPluginDb, vnffg_db.VnffgPluginDbMixin,
|
|||
ns['vnfd_details'] = vnfd_dict
|
||||
# Step-3
|
||||
kwargs = {'ns': ns, 'params': param_values}
|
||||
workflow = self._vim_drivers.invoke(driver_type,
|
||||
'prepare_and_create_workflow',
|
||||
resource='vnf',
|
||||
action='create',
|
||||
auth_dict=self.get_auth_dict(context),
|
||||
kwargs=kwargs)
|
||||
|
||||
# NOTE NoTasksException is raised if no tasks.
|
||||
workflow = self._vim_drivers.invoke(
|
||||
driver_type,
|
||||
'prepare_and_create_workflow',
|
||||
resource='vnf',
|
||||
action='create',
|
||||
auth_dict=self.get_auth_dict(context),
|
||||
kwargs=kwargs)
|
||||
try:
|
||||
mistral_execution = self._vim_drivers.invoke(
|
||||
driver_type,
|
||||
|
@ -674,26 +677,32 @@ class NfvoPlugin(nfvo_db.NfvoPluginDb, vnffg_db.VnffgPluginDbMixin,
|
|||
ns = super(NfvoPlugin, self).get_ns(context, ns_id)
|
||||
vim_res = self.vim_client.get_vim(context, ns['vim_id'])
|
||||
driver_type = vim_res['vim_type']
|
||||
workflow = self._vim_drivers.invoke(driver_type,
|
||||
'prepare_and_create_workflow',
|
||||
resource='vnf',
|
||||
action='delete',
|
||||
auth_dict=self.get_auth_dict(context),
|
||||
kwargs={'ns': ns})
|
||||
workflow = None
|
||||
try:
|
||||
mistral_execution = self._vim_drivers.invoke(
|
||||
driver_type,
|
||||
'execute_workflow',
|
||||
workflow=workflow,
|
||||
auth_dict=self.get_auth_dict(context))
|
||||
except Exception as ex:
|
||||
LOG.error(_('Error while executing workflow: %s'), ex)
|
||||
self._vim_drivers.invoke(driver_type,
|
||||
'delete_workflow',
|
||||
workflow_id=workflow['id'],
|
||||
auth_dict=self.get_auth_dict(context))
|
||||
workflow = self._vim_drivers.invoke(driver_type,
|
||||
'prepare_and_create_workflow',
|
||||
resource='vnf',
|
||||
action='delete',
|
||||
auth_dict=self.get_auth_dict(context),
|
||||
kwargs={'ns': ns})
|
||||
except nfvo.NoTasksException:
|
||||
LOG.warning(_("No VNF deletion task(s)."))
|
||||
if workflow:
|
||||
try:
|
||||
mistral_execution = self._vim_drivers.invoke(
|
||||
driver_type,
|
||||
'execute_workflow',
|
||||
workflow=workflow,
|
||||
auth_dict=self.get_auth_dict(context))
|
||||
|
||||
raise ex
|
||||
except Exception as ex:
|
||||
LOG.error(_('Error while executing workflow: %s'), ex)
|
||||
self._vim_drivers.invoke(driver_type,
|
||||
'delete_workflow',
|
||||
workflow_id=workflow['id'],
|
||||
auth_dict=self.get_auth_dict(context))
|
||||
|
||||
raise ex
|
||||
super(NfvoPlugin, self).delete_ns(context, ns_id)
|
||||
|
||||
def _delete_ns_wait(ns_id, execution_id):
|
||||
|
@ -731,5 +740,9 @@ class NfvoPlugin(nfvo_db.NfvoPluginDb, vnffg_db.VnffgPluginDbMixin,
|
|||
auth_dict=self.get_auth_dict(context))
|
||||
super(NfvoPlugin, self).delete_ns_post(context, ns_id, exec_obj,
|
||||
error_reason)
|
||||
self.spawn_n(_delete_ns_wait, ns['id'], mistral_execution.id)
|
||||
if workflow:
|
||||
self.spawn_n(_delete_ns_wait, ns['id'], mistral_execution.id)
|
||||
else:
|
||||
super(NfvoPlugin, self).delete_ns_post(
|
||||
context, ns_id, None, None)
|
||||
return ns['id']
|
||||
|
|
|
@ -18,6 +18,9 @@ import os
|
|||
import yaml
|
||||
|
||||
|
||||
DUMMY_NS_2_NAME = 'dummy_ns_2'
|
||||
|
||||
|
||||
def _get_template(name):
|
||||
filename = os.path.join(
|
||||
os.path.dirname(os.path.abspath(__file__)),
|
||||
|
@ -213,3 +216,15 @@ def get_dummy_ns_obj():
|
|||
'attributes': {
|
||||
'param_values': {'nsd': {'vl1_name': 'net_mgmt',
|
||||
'vl2_name': 'net0'}}}}}
|
||||
|
||||
|
||||
def get_dummy_ns_obj_2():
|
||||
return {'ns': {'description': 'dummy_ns_description',
|
||||
'id': u'ba6bf017-f6f7-45f1-a280-57b073bf78ea',
|
||||
'nsd_id': u'eb094833-995e-49f0-a047-dfb56aaf7c4e',
|
||||
'vim_id': u'6261579e-d6f3-49ad-8bc3-a9cb974778ff',
|
||||
'tenant_id': u'ad7ebc56538745a08ef7c5e97f8bd437',
|
||||
'name': DUMMY_NS_2_NAME,
|
||||
'attributes': {
|
||||
'param_values': {'nsd': {'vl1_name': 'net_mgmt',
|
||||
'vl2_name': 'net0'}}}}}
|
||||
|
|
|
@ -37,6 +37,7 @@ from tacker.tests.unit.db import utils
|
|||
from tacker.vnfm import vim_client
|
||||
|
||||
SECRET_PASSWORD = '***'
|
||||
DUMMY_NS_2 = 'ba6bf017-f6f7-45f1-a280-57b073bf78ef'
|
||||
|
||||
|
||||
def dummy_get_vim(*args, **kwargs):
|
||||
|
@ -63,6 +64,14 @@ class FakeDriverManager(mock.Mock):
|
|||
mock_execution.id.return_value = \
|
||||
"ba6bf017-f6f7-45f1-a280-57b073bf78ea"
|
||||
return mock_execution
|
||||
elif ('prepare_and_create_workflow' in args and
|
||||
'delete' == kwargs['action'] and
|
||||
DUMMY_NS_2 == kwargs['kwargs']['ns']['id']):
|
||||
raise nfvo.NoTasksException()
|
||||
elif ('prepare_and_create_workflow' in args and
|
||||
'create' == kwargs['action'] and
|
||||
utils.DUMMY_NS_2_NAME == kwargs['kwargs']['ns']['ns']['name']):
|
||||
raise nfvo.NoTasksException()
|
||||
|
||||
|
||||
def get_fake_nsd():
|
||||
|
@ -588,13 +597,25 @@ class TestNfvoPlugin(db_base.SqlTestCase):
|
|||
session.flush()
|
||||
return ns
|
||||
|
||||
def _insert_dummy_ns_2(self):
|
||||
session = self.context.session
|
||||
ns = ns_db.NS(
|
||||
id=DUMMY_NS_2,
|
||||
name='fake_ns',
|
||||
tenant_id='ad7ebc56538745a08ef7c5e97f8bd437',
|
||||
status='ACTIVE',
|
||||
nsd_id='eb094833-995e-49f0-a047-dfb56aaf7c4e',
|
||||
vim_id='6261579e-d6f3-49ad-8bc3-a9cb974778ff',
|
||||
description='fake_ns_description')
|
||||
session.add(ns)
|
||||
session.flush()
|
||||
return ns
|
||||
|
||||
def test_create_nsd(self):
|
||||
nsd_obj = utils.get_dummy_nsd_obj()
|
||||
with patch.object(TackerManager, 'get_service_plugins') as \
|
||||
mock_plugins:
|
||||
mock_plugins.return_value = {'VNFM': FakeVNFMPlugin()}
|
||||
mock.patch('tacker.common.driver_manager.DriverManager',
|
||||
side_effect=FakeDriverManager()).start()
|
||||
result = self.nfvo_plugin.create_nsd(self.context, nsd_obj)
|
||||
self.assertIsNotNone(result)
|
||||
self.assertEqual(result['name'], 'dummy_NSD')
|
||||
|
@ -614,8 +635,6 @@ class TestNfvoPlugin(db_base.SqlTestCase):
|
|||
with patch.object(TackerManager, 'get_service_plugins') as \
|
||||
mock_plugins:
|
||||
mock_plugins.return_value = {'VNFM': FakeVNFMPlugin()}
|
||||
mock.patch('tacker.common.driver_manager.DriverManager',
|
||||
side_effect=FakeDriverManager()).start()
|
||||
mock_get_by_name.return_value = get_by_name()
|
||||
|
||||
ns_obj = utils.get_dummy_ns_obj()
|
||||
|
@ -627,6 +646,29 @@ class TestNfvoPlugin(db_base.SqlTestCase):
|
|||
self.assertIn('status', result)
|
||||
self.assertIn('tenant_id', result)
|
||||
|
||||
@mock.patch.object(nfvo_plugin.NfvoPlugin, 'get_auth_dict')
|
||||
@mock.patch.object(vim_client.VimClient, 'get_vim')
|
||||
@mock.patch.object(nfvo_plugin.NfvoPlugin, '_get_by_name')
|
||||
def test_create_ns_workflow_no_task_exception(
|
||||
self, mock_get_by_name, mock_get_vimi, mock_auth_dict):
|
||||
self._insert_dummy_ns_template()
|
||||
self._insert_dummy_vim()
|
||||
mock_auth_dict.return_value = {
|
||||
'auth_url': 'http://127.0.0.1',
|
||||
'token': 'DummyToken',
|
||||
'project_domain_name': 'dummy_domain',
|
||||
'project_name': 'dummy_project'
|
||||
}
|
||||
with patch.object(TackerManager, 'get_service_plugins') as \
|
||||
mock_plugins:
|
||||
mock_plugins.return_value = {'VNFM': FakeVNFMPlugin()}
|
||||
mock_get_by_name.return_value = get_by_name()
|
||||
|
||||
ns_obj = utils.get_dummy_ns_obj_2()
|
||||
self.assertRaises(nfvo.NoTasksException,
|
||||
self.nfvo_plugin.create_ns,
|
||||
self.context, ns_obj)
|
||||
|
||||
@mock.patch.object(nfvo_plugin.NfvoPlugin, 'get_auth_dict')
|
||||
@mock.patch.object(vim_client.VimClient, 'get_vim')
|
||||
@mock.patch.object(nfvo_plugin.NfvoPlugin, '_get_by_name')
|
||||
|
@ -644,9 +686,34 @@ class TestNfvoPlugin(db_base.SqlTestCase):
|
|||
with patch.object(TackerManager, 'get_service_plugins') as \
|
||||
mock_plugins:
|
||||
mock_plugins.return_value = {'VNFM': FakeVNFMPlugin()}
|
||||
mock.patch('tacker.common.driver_manager.DriverManager',
|
||||
side_effect=FakeDriverManager()).start()
|
||||
mock_get_by_name.return_value = get_by_name()
|
||||
result = self.nfvo_plugin.delete_ns(self.context,
|
||||
'ba6bf017-f6f7-45f1-a280-57b073bf78ea')
|
||||
self.assertIsNotNone(result)
|
||||
|
||||
@mock.patch.object(nfvo_plugin.NfvoPlugin, 'get_auth_dict')
|
||||
@mock.patch.object(vim_client.VimClient, 'get_vim')
|
||||
@mock.patch.object(nfvo_plugin.NfvoPlugin, '_get_by_name')
|
||||
@mock.patch("tacker.db.nfvo.ns_db.NSPluginDb.delete_ns_post")
|
||||
def test_delete_ns_no_task_exception(
|
||||
self, mock_delete_ns_post, mock_get_by_name, mock_get_vim,
|
||||
mock_auth_dict):
|
||||
|
||||
self._insert_dummy_vim()
|
||||
self._insert_dummy_ns_template()
|
||||
self._insert_dummy_ns_2()
|
||||
mock_auth_dict.return_value = {
|
||||
'auth_url': 'http://127.0.0.1',
|
||||
'token': 'DummyToken',
|
||||
'project_domain_name': 'dummy_domain',
|
||||
'project_name': 'dummy_project'
|
||||
}
|
||||
|
||||
with patch.object(TackerManager, 'get_service_plugins') as \
|
||||
mock_plugins:
|
||||
mock_plugins.return_value = {'VNFM': FakeVNFMPlugin()}
|
||||
mock_get_by_name.return_value = get_by_name()
|
||||
self.nfvo_plugin.delete_ns(self.context,
|
||||
DUMMY_NS_2)
|
||||
mock_delete_ns_post.assert_called_with(
|
||||
self.context, DUMMY_NS_2, None, None)
|
||||
|
|
Loading…
Reference in New Issue