Fix not update stateEnteredTime in VnfLcmOpOcc

This patch fixes a problem where stateEnteredTime is not
updated when updating operationState in VnfLcmOpOcc of v2 API.

Closes-Bug: #2043528
Change-Id: Ia9eba31f471bb234e537ae58cd7379ad569d8fc8
This commit is contained in:
Ken Fujimoto
2023-11-15 00:43:47 +00:00
parent bd5dcda608
commit 0996763076
5 changed files with 109 additions and 14 deletions

View File

@@ -607,3 +607,8 @@ def check_lcmocc_in_progress(context, inst_id):
operationState=fields.LcmOperationStateType.FAILED_TEMP)
if lcmoccs:
raise sol_ex.OtherOperationInProgress(inst_id=inst_id)
def update_lcmocc_status(lcmocc, op_state):
lcmocc.operationState = op_state
lcmocc.stateEnteredTime = datetime.utcnow()

View File

@@ -92,7 +92,7 @@ class ConductorV2(object):
lcmoccs = objects.VnfLcmOpOccV2.get_by_filter(context,
operationState=before_state)
for lcmocc in lcmoccs:
lcmocc.operationState = after_state
lcmocc_utils.update_lcmocc_status(lcmocc, after_state)
self._set_lcmocc_error(lcmocc, ex)
inst = inst_utils.get_inst(context, lcmocc.vnfInstanceId)
lcmocc.update(context)
@@ -158,7 +158,8 @@ class ConductorV2(object):
self.vnflcm_driver.post_grant(context, lcmocc, inst, grant_req,
grant, vnfd)
lcmocc.operationState = fields.LcmOperationStateType.PROCESSING
lcmocc_utils.update_lcmocc_status(
lcmocc, fields.LcmOperationStateType.PROCESSING)
lcmocc.grantId = grant.id
with context.session.begin(subtransactions=True):
# save grant_req and grant to be used when retry
@@ -173,7 +174,8 @@ class ConductorV2(object):
lcmocc.update(context)
except Exception as ex:
LOG.exception("STARTING %s failed", lcmocc.operation)
lcmocc.operationState = fields.LcmOperationStateType.ROLLED_BACK
lcmocc_utils.update_lcmocc_status(
lcmocc, fields.LcmOperationStateType.ROLLED_BACK)
self._set_lcmocc_error(lcmocc, ex)
lcmocc.update(context)
@@ -189,7 +191,8 @@ class ConductorV2(object):
grant, vnfd,
user_script_err_handling_data)
lcmocc.operationState = fields.LcmOperationStateType.COMPLETED
lcmocc_utils.update_lcmocc_status(
lcmocc, fields.LcmOperationStateType.COMPLETED)
# update inst and lcmocc at the same time
with context.session.begin(subtransactions=True):
inst.update(context)
@@ -199,7 +202,8 @@ class ConductorV2(object):
grant.delete(context)
except Exception as ex:
LOG.exception("PROCESSING %s failed", lcmocc.operation)
lcmocc.operationState = fields.LcmOperationStateType.FAILED_TEMP
lcmocc_utils.update_lcmocc_status(
lcmocc, fields.LcmOperationStateType.FAILED_TEMP)
self._set_lcmocc_error(lcmocc, ex, user_script_err_handling_data)
lcmocc.update(context)
@@ -229,7 +233,8 @@ class ConductorV2(object):
else:
user_script_err_handling_data = {}
lcmocc.operationState = fields.LcmOperationStateType.PROCESSING
lcmocc_utils.update_lcmocc_status(
lcmocc, fields.LcmOperationStateType.PROCESSING)
lcmocc.update(context)
# send notification PROCESSING
self.nfvo_client.send_lcmocc_notification(context, lcmocc, inst,
@@ -250,7 +255,8 @@ class ConductorV2(object):
grant, vnfd,
user_script_err_handling_data)
lcmocc.operationState = fields.LcmOperationStateType.COMPLETED
lcmocc_utils.update_lcmocc_status(
lcmocc, fields.LcmOperationStateType.COMPLETED)
lcmocc.error = None # clear error
# update inst and lcmocc at the same time
with context.session.begin(subtransactions=True):
@@ -262,7 +268,8 @@ class ConductorV2(object):
grant.delete(context)
except Exception as ex:
LOG.exception("PROCESSING %s failed", lcmocc.operation)
lcmocc.operationState = fields.LcmOperationStateType.FAILED_TEMP
lcmocc_utils.update_lcmocc_status(
lcmocc, fields.LcmOperationStateType.FAILED_TEMP)
self._set_lcmocc_error(lcmocc, ex, user_script_err_handling_data)
lcmocc.update(context)
# grant_req and grant are already saved. they are not deleted
@@ -294,7 +301,8 @@ class ConductorV2(object):
else:
user_script_err_handling_data = {}
lcmocc.operationState = fields.LcmOperationStateType.ROLLING_BACK
lcmocc_utils.update_lcmocc_status(
lcmocc, fields.LcmOperationStateType.ROLLING_BACK)
lcmocc.update(context)
# send notification ROLLING_BACK
self.nfvo_client.send_lcmocc_notification(context, lcmocc, inst,
@@ -311,7 +319,8 @@ class ConductorV2(object):
grant, vnfd,
user_script_err_handling_data)
lcmocc.operationState = fields.LcmOperationStateType.ROLLED_BACK
lcmocc_utils.update_lcmocc_status(
lcmocc, fields.LcmOperationStateType.ROLLED_BACK)
if (lcmocc.obj_attr_is_set('error') and
lcmocc.error.obj_attr_is_set('userScriptErrHandlingData')):
del lcmocc.error.userScriptErrHandlingData
@@ -330,7 +339,8 @@ class ConductorV2(object):
grant.delete(context)
except Exception as ex:
LOG.exception("ROLLING_BACK %s failed", lcmocc.operation)
lcmocc.operationState = fields.LcmOperationStateType.FAILED_TEMP
lcmocc_utils.update_lcmocc_status(
lcmocc, fields.LcmOperationStateType.FAILED_TEMP)
self._set_lcmocc_error(lcmocc, ex, user_script_err_handling_data)
lcmocc.update(context)
# grant_req and grant are already saved. they are not deleted
@@ -365,14 +375,16 @@ class ConductorV2(object):
vnfd = self.nfvo_client.get_vnfd(context, inst.vnfdId)
self.vnflcm_driver.process(context, lcmocc, inst, None, None, vnfd,
user_script_err_handling_data)
lcmocc.operationState = fields.LcmOperationStateType.COMPLETED
lcmocc_utils.update_lcmocc_status(
lcmocc, fields.LcmOperationStateType.COMPLETED)
# update inst and lcmocc at the same time
with context.session.begin(subtransactions=True):
inst.update(context)
lcmocc.update(context)
except Exception as ex:
LOG.exception("PROCESSING %s failed", lcmocc.operation)
lcmocc.operationState = fields.LcmOperationStateType.FAILED_TEMP
lcmocc_utils.update_lcmocc_status(
lcmocc, fields.LcmOperationStateType.FAILED_TEMP)
self._set_lcmocc_error(lcmocc, ex, user_script_err_handling_data)
lcmocc.update(context)

