Skip resize actions in pre_condition phase

This patch is implementing detection of certain conditions and moving
the action to SKIPPED status so that, execution is not started. We will
check that:
- The instance exists
On other contitions the action will be FAILED in the pre_condition
check:
- Destination flavor does not exist

Implements: blueprint skip-actions-in-pre-condition

Change-Id: I1f6c8d99df3925556ea3ab22c81513dd0d4d7197
Signed-off-by: Alfredo Moralejo <amoralej@redhat.com>
This commit is contained in:
Alfredo Moralejo
2026-02-23 12:50:53 +01:00
parent 64ecc88972
commit f40bd2f637
4 changed files with 78 additions and 3 deletions

View File

@@ -23,3 +23,16 @@ parameter type required description
``flavor`` string yes ID or Name of Flavor (Nova accepts
either ID or Name)
======================== ====== ======== ===================================
Skipping conditions
--------------------
Resize actions will be automatically skipped in the pre_condition phase in
the following case:
- The server does not exist
On other condition the action will be FAILED in the pre_condition check:
- Destination flavor does not exist

View File

@@ -0,0 +1,15 @@
---
features:
- |
Added a pre-condition check to the resize action to prevent executing
it when required criteria are not met. In following condition,
the action status will be set to SKIPPED:
- Instance is not found
On other condition the action will be FAILED in the pre_condition
check:
- Destination flavor does not exist
This improves safety and correctness of migrations.

View File

@@ -18,7 +18,9 @@
from oslo_log import log
from watcher._i18n import _
from watcher.applier.actions import base
from watcher.common import exception
from watcher.common import nova_helper
LOG = log.getLogger(__name__)
@@ -97,9 +99,27 @@ class Resize(base.BaseAction):
LOG.warning("revert not supported")
def pre_condition(self):
# TODO(jed): check if the instance exists / check if the instance is on
# the source_node
pass
"""Check resize preconditions
Skipping conditions:
- Instance does not exist
Failing conditions:
- Flavor does not exist
"""
nova = nova_helper.NovaHelper(osc=self.osc)
# Check that the instance exists
try:
nova.find_instance(self.instance_uuid)
except exception.ComputeResourceNotFound:
raise exception.ActionSkipped(
_("Instance %s not found") % self.instance_uuid)
try:
nova.get_flavor_id(self.flavor)
except exception.ComputeResourceNotFound:
raise exception.ActionExecutionFailure(
_("Flavor %s not found") % self.flavor)
def post_condition(self):
# TODO(jed): check extra parameters (network response, etc.)

View File

@@ -18,6 +18,7 @@ from unittest import mock
from watcher.applier.actions import base as baction
from watcher.applier.actions import resize
from watcher.common import clients
from watcher.common import exception
from watcher.common import nova_helper
from watcher.tests.unit import base
@@ -89,3 +90,29 @@ class TestResize(base.TestCase):
self.action.execute()
self.r_helper.resize_instance.assert_called_once_with(
instance_id=self.INSTANCE_UUID, flavor='x1')
def test_pre_condition_success(self):
"""Test pre_condition succeeds when instance and flavor exist"""
self.r_helper.find_instance.return_value = self.INSTANCE_UUID
self.r_helper.get_flavor_id.return_value = '123'
self.action.pre_condition()
def test_pre_condition_instance_not_found(self):
"""Test pre_condition fails when instance doesn't exist"""
err = exception.ComputeResourceNotFound()
self.r_helper.find_instance.side_effect = err
self.assertRaisesRegex(
exception.ActionSkipped,
f"Instance {self.INSTANCE_UUID} not found",
self.action.pre_condition)
def test_pre_condition_flavor_not_found(self):
"""Test pre_condition fails when flavor doesn't exist"""
err = exception.ComputeResourceNotFound()
self.r_helper.get_flavor_id.side_effect = err
self.assertRaisesRegex(
exception.ActionExecutionFailure,
"Flavor x1 not found",
self.action.pre_condition)