Merge "Save VNF instance before scale is marked as COMPLETED"

This commit is contained in:
Zuul authored and Gerrit Code Review committed 2026-09-09 13:41:39 +00:00
commit a210aff6e8
3 files changed
+44 -7

No files matched your search

@@ -0,0 +1,12 @@
---
fixes:
- |
Fix `bug 2162060`_ for the order of updating the database in the v1 scale
operation. The ``vnflcm_op_occs`` record was marked as ``COMPLETED``
before the VNF instance was saved, and a client reacting to the
``COMPLETED`` state could get the ``scaleLevel`` of ``scaleStatus``
before the scaling. The VNF instance is now saved first so that its
``scaleStatus`` is already updated once the operation has reached
``COMPLETED``, which is the same order as the instantiate operation.
.. _bug 2162060: https://bugs.launchpad.net/tacker/+bug/2162060
@@ -450,6 +450,21 @@ class BaseVnfLcmKubernetesTest(base.BaseTackerTest):
raise Exception(f"aspectId {aspect_id} is not found.")
return scale_level
def _wait_scale_level(self, id, aspect_id, expected_level, timeout):
start_time = int(time.time())
while True:
vnf_instance = self._show_vnf_instance(id)
scale_level = self._get_scale_level_by_aspect_id(
vnf_instance, aspect_id)
if scale_level == expected_level:
return scale_level
if (int(time.time()) - start_time) > timeout:
self.fail(f"Timeout waiting for scaleLevel of {aspect_id} to"
f" become {expected_level}, but {scale_level}.")
time.sleep(RETRY_WAIT_TIME)
def _test_scale(self, id, type, aspect_id, previous_level,
number_of_steps=1, error=False):
# scale operation
@@ -468,12 +483,19 @@ class BaseVnfLcmKubernetesTest(base.BaseTackerTest):
self.context, id, self.lcm_timeout['scale'], wait_state,
vnf_lcm_op_occ_id=vnf_lcm_op_occ_id)
# check scaleStatus after scale operation
vnf_instance = self._show_vnf_instance(id)
scale_level = self._get_scale_level_by_aspect_id(
vnf_instance, aspect_id)
self.assertEqual(scale_level, expected_level)
if error:
# A failed operation does not update scaleStatus, so there is
# nothing to wait for.
vnf_instance = self._show_vnf_instance(id)
scale_level = self._get_scale_level_by_aspect_id(
vnf_instance, aspect_id)
self.assertEqual(expected_level, scale_level)
return scale_level
return scale_level
# Note that scaleStatus can be committed slightly after the
# operation state is updated.
return self._wait_scale_level(
id, aspect_id, expected_level, self.lcm_timeout['scale'])
def _test_scale_out_and_in(self, vnf_instance, aspect_id,
number_of_steps=1, error=False):
+5 -2
View File
@@ -1156,13 +1156,16 @@ class VnfLcmDriver(abstract_driver.VnfInstanceAbstractDriver):
if vnf_info['before_error_point'] < EP.NOTIFY_COMPLETED:
self._vnfm_plugin._update_vnf_scaling(context, vnf_info,
'PENDING_' + scale_vnf_request.type, 'ACTIVE')
# NOTE: Save the VNF instance before the operation is marked as
# COMPLETED, so that its `scaleStatus` is already updated when a
# client reacts to the COMPLETED state.
vnf_instance.task_state = None
vnf_instance.save()
vnf_lcm_op_occ = vnf_info['vnf_lcm_op_occ']
vnf_lcm_op_occ.operation_state = 'COMPLETED'
vnf_lcm_op_occ.resource_changes = resource_changes
vnf_lcm_op_occ.state_entered_time = timeutils.utcnow()
vnf_lcm_op_occ.save()
vnf_instance.task_state = None
vnf_instance.save()
vnf_info['current_error_point'] = EP.NOTIFY_COMPLETED