View File

@@ -610,7 +610,8 @@ class VnfLcmControllerV2(sol_wsgi.SolAPIController):
grant_req, grant = lcmocc_utils.get_grant_req_and_grant(context,
lcmocc)
lcmocc.operationState = v2fields.LcmOperationStateType.FAILED
lcmocc_utils.update_lcmocc_status(
lcmocc, v2fields.LcmOperationStateType.FAILED)
with context.session.begin(subtransactions=True):
lcmocc.update(context)
if grant_req is not None:

View File

@@ -152,9 +152,11 @@ class TestConductorV2(db_base.SqlTestCase):
mocked_grant.return_value = grant_req, grant
op_state = []
op_state_entered_time = []
def _store_state(context, lcmocc, inst, endpoint):
op_state.append(lcmocc.operationState)
op_state_entered_time.append(lcmocc.stateEnteredTime)
mocked_send_lcmocc_notification.side_effect = _store_state
@@ -167,6 +169,10 @@ class TestConductorV2(db_base.SqlTestCase):
self.assertEqual(fields.LcmOperationStateType.PROCESSING, op_state[1])
self.assertEqual(fields.LcmOperationStateType.COMPLETED, op_state[2])
# check stateEnteredTime
self.assertNotEqual(op_state_entered_time[0], op_state_entered_time[1])
self.assertNotEqual(op_state_entered_time[1], op_state_entered_time[2])
# check grant_req and grant are deleted
self.assertRaises(sol_ex.GrantRequestOrGrantNotFound,
lcmocc_utils.get_grant_req_and_grant, self.context, lcmocc)
@@ -184,9 +190,11 @@ class TestConductorV2(db_base.SqlTestCase):
mocked_grant.return_value = self._make_grant_req_and_grant(lcmocc)
mocked_process.return_value = mock.Mock()
op_state = []
op_state_entered_time = []
def _store_state(context, lcmocc, inst, endpoint):
op_state.append(lcmocc.operationState)
op_state_entered_time.append(lcmocc.stateEnteredTime)
mocked_send_lcmocc_notification.side_effect = _store_state
@@ -199,6 +207,10 @@ class TestConductorV2(db_base.SqlTestCase):
self.assertEqual(fields.LcmOperationStateType.PROCESSING, op_state[1])
self.assertEqual(fields.LcmOperationStateType.COMPLETED, op_state[2])
# check stateEnteredTime
self.assertNotEqual(op_state_entered_time[0], op_state_entered_time[1])
self.assertNotEqual(op_state_entered_time[1], op_state_entered_time[2])
@mock.patch.object(nfvo_client.NfvoClient, 'send_lcmocc_notification')
@mock.patch.object(nfvo_client.NfvoClient, 'get_vnfd')
@mock.patch.object(vnflcm_driver_v2.VnfLcmDriverV2, 'grant')
@@ -211,9 +223,11 @@ class TestConductorV2(db_base.SqlTestCase):
mocked_grant.side_effect = ex
op_state = []
op_state_entered_time = []
def _store_state(context, lcmocc, inst, endpoint):
op_state.append(lcmocc.operationState)
op_state_entered_time.append(lcmocc.stateEnteredTime)
mocked_send_lcmocc_notification.side_effect = _store_state
@@ -225,6 +239,9 @@ class TestConductorV2(db_base.SqlTestCase):
self.assertEqual(fields.LcmOperationStateType.STARTING, op_state[0])
self.assertEqual(fields.LcmOperationStateType.ROLLED_BACK, op_state[1])
# check stateEnteredTime
self.assertNotEqual(op_state_entered_time[0], op_state_entered_time[1])
# check lcmocc.error
# get lcmocc from DB to be sure lcmocc saved to DB
lcmocc = lcmocc_utils.get_lcmocc(self.context, lcmocc.id)
@@ -247,9 +264,11 @@ class TestConductorV2(db_base.SqlTestCase):
mocked_process.side_effect = ex
op_state = []
op_state_entered_time = []
def _store_state(context, lcmocc, inst, endpoint):
op_state.append(lcmocc.operationState)
op_state_entered_time.append(lcmocc.stateEnteredTime)
mocked_send_lcmocc_notification.side_effect = _store_state
@@ -262,6 +281,10 @@ class TestConductorV2(db_base.SqlTestCase):
self.assertEqual(fields.LcmOperationStateType.PROCESSING, op_state[1])
self.assertEqual(fields.LcmOperationStateType.FAILED_TEMP, op_state[2])
# check stateEnteredTime
self.assertNotEqual(op_state_entered_time[0], op_state_entered_time[1])
self.assertNotEqual(op_state_entered_time[1], op_state_entered_time[2])
# check lcmocc.error
# get lcmocc from DB to be sure lcmocc saved to DB
lcmocc = lcmocc_utils.get_lcmocc(self.context, lcmocc.id)
@@ -285,9 +308,11 @@ class TestConductorV2(db_base.SqlTestCase):
mocked_get_vnfd.return_value = mock.Mock()
op_state = []
op_state_entered_time = []
def _store_state(context, lcmocc, inst, endpoint):
op_state.append(lcmocc.operationState)
op_state_entered_time.append(lcmocc.stateEnteredTime)
mocked_send_lcmocc_notification.side_effect = _store_state
@@ -299,6 +324,9 @@ class TestConductorV2(db_base.SqlTestCase):
self.assertEqual(fields.LcmOperationStateType.PROCESSING, op_state[0])
self.assertEqual(fields.LcmOperationStateType.COMPLETED, op_state[1])
# check stateEnteredTime
self.assertNotEqual(op_state_entered_time[0], op_state_entered_time[1])
# check grant_req and grant are deleted
self.assertRaises(sol_ex.GrantRequestOrGrantNotFound,
lcmocc_utils.get_grant_req_and_grant, self.context, lcmocc)
@@ -321,9 +349,11 @@ class TestConductorV2(db_base.SqlTestCase):
mocked_process.side_effect = ex
op_state = []
op_state_entered_time = []
def _store_state(context, lcmocc, inst, endpoint):
op_state.append(lcmocc.operationState)
op_state_entered_time.append(lcmocc.stateEnteredTime)
mocked_send_lcmocc_notification.side_effect = _store_state
@@ -335,6 +365,9 @@ class TestConductorV2(db_base.SqlTestCase):
self.assertEqual(fields.LcmOperationStateType.PROCESSING, op_state[0])
self.assertEqual(fields.LcmOperationStateType.FAILED_TEMP, op_state[1])
# check stateEnteredTime
self.assertNotEqual(op_state_entered_time[0], op_state_entered_time[1])
# check lcmocc.error
# get lcmocc from DB to be sure lcmocc saved to DB
lcmocc = lcmocc_utils.get_lcmocc(self.context, lcmocc.id)
@@ -362,9 +395,11 @@ class TestConductorV2(db_base.SqlTestCase):
mocked_get_vnfd.return_value = mock.Mock()
op_state = []
op_state_entered_time = []
def _store_state(context, lcmocc, inst, endpoint):
op_state.append(lcmocc.operationState)
op_state_entered_time.append(lcmocc.stateEnteredTime)
mocked_send_lcmocc_notification.side_effect = _store_state
@@ -377,6 +412,9 @@ class TestConductorV2(db_base.SqlTestCase):
op_state[0])
self.assertEqual(fields.LcmOperationStateType.ROLLED_BACK, op_state[1])
# check stateEnteredTime
self.assertNotEqual(op_state_entered_time[0], op_state_entered_time[1])
# check grant_req and grant are deleted
self.assertRaises(sol_ex.GrantRequestOrGrantNotFound,
lcmocc_utils.get_grant_req_and_grant, self.context, lcmocc)
@@ -400,9 +438,11 @@ class TestConductorV2(db_base.SqlTestCase):
mocked_rollback.side_effect = ex
op_state = []
op_state_entered_time = []
def _store_state(context, lcmocc, inst, endpoint):
op_state.append(lcmocc.operationState)
op_state_entered_time.append(lcmocc.stateEnteredTime)
mocked_send_lcmocc_notification.side_effect = _store_state
@@ -415,6 +455,9 @@ class TestConductorV2(db_base.SqlTestCase):
op_state[0])
self.assertEqual(fields.LcmOperationStateType.FAILED_TEMP, op_state[1])
# check stateEnteredTime
self.assertNotEqual(op_state_entered_time[0], op_state_entered_time[1])
# check lcmocc.error
# get lcmocc from DB to be sure lcmocc saved to DB
lcmocc = lcmocc_utils.get_lcmocc(self.context, lcmocc.id)
@@ -437,9 +480,11 @@ class TestConductorV2(db_base.SqlTestCase):
mocked_get_vnfd.return_value = mock.Mock()
op_state = []
op_state_entered_time = []
def _store_state(context, lcmocc, inst, endpoint):
op_state.append(lcmocc.operationState)
op_state_entered_time.append(lcmocc.stateEnteredTime)
mocked_send_lcmocc_notification.side_effect = _store_state
@@ -451,6 +496,9 @@ class TestConductorV2(db_base.SqlTestCase):
self.assertEqual(fields.LcmOperationStateType.PROCESSING, op_state[0])
self.assertEqual(fields.LcmOperationStateType.COMPLETED, op_state[1])
# check stateEnteredTime
self.assertNotEqual(op_state_entered_time[0], op_state_entered_time[1])
@mock.patch.object(nfvo_client.NfvoClient, 'send_lcmocc_notification')
@mock.patch.object(nfvo_client.NfvoClient, 'get_vnfd')
@mock.patch.object(vnflcm_driver_v2.VnfLcmDriverV2, 'process')
@@ -465,9 +513,11 @@ class TestConductorV2(db_base.SqlTestCase):
mocked_process.side_effect = ex
op_state = []
op_state_entered_time = []
def _store_state(context, lcmocc, inst, endpoint):
op_state.append(lcmocc.operationState)
op_state_entered_time.append(lcmocc.stateEnteredTime)
mocked_send_lcmocc_notification.side_effect = _store_state
@@ -479,6 +529,9 @@ class TestConductorV2(db_base.SqlTestCase):
self.assertEqual(fields.LcmOperationStateType.PROCESSING, op_state[0])
self.assertEqual(fields.LcmOperationStateType.FAILED_TEMP, op_state[1])
# check stateEnteredTime
self.assertNotEqual(op_state_entered_time[0], op_state_entered_time[1])
# check lcmocc.error
# get lcmocc from DB to be sure lcmocc saved to DB
lcmocc = lcmocc_utils.get_lcmocc(self.context, lcmocc.id)
@@ -528,13 +581,16 @@ class TestConductorV2(db_base.SqlTestCase):
mocked_send_lcmocc_notification, before_state, after_state):
# prepare
lcmocc = self._prepare_change_lcm_op_state(before_state)
before_state_entered_time = lcmocc.stateEnteredTime
mocked_get_vnfd.return_value = mock.Mock()
ex = sol_ex.ConductorProcessingError()
op_state = []
op_state_entered_time = []
def _store_state(context, lcmocc, inst, endpoint):
op_state.append(lcmocc.operationState)
op_state_entered_time.append(lcmocc.stateEnteredTime)
mocked_send_lcmocc_notification.side_effect = _store_state
@@ -545,6 +601,10 @@ class TestConductorV2(db_base.SqlTestCase):
self.assertEqual(1, mocked_send_lcmocc_notification.call_count)
self.assertEqual(after_state, op_state[0])
# check stateEnteredTime
self.assertNotEqual(before_state_entered_time,
op_state_entered_time[0])
# check lcmocc.error
# get lcmocc from DB to be sure lcmocc saved to DB
lcmocc = lcmocc_utils.get_lcmocc(self.context, lcmocc.id)
@@ -582,9 +642,11 @@ class TestConductorV2(db_base.SqlTestCase):
mocked_get_vnfd.return_value = mock.Mock()
op_state = []
op_state_entered_time = []
def _store_state(context, lcmocc, inst, endpoint):
op_state.append(lcmocc.operationState)
op_state_entered_time.append(lcmocc.stateEnteredTime)
mocked_send_lcmocc_notification.side_effect = _store_state
@@ -596,6 +658,9 @@ class TestConductorV2(db_base.SqlTestCase):
self.assertEqual(fields.LcmOperationStateType.PROCESSING, op_state[0])
self.assertEqual(fields.LcmOperationStateType.COMPLETED, op_state[1])
# check stateEnteredTime
self.assertNotEqual(op_state_entered_time[0], op_state_entered_time[1])
# check grant_req and grant are deleted
self.assertRaises(sol_ex.GrantRequestOrGrantNotFound,
lcmocc_utils.get_grant_req_and_grant, self.context, lcmocc)
@@ -621,9 +686,11 @@ class TestConductorV2(db_base.SqlTestCase):
mocked_get_vnfd.return_value = mock.Mock()
op_state = []
op_state_entered_time = []
def _store_state(context, lcmocc, inst, endpoint):
op_state.append(lcmocc.operationState)
op_state_entered_time.append(lcmocc.stateEnteredTime)
mocked_send_lcmocc_notification.side_effect = _store_state
@@ -636,6 +703,9 @@ class TestConductorV2(db_base.SqlTestCase):
op_state[0])
self.assertEqual(fields.LcmOperationStateType.ROLLED_BACK, op_state[1])
# check stateEnteredTime
self.assertNotEqual(op_state_entered_time[0], op_state_entered_time[1])
# check grant_req and grant are deleted
self.assertRaises(sol_ex.GrantRequestOrGrantNotFound,
lcmocc_utils.get_grant_req_and_grant, self.context, lcmocc)

View File

@@ -1465,11 +1465,14 @@ class TestVnflcmV2(db_base.SqlTestCase):
def test_lcm_op_occ_fail(self, mocked_send_lcmocc_notification):
# prepare
lcmocc = self._prepare_db_for_fail()
before_state_entered_time = lcmocc.stateEnteredTime
op_state = []
op_state_entered_time = []
def _store_state(context, lcmocc, inst, endpoint):
op_state.append(lcmocc.operationState)
op_state_entered_time.append(lcmocc.stateEnteredTime)
mocked_send_lcmocc_notification.side_effect = _store_state
@@ -1480,6 +1483,10 @@ class TestVnflcmV2(db_base.SqlTestCase):
self.assertEqual(1, mocked_send_lcmocc_notification.call_count)
self.assertEqual(fields.LcmOperationStateType.FAILED, op_state[0])
# check stateEnteredTime
self.assertNotEqual(before_state_entered_time,
op_state_entered_time[0])
# check grant_req and grant are deleted
self.assertRaises(sol_ex.GrantRequestOrGrantNotFound,
lcmocc_utils.get_grant_req_and_grant, self.context, lcmocc)