Browse Source

Yoga: Change default boot mode to uefi

Change the default boot mode to UEFI, as discussed during the end
of the Wallaby release cycle and previously agreed a very long time
ago by the Ironic community.

Change-Id: I6d735604d56d1687f42d0573a2eed765cbb08aec
changes/49/810249/11
Julia Kreger 1 month ago
parent
commit
493b4f0caf
  1. 4
      devstack/common_settings
  2. 7
      devstack/lib/ironic
  3. 10
      doc/source/install/include/boot-mode.inc
  4. 11
      ironic/conf/deploy.py
  5. 14
      ironic/drivers/modules/boot_mode_utils.py
  6. 2
      ironic/drivers/modules/deploy_utils.py
  7. 100
      ironic/tests/unit/common/test_pxe_utils.py
  8. 1
      ironic/tests/unit/drivers/modules/ansible/test_deploy.py
  9. 2
      ironic/tests/unit/drivers/modules/redfish/test_management.py
  10. 135
      ironic/tests/unit/drivers/modules/test_agent_base.py
  11. 15
      ironic/tests/unit/drivers/modules/test_boot_mode_utils.py
  12. 51
      ironic/tests/unit/drivers/modules/test_deploy_utils.py
  13. 56
      ironic/tests/unit/drivers/modules/test_image_utils.py
  14. 54
      ironic/tests/unit/drivers/modules/test_ipmitool.py
  15. 231
      ironic/tests/unit/drivers/modules/test_ipxe.py
  16. 178
      ironic/tests/unit/drivers/modules/test_pxe.py
  17. 4
      ironic/tests/unit/drivers/modules/test_ramdisk.py
  18. 16
      releasenotes/notes/uefi-is-now-the-default-562b0d68adc59008.yaml
  19. 38
      zuul.d/ironic-jobs.yaml

4
devstack/common_settings

