Ensure enable_netboot_fallback writes out pxe config on adopt.

without the ipxe config adopted nodes that would have needed
the fallback ipxe config to boot from disk will fail (as they
continuously attempt to network boot) and instead boot into
the discovery image.

Story: #2009259
Task: #43471

Change-Id: I42e555a1a01eb4124e3152669578f3403db83801
This commit is contained in:
Derek Higgins 2021-09-30 10:26:00 +01:00
parent b9baf7dbc8
commit eb65c0de92
6 changed files with 50 additions and 5 deletions

View File

@ -967,7 +967,7 @@ def build_service_pxe_config(task, instance_image_info,
# fail if the agent was booted outside the direct actions of the # fail if the agent was booted outside the direct actions of the
# boot interface. # boot interface.
if (node.provision_state in [states.ACTIVE, states.UNRESCUING, if (node.provision_state in [states.ACTIVE, states.UNRESCUING,
states.DEPLOYING] states.DEPLOYING, states.ADOPTING]
and not os.path.isfile(pxe_config_path)): and not os.path.isfile(pxe_config_path)):
pxe_options = build_pxe_config_options(task, instance_image_info, pxe_options = build_pxe_config_options(task, instance_image_info,
service=True, service=True,

View File

@ -364,10 +364,11 @@ class CustomAgentDeploy(agent_base.AgentBaseMixin, agent_base.AgentDeployMixin,
# Alternatively, we could be in a fast track deployment # Alternatively, we could be in a fast track deployment
# and again, we should have nothing to do here. # and again, we should have nothing to do here.
return return
if node.provision_state in (states.ACTIVE, states.UNRESCUING): if node.provision_state in (states.ACTIVE, states.UNRESCUING,
states.ADOPTING):
# Call is due to conductor takeover # Call is due to conductor takeover
task.driver.boot.prepare_instance(task) task.driver.boot.prepare_instance(task)
elif node.provision_state != states.ADOPTING: else:
if node.provision_state not in (states.RESCUING, states.RESCUEWAIT, if node.provision_state not in (states.RESCUING, states.RESCUEWAIT,
states.RESCUE, states.RESCUEFAIL): states.RESCUE, states.RESCUEFAIL):
self._update_instance_info(task) self._update_instance_info(task)

View File

@ -283,7 +283,8 @@ class PXEBaseMixin(object):
# NOTE(pas-ha) do not re-set boot device on ACTIVE nodes # NOTE(pas-ha) do not re-set boot device on ACTIVE nodes
# during takeover # during takeover
if boot_device and task.node.provision_state != states.ACTIVE: if boot_device and (task.node.provision_state not in
(states.ACTIVE, states.ADOPTING)):
manager_utils.node_set_boot_device(task, boot_device, manager_utils.node_set_boot_device(task, boot_device,
persistent=True) persistent=True)

View File

@ -2387,6 +2387,41 @@ class iPXEBuildConfigOptionsTestCase(db_base.DbTestCase):
os.path.join(CONF.deploy.http_root, self.node.uuid)) os.path.join(CONF.deploy.http_root, self.node.uuid))
@mock.patch.object(ipxe.iPXEBoot, '__init__', lambda self: None)
class iPXEBuildServicePXEConfigTestCase(db_base.DbTestCase):
def setUp(self):
super(iPXEBuildServicePXEConfigTestCase, self).setUp()
n = {
'driver': 'fake-hardware',
'boot_interface': 'ipxe',
'instance_info': INST_INFO_DICT,
'driver_info': DRV_INFO_DICT,
'driver_internal_info': DRV_INTERNAL_INFO_DICT,
}
self.config(enabled_boot_interfaces=['ipxe'])
self.node = object_utils.create_test_node(self.context, **n)
@mock.patch.object(pxe_utils, 'create_pxe_config', autospec=True)
@mock.patch.object(deploy_utils, 'switch_pxe_config', autospec=True)
def test_build_service_pxe_config_adopt(self, mock_switch, mock_pxe_utils):
self.node.provision_state = states.ADOPTING
driver_internal_info = self.node.driver_internal_info
driver_internal_info['is_whole_disk_image'] = True
self.node.driver_internal_info = driver_internal_info
self.node.save()
image_info = {}
with task_manager.acquire(self.context, self.node.uuid,
shared=True) as task:
pxe_utils.build_service_pxe_config(task, image_info, 'id',
is_whole_disk_image=True)
mock_pxe_utils.assert_called()
mock_switch.assert_called()
@mock.patch.object(ironic_utils, 'unlink_without_raise', autospec=True) @mock.patch.object(ironic_utils, 'unlink_without_raise', autospec=True)
@mock.patch.object(pxe_utils, 'clean_up_pxe_config', autospec=True) @mock.patch.object(pxe_utils, 'clean_up_pxe_config', autospec=True)
@mock.patch.object(pxe_utils, 'TFTPImageCache', autospec=True) @mock.patch.object(pxe_utils, 'TFTPImageCache', autospec=True)

View File

@ -984,6 +984,7 @@ class TestAgentDeploy(CommonTestsMixin, db_base.DbTestCase):
self.assertTrue(storage_attach_volumes_mock.called) self.assertTrue(storage_attach_volumes_mock.called)
self.assertEqual(2, should_write_image_mock.call_count) self.assertEqual(2, should_write_image_mock.call_count)
@mock.patch.object(pxe.PXEBoot, 'prepare_instance', autospec=True)
@mock.patch.object(flat_network.FlatNetwork, 'add_provisioning_network', @mock.patch.object(flat_network.FlatNetwork, 'add_provisioning_network',
spec_set=True, autospec=True) spec_set=True, autospec=True)
@mock.patch.object(pxe.PXEBoot, 'prepare_ramdisk', autospec=True) @mock.patch.object(pxe.PXEBoot, 'prepare_ramdisk', autospec=True)
@ -992,7 +993,8 @@ class TestAgentDeploy(CommonTestsMixin, db_base.DbTestCase):
autospec=True) autospec=True)
def test_prepare_adopting( def test_prepare_adopting(
self, build_instance_info_mock, build_options_mock, self, build_instance_info_mock, build_options_mock,
pxe_prepare_ramdisk_mock, add_provisioning_net_mock): pxe_prepare_ramdisk_mock, add_provisioning_net_mock,
prepare_instance_mock):
with task_manager.acquire( with task_manager.acquire(
self.context, self.node['uuid'], shared=False) as task: self.context, self.node['uuid'], shared=False) as task:
task.node.provision_state = states.ADOPTING task.node.provision_state = states.ADOPTING
@ -1003,6 +1005,7 @@ class TestAgentDeploy(CommonTestsMixin, db_base.DbTestCase):
self.assertFalse(build_options_mock.called) self.assertFalse(build_options_mock.called)
self.assertFalse(pxe_prepare_ramdisk_mock.called) self.assertFalse(pxe_prepare_ramdisk_mock.called)
self.assertFalse(add_provisioning_net_mock.called) self.assertFalse(add_provisioning_net_mock.called)
self.assertTrue(prepare_instance_mock.called)
@mock.patch.object(flat_network.FlatNetwork, 'add_provisioning_network', @mock.patch.object(flat_network.FlatNetwork, 'add_provisioning_network',
spec_set=True, autospec=True) spec_set=True, autospec=True)

View File

@ -0,0 +1,5 @@
---
fixes:
- |
Fixes ``enable_netboot_fallback`` to write out pxe config
on adopt.