Merge "Inspection: account for disable_power_off"

This commit is contained in:
Zuul 2024-11-21 15:17:07 +00:00 committed by Gerrit Code Review
commit e57e3cb330
4 changed files with 103 additions and 8 deletions

View File

@ -53,16 +53,17 @@ class AgentInspect(common.Common):
ep = f'{ep}/v1/continue_inspection'
common.prepare_managed_inspection(task, ep)
cond_utils.node_power_action(task, states.POWER_ON)
self._power_on_or_reboot(task)
def _start_unmanaged_inspection(self, task):
"""Start unmanaged inspection."""
try:
cond_utils.node_power_action(task, states.POWER_OFF)
if not task.node.disable_power_off:
cond_utils.node_power_action(task, states.POWER_OFF)
# Only network boot is supported for unmanaged inspection.
cond_utils.node_set_boot_device(task, boot_devices.PXE,
persistent=False)
cond_utils.node_power_action(task, states.POWER_ON)
self._power_on_or_reboot(task)
except Exception as exc:
LOG.exception('Unable to start unmanaged inspection for node '
'%(uuid)s: %(err)s',

View File

@ -86,11 +86,20 @@ def tear_down_managed_boot(task, always_power_off=False):
if ((ironic_manages_boot or always_power_off)
and CONF.inspector.power_off
and not utils.fast_track_enabled(task.node)):
if task.node.disable_power_off:
LOG.debug('Rebooting node %s instead of powering it off because '
'disable_power_off is set to True', task.node.uuid)
power_state = states.REBOOT
err_msg = _('unable to reboot the node: %s')
else:
power_state = states.POWER_OFF
err_msg = _('unable to power off the node: %s')
try:
cond_utils.node_power_action(task, states.POWER_OFF)
cond_utils.node_power_action(task, power_state)
except Exception as exc:
errors.append(_('unable to power off the node: %s') % exc)
LOG.exception('Unable to power off node %s', task.node.uuid)
errors.append(err_msg % exc)
LOG.exception(err_msg, task.node.uuid)
return errors
@ -146,7 +155,8 @@ def prepare_managed_inspection(task, endpoint):
if utils.fast_track_enabled(task.node):
params['ipa-api-url'] = deploy_utils.get_ironic_api_url()
cond_utils.node_power_action(task, states.POWER_OFF)
if not task.node.disable_power_off:
cond_utils.node_power_action(task, states.POWER_OFF)
with cond_utils.power_state_for_network_configuration(task):
task.driver.network.add_inspection_network(task)
task.driver.boot.prepare_ramdisk(task, ramdisk_params=params)
@ -232,6 +242,12 @@ class Common(base.InspectInterface):
self._start_unmanaged_inspection(task)
return states.INSPECTWAIT
def _power_on_or_reboot(self, task):
# Handles disable_power_off properly
next_state = (states.REBOOT if task.node.disable_power_off
else states.POWER_ON)
cond_utils.node_power_action(task, next_state)
class Inspector(Common):
"""In-band inspection via ironic-inspector project."""
@ -242,7 +258,7 @@ class Inspector(Common):
endpoint = _get_callback_endpoint(cli)
prepare_managed_inspection(task, endpoint)
cli.start_introspection(task.node.uuid, manage_boot=False)
cond_utils.node_power_action(task, states.POWER_ON)
self._power_on_or_reboot(task)
def _start_unmanaged_inspection(self, task):
"""Call to inspector to start inspection."""

View File

@ -61,6 +61,24 @@ class InspectHardwareTestCase(db_base.DbTestCase):
self.assertFalse(self.driver.network.remove_inspection_network.called)
self.assertFalse(self.driver.boot.clean_up_ramdisk.called)
def test_unmanaged_disable_power_off(self, mock_create_ports_if_not_exist):
CONF.set_override('require_managed_boot', False, group='inspector')
self.driver.boot.validate_inspection.side_effect = (
exception.UnsupportedDriverExtension(''))
self.node.disable_power_off = True
self.assertEqual(states.INSPECTWAIT,
self.iface.inspect_hardware(self.task))
mock_create_ports_if_not_exist.assert_called_once_with(self.task)
self.assertFalse(self.driver.boot.prepare_ramdisk.called)
self.assertFalse(self.driver.network.add_inspection_network.called)
self.driver.management.set_boot_device.assert_called_once_with(
self.task, device=boot_devices.PXE, persistent=False)
self.driver.power.reboot.assert_called_once_with(
self.task, timeout=None)
self.driver.power.set_power_state.assert_not_called()
self.assertFalse(self.driver.network.remove_inspection_network.called)
self.assertFalse(self.driver.boot.clean_up_ramdisk.called)
def test_unmanaged_disallowed(self, mock_create_ports_if_not_exist):
self.driver.boot.validate_inspection.side_effect = (
exception.UnsupportedDriverExtension(''))
@ -109,6 +127,27 @@ class InspectHardwareTestCase(db_base.DbTestCase):
self.assertFalse(self.driver.network.remove_inspection_network.called)
self.assertFalse(self.driver.boot.clean_up_ramdisk.called)
@mock.patch.object(deploy_utils, 'get_ironic_api_url', autospec=True)
def test_managed_disable_power_off(self, mock_get_url,
mock_create_ports_if_not_exist):
endpoint = 'http://192.169.0.42:6385/v1'
mock_get_url.return_value = endpoint
self.node.disable_power_off = True
self.assertEqual(states.INSPECTWAIT,
self.iface.inspect_hardware(self.task))
self.driver.boot.prepare_ramdisk.assert_called_once_with(
self.task, ramdisk_params={
'ipa-inspection-callback-url':
f'{endpoint}/continue_inspection',
})
self.driver.network.add_inspection_network.assert_called_once_with(
self.task)
self.driver.power.reboot.assert_called_once_with(
self.task, timeout=None)
self.driver.power.set_power_state.assert_not_called()
self.assertFalse(self.driver.network.remove_inspection_network.called)
self.assertFalse(self.driver.boot.clean_up_ramdisk.called)
@mock.patch.object(common, 'tear_down_managed_boot', autospec=True)
@mock.patch.object(inspector, 'run_inspection_hooks', autospec=True)

View File

@ -322,6 +322,31 @@ class InspectHardwareTestCase(BaseTestCase):
self.driver.power.set_power_state.assert_called_with(
self.task, 'power off', timeout=None)
@mock.patch.object(redfish_utils, 'get_system', autospec=True)
@mock.patch.object(inspect_utils, 'create_ports_if_not_exist',
autospec=True)
def test_managed_disable_power_off(self, mock_create_ports_if_not_exist,
mock_get_system, mock_client):
endpoint = 'http://192.169.0.42:5050/v1'
mock_client.return_value.get_endpoint.return_value = endpoint
mock_introspect = mock_client.return_value.start_introspection
self.node.disable_power_off = True
self.assertEqual(states.INSPECTWAIT,
self.iface.inspect_hardware(self.task))
mock_introspect.assert_called_once_with(self.node.uuid,
manage_boot=False)
self.driver.boot.prepare_ramdisk.assert_called_once_with(
self.task, ramdisk_params={
'ipa-inspection-callback-url': endpoint + '/continue',
})
self.driver.network.add_inspection_network.assert_called_once_with(
self.task)
self.driver.power.reboot.assert_called_once_with(
self.task, timeout=None)
self.driver.power.set_power_state.assert_not_called()
self.assertFalse(self.driver.network.remove_inspection_network.called)
self.assertFalse(self.driver.boot.clean_up_ramdisk.called)
class TearDownManagedInspectionTestCase(BaseTestCase):
@ -379,6 +404,20 @@ class TearDownManagedInspectionTestCase(BaseTestCase):
self.driver.boot.clean_up_ramdisk.assert_called_once_with(self.task)
self.assertFalse(self.driver.power.set_power_state.called)
def test_managed_disable_power_off(self):
utils.set_node_nested_field(self.node, 'driver_internal_info',
'inspector_manage_boot', True)
self.node.disable_power_off = True
self.node.save()
inspector.tear_down_managed_boot(self.task)
self.driver.network.remove_inspection_network.assert_called_once_with(
self.task)
self.driver.boot.clean_up_ramdisk.assert_called_once_with(self.task)
self.driver.power.reboot.assert_called_once_with(
self.task, timeout=None)
def _test_clean_up_failed(self):
utils.set_node_nested_field(self.node, 'driver_internal_info',
'inspector_manage_boot', True)