summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJulia Kreger <juliaashleykreger@gmail.com>2021-09-21 07:13:37 -0700
committerJulia Kreger <juliaashleykreger@gmail.com>2021-10-04 11:57:55 -0700
commit493b4f0caf591caeaa3285c7f597a54121d99985 (patch)
treef11d4ca6164860260b4106a8bf92a3651a48d212
parent29313ae4d7a32808caacbe75f09a75b959473b85 (diff)
downloadironic-493b4f0caf591caeaa3285c7f597a54121d99985.tar.gz
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
-rw-r--r--devstack/common_settings4
-rw-r--r--devstack/lib/ironic7
-rw-r--r--doc/source/install/include/boot-mode.inc10
-rw-r--r--ironic/conf/deploy.py11
-rw-r--r--ironic/drivers/modules/boot_mode_utils.py14
-rw-r--r--ironic/drivers/modules/deploy_utils.py2
-rw-r--r--ironic/tests/unit/common/test_pxe_utils.py100
-rw-r--r--ironic/tests/unit/drivers/modules/ansible/test_deploy.py1
-rw-r--r--ironic/tests/unit/drivers/modules/redfish/test_management.py2
-rw-r--r--ironic/tests/unit/drivers/modules/test_agent_base.py135
-rw-r--r--ironic/tests/unit/drivers/modules/test_boot_mode_utils.py15
-rw-r--r--ironic/tests/unit/drivers/modules/test_deploy_utils.py51
-rw-r--r--ironic/tests/unit/drivers/modules/test_image_utils.py56
-rw-r--r--ironic/tests/unit/drivers/modules/test_ipmitool.py54
-rw-r--r--ironic/tests/unit/drivers/modules/test_ipxe.py231
-rw-r--r--ironic/tests/unit/drivers/modules/test_pxe.py178
-rw-r--r--ironic/tests/unit/drivers/modules/test_ramdisk.py4
-rw-r--r--releasenotes/notes/uefi-is-now-the-default-562b0d68adc59008.yaml16
-rw-r--r--zuul.d/ironic-jobs.yaml38
19 files changed, 819 insertions, 110 deletions
diff --git a/devstack/common_settings b/devstack/common_settings
index d649f70a5..8d5660c4d 100644
--- a/devstack/common_settings
+++ b/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 &&
diff --git a/devstack/lib/ironic b/devstack/lib/ironic
index 5aec60a15..5fa1db08f 100644
--- a/devstack/lib/ironic
+++ b/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
diff --git a/doc/source/install/include/boot-mode.inc b/doc/source/install/include/boot-mode.inc
index 622c6cc71..1beb7dac0 100644
--- a/doc/source/install/include/boot-mode.inc
+++ b/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::
diff --git a/ironic/conf/deploy.py b/ironic/conf/deploy.py
index 5729be74f..32f53644a 100644
--- a/ironic/conf/deploy.py
+++ b/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,
diff --git a/ironic/drivers/modules/boot_mode_utils.py b/ironic/drivers/modules/boot_mode_utils.py
index b88e6d3db..6150a71bf 100644
--- a/ironic/drivers/modules/boot_mode_utils.py
+++ b/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
diff --git a/ironic/drivers/modules/deploy_utils.py b/ironic/drivers/modules/deploy_utils.py
index 012451651..37b818531 100644
--- a/ironic/drivers/modules/deploy_utils.py
+++ b/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
diff --git a/ironic/tests/unit/common/test_pxe_utils.py b/ironic/tests/unit/common/test_pxe_utils.py
index 3b2ff0cf3..2ae878edb 100644
--- a/ironic/tests/unit/common/test_pxe_utils.py
+++ b/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,16 +502,20 @@ 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
@@ -514,6 +524,36 @@ 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 ))'}
+ )
+ 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,
+ 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 }}'}
)
@@ -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)
diff --git a/ironic/tests/unit/drivers/modules/ansible/test_deploy.py b/ironic/tests/unit/drivers/modules/ansible/test_deploy.py
index 886c01db5..ed9199575 100644
--- a/ironic/tests/unit/drivers/modules/ansible/test_deploy.py
+++ b/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',
diff --git a/ironic/tests/unit/drivers/modules/redfish/test_management.py b/ironic/tests/unit/drivers/modules/redfish/test_management.py
index 99da1265b..88895ec16 100644
--- a/ironic/tests/unit/drivers/modules/redfish/test_management.py
+++ b/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,
diff --git a/ironic/tests/unit/drivers/modules/test_agent_base.py b/ironic/tests/unit/drivers/modules/test_agent_base.py
index c5a097c0f..21c0b4fff 100644
--- a/ironic/tests/unit/drivers/modules/test_agent_base.py
+++ b/ironic/tests/unit/drivers/modules/test_agent_base.py
@@ -985,6 +985,24 @@ class AgentDeployMixinTest(AgentDeployMixinBaseTest):
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)
self.assertFalse(install_bootloader_mock.called)
try_set_boot_device_mock.assert_called_once_with(
task, boot_devices.DISK, persistent=True)
@@ -1056,6 +1074,45 @@ class AgentDeployMixinTest(AgentDeployMixinBaseTest):
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
+ 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='bios',
software_raid=True)
try_set_boot_device_mock.assert_called_once_with(
@@ -1093,6 +1150,44 @@ class AgentDeployMixinTest(AgentDeployMixinBaseTest):
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
+ 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='bios',
software_raid=True)
try_set_boot_device_mock.assert_called_once_with(
@@ -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:
diff --git a/ironic/tests/unit/drivers/modules/test_boot_mode_utils.py b/ironic/tests/unit/drivers/modules/test_boot_mode_utils.py
index 611bc0ec4..646d30789 100644
--- a/ironic/tests/unit/drivers/modules/test_boot_mode_utils.py
+++ b/ironic/tests/unit/drivers/modules/test_boot_mode_utils.py
@@ -53,10 +53,23 @@ class GetBootModeTestCase(tests_base.TestCase):
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',
diff --git a/ironic/tests/unit/drivers/modules/test_deploy_utils.py b/ironic/tests/unit/drivers/modules/test_deploy_utils.py
index 4021558bf..cf6c8484e 100644
--- a/ironic/tests/unit/drivers/modules/test_deploy_utils.py
+++ b/ironic/tests/unit/drivers/modules/test_deploy_utils.py
@@ -579,9 +579,23 @@ class GetPxeBootConfigTestCase(db_base.DbTestCase):
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)
@@ -605,6 +619,15 @@ class GetPxeBootConfigTestCase(db_base.DbTestCase):
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')
result = utils.get_ipxe_boot_file(self.node)
self.assertEqual('lolcat', result)
@@ -614,6 +637,14 @@ class GetPxeBootConfigTestCase(db_base.DbTestCase):
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')
+ result = utils.get_pxe_config_template(self.node)
self.assertEqual('bios-template', result)
def test_get_pxe_config_template_per_node(self):
@@ -632,6 +663,16 @@ class GetPxeBootConfigTestCase(db_base.DbTestCase):
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')
node = obj_utils.create_test_node(
@@ -1013,6 +1054,13 @@ class ParseInstanceInfoCapabilitiesTestCase(tests_base.TestCase):
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)
self.assertIsNone(result)
def test_get_disk_label_uefi_mode(self):
@@ -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:
diff --git a/ironic/tests/unit/drivers/modules/test_image_utils.py b/ironic/tests/unit/drivers/modules/test_image_utils.py
index ff061277a..58a806172 100644
--- a/ironic/tests/unit/drivers/modules/test_image_utils.py
+++ b/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)
@@ -573,6 +574,29 @@ 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='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)
+
+ 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,
kernel_params=kernel_params,
root_uuid='1be26c0b-03f2-4d2e-ae87-c02d7f33c123',
@@ -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:
@@ -596,6 +620,30 @@ 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='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)
+
+ 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,
kernel_params="root=/dev/ram0 text " + kernel_params,
root_uuid='1be26c0b-03f2-4d2e-ae87-c02d7f33c123',
@@ -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)
diff --git a/ironic/tests/unit/drivers/modules/test_ipmitool.py b/ironic/tests/unit/drivers/modules/test_ipmitool.py
index 1c9e61bf9..2507b431f 100644
--- a/ironic/tests/unit/drivers/modules/test_ipmitool.py
+++ b/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:
diff --git a/ironic/tests/unit/drivers/modules/test_ipxe.py b/ironic/tests/unit/drivers/modules/test_ipxe.py
index 32bc1f3ed..45a68eeb3 100644
--- a/ironic/tests/unit/drivers/modules/test_ipxe.py
+++ b/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)
@@ -851,6 +992,59 @@ class iPXEBootTestCase(db_base.DbTestCase):
@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)
@mock.patch.object(deploy_utils, 'switch_pxe_config', autospec=True)
@mock.patch.object(dhcp_factory, 'DHCPFactory', 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)
diff --git a/ironic/tests/unit/drivers/modules/test_pxe.py b/ironic/tests/unit/drivers/modules/test_pxe.py
index 8847b9813..5b8940e29 100644
--- a/ironic/tests/unit/drivers/modules/test_pxe.py
+++ b/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):
self.node.provision_state = states.DEPLOYING
self.node.save()
- self._test_prepare_ramdisk(node_boot_mode=boot_modes.LEGACY_BIOS)
+ self._test_prepare_ramdisk(node_boot_mode=boot_modes.LEGACY_BIOS,
+ uefi=False)
with task_manager.acquire(self.context, self.node.uuid) as task:
driver_internal_info = task.node.driver_internal_info
@@ -408,8 +420,7 @@ class PXEBootTestCase(db_base.DbTestCase):
self.config(default_boot_mode=boot_modes.LEGACY_BIOS, group='deploy')
- self._test_prepare_ramdisk()
-
+ self._test_prepare_ramdisk(uefi=False)
with task_manager.acquire(self.context, self.node.uuid) as task:
driver_internal_info = task.node.driver_internal_info
self.assertIn('deploy_boot_mode', driver_internal_info)
@@ -470,7 +481,7 @@ class PXEBootTestCase(db_base.DbTestCase):
properties['capabilities'] = 'boot_mode:uefi'
self.node.properties = properties
self.node.save()
- self._test_prepare_ramdisk(uefi=True, node_boot_mode=boot_modes.UEFI)
+ self._test_prepare_ramdisk(node_boot_mode=boot_modes.UEFI)
self.assertEqual(set_boot_mode_mock.call_count, 0)
@mock.patch.object(pxe_utils, 'clean_up_pxe_env', autospec=True)
@@ -504,7 +515,7 @@ class PXEBootTestCase(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(
+ def test_prepare_instance_netboot_bios(
self, get_image_info_mock, cache_mock,
dhcp_factory_mock, switch_pxe_config_mock,
set_boot_device_mock):
@@ -514,18 +525,60 @@ class PXEBootTestCase(db_base.DbTestCase):
'ramdisk': ('', '/path/to/ramdisk')}
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.driver_internal_info['root_uuid_or_disk_id'] = (
+ "30212642-09d3-467f-8e09-21685826ab50")
+ task.node.driver_internal_info['is_whole_disk_image'] = False
+ task.node.instance_info = {
+ 'capabilities': {'boot_option': 'netboot',
+ 'boot_mode': 'bios'}}
dhcp_opts = pxe_utils.dhcp_options_for_instance(
task, ipxe_enabled=False, ip_version=4)
dhcp_opts += pxe_utils.dhcp_options_for_instance(
task, ipxe_enabled=False, ip_version=6)
pxe_config_path = pxe_utils.get_pxe_config_file_path(
task.node.uuid)
- task.node.properties['capabilities'] = 'boot_mode:bios'
+ task.driver.boot.prepare_instance(task)
+
+ get_image_info_mock.assert_called_once_with(
+ task, ipxe_enabled=False)
+ cache_mock.assert_called_once_with(
+ task, image_info, ipxe_enabled=False)
+ 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",
+ 'bios', False, False, False, False, ipxe_enabled=False,
+ 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_uefi(
+ 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
+ with task_manager.acquire(self.context, self.node.uuid) as task:
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.node.instance_info = {
'capabilities': {'boot_option': 'netboot'}}
+ dhcp_opts = pxe_utils.dhcp_options_for_instance(
+ task, ipxe_enabled=False, ip_version=4)
+ dhcp_opts += pxe_utils.dhcp_options_for_instance(
+ task, ipxe_enabled=False, ip_version=6)
+ pxe_config_path = pxe_utils.get_pxe_config_file_path(
+ task.node.uuid)
task.driver.boot.prepare_instance(task)
get_image_info_mock.assert_called_once_with(
@@ -535,7 +588,7 @@ class PXEBootTestCase(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, "30212642-09d3-467f-8e09-21685826ab50",
- 'bios', False, False, False, False, ipxe_enabled=False,
+ 'uefi', False, False, False, False, ipxe_enabled=False,
anaconda_boot=False)
set_boot_device_mock.assert_called_once_with(task,
boot_devices.PXE,
@@ -561,18 +614,18 @@ class PXEBootTestCase(db_base.DbTestCase):
self.node.provision_state = states.ACTIVE
self.node.save()
with task_manager.acquire(self.context, self.node.uuid) as task:
- dhcp_opts = pxe_utils.dhcp_options_for_instance(
- task, ipxe_enabled=False)
- dhcp_opts += pxe_utils.dhcp_options_for_instance(
- task, ipxe_enabled=False, ip_version=6)
- pxe_config_path = pxe_utils.get_pxe_config_file_path(
- task.node.uuid)
task.node.properties['capabilities'] = 'boot_mode:bios'
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.node.instance_info['capabilities'] = instance_info
task.driver.boot.prepare_instance(task)
+ dhcp_opts = pxe_utils.dhcp_options_for_instance(
+ task, ipxe_enabled=False)
+ dhcp_opts += pxe_utils.dhcp_options_for_instance(
+ task, ipxe_enabled=False, ip_version=6)
+ pxe_config_path = pxe_utils.get_pxe_config_file_path(
+ task.node.uuid)
get_image_info_mock.assert_called_once_with(
task, ipxe_enabled=False)
@@ -604,13 +657,13 @@ class PXEBootTestCase(db_base.DbTestCase):
instance_info = {"boot_option": "netboot"}
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['is_whole_disk_image'] = False
dhcp_opts = pxe_utils.dhcp_options_for_instance(
task, ipxe_enabled=False)
dhcp_opts += pxe_utils.dhcp_options_for_instance(
task, ipxe_enabled=False, 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'] = False
task.driver.boot.prepare_instance(task)
@@ -637,13 +690,13 @@ class PXEBootTestCase(db_base.DbTestCase):
get_image_info_mock.return_value = {}
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'] = True
dhcp_opts = pxe_utils.dhcp_options_for_instance(
task, ipxe_enabled=False)
dhcp_opts += pxe_utils.dhcp_options_for_instance(
task, ipxe_enabled=False, 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=False)
@@ -702,7 +755,8 @@ class PXEBootTestCase(db_base.DbTestCase):
self, get_image_info_mock, cache_mock,
dhcp_factory_mock, create_pxe_config_mock,
switch_pxe_config_mock,
- set_boot_device_mock, config_file_exits=False):
+ set_boot_device_mock, config_file_exits=False,
+ uefi=True):
image_info = {'kernel': ['', '/path/to/kernel'],
'ramdisk': ['', '/path/to/ramdisk']}
get_image_info_mock.return_value = image_info
@@ -731,12 +785,22 @@ class PXEBootTestCase(db_base.DbTestCase):
if config_file_exits:
self.assertFalse(create_pxe_config_mock.called)
else:
- create_pxe_config_mock.assert_called_once_with(
- task, mock.ANY, CONF.pxe.pxe_config_template,
- ipxe_enabled=False)
+ if not uefi:
+ create_pxe_config_mock.assert_called_once_with(
+ task, mock.ANY, CONF.pxe.pxe_config_template,
+ ipxe_enabled=False)
+ else:
+ create_pxe_config_mock.assert_called_once_with(
+ task, mock.ANY, CONF.pxe.uefi_pxe_config_template,
+ ipxe_enabled=False)
+ if uefi:
+ boot_mode = 'uefi'
+ else:
+ boot_mode = 'bios'
+
switch_pxe_config_mock.assert_called_once_with(
pxe_config_path, None,
- 'bios', False, ipxe_enabled=False, iscsi_boot=False,
+ boot_mode, False, ipxe_enabled=False, iscsi_boot=False,
ramdisk_boot=True, anaconda_boot=False)
set_boot_device_mock.assert_called_once_with(task,
boot_devices.PXE,
@@ -802,6 +866,70 @@ class PXEBootTestCase(db_base.DbTestCase):
'/path/to/ks.cfg', render_mock.return_value
)
create_pxe_config_mock.assert_called_once_with(
+ task, mock.ANY, CONF.pxe.uefi_pxe_config_template,
+ ipxe_enabled=False)
+ switch_pxe_config_mock.assert_called_once_with(
+ pxe_config_path, None,
+ 'uefi', False, ipxe_enabled=False, iscsi_boot=False,
+ ramdisk_boot=False, anaconda_boot=True)
+ 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(pxe_utils, 'create_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)
+ @mock.patch('ironic.drivers.modules.deploy_utils.get_boot_option',
+ return_value='kickstart', autospec=True)
+ @mock.patch('ironic.drivers.modules.deploy_utils.get_ironic_api_url',
+ return_value='http://fakeserver/api', autospec=True)
+ @mock.patch('ironic.common.utils.render_template', autospec=True)
+ @mock.patch('ironic.common.utils.write_to_file', autospec=True)
+ @mock.patch('ironic.common.utils.execute', autospec=True)
+ def test_prepare_instance_kickstart_bios(
+ self, exec_mock, write_file_mock, render_mock, api_url_mock,
+ boot_opt_mock, get_image_info_mock, cache_mock, dhcp_factory_mock,
+ create_pxe_config_mock, switch_pxe_config_mock,
+ set_boot_device_mock):
+ image_info = {'kernel': ['ins_kernel_id', '/path/to/kernel'],
+ 'ramdisk': ['ins_ramdisk_id', '/path/to/ramdisk'],
+ 'stage2': ['ins_stage2_id', '/path/to/stage2'],
+ 'ks_cfg': ['', '/path/to/ks.cfg'],
+ 'ks_template': ['template_id', '/path/to/ks_template']}
+ get_image_info_mock.return_value = image_info
+ provider_mock = mock.MagicMock()
+ dhcp_factory_mock.return_value = provider_mock
+ self.node.provision_state = states.DEPLOYING
+ self.config(http_url='http://fake_url', group='deploy')
+ self.config(default_boot_mode='bios', group='deploy')
+
+ with task_manager.acquire(self.context, self.node.uuid) as task:
+ dhcp_opts = pxe_utils.dhcp_options_for_instance(
+ task, ipxe_enabled=False)
+ dhcp_opts += pxe_utils.dhcp_options_for_instance(
+ task, ipxe_enabled=False, ip_version=6)
+ pxe_config_path = pxe_utils.get_pxe_config_file_path(
+ task.node.uuid)
+
+ task.driver.boot.prepare_instance(task)
+
+ get_image_info_mock.assert_called_once_with(task,
+ ipxe_enabled=False)
+ cache_mock.assert_called_once_with(
+ task, image_info, False)
+ if os.path.isfile('/usr/bin/ksvalidator'):
+ exec_mock.assert_called_once_with(
+ 'ksvalidator', mock.ANY, check_on_exit=[0], attempts=1
+ )
+ provider_mock.update_dhcp.assert_called_once_with(task, dhcp_opts)
+ render_mock.assert_called()
+ write_file_mock.assert_called_with(
+ '/path/to/ks.cfg', render_mock.return_value
+ )
+ create_pxe_config_mock.assert_called_once_with(
task, mock.ANY, CONF.pxe.pxe_config_template,
ipxe_enabled=False)
switch_pxe_config_mock.assert_called_once_with(
diff --git a/ironic/tests/unit/drivers/modules/test_ramdisk.py b/ironic/tests/unit/drivers/modules/test_ramdisk.py
index b8e874379..4deedbfc2 100644
--- a/ironic/tests/unit/drivers/modules/test_ramdisk.py
+++ b/ironic/tests/unit/drivers/modules/test_ramdisk.py
@@ -106,8 +106,8 @@ class RamdiskDeployTestCase(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, ipxe_enabled=False, iscsi_boot=False,
- ramdisk_boot=True, anaconda_boot=False)
+ CONF.deploy.default_boot_mode, False, ipxe_enabled=False,
+ iscsi_boot=False, ramdisk_boot=True, anaconda_boot=False)
set_boot_device_mock.assert_called_once_with(task,
boot_devices.PXE,
persistent=True)
diff --git a/releasenotes/notes/uefi-is-now-the-default-562b0d68adc59008.yaml b/releasenotes/notes/uefi-is-now-the-default-562b0d68adc59008.yaml
new file mode 100644
index 000000000..dc84a5fed
--- /dev/null
+++ b/releasenotes/notes/uefi-is-now-the-default-562b0d68adc59008.yaml
@@ -0,0 +1,16 @@
+---
+features:
+ - |
+ The default deployment boot mode is *now* UEFI. Legacy BIOS is still
+ supported, however operators who require BIOS nodes will need to
+ set their nodes, or deployment, appropriately.
+upgrade:
+ - |
+ The default boot mode has been changed and now UEFI. Operators who
+ were explicitly relying upon BIOS based deployments in the past,
+ may wish to consider setting an explicit node level override for
+ the node to only utilize BIOS mode. This can be configured at a
+ conductor level with the ``[deploy]default_boot_mode``. Options
+ to set this at a node level can be found in the
+ `Ironic Installation guide - Advanced features <https://docs.openstack.org/ironic/latest/install/advanced.html#boot-mode-support>`_
+ documentation.
diff --git a/zuul.d/ironic-jobs.yaml b/zuul.d/ironic-jobs.yaml
index e00e7397c..bc7ea7910 100644
--- a/zuul.d/ironic-jobs.yaml
+++ b/zuul.d/ironic-jobs.yaml
@@ -213,29 +213,43 @@
- job:
name: ironic-tempest-partition-bios-redfish-pxe
description: "Deploy ironic node over PXE using BIOS boot mode"
- parent: ironic-base
+ parent: ironic-tempest-partition-uefi-redfish-vmedia
required-projects:
- opendev.org/openstack/sushy-tools
vars:
devstack_localrc:
- IRONIC_DEPLOY_DRIVER: redfish
- IRONIC_ENABLED_HARDWARE_TYPES: redfish
- IRONIC_ENABLED_POWER_INTERFACES: redfish
- IRONIC_ENABLED_MANAGEMENT_INTERFACES: redfish
- IRONIC_AUTOMATED_CLEAN_ENABLED: False
+ IRONIC_ENABLED_BOOT_INTERFACES: ipxe
+ SWIFT_ENABLE_TEMPURLS: False
+ SWIFT_TEMPURL_KEY: ''
+ # Parent job has a longer timeout due to vmedia usage,
+ # Reset the callback to a normal-ish value.
+ IRONIC_CALLBACK_TIMEOUT: 600
IRONIC_DEFAULT_BOOT_OPTION: netboot
+ IRONIC_BOOT_MODE: bios
+ devstack_services:
+ # Parent job uses swift, this one does not, thus we can turn it off.
+ s-account: False
+ s-container: False
+ s-object: False
+ s-proxy: False
- job:
name: ironic-tempest-partition-uefi-redfish-vmedia
description: "Deploy ironic node over Redfish virtual media using UEFI boot mode"
- parent: ironic-tempest-partition-bios-redfish-pxe
+ parent: ironic-base
vars:
devstack_localrc:
- IRONIC_BOOT_MODE: uefi
+ IRONIC_DEPLOY_DRIVER: redfish
+ IRONIC_ENABLED_HARDWARE_TYPES: redfish
+ IRONIC_ENABLED_POWER_INTERFACES: redfish
+ IRONIC_ENABLED_MANAGEMENT_INTERFACES: redfish
+ IRONIC_AUTOMATED_CLEAN_ENABLED: False
+ # TODO(TheJulia): We need to excise netboot from
+ # jobs at some point.
+ IRONIC_DEFAULT_BOOT_OPTION: netboot
IRONIC_ENABLED_BOOT_INTERFACES: redfish-virtual-media
SWIFT_ENABLE_TEMPURLS: True
SWIFT_TEMPURL_KEY: secretkey
- IRONIC_AUTOMATED_CLEAN_ENABLED: False
# Ironic has to master a new image, and this CAN take longer as a
# result and makes this job VERY sensitive to heavy disk IO of the
# underlying hypervisor/cloud.
@@ -297,6 +311,7 @@
IRONIC_VM_SPECS_RAM: 3096
SWIFT_ENABLE_TEMPURLS: True
SWIFT_TEMPURL_KEY: secretkey
+ IRONIC_BOOT_MODE: bios
devstack_services:
s-account: True
s-container: True
@@ -315,6 +330,7 @@
IRONIC_VM_EPHEMERAL_DISK: 0
IRONIC_AUTOMATED_CLEAN_ENABLED: False
IRONIC_ENFORCE_SCOPE: True
+ IRONIC_BOOT_MODE: bios
- job:
name: ironic-tempest-ipa-partition-uefi-pxe_ipmitool
@@ -322,7 +338,6 @@
parent: ironic-base
vars:
devstack_localrc:
- IRONIC_BOOT_MODE: uefi
IRONIC_VM_SPECS_RAM: 4096
IRONIC_AUTOMATED_CLEAN_ENABLED: False
IRONIC_DEFAULT_BOOT_OPTION: netboot
@@ -655,7 +670,6 @@
IRONIC_ENABLED_HARDWARE_TYPES: ipmi
IRONIC_ENABLED_BOOT_INTERFACES: pxe
IRONIC_IPXE_ENABLED: False
- IRONIC_BOOT_MODE: uefi
IRONIC_RAMDISK_TYPE: tinyipa
IRONIC_AUTOMATED_CLEAN_ENABLED: False
IRONIC_DEFAULT_BOOT_OPTION: netboot
@@ -700,6 +714,7 @@
IRONIC_AUTOMATED_CLEAN_ENABLED: False
SWIFT_ENABLE_TEMPURLS: True
SWIFT_TEMPURL_KEY: secretkey
+ IRONIC_BOOT_MODE: bios
- job:
name: ironic-tempest-ipxe-ipv6
@@ -777,6 +792,7 @@
IRONIC_VM_EPHEMERAL_DISK: 0
SWIFT_ENABLE_TEMPURLS: True
SWIFT_TEMPURL_KEY: secretkey
+ IRONIC_BOOT_MODE: bios
devstack_services:
s-account: True
s-container: True