Merge "Enable processing of active nodes"

This commit is contained in:
Zuul 2019-07-04 01:23:24 +00:00 committed by Gerrit Code Review
commit c04f54ced0
5 changed files with 74 additions and 6 deletions

View File

@ -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)

View File

@ -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.')),
]

View File

@ -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

View File

@ -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:])

View File

@ -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.