Skip change_nova_service_state 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 specified nova-compute service exist
- The spedified nova-compute service is in the desired state

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

Change-Id: I0fa0869468b2f4478b592a59bc301abb7618ec74
Signed-off-by: Alfredo Moralejo <amoralej@redhat.com>
This commit is contained in:
Alfredo Moralejo
2026-02-19 17:23:54 +01:00
parent 8546305266
commit 4a41404e28
4 changed files with 84 additions and 7 deletions

View File

@@ -30,3 +30,12 @@ parameter type required description
``watcher_disabled`` or
``watcher_maintaining``
======================== ====== ======== ===================================
Skipping conditions
--------------------
Change nova service state actions will be automatically skipped in the
pre_condition phase in the following cases:
- nova-compute service does not exist
- nova-compute service is already in the desired state (enabled or disabled)

View File

@@ -0,0 +1,9 @@
---
features:
- |
Added a pre-condition check to the change_nova_service_state action
to prevent executing it when required criteria are not met. In the
following conditions, the action status will be set to SKIPPED:
- The specified nova-compute service is not found
- The specified nova-compute service is in the desired state

View File

@@ -118,7 +118,22 @@ class ChangeNovaServiceState(base.BaseAction):
return nova.disable_service_nova_compute(self.host, self.reason)
def pre_condition(self):
pass
"""Check change_nova_service_state preconditions
Skipping conditions:
- nova-compute service does not exist
- nova-compute service is already in the desired state
"""
nova = nova_helper.NovaHelper(osc=self.osc)
services = nova.get_service_list()
service = next((s for s in services if s.host == self.host), None)
if service is None:
raise exception.ActionSkipped(
_("nova-compute service %s not found") % self.host)
if service.status == self.state:
raise exception.ActionSkipped(
_("nova-compute service %s is already in state %s") %
(self.host, self.state))
def post_condition(self):
pass

View File

@@ -20,12 +20,14 @@ import jsonschema
from watcher.applier.actions import base as baction
from watcher.applier.actions import change_nova_service_state
from watcher.common import clients
from watcher.common import exception
from watcher.common import nova_helper
from watcher.decision_engine.model import element
from watcher.tests.unit import base
from watcher.tests.unit.common import utils as test_utils
class TestChangeNovaServiceState(base.TestCase):
class TestChangeNovaServiceState(test_utils.NovaResourcesMixin, base.TestCase):
def setUp(self):
super().setUp()
@@ -87,11 +89,53 @@ class TestChangeNovaServiceState(base.TestCase):
self.assertRaises(jsonschema.ValidationError,
self.action.validate_parameters)
def test_change_service_state_pre_condition(self):
try:
self.action.pre_condition()
except Exception as exc:
self.fail(exc)
def test_change_service_state_pre_condition_enable(self):
svc1 = nova_helper.Service.from_openstacksdk(
self.create_openstacksdk_service(
host='compute-1',
status=element.ServiceState.DISABLED.value)
)
self.m_helper.get_service_list.return_value = [svc1]
self.action.pre_condition()
self.m_helper.get_service_list.assert_called_once_with()
def test_change_service_state_pre_condition_disable(self):
self.action.input_parameters["state"] = (
element.ServiceState.DISABLED.value)
svc1 = nova_helper.Service.from_openstacksdk(
self.create_openstacksdk_service(
host='compute-1',
status=element.ServiceState.ENABLED.value)
)
self.m_helper.get_service_list.return_value = [svc1]
self.action.pre_condition()
self.m_helper.get_service_list.assert_called_once_with()
def test_change_service_state_pre_condition_skipped_not_found(self):
svc1 = nova_helper.Service.from_openstacksdk(
self.create_openstacksdk_service(
host='compute-2',
status=element.ServiceState.DISABLED.value)
)
self.m_helper.get_service_list.return_value = [svc1]
self.assertRaisesRegex(
exception.ActionSkipped,
"nova-compute service compute-1 not found",
self.action.pre_condition)
self.m_helper.get_service_list.assert_called_once_with()
def test_change_service_state_pre_condition_skipped_state(self):
svc1 = nova_helper.Service.from_openstacksdk(
self.create_openstacksdk_service(
host='compute-1',
status=element.ServiceState.ENABLED.value)
)
self.m_helper.get_service_list.return_value = [svc1]
self.assertRaisesRegex(
exception.ActionSkipped,
"nova-compute service compute-1 is already in state enabled",
self.action.pre_condition)
self.m_helper.get_service_list.assert_called_once_with()
def test_change_service_state_post_condition(self):
try: