Enable processing of active nodes
Change-Id: Ie369251bb11f36006c3921b3b40800288b49bbc2 Story: 2005896 Task: 33755
This commit is contained in:
parent
3e702f65db
commit
46a90d6dad
@ -27,8 +27,11 @@ CONF = cfg.CONF
|
||||
LOG = utils.getProcessingLogger(__name__)
|
||||
|
||||
# See https://docs.openstack.org/ironic/latest/contributor/states.html # noqa
|
||||
VALID_STATES = {'enroll', 'manageable', 'inspecting', 'inspect wait',
|
||||
'inspect failed'}
|
||||
VALID_STATES = frozenset(['enroll', 'manageable', 'inspecting', 'inspect wait',
|
||||
'inspect failed'])
|
||||
|
||||
# States where an instance is deployed and an admin may be doing something.
|
||||
VALID_ACTIVE_STATES = frozenset(['active', 'rescue'])
|
||||
|
||||
# 1.38 is the latest API version in the Queens release series, 10.1.0.
|
||||
# 1.46 is the latest API version in the Rocky release series, 11.1.0.
|
||||
@ -135,11 +138,27 @@ def get_client(token=None,
|
||||
|
||||
|
||||
def check_provision_state(node):
|
||||
"""Sanity checks the provision state of the node.
|
||||
|
||||
:param node: An API client returned node object describing
|
||||
the baremetal node according to ironic's node
|
||||
data model.
|
||||
:returns: None if no action is to be taken, True if the
|
||||
power node state should not be modified.
|
||||
:raises: Error on an invalid state being detected.
|
||||
"""
|
||||
state = node.provision_state.lower()
|
||||
if state not in VALID_STATES:
|
||||
if (CONF.processing.permit_active_introspection
|
||||
and state in VALID_ACTIVE_STATES):
|
||||
# Hey, we can leave the power on! Lets return
|
||||
# True to let the caller know.
|
||||
return True
|
||||
|
||||
msg = _('Invalid provision state for introspection: '
|
||||
'"%(state)s", valid states are "%(valid)s"')
|
||||
raise utils.Error(msg % {'state': state, 'valid': list(VALID_STATES)},
|
||||
raise utils.Error(msg % {'state': state,
|
||||
'valid': list(VALID_STATES)},
|
||||
node_info=node)
|
||||
|
||||
|
||||
|
@ -94,7 +94,15 @@ _OPTS = [
|
||||
'{mac} - PXE booting MAC or "unknown".')),
|
||||
cfg.BoolOpt('power_off',
|
||||
default=True,
|
||||
help=_('Whether to power off a node after introspection.')),
|
||||
help=_('Whether to power off a node after introspection.'
|
||||
'Nodes in active or rescue states which submit '
|
||||
'introspection data will be left on if the feature '
|
||||
'is enabled via the \'permit_active_introspection\' '
|
||||
'configuration option.')),
|
||||
cfg.BoolOpt('permit_active_introspection',
|
||||
default=False,
|
||||
help=_('Whether to process nodes that are in running '
|
||||
'states.')),
|
||||
]
|
||||
|
||||
|
||||
|
@ -259,7 +259,8 @@ def _run_post_hooks(node_info, introspection_data):
|
||||
@node_cache.fsm_transition(istate.Events.process, reentrant=False)
|
||||
def _process_node(node_info, node, introspection_data):
|
||||
# NOTE(dtantsur): repeat the check in case something changed
|
||||
ir_utils.check_provision_state(node)
|
||||
keep_power_on = ir_utils.check_provision_state(node)
|
||||
|
||||
_run_post_hooks(node_info, introspection_data)
|
||||
store_introspection_data(node_info.uuid, introspection_data)
|
||||
|
||||
@ -271,8 +272,13 @@ def _process_node(node_info, node, introspection_data):
|
||||
|
||||
resp = {'uuid': node.uuid}
|
||||
|
||||
# determine how to handle power
|
||||
if keep_power_on:
|
||||
power_action = False
|
||||
else:
|
||||
power_action = CONF.processing.power_off
|
||||
utils.executor().submit(_finish, node_info, ironic, introspection_data,
|
||||
power_off=CONF.processing.power_off)
|
||||
power_off=power_action)
|
||||
|
||||
return resp
|
||||
|
||||
|
@ -433,6 +433,30 @@ class TestProcessNode(BaseTest):
|
||||
post_hook_mock.assert_called_once_with(self.data, self.node_info)
|
||||
finished_mock.assert_called_once_with(mock.ANY, istate.Events.finish)
|
||||
|
||||
@mock.patch.object(example_plugin.ExampleProcessingHook, 'before_update',
|
||||
autospec=True)
|
||||
@mock.patch.object(node_cache.NodeInfo, 'finished', autospec=True)
|
||||
def test_ok_node_active(self, finished_mock, post_hook_mock):
|
||||
self.node.provision_state = 'active'
|
||||
CONF.set_override('permit_active_introspection', True, 'processing')
|
||||
process._process_node(self.node_info, self.node, self.data)
|
||||
|
||||
self.cli.port.create.assert_any_call(node_uuid=self.uuid,
|
||||
address=self.macs[0],
|
||||
extra={},
|
||||
pxe_enabled=True)
|
||||
self.cli.port.create.assert_any_call(node_uuid=self.uuid,
|
||||
address=self.macs[1],
|
||||
extra={},
|
||||
pxe_enabled=False)
|
||||
|
||||
self.cli.node.set_power_state.assert_not_called()
|
||||
self.assertFalse(self.cli.node.validate.called)
|
||||
|
||||
post_hook_mock.assert_called_once_with(mock.ANY, self.data,
|
||||
self.node_info)
|
||||
finished_mock.assert_called_once_with(mock.ANY, istate.Events.finish)
|
||||
|
||||
def test_port_failed(self):
|
||||
self.cli.port.create.side_effect = (
|
||||
[exceptions.Conflict()] + self.ports[1:])
|
||||
|
@ -0,0 +1,11 @@
|
||||
---
|
||||
features:
|
||||
- |
|
||||
Adds the capability for introspection data to be posted to the API
|
||||
when a baremetal node is in ``active`` or ``rescue`` states. This
|
||||
feature may be useful for data center operators who wish to update
|
||||
introspection data periodically.
|
||||
|
||||
To enable this feature, set ``[processing]permit_active_introspection``
|
||||
to ``True``. When this is set, the value of ``[processing]power_off`` is
|
||||
overridden for nodes in ``active`` or ``rescue`` states.
|
Loading…
Reference in New Issue
Block a user