Handled exception in exception of instantiation

When exception occurs in exception block of
instantiation, heal, termination, change external connectivity
operations then notification was not sent.

Implemented exception handling in exception block of instantiation,
heal, termination, change external connectivity operations.

Closes-Bug: #1983096
Change-Id: I645e342167d22ac3764cdb20ef1a0f77f801fb95
This commit is contained in:
Pooja Singla 2022-09-05 07:26:55 +00:00
parent bff12b4cfb
commit 3bdb71c812
2 changed files with 184 additions and 73 deletions

View File

@ -1744,7 +1744,11 @@ class Conductor(manager.Manager, v2_hook.ConductorV2Hook):
or operation_state == \
fields.LcmOccsOperationState.FAILED:
notification_data['error'] = error
except Exception as ex:
LOG.error("Error in getting resources for op id - {}.\
Details: {}".format(vnf_lcm_op_occs_id, str(ex)))
try:
# send notification
self.send_notification(context, notification_data)
except Exception as ex:
@ -2000,29 +2004,33 @@ class Conductor(manager.Manager, v2_hook.ConductorV2Hook):
operation_state=fields.LcmOccsOperationState.COMPLETED)
except Exception as ex:
LOG.warning(traceback.format_exc())
LOG.warning("Exception occured in instantiation for vnf "
"instance %(id)s. Error: %(error)s",
{"id": vnf_instance.id, "error": ex})
self._change_vnf_status(context, vnf_instance.id,
try:
LOG.warning(traceback.format_exc())
LOG.warning("Exception occured in instantiation for vnf "
"instance %(id)s. Error: %(error)s",
{"id": vnf_instance.id, "error": ex})
self._change_vnf_status(context, vnf_instance.id,
constants.ALL_STATUSES, 'ERROR')
self._build_instantiated_vnf_info(context, vnf_instance,
instantiate_vnf)
self.vnflcm_driver._vnf_instance_update(context, vnf_instance,
self._build_instantiated_vnf_info(context, vnf_instance,
instantiate_vnf)
self.vnflcm_driver._vnf_instance_update(context, vnf_instance,
task_state=None)
# Update vnf_lcm_op_occs table and send notification "FAILED_TEMP"
self._send_lcm_op_occ_notification(
context=context,
vnf_lcm_op_occs_id=vnf_lcm_op_occs_id,
old_vnf_instance=None,
vnf_instance=vnf_instance,
operation=fields.LcmOccsOperationType.INSTANTIATE,
operation_state=fields.LcmOccsOperationState.FAILED_TEMP,
error=str(ex),
error_point=vnf_dict['current_error_point']
)
except Exception as exception:
LOG.warning("Failed to change VNF status to ERROR.\
Exception : %s", str(exception))
finally:
# Update vnf_lcm_op_occs table
# and send notification "FAILED_TEMP"
self._send_lcm_op_occ_notification(
context=context,
vnf_lcm_op_occs_id=vnf_lcm_op_occs_id,
old_vnf_instance=None,
vnf_instance=vnf_instance,
operation=fields.LcmOccsOperationType.INSTANTIATE,
operation_state=fields.LcmOccsOperationState.FAILED_TEMP,
error=str(ex),
error_point=vnf_dict['current_error_point']
)
@coordination.synchronized('{vnf_instance[id]}')
def terminate(self, context, vnf_lcm_op_occs_id,
@ -2080,24 +2088,29 @@ class Conductor(manager.Manager, v2_hook.ConductorV2Hook):
)
except Exception as exc:
# set vnf_status to error
self._change_vnf_status(context, vnf_instance.id,
try:
# set vnf_status to error
self._change_vnf_status(context, vnf_instance.id,
constants.ALL_STATUSES, 'ERROR')
self.vnflcm_driver._vnf_instance_update(
context, vnf_instance, task_state=None)
# Update vnf_lcm_op_occs table and send notification "FAILED_TEMP"
self._send_lcm_op_occ_notification(
context=context,
vnf_lcm_op_occs_id=vnf_lcm_op_occs_id,
old_vnf_instance=old_vnf_instance,
vnf_instance=None,
operation=fields.LcmOccsOperationType.TERMINATE,
operation_state=fields.LcmOccsOperationState.FAILED_TEMP,
error=str(exc),
error_point=vnf_dict['current_error_point']
)
self.vnflcm_driver._vnf_instance_update(
context, vnf_instance, task_state=None)
except Exception as exception:
LOG.warning("Failed to change VNF status to ERROR.\
Exception : %s", str(exception))
finally:
# Update vnf_lcm_op_occs table and send
# notification "FAILED_TEMP"
self._send_lcm_op_occ_notification(
context=context,
vnf_lcm_op_occs_id=vnf_lcm_op_occs_id,
old_vnf_instance=old_vnf_instance,
vnf_instance=None,
operation=fields.LcmOccsOperationType.TERMINATE,
operation_state=fields.LcmOccsOperationState.FAILED_TEMP,
error=str(exc),
error_point=vnf_dict['current_error_point']
)
def _update_vnf_attributes_stack_param(self, context, vnf_dict, vnf_id,
heal_vnf_request, inst_vnf_info):
@ -2183,25 +2196,30 @@ class Conductor(manager.Manager, v2_hook.ConductorV2Hook):
operation_state=fields.LcmOccsOperationState.COMPLETED
)
except Exception as ex:
# update vnf_status to 'ERROR' and create event with 'ERROR' status
self._change_vnf_status(context, vnf_instance.id,
try:
# update vnf_status to 'ERROR' and create
# event with 'ERROR' status
self._change_vnf_status(context, vnf_instance.id,
constants.ALL_STATUSES, constants.ERROR)
# call _update_instantiated_vnf_info for notification
self._update_instantiated_vnf_info(context, vnf_instance,
# call _update_instantiated_vnf_info for notification
self._update_instantiated_vnf_info(context, vnf_instance,
heal_vnf_request)
# update vnf_lcm_op_occs and send notification "FAILED_TEMP"
self._send_lcm_op_occ_notification(
context=context,
vnf_lcm_op_occs_id=vnf_lcm_op_occs_id,
old_vnf_instance=old_vnf_instance,
vnf_instance=vnf_instance,
operation=fields.LcmOccsOperationType.HEAL,
operation_state=fields.LcmOccsOperationState.FAILED_TEMP,
error=str(ex),
error_point=vnf_dict['current_error_point']
)
except Exception as exception:
LOG.warning("Failed to change VNF status to ERROR.\
Exception : %s", str(exception))
finally:
# update vnf_lcm_op_occs and send notification "FAILED_TEMP"
self._send_lcm_op_occ_notification(
context=context,
vnf_lcm_op_occs_id=vnf_lcm_op_occs_id,
old_vnf_instance=old_vnf_instance,
vnf_instance=vnf_instance,
operation=fields.LcmOccsOperationType.HEAL,
operation_state=fields.LcmOccsOperationState.FAILED_TEMP,
error=str(ex),
error_point=vnf_dict['current_error_point']
)
@coordination.synchronized('{vnf_instance[id]}')
def scale(self, context, vnf_info, vnf_instance, scale_vnf_request):
@ -2452,27 +2470,32 @@ class Conductor(manager.Manager, v2_hook.ConductorV2Hook):
operation_state=fields.LcmOccsOperationState.COMPLETED
)
except Exception as e:
# update vnf_status to 'ERROR' and create event with 'ERROR' status
self._change_vnf_status(context, vnf_instance.id,
try:
# update vnf_status to 'ERROR' and create
# event with 'ERROR' status
self._change_vnf_status(context, vnf_instance.id,
constants.ALL_STATUSES, constants.ERROR)
LOG.error('Failed to execute operation. error={}'.format(e))
if vnf_dict['current_error_point'] in [EP.INTERNAL_PROCESSING,
EP.VNF_CONFIG_END]:
self._update_instantiated_vnf_info_change_ext_conn(
context, vnf_instance, change_ext_conn_req)
# update vnf_lcm_op_occs and send notification "FAILED_TEMP"
self._send_lcm_op_occ_notification(
context=context,
vnf_lcm_op_occs_id=vnf_lcm_op_occs_id,
old_vnf_instance=old_vnf_instance,
vnf_instance=vnf_instance,
operation=fields.LcmOccsOperationType.CHANGE_EXT_CONN,
operation_state=fields.LcmOccsOperationState.FAILED_TEMP,
error=str(e),
error_point=vnf_dict['current_error_point']
)
LOG.error('Failed to execute operation. error={}'.format(e))
if vnf_dict['current_error_point'] in [EP.INTERNAL_PROCESSING,
EP.VNF_CONFIG_END]:
self._update_instantiated_vnf_info_change_ext_conn(
context, vnf_instance, change_ext_conn_req)
except Exception as exception:
LOG.warning("Failed to change VNF status to ERROR.\
Exception : %s", str(exception))
finally:
# update vnf_lcm_op_occs and send notification "FAILED_TEMP"
self._send_lcm_op_occ_notification(
context=context,
vnf_lcm_op_occs_id=vnf_lcm_op_occs_id,
old_vnf_instance=old_vnf_instance,
vnf_instance=vnf_instance,
operation=fields.LcmOccsOperationType.CHANGE_EXT_CONN,
operation_state=fields.LcmOccsOperationState.FAILED_TEMP,
error=str(e),
error_point=vnf_dict['current_error_point']
)
def init(args, **kwargs):

View File

@ -553,7 +553,7 @@ class TestConductor(SqlTestCase, unit_base.FixturedTestCase):
mock_grants.return_value = MockResponse(json_data=grant_dict)
self.conductor.instantiate(self.context, vnf_instance, vnf_dict,
instantiate_vnf_req, vnf_lcm_op_occs_id)
self.assertEqual(mock_send_notification.call_count, 1)
self.assertEqual(mock_send_notification.call_count, 2)
self.assertEqual(mock_change_vnf_status.call_count, 1)
@mock.patch('tacker.conductor.conductor_server.Conductor'
@ -948,6 +948,94 @@ class TestConductor(SqlTestCase, unit_base.FixturedTestCase):
vnf_instance.id, mock.ANY, 'ERROR')
mock_update_vnf_attributes.assert_called_once()
@mock.patch('tacker.conductor.conductor_server.Conductor'
'.send_notification')
@mock.patch('tacker.conductor.conductor_server.Conductor'
'._update_vnf_attributes')
@mock.patch('tacker.conductor.conductor_server.Conductor'
'._change_vnf_status')
@mock.patch('tacker.conductor.conductor_server.Conductor'
'._build_instantiated_vnf_info')
@mock.patch.object(objects.VnfLcmOpOcc, "save")
@mock.patch.object(coordination.Coordinator, 'get_lock')
@mock.patch.object(objects.LccnSubscriptionRequest,
'vnf_lcm_subscriptions_get')
@mock.patch('tacker.vnflcm.utils._get_vnfd_dict')
@mock.patch('tacker.vnflcm.utils._convert_desired_capacity')
@mock.patch('tacker.conductor.conductor_server.LOG')
@mock.patch.object(objects.VnfLcmOpOcc, "get_by_id")
@mock.patch('tacker.vnflcm.utils._get_affected_resources')
def test_lcm_notification_exception_in_exception(
self, mock_res, mock_vnf_by_id, mock_log,
mock_des, mock_vnfd_dict,
mock_vnf_lcm_subscriptions_get,
mock_get_lock, mock_save,
mock_build_info,
mock_change_vnf_status,
mock_update_vnf_attributes,
mock_send_notification):
lcm_op_occs_data = fakes.get_lcm_op_occs_data()
mock_vnf_by_id.return_value = \
objects.VnfLcmOpOcc(context=self.context,
**lcm_op_occs_data)
vnf_package_vnfd = self._create_and_upload_vnf_package()
vnf_instance_data = fake_obj.get_vnf_instance_data(
vnf_package_vnfd.vnfd_id)
vnf_instance = objects.VnfInstance(context=self.context,
**vnf_instance_data)
vnf_instance.create()
instantiate_vnf_req = vnflcm_fakes.get_instantiate_vnf_request_obj()
vnf_lcm_op_occs_id = uuidsentinel.vnf_lcm_op_occs_id
vnf_dict = db_utils.get_dummy_vnf_etsi(instance_id=self.instance_uuid,
flavour=instantiate_vnf_req.flavour_id)
vnf_dict['before_error_point'] = fields.ErrorPoint.INITIAL
vnfd_key = 'vnfd_' + instantiate_vnf_req.flavour_id
vnfd_yaml = vnf_dict['vnfd']['attributes'].get(vnfd_key, '')
mock_vnfd_dict.return_value = yaml.safe_load(vnfd_yaml)
mock_vnf_lcm_subscriptions_get.return_value = \
[mock.MagicMock(**fakes.get_vnf_lcm_subscriptions())]
mock_res.return_value = {}
mock_change_vnf_status.side_effect = Exception
self.conductor.instantiate(self.context, vnf_instance, vnf_dict,
instantiate_vnf_req, vnf_lcm_op_occs_id)
mock_change_vnf_status.assert_called_with(self.context,
vnf_instance.id, mock.ANY, 'ERROR')
self.assertEqual("FAILED_TEMP",
mock_send_notification.call_args[0][1].get("operationState"))
heal_vnf_req = objects.HealVnfRequest(cause="healing request")
mock_change_vnf_status.side_effect = Exception
self.conductor.heal(self.context, vnf_instance, vnf_dict,
heal_vnf_req, vnf_lcm_op_occs_id)
mock_change_vnf_status.assert_called_with(self.context,
vnf_instance.id, mock.ANY, 'ERROR')
self.assertEqual("FAILED_TEMP",
mock_send_notification.call_args[0][1].get("operationState"))
terminate_vnf_req = objects.TerminateVnfRequest(
termination_type=fields.VnfInstanceTerminationType.GRACEFUL,
additional_params={"key": "value"})
self.conductor.terminate(self.context, vnf_lcm_op_occs_id,
vnf_instance, terminate_vnf_req, vnf_dict)
mock_change_vnf_status.assert_called_with(self.context,
vnf_instance.id, mock.ANY, 'ERROR')
self.assertEqual("FAILED_TEMP",
mock_send_notification.call_args[0][1].get("operationState"))
change_ext_conn_req = fakes.get_change_ext_conn_request_obj()
mock_change_vnf_status.side_effect = Exception
self.conductor.change_ext_conn(
self.context,
vnf_instance,
vnf_dict,
change_ext_conn_req,
vnf_lcm_op_occs_id)
mock_change_vnf_status.assert_called_with(self.context,
vnf_instance.id, mock.ANY, 'ERROR')
self.assertEqual("FAILED_TEMP",
mock_send_notification.call_args[0][1].get("operationState"))
@mock.patch('tacker.conductor.conductor_server.Conductor'
'._update_vnf_attributes')
@mock.patch('tacker.conductor.conductor_server.Conductor'