@ -5,8 +5,8 @@ if [[ -f $TOP_DIR/../../old/devstack/.localrc.auto ]]; then
fi
# Whether configure the nodes to boot in Legacy BIOS or UEFI mode. Accepted
# values are: "bios" or "uefi", defaults to "bios".
IRONIC_BOOT_MODE=${IRONIC_BOOT_MODE:-bios}
# values are: "bios" or "uefi", defaults to "uefi".
IRONIC_BOOT_MODE=${IRONIC_BOOT_MODE:-uefi}
CIRROS_VERSION_DEVSTACK=$(set +o xtrace &&
source $TOP_DIR/stackrc &&

7
devstack/lib/ironic

@ -2371,6 +2371,9 @@ function enroll_nodes {
if [[ "$IRONIC_BOOT_MODE" == "uefi" ]]; then
node_capabilities+=" --property capabilities=boot_mode:uefi"
fi
if [[ "$IRONIC_BOOT_MODE" == "bios" ]]; then
node_capabilities+=" --property capabilities=boot_mode:bios"
fi
if [[ "$IRONIC_SECURE_BOOT" == "True" ]]; then
if [[ -n "$node_capabilities" ]]; then
node_capabilities+=",secure_boot:true"
@ -2581,7 +2584,9 @@ function enroll_nodes {
if [[ "$IRONIC_BOOT_MODE" == "uefi" ]]; then
openstack --os-cloud $OS_CLOUD flavor set baremetal --property "capabilities:boot_mode"="uefi"
fi
if [[ "$IRONIC_BOOT_MODE" == "bios" ]]; then
openstack --os-cloud $OS_CLOUD flavor set baremetal --property "capabilities:boot_mode"="bios"
fi
for trait in $IRONIC_DEFAULT_TRAITS; do
openstack --os-cloud $OS_CLOUD flavor set baremetal --property "trait:$trait"="required"
done

10
doc/source/install/include/boot-mode.inc

@ -63,6 +63,16 @@ following way:
openstack baremetal node set <node-uuid> --property capabilities='boot_mode:uefi'
Conversely, to configure a node in ``bios`` mode, then set the
``capabilities`` as below::
openstack baremetal node set <node-uuid> --property capabilities='boot_mode:bios'
.. note::
The Ironic project changed the default boot mode setting for nodes from
``bios`` to ``uefi`` during the Yoga development cycle.
Nodes having ``boot_mode`` set to ``uefi`` may be requested by adding an
``extra_spec`` to the Compute service flavor::

11
ironic/conf/deploy.py

@ -132,14 +132,17 @@ opts = [
cfg.StrOpt('default_boot_mode',
choices=[(boot_modes.UEFI, _('UEFI boot mode')),
(boot_modes.LEGACY_BIOS, _('Legacy BIOS boot mode'))],
default=boot_modes.LEGACY_BIOS,
default=boot_modes.UEFI,
mutable=True,
help=_('Default boot mode to use when no boot mode is '
'requested in node\'s driver_info, capabilities or '
'in the `instance_info` configuration. Currently the '
'default boot mode is "%(bios)s", but it will be '
'changed to "%(uefi)s in the future. It is recommended '
'to set an explicit value for this option. This option '
'default boot mode is "%(uefi)s", but it was '
'"%(bios)s" previously in Ironic. It is recommended '
'to set an explicit value for this option, and if the '
'setting or default differs from nodes, to ensure that '
'nodes are configured specifically for their desired '
'boot mode. This option '
'only has effect when management interface supports '
'boot mode management') % {
'bios': boot_modes.LEGACY_BIOS,

14
ironic/drivers/modules/boot_mode_utils.py

@ -16,7 +16,6 @@
from oslo_log import log as logging
from oslo_utils import excutils
from ironic.common import boot_modes
from ironic.common import exception
from ironic.common.i18n import _
from ironic.common import utils as common_utils
@ -293,19 +292,6 @@ def get_boot_mode(node):
boot_mode = get_boot_mode_for_deploy(node)
if boot_mode:
return boot_mode
# TODO(hshiina): The default boot mode will be changed to UEFI.
global warn_about_default_boot_mode
if (not warn_about_default_boot_mode
and CONF.deploy.default_boot_mode == boot_modes.LEGACY_BIOS):
warn_about_default_boot_mode = True
LOG.warning('Boot mode is not configured for node %(node_uuid)s '
'explicitly. The default boot mode is "%(bios)s", but, '
'the default will be changed to "%(uefi)s" in the future. '
'It is recommended to set the boot option into '
'properties/capabilities/boot_mode for all nodes.',
{'node_uuid': node.uuid,
'bios': boot_modes.LEGACY_BIOS,
'uefi': boot_modes.UEFI})
return CONF.deploy.default_boot_mode

2
ironic/drivers/modules/deploy_utils.py

@ -608,7 +608,7 @@ def get_boot_option(node):
:raises: InvalidParameterValue if the capabilities string is not a
dict or is malformed.
:returns: A string representing the boot option type. Defaults to
'netboot'.
configuration setting [deploy]default_boot_mode.
"""
# NOTE(TheJulia): Software raid always implies local deployment

100
ironic/tests/unit/common/test_pxe_utils.py

@ -438,12 +438,14 @@ class TestPXEUtils(db_base.DbTestCase):
unlink_mock.assert_called_once_with('/tftpboot/10.10.0.1.conf')
create_link_mock.assert_has_calls(create_link_calls)
@mock.patch.object(pxe_utils, '_link_ip_address_pxe_configs',
autospec=True)
@mock.patch.object(os, 'chmod', autospec=True)
@mock.patch('ironic.common.utils.write_to_file', autospec=True)
@mock.patch('ironic.common.utils.render_template', autospec=True)
@mock.patch('oslo_utils.fileutils.ensure_tree', autospec=True)
def test_create_pxe_config(self, ensure_tree_mock, render_mock,
write_mock, chmod_mock):
write_mock, chmod_mock, mock_link_ip_addr):
self.config(tftp_root=tempfile.mkdtemp(), group='pxe')
with task_manager.acquire(self.context, self.node.uuid) as task:
pxe_utils.create_pxe_config(task, self.pxe_options,
@ -451,8 +453,8 @@ class TestPXEUtils(db_base.DbTestCase):
render_mock.assert_called_with(
CONF.pxe.pxe_config_template,
{'pxe_options': self.pxe_options,
'ROOT': '{{ ROOT }}',
'DISK_IDENTIFIER': '{{ DISK_IDENTIFIER }}'}
'ROOT': '(( ROOT ))',
'DISK_IDENTIFIER': '(( DISK_IDENTIFIER ))'}
)
node_dir = os.path.join(CONF.pxe.tftp_root, self.node.uuid)
pxe_dir = os.path.join(CONF.pxe.tftp_root, 'pxelinux.cfg')
@ -465,14 +467,18 @@ class TestPXEUtils(db_base.DbTestCase):
pxe_cfg_file_path = pxe_utils.get_pxe_config_file_path(self.node.uuid)
write_mock.assert_called_with(pxe_cfg_file_path,
render_mock.return_value)
self.assertTrue(mock_link_ip_addr.called)
@mock.patch.object(pxe_utils, '_link_ip_address_pxe_configs',
autospec=True)
@mock.patch.object(os, 'chmod', autospec=True)
@mock.patch('ironic.common.utils.write_to_file', autospec=True)
@mock.patch('ironic.common.utils.render_template', autospec=True)
@mock.patch('oslo_utils.fileutils.ensure_tree', autospec=True)
def test_create_pxe_config_set_dir_permission(self, ensure_tree_mock,
render_mock,
write_mock, chmod_mock):
write_mock, chmod_mock,
mock_link_ip_addr):
self.config(tftp_root=tempfile.mkdtemp(), group='pxe')
self.config(dir_permission=0o755, group='pxe')
with task_manager.acquire(self.context, self.node.uuid) as task:
@ -481,8 +487,8 @@ class TestPXEUtils(db_base.DbTestCase):
render_mock.assert_called_with(
CONF.pxe.pxe_config_template,
{'pxe_options': self.pxe_options,
'ROOT': '{{ ROOT }}',
'DISK_IDENTIFIER': '{{ DISK_IDENTIFIER }}'}
'ROOT': '(( ROOT ))',
'DISK_IDENTIFIER': '(( DISK_IDENTIFIER ))'}
)
node_dir = os.path.join(CONF.pxe.tftp_root, self.node.uuid)
pxe_dir = os.path.join(CONF.pxe.tftp_root, 'pxelinux.cfg')
@ -496,17 +502,51 @@ class TestPXEUtils(db_base.DbTestCase):
pxe_cfg_file_path = pxe_utils.get_pxe_config_file_path(self.node.uuid)
write_mock.assert_called_with(pxe_cfg_file_path,
render_mock.return_value)
self.assertTrue(mock_link_ip_addr.called)
@mock.patch.object(pxe_utils, '_link_ip_address_pxe_configs',
autospec=True)
@mock.patch.object(os.path, 'isdir', autospec=True)
@mock.patch.object(os, 'chmod', autospec=True)
@mock.patch('ironic.common.utils.write_to_file', autospec=True)
@mock.patch('ironic.common.utils.render_template', autospec=True)
@mock.patch('oslo_utils.fileutils.ensure_tree', autospec=True)
def test_create_pxe_config_existing_dirs(self, ensure_tree_mock,
render_mock,
write_mock, chmod_mock,
isdir_mock):
def test_create_pxe_config_existing_dirs_uefi(
self, ensure_tree_mock,
render_mock,
write_mock, chmod_mock,
isdir_mock, mock_link_ip_address):
self.config(dir_permission=0o755, group='pxe')
with task_manager.acquire(self.context, self.node.uuid) as task:
isdir_mock.return_value = True
pxe_utils.create_pxe_config(task, self.pxe_options,
CONF.pxe.pxe_config_template)
render_mock.assert_called_with(
CONF.pxe.pxe_config_template,
{'pxe_options': self.pxe_options,
'ROOT': '(( ROOT ))',
'DISK_IDENTIFIER': '(( DISK_IDENTIFIER ))'}
)
ensure_tree_mock.assert_has_calls([])
chmod_mock.assert_not_called()
isdir_mock.assert_has_calls([])
pxe_cfg_file_path = pxe_utils.get_pxe_config_file_path(self.node.uuid)
write_mock.assert_called_with(pxe_cfg_file_path,
render_mock.return_value)
self.assertTrue(mock_link_ip_address.called)
@mock.patch.object(os.path, 'isdir', autospec=True)
@mock.patch.object(os, 'chmod', autospec=True)
@mock.patch('ironic.common.utils.write_to_file', autospec=True)
@mock.patch('ironic.common.utils.render_template', autospec=True)
@mock.patch('oslo_utils.fileutils.ensure_tree', autospec=True)
def test_create_pxe_config_existing_dirs_bios(
self, ensure_tree_mock,
render_mock,
write_mock, chmod_mock,
isdir_mock):
self.config(dir_permission=0o755, group='pxe')
self.config(default_boot_mode='bios', group='deploy')
with task_manager.acquire(self.context, self.node.uuid) as task:
isdir_mock.return_value = True
pxe_utils.create_pxe_config(task, self.pxe_options,
@ -634,9 +674,12 @@ class TestPXEUtils(db_base.DbTestCase):
write_mock.assert_called_with(pxe_cfg_file_path,
render_mock.return_value)
@mock.patch('ironic.dhcp.neutron.NeutronDHCPApi.get_ip_addresses',
autospec=True)
@mock.patch('ironic.common.utils.rmtree_without_raise', autospec=True)
@mock.patch('ironic_lib.utils.unlink_without_raise', autospec=True)
def test_clean_up_pxe_config(self, unlink_mock, rmtree_mock):
def test_clean_up_pxe_config(self, unlink_mock, rmtree_mock,
mock_get_ip_addr):
address = "aa:aa:aa:aa:aa:aa"
object_utils.create_test_port(self.context, node_id=self.node.id,
address=address)
@ -654,6 +697,7 @@ class TestPXEUtils(db_base.DbTestCase):
unlink_mock.assert_has_calls(ensure_calls)
rmtree_mock.assert_called_once_with(
os.path.join(CONF.pxe.tftp_root, self.node.uuid))
self.assertTrue(mock_get_ip_addr.called)
@mock.patch.object(os.path, 'isfile', lambda path: False)
@mock.patch('ironic.common.utils.file_has_content', autospec=True)
@ -737,7 +781,19 @@ class TestPXEUtils(db_base.DbTestCase):
self.config(tftp_server='192.0.2.1', group='pxe')
elif ip_version == 6:
self.config(tftp_server='ff80::1', group='pxe')
self.config(pxe_bootfile_name='fake-bootfile', group='pxe')
if CONF.deploy.default_boot_mode == 'uefi':
if ipxe:
self.config(uefi_ipxe_bootfile_name='fake-bootfile-ipxe',
group='pxe')
else:
self.config(uefi_pxe_bootfile_name='fake-bootfile',
group='pxe')
else:
if ipxe:
self.config(ipxe_bootfile_name='fake-bootfile-ipxe',
group='pxe')
else:
self.config(pxe_bootfile_name='fake-bootfile', group='pxe')
self.config(tftp_root='/tftp-path/', group='pxe')
if ipxe:
bootfile = 'fake-bootfile-ipxe'
@ -774,12 +830,22 @@ class TestPXEUtils(db_base.DbTestCase):
pxe_utils.dhcp_options_for_instance(task))
def test_dhcp_options_for_instance(self):
self.config(default_boot_mode='uefi', group='deploy')
self._dhcp_options_for_instance(ip_version=4)
def test_dhcp_options_for_instance_bios(self):
self.config(default_boot_mode='bios', group='deploy')
self._dhcp_options_for_instance(ip_version=4)
def test_dhcp_options_for_instance_ipv6(self):
self.config(tftp_server='ff80::1', group='pxe')
self._dhcp_options_for_instance(ip_version=6)
def test_dhcp_options_for_instance_ipv6_bios(self):
self.config(tftp_server='ff80::1', group='pxe')
self.config(default_boot_mode='bios', group='deploy')
self._dhcp_options_for_instance(ip_version=6)
def _test_get_kernel_ramdisk_info(self, expected_dir, mode='deploy',
ipxe_enabled=False):
node_uuid = 'fake-node'
@ -1705,6 +1771,7 @@ class iPXEBuildConfigOptionsTestCase(db_base.DbTestCase):
def test_dhcp_options_for_instance_ipxe_bios(self):
self.config(ip_version=4, group='pxe')
boot_file = 'fake-bootfile-bios-ipxe'
self.config(default_boot_mode='bios', group='deploy')
self.config(ipxe_bootfile_name=boot_file, group='pxe')
with task_manager.acquire(self.context, self.node.uuid) as task:
self._dhcp_options_for_instance_ipxe(task, boot_file)
@ -1721,6 +1788,15 @@ class iPXEBuildConfigOptionsTestCase(db_base.DbTestCase):
self.config(ip_version=6, group='pxe')
boot_file = 'fake-bootfile-ipxe'
self.config(ipxe_bootfile_name=boot_file, group='pxe')
self.config(default_boot_mode='bios', group='deploy')
with task_manager.acquire(self.context, self.node.uuid) as task:
self._dhcp_options_for_instance_ipxe(task, boot_file, ip_version=6)
def test_dhcp_options_for_ipxe_ipv6_uefi(self):
self.config(ip_version=6, group='pxe')
boot_file = 'fake-bootfile-ipxe'
self.config(uefi_ipxe_bootfile_name=boot_file, group='pxe')
self.config(default_boot_mode='uefi', group='deploy')
with task_manager.acquire(self.context, self.node.uuid) as task:
self._dhcp_options_for_instance_ipxe(task, boot_file, ip_version=6)

1
ironic/tests/unit/drivers/modules/ansible/test_deploy.py

@ -242,6 +242,7 @@ class TestAnsibleMethods(AnsibleDeployTestCaseBase):
'--private-key=/path/to/key')
def test__parse_partitioning_info_root_msdos(self):
self.config(default_boot_mode='bios', group='deploy')
expected_info = {
'partition_info': {
'label': 'msdos',

2
ironic/tests/unit/drivers/modules/redfish/test_management.py

@ -290,7 +290,7 @@ class RedfishManagementTestCase(db_base.DbTestCase):
fake_system.set_system_boot_options.assert_has_calls(
[mock.call(sushy.BOOT_SOURCE_TARGET_PXE,
enabled=expected),
mock.call(mode=sushy.BOOT_SOURCE_MODE_BIOS)])
mock.call(mode=sushy.BOOT_SOURCE_MODE_UEFI)])
else:
fake_system.set_system_boot_options.assert_has_calls(
[mock.call(sushy.BOOT_SOURCE_TARGET_PXE,

135
ironic/tests/unit/drivers/modules/test_agent_base.py

@ -982,6 +982,24 @@ class AgentDeployMixinTest(AgentDeployMixinBaseTest):
def test_configure_local_boot_whole_disk_image(
self, install_bootloader_mock, try_set_boot_device_mock):
with task_manager.acquire(self.context, self.node['uuid'],
shared=False) as task:
self.deploy.configure_local_boot(task)
# NOTE(TheJulia): We explicitly call install_bootloader when
# we have a whole disk image *and* are in UEFI mode as setting
# the internal NVRAM helps negate need to know a root device
# hint if the boot order is weird.
self.assertTrue(install_bootloader_mock.called)
try_set_boot_device_mock.assert_called_once_with(
task, boot_devices.DISK, persistent=True)
@mock.patch.object(deploy_utils, 'try_set_boot_device', autospec=True)
@mock.patch.object(agent_client.AgentClient, 'install_bootloader',
autospec=True)
def test_configure_local_boot_whole_disk_image_bios(
self, install_bootloader_mock, try_set_boot_device_mock):
self.config(default_boot_mode='bios', group='deploy')
with task_manager.acquire(self.context, self.node['uuid'],
shared=False) as task:
self.deploy.configure_local_boot(task)
@ -1032,6 +1050,45 @@ class AgentDeployMixinTest(AgentDeployMixinBaseTest):
GlanceImageService_mock):
image = GlanceImageService_mock.return_value.show.return_value
image.get.return_value = {'rootfs_uuid': 'rootfs'}
with task_manager.acquire(self.context, self.node['uuid'],
shared=False) as task:
task.node.driver_internal_info['is_whole_disk_image'] = True
task.node.target_raid_config = {
"logical_disks": [
{
"size_gb": 100,
"raid_level": "1",
"controller": "software",
},
{
"size_gb": 'MAX',
"raid_level": "0",
"controller": "software",
}
]
}
self.deploy.configure_local_boot(task)
self.assertTrue(GlanceImageService_mock.called)
install_bootloader_mock.assert_called_once_with(
mock.ANY, task.node,
root_uuid='rootfs',
efi_system_part_uuid=None,
prep_boot_part_uuid=None,
target_boot_mode='uefi',
software_raid=True)
try_set_boot_device_mock.assert_called_once_with(
task, boot_devices.DISK, persistent=True)
@mock.patch.object(image_service, 'GlanceImageService', autospec=True)
@mock.patch.object(deploy_utils, 'try_set_boot_device', autospec=True)
@mock.patch.object(agent_client.AgentClient, 'install_bootloader',
autospec=True)
def test_configure_local_boot_on_software_raid_bios(
self, install_bootloader_mock, try_set_boot_device_mock,
GlanceImageService_mock):
self.config(default_boot_mode='bios', group='deploy')
image = GlanceImageService_mock.return_value.show.return_value
image.get.return_value = {'rootfs_uuid': 'rootfs'}
with task_manager.acquire(self.context, self.node['uuid'],
shared=False) as task:
task.node.driver_internal_info['is_whole_disk_image'] = True
@ -1068,6 +1125,44 @@ class AgentDeployMixinTest(AgentDeployMixinBaseTest):
def test_configure_local_boot_on_software_raid_explicit_uuid(
self, install_bootloader_mock, try_set_boot_device_mock,
GlanceImageService_mock):
with task_manager.acquire(self.context, self.node['uuid'],
shared=False) as task:
task.node.driver_internal_info['is_whole_disk_image'] = True
task.node.instance_info['image_rootfs_uuid'] = 'rootfs'
task.node.target_raid_config = {
"logical_disks": [
{
"size_gb": 100,
"raid_level": "1",
"controller": "software",
},
{
"size_gb": 'MAX',
"raid_level": "0",
"controller": "software",
}
]
}
self.deploy.configure_local_boot(task)
self.assertFalse(GlanceImageService_mock.called)
install_bootloader_mock.assert_called_once_with(
mock.ANY, task.node,
root_uuid='rootfs',
efi_system_part_uuid=None,
prep_boot_part_uuid=None,
target_boot_mode='uefi',
software_raid=True)
try_set_boot_device_mock.assert_called_once_with(
task, boot_devices.DISK, persistent=True)
@mock.patch.object(image_service, 'GlanceImageService', autospec=True)
@mock.patch.object(deploy_utils, 'try_set_boot_device', autospec=True)
@mock.patch.object(agent_client.AgentClient, 'install_bootloader',
autospec=True)
def test_configure_local_boot_on_software_raid_explicit_uuid_bios(
self, install_bootloader_mock, try_set_boot_device_mock,
GlanceImageService_mock):
self.config(default_boot_mode='bios', group='deploy')
with task_manager.acquire(self.context, self.node['uuid'],
shared=False) as task:
task.node.driver_internal_info['is_whole_disk_image'] = True
@ -1102,9 +1197,47 @@ class AgentDeployMixinTest(AgentDeployMixinBaseTest):
@mock.patch.object(deploy_utils, 'try_set_boot_device', autospec=True)
@mock.patch.object(agent_client.AgentClient, 'install_bootloader',
autospec=True)
def test_configure_local_boot_on_software_raid_exception(
def test_configure_local_boot_on_software_raid_exception_uefi(
self, install_bootloader_mock, try_set_boot_device_mock,
GlanceImageService_mock):
GlanceImageService_mock.side_effect = Exception('Glance not found')
with task_manager.acquire(self.context, self.node['uuid'],
shared=False) as task:
task.node.driver_internal_info['is_whole_disk_image'] = True
root_uuid = "1efecf88-2b58-4d4e-8fbd-7bef1a40a1b0"
task.node.driver_internal_info['root_uuid_or_disk_id'] = root_uuid
task.node.target_raid_config = {
"logical_disks": [
{
"size_gb": 100,
"raid_level": "1",
"controller": "software",
},
{
"size_gb": 'MAX',
"raid_level": "0",
"controller": "software",
}
]
}
self.deploy.configure_local_boot(task)
self.assertTrue(GlanceImageService_mock.called)
# check if the root_uuid comes from the driver_internal_info
install_bootloader_mock.assert_called_once_with(
mock.ANY, task.node, root_uuid=root_uuid,
efi_system_part_uuid=None, prep_boot_part_uuid=None,
target_boot_mode='uefi', software_raid=True)
try_set_boot_device_mock.assert_called_once_with(
task, boot_devices.DISK, persistent=True)
@mock.patch.object(image_service, 'GlanceImageService', autospec=True)
@mock.patch.object(deploy_utils, 'try_set_boot_device', autospec=True)
@mock.patch.object(agent_client.AgentClient, 'install_bootloader',
autospec=True)
def test_configure_local_boot_on_software_raid_exception_bios(
self, install_bootloader_mock, try_set_boot_device_mock,
GlanceImageService_mock):
self.config(default_boot_mode='bios', group='deploy')
GlanceImageService_mock.side_effect = Exception('Glance not found')
with task_manager.acquire(self.context, self.node['uuid'],
shared=False) as task:

15
ironic/tests/unit/drivers/modules/test_boot_mode_utils.py

@ -50,13 +50,26 @@ class GetBootModeTestCase(tests_base.TestCase):
@mock.patch.object(boot_mode_utils, 'get_boot_mode_for_deploy',
autospec=True)
def test_get_boot_mode_default(self, mock_for_deploy, mock_log):
boot_mode_utils.warn_about_default_boot_mode = False
mock_for_deploy.return_value = None
boot_mode = boot_mode_utils.get_boot_mode(self.node)
self.assertEqual(boot_modes.UEFI, boot_mode)
boot_mode = boot_mode_utils.get_boot_mode(self.node)
self.assertEqual(boot_modes.UEFI, boot_mode)
self.assertEqual(0, mock_log.warning.call_count)
@mock.patch.object(boot_mode_utils, 'LOG', autospec=True)
@mock.patch.object(boot_mode_utils, 'get_boot_mode_for_deploy',
autospec=True)
def test_get_boot_mode_bios_default(self, mock_for_deploy, mock_log):
self.config(default_boot_mode='bios', group='deploy')
boot_mode_utils.warn_about_default_boot_mode = False
mock_for_deploy.return_value = None
boot_mode = boot_mode_utils.get_boot_mode(self.node)
self.assertEqual(boot_modes.LEGACY_BIOS, boot_mode)
boot_mode = boot_mode_utils.get_boot_mode(self.node)
self.assertEqual(boot_modes.LEGACY_BIOS, boot_mode)
self.assertEqual(1, mock_log.warning.call_count)
self.assertEqual(0, mock_log.warning.call_count)
@mock.patch.object(boot_mode_utils, 'LOG', autospec=True)
@mock.patch.object(boot_mode_utils, 'get_boot_mode_for_deploy',

51
ironic/tests/unit/drivers/modules/test_deploy_utils.py

@ -575,13 +575,27 @@ class GetPxeBootConfigTestCase(db_base.DbTestCase):
self.assertEqual('aarch64-template', result)
def test_get_pxe_boot_file_emtpy_property(self):
self.node.properties = {}
self.config(pxe_bootfile_name_by_arch=self.bootfile_by_arch,
group='pxe')
result = utils.get_pxe_boot_file(self.node)
self.assertEqual('uefi-bootfile', result)
def test_get_pxe_boot_file_emtpy_property_bios_default(self):
self.config(default_boot_mode='bios', group='deploy')
self.node.properties = {}
self.config(pxe_bootfile_name_by_arch=self.bootfile_by_arch,
group='pxe')
result = utils.get_pxe_boot_file(self.node)
self.assertEqual('bios-bootfile', result)
def test_get_ipxe_boot_file(self):
def test_get_ipxe_boot_uefi(self):
self.config(uefi_ipxe_bootfile_name='meow', group='pxe')
result = utils.get_ipxe_boot_file(self.node)
self.assertEqual('meow', result)
def test_get_ipxe_boot_bios(self):
self.config(default_boot_mode='bios', group='deploy')
self.config(ipxe_bootfile_name='meow', group='pxe')
result = utils.get_ipxe_boot_file(self.node)
self.assertEqual('meow', result)
@ -603,6 +617,15 @@ class GetPxeBootConfigTestCase(db_base.DbTestCase):
self.assertEqual('ipxe-aa64.efi', result)
def test_get_ipxe_boot_file_fallback(self):
self.config(ipxe_bootfile_name=None, group='pxe')
self.config(uefi_ipxe_bootfile_name=None, group='pxe')
self.config(pxe_bootfile_name=None, group='pxe')
self.config(uefi_pxe_bootfile_name='lolcat', group='pxe')
result = utils.get_ipxe_boot_file(self.node)
self.assertEqual('lolcat', result)
def test_get_ipxe_boot_file_fallback_bios(self):
self.config(default_boot_mode='bios', group='deploy')
self.config(ipxe_bootfile_name=None, group='pxe')
self.config(uefi_ipxe_bootfile_name=None, group='pxe')
self.config(pxe_bootfile_name='lolcat', group='pxe')
@ -610,6 +633,14 @@ class GetPxeBootConfigTestCase(db_base.DbTestCase):
self.assertEqual('lolcat', result)
def test_get_pxe_config_template_emtpy_property(self):
self.node.properties = {}
self.config(pxe_config_template_by_arch=self.template_by_arch,
group='pxe')
result = utils.get_pxe_config_template(self.node)
self.assertEqual('uefi-template', result)
def test_get_pxe_config_template_emtpy_property_bios(self):
self.config(default_boot_mode='bios', group='deploy')
self.node.properties = {}
self.config(pxe_config_template_by_arch=self.template_by_arch,
group='pxe')
@ -631,6 +662,16 @@ class GetPxeBootConfigTestCase(db_base.DbTestCase):
utils.get_ipxe_config_template(node))
def test_get_ipxe_config_template_none(self):
self.config(ipxe_config_template=None, group='pxe')
self.config(uefi_pxe_config_template='magical_bootloader',
group='pxe')
node = obj_utils.create_test_node(
self.context, driver='fake-hardware')
self.assertEqual('magical_bootloader',
utils.get_ipxe_config_template(node))
def test_get_ipxe_config_template_none_bios(self):
self.config(default_boot_mode='bios', group='deploy')
self.config(ipxe_config_template=None, group='pxe')
self.config(pxe_config_template='magical_bootloader',
group='pxe')
@ -1010,6 +1051,13 @@ class ParseInstanceInfoCapabilitiesTestCase(tests_base.TestCase):
self.assertEqual('gpt', result)
def test_get_disk_label_nothing_set(self):
inst_info = {'capabilities': {'cat': 'meows'}}
self.node.instance_info = inst_info
result = utils.get_disk_label(self.node)
self.assertEqual('gpt', result)
def test_get_disk_label_nothing_set_bios_mode(self):
self.config(default_boot_mode='bios', group='deploy')
inst_info = {'capabilities': {'cat': 'meows'}}
self.node.instance_info = inst_info
result = utils.get_disk_label(self.node)
@ -1058,6 +1106,7 @@ class TrySetBootDeviceTestCase(db_base.DbTestCase):
@mock.patch.object(manager_utils, 'node_set_boot_device', autospec=True)
def test_try_set_boot_device_ipmifailure_bios(
self, node_set_boot_device_mock):
self.config(default_boot_mode='bios', group='deploy')
node_set_boot_device_mock.side_effect = exception.IPMIFailure(cmd='a')
with task_manager.acquire(self.context, self.node.uuid,
shared=False) as task:

56
ironic/tests/unit/drivers/modules/test_image_utils.py

@ -509,6 +509,7 @@ class RedfishImageUtilsTestCase(db_base.DbTestCase):
@mock.patch.object(images, 'create_boot_iso', autospec=True)
def test__prepare_iso_image_bios(
self, mock_create_boot_iso, mock_publish_image):
self.config(default_boot_mode='bios', group='deploy')
with task_manager.acquire(self.context, self.node.uuid,
shared=True) as task:
@ -551,7 +552,7 @@ class RedfishImageUtilsTestCase(db_base.DbTestCase):
mock_create_boot_iso.assert_called_once_with(
mock.ANY, mock.ANY, 'http://kernel/img', 'http://ramdisk/img',
boot_mode='bios', esp_image_href=None,
boot_mode='uefi', esp_image_href=None,
kernel_params=kernel_params,
root_uuid='1be26c0b-03f2-4d2e-ae87-c02d7f33c123',
inject_files=None)
@ -567,6 +568,29 @@ class RedfishImageUtilsTestCase(db_base.DbTestCase):
task.node.driver_info['kernel_append_params'] = kernel_params
image_utils._prepare_iso_image(
task, 'http://kernel/img', 'http://ramdisk/img',
bootloader_href=None, root_uuid=task.node.uuid)
mock_create_boot_iso.assert_called_once_with(
mock.ANY, mock.ANY, 'http://kernel/img', 'http://ramdisk/img',
boot_mode='uefi', esp_image_href=None,
kernel_params=kernel_params,
root_uuid='1be26c0b-03f2-4d2e-ae87-c02d7f33c123',
inject_files=None)
@mock.patch.object(image_utils.ImageHandler, 'publish_image',
autospec=True)
@mock.patch.object(images, 'create_boot_iso', autospec=True)
def test__prepare_iso_image_kernel_params_driver_info_bios(
self, mock_create_boot_iso, mock_publish_image):
self.config(default_boot_mode='bios', group='deploy')
with task_manager.acquire(self.context, self.node.uuid,
shared=True) as task:
kernel_params = 'network-config=base64-cloudinit-blob'
task.node.driver_info['kernel_append_params'] = kernel_params
image_utils._prepare_iso_image(
task, 'http://kernel/img', 'http://ramdisk/img',
bootloader_href=None, root_uuid=task.node.uuid)
@ -582,7 +606,7 @@ class RedfishImageUtilsTestCase(db_base.DbTestCase):
@mock.patch.object(image_utils.ImageHandler, 'publish_image',
autospec=True)
@mock.patch.object(images, 'create_boot_iso', autospec=True)
def test__prepare_iso_image_kernel_params_for_ramdisk(
def test__prepare_iso_image_kernel_params_for_ramdisk_uefi(
self, mock_create_boot_iso, mock_publish_image):
with task_manager.acquire(self.context, self.node.uuid,
shared=True) as task:
@ -590,6 +614,30 @@ class RedfishImageUtilsTestCase(db_base.DbTestCase):
task.node.instance_info['ramdisk_kernel_arguments'] = kernel_params
image_utils._prepare_iso_image(
task, 'http://kernel/img', 'http://ramdisk/img',
bootloader_href=None, root_uuid=task.node.uuid)
mock_create_boot_iso.assert_called_once_with(
mock.ANY, mock.ANY, 'http://kernel/img', 'http://ramdisk/img',
boot_mode='uefi', esp_image_href=None,
kernel_params="root=/dev/ram0 text " + kernel_params,
root_uuid='1be26c0b-03f2-4d2e-ae87-c02d7f33c123',
inject_files=None)
@mock.patch.object(deploy_utils, 'get_boot_option', lambda node: 'ramdisk')
@mock.patch.object(image_utils.ImageHandler, 'publish_image',
autospec=True)
@mock.patch.object(images, 'create_boot_iso', autospec=True)
def test__prepare_iso_image_kernel_params_for_ramdisk_bios(
self, mock_create_boot_iso, mock_publish_image):
self.config(default_boot_mode='bios', group='deploy')
with task_manager.acquire(self.context, self.node.uuid,
shared=True) as task:
kernel_params = 'network-config=base64-cloudinit-blob'
task.node.instance_info['ramdisk_kernel_arguments'] = kernel_params
image_utils._prepare_iso_image(
task, 'http://kernel/img', 'http://ramdisk/img',
bootloader_href=None, root_uuid=task.node.uuid)
@ -620,7 +668,7 @@ class RedfishImageUtilsTestCase(db_base.DbTestCase):
mock_create_boot_iso.assert_called_once_with(
mock.ANY, mock.ANY, 'http://kernel/img', 'http://ramdisk/img',
boot_mode='bios', esp_image_href=None,
boot_mode='uefi', esp_image_href=None,
kernel_params=kernel_params,
root_uuid='1be26c0b-03f2-4d2e-ae87-c02d7f33c123',
inject_files=None)
@ -643,7 +691,7 @@ class RedfishImageUtilsTestCase(db_base.DbTestCase):
mock_create_boot_iso.assert_called_once_with(
mock.ANY, mock.ANY, 'http://kernel/img', 'http://ramdisk/img',
boot_mode='bios', esp_image_href=None,
boot_mode='uefi', esp_image_href=None,
kernel_params=kernel_params + ' foo=bar banana',
root_uuid='1be26c0b-03f2-4d2e-ae87-c02d7f33c123',
inject_files=None)

54
ironic/tests/unit/drivers/modules/test_ipmitool.py

@ -2446,9 +2446,9 @@ class IPMIToolDriverTestCase(Base):
self.assertEqual({}, driver_routes)
@mock.patch.object(ipmi, '_exec_ipmitool', autospec=True)
def test_management_interface_set_boot_device_ok(self, mock_exec):
def test_management_interface_set_boot_device_ok_bios(self, mock_exec):
mock_exec.return_value = [None, None]
self.config(default_boot_mode='bios', group='deploy')
with task_manager.acquire(self.context, self.node.uuid) as task:
self.management.set_boot_device(task, boot_devices.PXE)
@ -2458,10 +2458,10 @@ class IPMIToolDriverTestCase(Base):
@mock.patch.object(driver_utils, 'force_persistent_boot', autospec=True)
@mock.patch.object(ipmi, '_exec_ipmitool', autospec=True)
def test_management_interface_no_force_set_boot_device(self,
mock_exec,
mock_force_boot):
def test_management_interface_no_force_set_boot_device_bios(
self, mock_exec, mock_force_boot):
mock_exec.return_value = [None, None]
self.config(default_boot_mode='bios', group='deploy')
with task_manager.acquire(self.context, self.node.uuid) as task:
driver_info = task.node.driver_info
@ -2476,8 +2476,10 @@ class IPMIToolDriverTestCase(Base):
self.assertFalse(mock_force_boot.called)
@mock.patch.object(ipmi, '_exec_ipmitool', autospec=True)
def test_management_interface_force_set_boot_device_ok(self, mock_exec):
def test_management_interface_force_set_boot_device_ok_bios(self,
mock_exec):
mock_exec.return_value = [None, None]
self.config(default_boot_mode='bios', group='deploy')
with task_manager.acquire(self.context, self.node.uuid) as task:
driver_info = task.node.driver_info
@ -2496,8 +2498,10 @@ class IPMIToolDriverTestCase(Base):
mock_exec.assert_has_calls(mock_calls)
@mock.patch.object(ipmi, '_exec_ipmitool', autospec=True)
def test_management_interface_set_boot_device_persistent(self, mock_exec):
def test_management_interface_set_boot_device_persistent_bios(self,
mock_exec):
mock_exec.return_value = [None, None]
self.config(default_boot_mode='bios', group='deploy')
with task_manager.acquire(self.context, self.node.uuid) as task:
driver_info = task.node.driver_info
@ -2520,10 +2524,24 @@ class IPMIToolDriverTestCase(Base):
task, 'fake-device')
@mock.patch.object(ipmi, '_exec_ipmitool', autospec=True)
def test_management_interface_set_boot_device_without_timeout_1(self,
mock_exec):
def test_management_interface_set_boot_device_without_timeout_1_uefi(
self, mock_exec):
mock_exec.return_value = [None, None]
with task_manager.acquire(self.context, self.node.uuid) as task:
driver_info = task.node.driver_info
driver_info['ipmi_disable_boot_timeout'] = 'False'
task.node.driver_info = driver_info
self.management.set_boot_device(task, boot_devices.PXE)
mock_calls = [mock.call(self.info, "raw 0x00 0x08 0x05 0xa0 0x04 "
"0x00 0x00 0x00")]
mock_exec.assert_has_calls(mock_calls)
@mock.patch.object(ipmi, '_exec_ipmitool', autospec=True)
def test_management_interface_set_boot_device_without_timeout_1_bios(
self, mock_exec):
mock_exec.return_value = [None, None]
self.config(default_boot_mode='bios', group='deploy')
with task_manager.acquire(self.context, self.node.uuid) as task:
driver_info = task.node.driver_info
driver_info['ipmi_disable_boot_timeout'] = 'False'
@ -2534,9 +2552,23 @@ class IPMIToolDriverTestCase(Base):
mock_exec.assert_has_calls(mock_calls)
@mock.patch.object(ipmi, '_exec_ipmitool', autospec=True)
def test_management_interface_set_boot_device_without_timeout_2(self,
mock_exec):
def test_management_interface_set_boot_device_without_timeout_2_uefi(
self, mock_exec):
CONF.set_override('disable_boot_timeout', False, 'ipmi')
mock_exec.return_value = [None, None]
with task_manager.acquire(self.context, self.node.uuid) as task:
self.management.set_boot_device(task, boot_devices.PXE)
mock_calls = [mock.call(self.info, "raw 0x00 0x08 0x05 0xa0 0x04 "
"0x00 0x00 0x00")]
mock_exec.assert_has_calls(mock_calls)
@mock.patch.object(ipmi, '_exec_ipmitool', autospec=True)
def test_management_interface_set_boot_device_without_timeout_2_bios(
self, mock_exec):
CONF.set_override('disable_boot_timeout', False, 'ipmi')
self.config(default_boot_mode='bios', group='deploy')
mock_exec.return_value = [None, None]
with task_manager.acquire(self.context, self.node.uuid) as task:

231
ironic/tests/unit/drivers/modules/test_ipxe.py

@ -606,12 +606,57 @@ class iPXEBootTestCase(db_base.DbTestCase):
task, ipxe_enabled=True, ip_version=6)
pxe_config_path = pxe_utils.get_pxe_config_file_path(
task.node.uuid, ipxe_enabled=True)
task.node.properties['capabilities'] = 'boot_mode:uefi'
task.node.instance_info['capabilities'] = instance_info
task.node.driver_internal_info['root_uuid_or_disk_id'] = (
"30212642-09d3-467f-8e09-21685826ab50")
task.node.driver_internal_info['is_whole_disk_image'] = False
task.driver.boot.prepare_instance(task)
get_image_info_mock.assert_called_once_with(
task, ipxe_enabled=True)
cache_mock.assert_called_once_with(task, image_info,
ipxe_enabled=True)
provider_mock.update_dhcp.assert_called_once_with(task, dhcp_opts)
switch_pxe_config_mock.assert_called_once_with(
pxe_config_path, "30212642-09d3-467f-8e09-21685826ab50",
'uefi', False, False, False, False, ipxe_enabled=True,
anaconda_boot=False)
set_boot_device_mock.assert_called_once_with(task,
boot_devices.PXE,
persistent=True)
@mock.patch.object(manager_utils, 'node_set_boot_device', autospec=True)
@mock.patch.object(deploy_utils, 'switch_pxe_config', autospec=True)
@mock.patch.object(dhcp_factory, 'DHCPFactory', autospec=True)
@mock.patch.object(pxe_utils, 'cache_ramdisk_kernel', autospec=True)
@mock.patch.object(pxe_utils, 'get_instance_image_info', autospec=True)
def test_prepare_instance_netboot_bios(
self, get_image_info_mock, cache_mock,
dhcp_factory_mock, switch_pxe_config_mock,
set_boot_device_mock):
provider_mock = mock.MagicMock()
dhcp_factory_mock.return_value = provider_mock
image_info = {'kernel': ('', '/path/to/kernel'),
'ramdisk': ('', '/path/to/ramdisk')}
instance_info = {"boot_option": "netboot",
"boot_mode": "bios"}
get_image_info_mock.return_value = image_info
with task_manager.acquire(self.context, self.node.uuid) as task:
task.node.properties['capabilities'] = 'boot_mode:bios'
task.node.instance_info['capabilities'] = instance_info
task.node.driver_internal_info['root_uuid_or_disk_id'] = (
"30212642-09d3-467f-8e09-21685826ab50")
task.node.driver_internal_info['is_whole_disk_image'] = False
dhcp_opts = pxe_utils.dhcp_options_for_instance(
task, ipxe_enabled=True)
dhcp_opts += pxe_utils.dhcp_options_for_instance(
task, ipxe_enabled=True, ip_version=6)
pxe_config_path = pxe_utils.get_pxe_config_file_path(
task.node.uuid, ipxe_enabled=True)
task.driver.boot.prepare_instance(task)
get_image_info_mock.assert_called_once_with(
@ -641,23 +686,79 @@ class iPXEBootTestCase(db_base.DbTestCase):
dhcp_factory_mock.return_value = provider_mock
image_info = {'kernel': ('', '/path/to/kernel'),
'ramdisk': ('', '/path/to/ramdisk')}
i_info_caps = {"boot_option": "ramdisk"}
i_info_caps = {"boot_option": "ramdisk",
"boot_mode": "bios"}
kernel_arg = "meow"
get_image_info_mock.return_value = image_info
with task_manager.acquire(self.context, self.node.uuid) as task:
task.node.properties['capabilities'] = 'boot_mode:bios'
i_info = task.node.instance_info
i_info['capabilities'] = i_info_caps
i_info['kernel_append_params'] = kernel_arg
task.node.instance_info = i_info
task.node.save()
dhcp_opts = pxe_utils.dhcp_options_for_instance(
task, ipxe_enabled=True)
dhcp_opts += pxe_utils.dhcp_options_for_instance(
task, ipxe_enabled=True, ip_version=6)
pxe_config_path = pxe_utils.get_pxe_config_file_path(
task.node.uuid, ipxe_enabled=True)
task.node.properties['capabilities'] = 'boot_mode:bios'
task.driver.boot.prepare_instance(task)
get_image_info_mock.assert_called_once_with(
task, ipxe_enabled=True)
cache_mock.assert_called_once_with(task, image_info,
ipxe_enabled=True)
provider_mock.update_dhcp.assert_called_once_with(task, dhcp_opts)
switch_pxe_config_mock.assert_called_once_with(
pxe_config_path, None,
'bios', False, iscsi_boot=False, ramdisk_boot=True,
ipxe_enabled=True, anaconda_boot=False)
set_boot_device_mock.assert_called_once_with(task,
boot_devices.PXE,
persistent=True)
expected_params = {
'aki_path': 'http://myserver/' + task.node.uuid + '/kernel',
'ari_path': 'http://myserver/' + task.node.uuid + '/ramdisk',
'pxe_append_params': 'meow ipa-debug=1 ipa-global-request-id'
'=' + task.context.request_id,
'tftp_server': mock.ANY,
'ipxe_timeout': 0}
mock_create_pxe_config.assert_called_once_with(
task, expected_params, mock.ANY, ipxe_enabled=True)
@mock.patch.object(pxe_utils, 'create_pxe_config', autospec=True)
@mock.patch.object(manager_utils, 'node_set_boot_device', autospec=True)
@mock.patch.object(deploy_utils, 'switch_pxe_config', autospec=True)
@mock.patch.object(dhcp_factory, 'DHCPFactory', autospec=True)
@mock.patch.object(pxe_utils, 'cache_ramdisk_kernel', autospec=True)
@mock.patch.object(pxe_utils, 'get_instance_image_info', autospec=True)
def test_prepare_instance_ramdisk_bios(
self, get_image_info_mock, cache_mock,
dhcp_factory_mock, switch_pxe_config_mock,
set_boot_device_mock, mock_create_pxe_config):
provider_mock = mock.MagicMock()
dhcp_factory_mock.return_value = provider_mock
image_info = {'kernel': ('', '/path/to/kernel'),
'ramdisk': ('', '/path/to/ramdisk')}
i_info_caps = {"boot_option": "ramdisk"}
kernel_arg = "meow"
get_image_info_mock.return_value = image_info
with task_manager.acquire(self.context, self.node.uuid) as task:
i_info = task.node.instance_info
i_info['capabilities'] = i_info_caps
i_info['kernel_append_params'] = kernel_arg
task.node.instance_info = i_info
task.node.save()
dhcp_opts = pxe_utils.dhcp_options_for_instance(
task, ipxe_enabled=True)
dhcp_opts += pxe_utils.dhcp_options_for_instance(
task, ipxe_enabled=True, ip_version=6)
pxe_config_path = pxe_utils.get_pxe_config_file_path(
task.node.uuid, ipxe_enabled=True)
task.driver.boot.prepare_instance(task)
get_image_info_mock.assert_called_once_with(
task, ipxe_enabled=True)
@ -666,7 +767,7 @@ class iPXEBootTestCase(db_base.DbTestCase):
provider_mock.update_dhcp.assert_called_once_with(task, dhcp_opts)
switch_pxe_config_mock.assert_called_once_with(
pxe_config_path, None,
'bios', False, iscsi_boot=False, ramdisk_boot=True,
'uefi', False, iscsi_boot=False, ramdisk_boot=True,
ipxe_enabled=True, anaconda_boot=False)
set_boot_device_mock.assert_called_once_with(task,
boot_devices.PXE,
@ -701,17 +802,18 @@ class iPXEBootTestCase(db_base.DbTestCase):
self.node.provision_state = states.ACTIVE
self.node.save()
with task_manager.acquire(self.context, self.node.uuid) as task:
task.node.properties['capabilities'] = 'boot_mode:bios'
task.node.instance_info['capabilities'] = instance_info
task.node.driver_internal_info['root_uuid_or_disk_id'] = (
"30212642-09d3-467f-8e09-21685826ab50")
task.node.driver_internal_info['is_whole_disk_image'] = False
dhcp_opts = pxe_utils.dhcp_options_for_instance(
task, ipxe_enabled=True)
dhcp_opts += pxe_utils.dhcp_options_for_instance(
task, ipxe_enabled=True, ip_version=6)
pxe_config_path = pxe_utils.get_pxe_config_file_path(
task.node.uuid, ipxe_enabled=True)
task.node.properties['capabilities'] = 'boot_mode:bios'
task.node.instance_info['capabilities'] = instance_info
task.node.driver_internal_info['root_uuid_or_disk_id'] = (
"30212642-09d3-467f-8e09-21685826ab50")
task.node.driver_internal_info['is_whole_disk_image'] = False
task.driver.boot.prepare_instance(task)
@ -745,13 +847,48 @@ class iPXEBootTestCase(db_base.DbTestCase):
get_image_info_mock.return_value = image_info
instance_info = {"boot_option": "netboot"}
with task_manager.acquire(self.context, self.node.uuid) as task:
task.node.properties['capabilities'] = 'boot_mode:bios'
task.node.instance_info['capabilities'] = instance_info
task.node.driver_internal_info['is_whole_disk_image'] = False
dhcp_opts = pxe_utils.dhcp_options_for_instance(
task, ipxe_enabled=True, ip_version=4)
dhcp_opts += pxe_utils.dhcp_options_for_instance(
task, ipxe_enabled=True, ip_version=6)
task.node.properties['capabilities'] = 'boot_mode:bios'
task.node.instance_info['capabilities'] = instance_info
task.driver.boot.prepare_instance(task)
get_image_info_mock.assert_called_once_with(
task, ipxe_enabled=True)
cache_mock.assert_called_once_with(task, image_info,
ipxe_enabled=True)
provider_mock.update_dhcp.assert_called_once_with(task, dhcp_opts)
self.assertFalse(switch_pxe_config_mock.called)
self.assertFalse(set_boot_device_mock.called)
@mock.patch.object(manager_utils, 'node_set_boot_device', autospec=True)
@mock.patch.object(deploy_utils, 'switch_pxe_config', autospec=True)
@mock.patch.object(dhcp_factory, 'DHCPFactory', autospec=True)
@mock.patch.object(pxe_utils, 'cache_ramdisk_kernel', autospec=True)
@mock.patch.object(pxe_utils, 'get_instance_image_info', autospec=True)
def test_prepare_instance_netboot_missing_root_uuid_default(
self, get_image_info_mock, cache_mock,
dhcp_factory_mock, switch_pxe_config_mock,
set_boot_device_mock):
provider_mock = mock.MagicMock()
dhcp_factory_mock.return_value = provider_mock
image_info = {'kernel': ('', '/path/to/kernel'),
'ramdisk': ('', '/path/to/ramdisk')}
get_image_info_mock.return_value = image_info
instance_info = self.node.instance_info
instance_info['capabilities'] = {"boot_option": "netboot"}
self.node.instance_info = instance_info
self.node.save()
with task_manager.acquire(self.context, self.node.uuid) as task:
task.node.driver_internal_info['is_whole_disk_image'] = False
dhcp_opts = pxe_utils.dhcp_options_for_instance(
task, ipxe_enabled=True, ip_version=4)
dhcp_opts += pxe_utils.dhcp_options_for_instance(
task, ipxe_enabled=True, ip_version=6)
task.driver.boot.prepare_instance(task)
@ -778,15 +915,17 @@ class iPXEBootTestCase(db_base.DbTestCase):
provider_mock = mock.MagicMock()
dhcp_factory_mock.return_value = provider_mock
get_image_info_mock.return_value = {}
instance_info = {"boot_option": "netboot"}
instance_info = {"boot_option": "netboot",
"boot_mode": "bios"}
with task_manager.acquire(self.context, self.node.uuid) as task:
task.node.properties['capabilities'] = 'boot_mode:bios'
task.node.instance_info['capabilities'] = instance_info
task.node.driver_internal_info['is_whole_disk_image'] = True
dhcp_opts = pxe_utils.dhcp_options_for_instance(
task, ipxe_enabled=True)
dhcp_opts += pxe_utils.dhcp_options_for_instance(
task, ipxe_enabled=True, ip_version=6)
task.node.properties['capabilities'] = 'boot_mode:bios'
task.node.instance_info['capabilities'] = instance_info
task.node.driver_internal_info['is_whole_disk_image'] = True
task.driver.boot.prepare_instance(task)
get_image_info_mock.assert_called_once_with(
task, ipxe_enabled=True)
@ -807,7 +946,7 @@ class iPXEBootTestCase(db_base.DbTestCase):
@mock.patch.object(dhcp_factory, 'DHCPFactory', autospec=True)
@mock.patch.object(pxe_utils, 'cache_ramdisk_kernel', autospec=True)
@mock.patch.object(pxe_utils, 'get_instance_image_info', autospec=True)
def test_prepare_instance_netboot_iscsi(
def test_prepare_instance_netboot_iscsi_bios(
self, get_image_info_mock, cache_mock,
dhcp_factory_mock, switch_pxe_config_mock,
set_boot_device_mock, create_pxe_config_mock):
@ -827,13 +966,15 @@ class iPXEBootTestCase(db_base.DbTestCase):
with task_manager.acquire(self.context, self.node.uuid) as task:
task.node.driver_internal_info = {
'boot_from_volume': vol_id}
task.node.properties['capabilities'] = 'boot_mode:bios'
task.node.instance_info['capabilities'] = {'boot_mode': 'bios'}
dhcp_opts = pxe_utils.dhcp_options_for_instance(task,
ipxe_enabled=True)
dhcp_opts += pxe_utils.dhcp_options_for_instance(
task, ipxe_enabled=True, ip_version=6)
pxe_config_path = pxe_utils.get_pxe_config_file_path(
task.node.uuid, ipxe_enabled=True)
task.node.properties['capabilities'] = 'boot_mode:bios'
task.driver.boot.prepare_instance(task)
self.assertFalse(get_image_info_mock.called)
self.assertFalse(cache_mock.called)
@ -849,6 +990,59 @@ class iPXEBootTestCase(db_base.DbTestCase):
boot_devices.PXE,
persistent=True)
@mock.patch('os.path.isfile', lambda filename: False)
@mock.patch.object(pxe_utils, 'create_pxe_config', autospec=True)
@mock.patch.object(deploy_utils, 'is_iscsi_boot', lambda task: True)
@mock.patch.object(noop_storage.NoopStorage, 'should_write_image',
lambda task: False)
@mock.patch.object(manager_utils, 'node_set_boot_device', autospec=True)
@mock.patch.object(deploy_utils, 'switch_pxe_config', autospec=True)
@mock.patch.object(dhcp_factory, 'DHCPFactory', autospec=True)
@mock.patch.object(pxe_utils, 'cache_ramdisk_kernel', autospec=True)
@mock.patch.object(pxe_utils, 'get_instance_image_info', autospec=True)
def test_prepare_instance_netboot_iscsi(
self, get_image_info_mock, cache_mock,
dhcp_factory_mock, switch_pxe_config_mock,
set_boot_device_mock, create_pxe_config_mock):
http_url = 'http://192.1.2.3:1234'
self.config(http_url=http_url, group='deploy')
provider_mock = mock.MagicMock()
dhcp_factory_mock.return_value = provider_mock
vol_id = uuidutils.generate_uuid()
obj_utils.create_test_volume_target(
self.context, node_id=self.node.id, volume_type='iscsi',
boot_index=0, volume_id='1234', uuid=vol_id,
properties={'target_lun': 0,
'target_portal': 'fake_host:3260',
'target_iqn': 'fake_iqn',
'auth_username': 'fake_username',
'auth_password': 'fake_password'})
with task_manager.acquire(self.context, self.node.uuid) as task:
task.node.driver_internal_info = {
'boot_from_volume': vol_id}
dhcp_opts = pxe_utils.dhcp_options_for_instance(task,
ipxe_enabled=True)
dhcp_opts += pxe_utils.dhcp_options_for_instance(
task, ipxe_enabled=True, ip_version=6)
pxe_config_path = pxe_utils.get_pxe_config_file_path(
task.node.uuid, ipxe_enabled=True)
task.driver.boot.prepare_instance(task)
self.assertFalse(get_image_info_mock.called)
self.assertFalse(cache_mock.called)
provider_mock.update_dhcp.assert_called_once_with(task, dhcp_opts)
create_pxe_config_mock.assert_called_once_with(
task, mock.ANY, CONF.pxe.ipxe_config_template,
ipxe_enabled=True)
switch_pxe_config_mock.assert_called_once_with(
pxe_config_path, None, boot_modes.UEFI, False,
ipxe_enabled=True, iscsi_boot=True, ramdisk_boot=False,
anaconda_boot=False)
set_boot_device_mock.assert_called_once_with(task,
boot_devices.PXE,
persistent=True)
@mock.patch('os.path.isfile', lambda filename: False)
@mock.patch.object(pxe_utils, 'create_pxe_config', autospec=True)
@mock.patch.object(manager_utils, 'node_set_boot_device', autospec=True)
@ -874,7 +1068,6 @@ class iPXEBootTestCase(db_base.DbTestCase):
self.node.provision_state = states.DEPLOYING
self.node.save()
with task_manager.acquire(self.context, self.node.uuid) as task:
print(task.node)
dhcp_opts = pxe_utils.dhcp_options_for_instance(task,
ipxe_enabled=True)
dhcp_opts += pxe_utils.dhcp_options_for_instance(
@ -889,7 +1082,7 @@ class iPXEBootTestCase(db_base.DbTestCase):
task, mock.ANY, CONF.pxe.ipxe_config_template,
ipxe_enabled=True)
switch_pxe_config_mock.assert_called_once_with(
pxe_config_path, None, boot_modes.LEGACY_BIOS, False,
pxe_config_path, None, boot_modes.UEFI, False,
ipxe_enabled=True, iscsi_boot=False, ramdisk_boot=True,
anaconda_boot=False)
set_boot_device_mock.assert_called_once_with(task,
@ -959,7 +1152,7 @@ class iPXEBootTestCase(db_base.DbTestCase):
persistent=True)
switch_pxe_config_mock.assert_called_once_with(
pxe_config_path, "30212642-09d3-467f-8e09-21685826ab50",
'bios', True, False, False, False, ipxe_enabled=True,
'uefi', True, False, False, False, ipxe_enabled=True,
anaconda_boot=False)
# No clean up
self.assertFalse(clean_up_pxe_config_mock.called)

178
ironic/tests/unit/drivers/modules/test_pxe.py

@ -271,7 +271,7 @@ class PXEBootTestCase(db_base.DbTestCase):
dhcp_factory_mock,
set_boot_device_mock,
get_boot_mode_mock,
uefi=False,
uefi=True,
cleaning=False,
ipxe_use_swift=False,
whole_disk_image=False,
@ -295,6 +295,7 @@ class PXEBootTestCase(db_base.DbTestCase):
driver_internal_info = self.node.driver_internal_info
driver_internal_info['is_whole_disk_image'] = whole_disk_image
self.node.driver_internal_info = driver_internal_info
if mode == 'rescue':
mock_deploy_img_info.return_value = {
'rescue_kernel': 'a',
@ -356,11 +357,21 @@ class PXEBootTestCase(db_base.DbTestCase):
self.node.save()
self._test_prepare_ramdisk()
def test_prepare_ramdisk_bios(self):
self.node.provision_state = states.DEPLOYING
self.node.save()
self._test_prepare_ramdisk(uefi=True)
def test_prepare_ramdisk_rescue(self):
self.node.provision_state = states.RESCUING
self.node.save()
self._test_prepare_ramdisk(mode='rescue')
def test_prepare_ramdisk_rescue_bios(self):
self.node.provision_state = states.RESCUING
self.node.save()
self._test_prepare_ramdisk(mode='rescue', uefi=True)
def test_prepare_ramdisk_uefi(self):
self.node.provision_state = states.DEPLOYING
self.node.save()
@ -391,7 +402,8 @@ class PXEBootTestCase(db_base.DbTestCase):
self, set_boot_mode_mock):