summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorArne Wiebalck <Arne.Wiebalck@cern.ch>2022-01-24 15:00:05 +0100
committerArne Wiebalck <Arne.Wiebalck@cern.ch>2022-01-28 17:19:51 +0100
commitc9033fcce3b0fbbfbe282c1722bbe592fec2ccf3 (patch)
treeb8230af2bcc7c9f0bddb84bf22002fdd13273f38
parentd2d3cd64852fb0d3a64947f88042c1b3e98261ce (diff)
downloadironic-python-agent-c9033fcce3b0fbbfbe282c1722bbe592fec2ccf3.tar.gz
SoftwareRAID: Use efibootmgr (and drop grub2-install)
Move the software RAID code path from grub2-install to efibootmgr: - remove the UEFI efibootmgr exception for software RAID - create and populate the ESPs on the holder disks - update the NVRAM with all ESPs (the component devices of the ESP mirror, use unique labels to avoid unintentional deduplication of entries in the NVRAM) Story: #2009794 Change-Id: I7ed34e595215194a589c2f1cd0b39ff0336da8f1 (cherry picked from commit 62c5674a600baeeef0af3b12baeab486870eb103)
-rw-r--r--ironic_python_agent/efi_utils.py73
-rw-r--r--ironic_python_agent/extensions/image.py10
-rw-r--r--ironic_python_agent/hardware.py6
-rw-r--r--ironic_python_agent/tests/unit/extensions/test_image.py24
-rw-r--r--ironic_python_agent/tests/unit/test_efi_utils.py83
-rw-r--r--ironic_python_agent/tests/unit/test_hardware.py14
-rw-r--r--releasenotes/notes/move_swraid_to_efibootmgr-d87c1bfde1661fb5.yaml7
7 files changed, 172 insertions, 45 deletions
diff --git a/ironic_python_agent/efi_utils.py b/ironic_python_agent/efi_utils.py
index 156f818a..54d1e62f 100644
--- a/ironic_python_agent/efi_utils.py
+++ b/ironic_python_agent/efi_utils.py
@@ -20,6 +20,8 @@ from oslo_concurrency import processutils
from oslo_log import log
from ironic_python_agent import errors
+from ironic_python_agent.extensions import image
+from ironic_python_agent import hardware
from ironic_python_agent import partition_utils
from ironic_python_agent import utils
@@ -92,16 +94,60 @@ def manage_uefi(device, efi_system_part_uuid=None):
efi_mounted = True
valid_efi_bootloaders = _get_efi_bootloaders(efi_partition_mount_point)
- if valid_efi_bootloaders:
- _run_efibootmgr(valid_efi_bootloaders, device, efi_partition,
- efi_partition_mount_point)
- return True
- else:
+ if not valid_efi_bootloaders:
# NOTE(dtantsur): if we have an empty EFI partition, try to use
# grub-install to populate it.
LOG.warning('Empty EFI partition detected.')
return False
+ if not hardware.is_md_device(device):
+ efi_devices = [device]
+ efi_partition_numbers = [efi_partition]
+ efi_label_suffix = ''
+ else:
+ # umount to allow for signature removal (to avoid confusion about
+ # which ESP to mount once the instance is deployed)
+ utils.execute('umount', efi_partition_mount_point, attempts=3,
+ delay_on_retry=True)
+ efi_mounted = False
+
+ holders = hardware.get_holder_disks(device)
+ efi_md_device = image.prepare_boot_partitions_for_softraid(
+ device, holders, efi_device_part, target_boot_mode='uefi'
+ )
+ efi_devices = hardware.get_component_devices(efi_md_device)
+ efi_partition_numbers = []
+ _PARTITION_NUMBER = re.compile(r'(\d+)$')
+ for dev in efi_devices:
+ match = _PARTITION_NUMBER.search(dev)
+ if match:
+ partition_number = match.group(1)
+ efi_partition_numbers.append(partition_number)
+ else:
+ raise errors.DeviceNotFound(
+ "Could not extract the partition number "
+ "from %s!" % dev)
+ efi_label_suffix = "(RAID, part%s)"
+
+ # remount for _run_efibootmgr
+ utils.execute('mount', efi_device_part, efi_partition_mount_point)
+ efi_mounted = True
+
+ efi_dev_part = zip(efi_devices, efi_partition_numbers)
+ for i, (efi_dev, efi_part) in enumerate(efi_dev_part):
+ LOG.debug("Calling efibootmgr with dev %s part %s",
+ efi_dev, efi_part)
+ if efi_label_suffix:
+ # NOTE (arne_wiebalck): uniqify the labels to prevent
+ # unintentional boot entry cleanup
+ _run_efibootmgr(valid_efi_bootloaders, efi_dev, efi_part,
+ efi_partition_mount_point,
+ efi_label_suffix % i)
+ else:
+ _run_efibootmgr(valid_efi_bootloaders, efi_dev, efi_part,
+ efi_partition_mount_point)
+ return True
+
except processutils.ProcessExecutionError as e:
error_msg = ('Could not verify uefi on device %(dev)s, '
'failed with %(err)s.' % {'dev': device, 'err': e})
@@ -227,7 +273,7 @@ def remove_boot_record(boot_num):
def _run_efibootmgr(valid_efi_bootloaders, device, efi_partition,
- mount_point):
+ mount_point, label_suffix=None):
"""Executes efibootmgr and removes duplicate entries.
:param valid_efi_bootloaders: the list of valid efi bootloaders
@@ -236,6 +282,9 @@ def _run_efibootmgr(valid_efi_bootloaders, device, efi_partition,
:param mount_point: The mountpoint for the EFI partition so we can
read contents of files if necessary to perform
proper bootloader injection operations.
+ :param label_suffix: a string to be appended to the EFI label,
+ mainly used in the case of software to uniqify
+ the entries for the md components.
"""
# Before updating let's get information about the bootorder
@@ -255,9 +304,13 @@ def _run_efibootmgr(valid_efi_bootloaders, device, efi_partition,
v_efi_bl_path = v_bl.replace(csv_filename, str(csv_contents[0]))
v_efi_bl_path = '\\' + v_efi_bl_path.replace('/', '\\')
label = csv_contents[1]
+ if label_suffix:
+ label = label + " " + str(label_suffix)
else:
v_efi_bl_path = '\\' + v_bl.replace('/', '\\')
label = 'ironic' + str(label_id)
+ if label_suffix:
+ label = label + " " + str(label_suffix)
# Iterate through standard out, and look for duplicates
for boot_num, boot_rec in boot_records:
@@ -268,9 +321,11 @@ def _run_efibootmgr(valid_efi_bootloaders, device, efi_partition,
LOG.debug("Found bootnum %s matching label", boot_num)
remove_boot_record(boot_num)
- LOG.debug("Adding loader %(path)s on partition %(part)s of device "
- " %(dev)s", {'path': v_efi_bl_path, 'part': efi_partition,
- 'dev': device})
+ LOG.info("Adding loader %(path)s on partition %(part)s of device "
+ " %(dev)s with label %(label)s",
+ {'path': v_efi_bl_path, 'part': efi_partition,
+ 'dev': device, 'label': label})
+
# Update the nvram using efibootmgr
add_boot_record(device, efi_partition, v_efi_bl_path, label)
# Increment the ID in case the loop runs again.
diff --git a/ironic_python_agent/extensions/image.py b/ironic_python_agent/extensions/image.py
index 11caf585..c917c111 100644
--- a/ironic_python_agent/extensions/image.py
+++ b/ironic_python_agent/extensions/image.py
@@ -105,8 +105,8 @@ def _is_bootloader_loaded(dev):
# TODO(rg): handle PreP boot parts relocation as well
-def _prepare_boot_partitions_for_softraid(device, holders, efi_part,
- target_boot_mode):
+def prepare_boot_partitions_for_softraid(device, holders, efi_part,
+ target_boot_mode):
"""Prepare boot partitions when relevant.
Create either a RAIDed EFI partition or bios boot partitions for software
@@ -311,7 +311,7 @@ def _install_grub2(device, root_uuid, efi_system_part_uuid=None,
efi_partition = efi_part
if hardware.is_md_device(device):
holders = hardware.get_holder_disks(device)
- efi_partition = _prepare_boot_partitions_for_softraid(
+ efi_partition = prepare_boot_partitions_for_softraid(
device, holders, efi_part, target_boot_mode
)
@@ -648,9 +648,7 @@ def _efi_boot_setup(device, efi_system_part_uuid=None, target_boot_mode=None):
{'target': target_boot_mode,
'current': boot.current_boot_mode})
- # FIXME(arne_wiebalck): make software RAID work with efibootmgr
- if (boot.current_boot_mode == 'uefi'
- and not hardware.is_md_device(device)):
+ if boot.current_boot_mode == 'uefi':
try:
utils.execute('efibootmgr', '--version')
except FileNotFoundError:
diff --git a/ironic_python_agent/hardware.py b/ironic_python_agent/hardware.py
index ba42800a..ceafe31e 100644
--- a/ironic_python_agent/hardware.py
+++ b/ironic_python_agent/hardware.py
@@ -181,7 +181,7 @@ def _get_md_uuid(raid_device):
return match.group(1)
-def _get_component_devices(raid_device):
+def get_component_devices(raid_device):
"""Get the component devices of a Software RAID device.
Get the UUID of the md device and scan all other devices
@@ -325,7 +325,7 @@ def md_restart(raid_device):
"""
try:
LOG.debug('Restarting software RAID device %s', raid_device)
- component_devices = _get_component_devices(raid_device)
+ component_devices = get_component_devices(raid_device)
il_utils.execute('mdadm', '--stop', raid_device)
il_utils.execute('mdadm', '--assemble', raid_device,
*component_devices)
@@ -2221,7 +2221,7 @@ class GenericHardwareManager(HardwareManager):
def _delete_config_pass(self, raid_devices):
all_holder_disks = []
for raid_device in raid_devices:
- component_devices = _get_component_devices(raid_device.name)
+ component_devices = get_component_devices(raid_device.name)
if not component_devices:
# A "Software RAID device" without components is usually
# a partition on an md device (as, for instance, created
diff --git a/ironic_python_agent/tests/unit/extensions/test_image.py b/ironic_python_agent/tests/unit/extensions/test_image.py
index 4d389005..c687e59e 100644
--- a/ironic_python_agent/tests/unit/extensions/test_image.py
+++ b/ironic_python_agent/tests/unit/extensions/test_image.py
@@ -1654,7 +1654,7 @@ Boot0004* ironic1 HD(1,GPT,55db8d03-c8f6-4a5b-9155-790dddc348fa,0x800,0x640
self.assertFalse(mock_dispatch.called)
@mock.patch.object(disk_utils, 'find_efi_partition', autospec=True)
- def test__prepare_boot_partitions_for_softraid_uefi_gpt(
+ def test_prepare_boot_partitions_for_softraid_uefi_gpt(
self, mock_efi_part, mock_execute, mock_dispatch):
mock_efi_part.return_value = {'number': '12'}
mock_execute.side_effect = [
@@ -1673,7 +1673,7 @@ Boot0004* ironic1 HD(1,GPT,55db8d03-c8f6-4a5b-9155-790dddc348fa,0x800,0x640
(None, None), # wipefs
]
- efi_part = image._prepare_boot_partitions_for_softraid(
+ efi_part = image.prepare_boot_partitions_for_softraid(
'/dev/md0', ['/dev/sda', '/dev/sdb'], None,
target_boot_mode='uefi')
@@ -1704,7 +1704,7 @@ Boot0004* ironic1 HD(1,GPT,55db8d03-c8f6-4a5b-9155-790dddc348fa,0x800,0x640
@mock.patch.object(disk_utils, 'find_efi_partition', autospec=True)
@mock.patch.object(ilib_utils, 'mkfs', autospec=True)
- def test__prepare_boot_partitions_for_softraid_uefi_gpt_esp_not_found(
+ def test_prepare_boot_partitions_for_softraid_uefi_gpt_esp_not_found(
self, mock_mkfs, mock_efi_part, mock_execute, mock_dispatch):
mock_efi_part.return_value = None
mock_execute.side_effect = [
@@ -1721,7 +1721,7 @@ Boot0004* ironic1 HD(1,GPT,55db8d03-c8f6-4a5b-9155-790dddc348fa,0x800,0x640
(None, None), # mdadm
]
- efi_part = image._prepare_boot_partitions_for_softraid(
+ efi_part = image.prepare_boot_partitions_for_softraid(
'/dev/md0', ['/dev/sda', '/dev/sdb'], None,
target_boot_mode='uefi')
@@ -1748,7 +1748,7 @@ Boot0004* ironic1 HD(1,GPT,55db8d03-c8f6-4a5b-9155-790dddc348fa,0x800,0x640
], any_order=False)
self.assertEqual(efi_part, '/dev/md/esp')
- def test__prepare_boot_partitions_for_softraid_uefi_gpt_efi_provided(
+ def test_prepare_boot_partitions_for_softraid_uefi_gpt_efi_provided(
self, mock_execute, mock_dispatch):
mock_execute.side_effect = [
('451', None), # sgdisk -F
@@ -1766,7 +1766,7 @@ Boot0004* ironic1 HD(1,GPT,55db8d03-c8f6-4a5b-9155-790dddc348fa,0x800,0x640
(None, None), # wipefs
]
- efi_part = image._prepare_boot_partitions_for_softraid(
+ efi_part = image.prepare_boot_partitions_for_softraid(
'/dev/md0', ['/dev/sda', '/dev/sdb'], '/dev/md0p15',
target_boot_mode='uefi')
@@ -1796,10 +1796,10 @@ Boot0004* ironic1 HD(1,GPT,55db8d03-c8f6-4a5b-9155-790dddc348fa,0x800,0x640
@mock.patch.object(disk_utils, 'get_partition_table_type', autospec=True,
return_value='msdos')
- def test__prepare_boot_partitions_for_softraid_bios_msdos(
+ def test_prepare_boot_partitions_for_softraid_bios_msdos(
self, mock_label_scan, mock_execute, mock_dispatch):
- efi_part = image._prepare_boot_partitions_for_softraid(
+ efi_part = image.prepare_boot_partitions_for_softraid(
'/dev/md0', ['/dev/sda', '/dev/sdb'], 'notusedanyway',
target_boot_mode='bios')
@@ -1812,7 +1812,7 @@ Boot0004* ironic1 HD(1,GPT,55db8d03-c8f6-4a5b-9155-790dddc348fa,0x800,0x640
@mock.patch.object(disk_utils, 'get_partition_table_type', autospec=True,
return_value='gpt')
- def test__prepare_boot_partitions_for_softraid_bios_gpt(
+ def test_prepare_boot_partitions_for_softraid_bios_gpt(
self, mock_label_scan, mock_execute, mock_dispatch):
mock_execute.side_effect = [
@@ -1822,7 +1822,7 @@ Boot0004* ironic1 HD(1,GPT,55db8d03-c8f6-4a5b-9155-790dddc348fa,0x800,0x640
(None, None), # bios boot grub
]
- efi_part = image._prepare_boot_partitions_for_softraid(
+ efi_part = image.prepare_boot_partitions_for_softraid(
'/dev/md0', ['/dev/sda', '/dev/sdb'], 'notusedanyway',
target_boot_mode='bios')
@@ -1854,7 +1854,7 @@ Boot0004* ironic1 HD(1,GPT,55db8d03-c8f6-4a5b-9155-790dddc348fa,0x800,0x640
@mock.patch.object(os, 'environ', autospec=True)
@mock.patch.object(os, 'makedirs', autospec=True)
@mock.patch.object(partition_utils, 'get_partition', autospec=True)
- @mock.patch.object(image, '_prepare_boot_partitions_for_softraid',
+ @mock.patch.object(image, 'prepare_boot_partitions_for_softraid',
autospec=True,
return_value='/dev/md/esp')
@mock.patch.object(image, '_has_dracut',
@@ -1972,7 +1972,7 @@ Boot0004* ironic1 HD(1,GPT,55db8d03-c8f6-4a5b-9155-790dddc348fa,0x800,0x640
@mock.patch.object(os, 'environ', autospec=True)
@mock.patch.object(os, 'makedirs', autospec=True)
@mock.patch.object(partition_utils, 'get_partition', autospec=True)
- @mock.patch.object(image, '_prepare_boot_partitions_for_softraid',
+ @mock.patch.object(image, 'prepare_boot_partitions_for_softraid',
autospec=True,
return_value=[])
@mock.patch.object(image, '_has_dracut',
diff --git a/ironic_python_agent/tests/unit/test_efi_utils.py b/ironic_python_agent/tests/unit/test_efi_utils.py
index 0933cc32..775d0fce 100644
--- a/ironic_python_agent/tests/unit/test_efi_utils.py
+++ b/ironic_python_agent/tests/unit/test_efi_utils.py
@@ -19,6 +19,8 @@ from ironic_lib import disk_utils
from ironic_python_agent import efi_utils
from ironic_python_agent import errors
+from ironic_python_agent.extensions import image
+from ironic_python_agent import hardware
from ironic_python_agent import partition_utils
from ironic_python_agent.tests.unit import base
from ironic_python_agent import utils
@@ -158,12 +160,15 @@ class TestManageUefi(base.IronicAgentTest):
mock_rescan.assert_called_once_with(self.fake_dev)
@mock.patch.object(os.path, 'exists', lambda *_: False)
+ @mock.patch.object(hardware, 'is_md_device', autospec=True)
@mock.patch.object(efi_utils, '_get_efi_bootloaders', autospec=True)
@mock.patch.object(os, 'makedirs', autospec=True)
- def test_ok(self, mkdir_mock, mock_efi_bl, mock_utils_efi_part,
- mock_get_part_uuid, mock_execute, mock_rescan):
+ def test_ok(self, mkdir_mock, mock_efi_bl, mock_is_md_device,
+ mock_utils_efi_part, mock_get_part_uuid, mock_execute,
+ mock_rescan):
mock_utils_efi_part.return_value = {'number': '1'}
mock_get_part_uuid.return_value = self.fake_dev
+ mock_is_md_device.return_value = False
mock_efi_bl.return_value = ['EFI/BOOT/BOOTX64.EFI']
@@ -192,13 +197,16 @@ class TestManageUefi(base.IronicAgentTest):
mock_rescan.assert_called_once_with(self.fake_dev)
@mock.patch.object(os.path, 'exists', lambda *_: False)
+ @mock.patch.object(hardware, 'is_md_device', autospec=True)
@mock.patch.object(efi_utils, '_get_efi_bootloaders', autospec=True)
@mock.patch.object(os, 'makedirs', autospec=True)
- def test_found_csv(self, mkdir_mock, mock_efi_bl, mock_utils_efi_part,
- mock_get_part_uuid, mock_execute, mock_rescan):
+ def test_found_csv(self, mkdir_mock, mock_efi_bl, mock_is_md_device,
+ mock_utils_efi_part, mock_get_part_uuid, mock_execute,
+ mock_rescan):
mock_utils_efi_part.return_value = {'number': '1'}
mock_get_part_uuid.return_value = self.fake_dev
mock_efi_bl.return_value = ['EFI/vendor/BOOTX64.CSV']
+ mock_is_md_device.return_value = False
# Format is <file>,<entry_name>,<options>,humanfriendlytextnotused
# https://www.rodsbooks.com/efi-bootloaders/fallback.html
@@ -242,12 +250,15 @@ Boot0002: VENDMAGIC FvFile(9f3c6294-bf9b-4208-9808-be45dfc34b51)
mock_execute.assert_has_calls(expected)
@mock.patch.object(os.path, 'exists', lambda *_: False)
+ @mock.patch.object(hardware, 'is_md_device', autospec=True)
@mock.patch.object(efi_utils, '_get_efi_bootloaders', autospec=True)
@mock.patch.object(os, 'makedirs', autospec=True)
- def test_nvme_device(self, mkdir_mock, mock_efi_bl, mock_utils_efi_part,
- mock_get_part_uuid, mock_execute, mock_rescan):
+ def test_nvme_device(self, mkdir_mock, mock_efi_bl, mock_is_md_device,
+ mock_utils_efi_part, mock_get_part_uuid,
+ mock_execute, mock_rescan):
mock_utils_efi_part.return_value = {'number': '1'}
mock_get_part_uuid.return_value = '/dev/fakenvme0p1'
+ mock_is_md_device.return_value = False
mock_efi_bl.return_value = ['EFI/BOOT/BOOTX64.EFI']
@@ -274,12 +285,15 @@ Boot0002: VENDMAGIC FvFile(9f3c6294-bf9b-4208-9808-be45dfc34b51)
mock_execute.assert_has_calls(expected)
@mock.patch.object(os.path, 'exists', lambda *_: False)
+ @mock.patch.object(hardware, 'is_md_device', autospec=True)
@mock.patch.object(efi_utils, '_get_efi_bootloaders', autospec=True)
@mock.patch.object(os, 'makedirs', autospec=True)
- def test_wholedisk(self, mkdir_mock, mock_efi_bl, mock_utils_efi_part,
- mock_get_part_uuid, mock_execute, mock_rescan):
+ def test_wholedisk(self, mkdir_mock, mock_efi_bl, mock_is_md_device,
+ mock_utils_efi_part, mock_get_part_uuid, mock_execute,
+ mock_rescan):
mock_utils_efi_part.return_value = {'number': '1'}
mock_get_part_uuid.side_effect = Exception
+ mock_is_md_device.return_value = False
mock_efi_bl.return_value = ['EFI/BOOT/BOOTX64.EFI']
@@ -304,3 +318,56 @@ Boot0002: VENDMAGIC FvFile(9f3c6294-bf9b-4208-9808-be45dfc34b51)
mkdir_mock.assert_called_once_with(self.fake_dir + '/boot/efi')
mock_efi_bl.assert_called_once_with(self.fake_dir + '/boot/efi')
mock_execute.assert_has_calls(expected)
+
+ @mock.patch.object(os.path, 'exists', lambda *_: False)
+ @mock.patch.object(hardware, 'get_component_devices', autospec=True)
+ @mock.patch.object(image,
+ 'prepare_boot_partitions_for_softraid',
+ autospec=True)
+ @mock.patch.object(hardware, 'get_holder_disks', autospec=True)
+ @mock.patch.object(hardware, 'is_md_device', autospec=True)
+ @mock.patch.object(efi_utils, '_get_efi_bootloaders', autospec=True)
+ @mock.patch.object(os, 'makedirs', autospec=True)
+ def test_software_raid(self, mkdir_mock, mock_efi_bl, mock_is_md_device,
+ mock_get_holder_disks, mock_prepare,
+ mock_get_component_devices,
+ mock_utils_efi_part, mock_get_part_uuid,
+ mock_execute, mock_rescan):
+ mock_utils_efi_part.return_value = {'number': '1'}
+ mock_get_part_uuid.side_effect = Exception
+ mock_is_md_device.return_value = True
+ mock_get_holder_disks.return_value = ['/dev/sda', '/dev/sdb']
+ mock_prepare.return_value = '/dev/md125'
+ mock_get_component_devices.return_value = ['/dev/sda3', '/dev/sdb3']
+
+ mock_efi_bl.return_value = ['EFI/BOOT/BOOTX64.EFI']
+
+ mock_execute.side_effect = iter([('', ''), ('', ''),
+ ('', ''), ('', ''),
+ ('', ''), ('', ''),
+ ('', ''), ('', ''),
+ ('', '')])
+
+ expected = [mock.call('mount', self.fake_efi_system_part,
+ self.fake_dir + '/boot/efi'),
+ mock.call('umount', self.fake_dir + '/boot/efi',
+ attempts=3, delay_on_retry=True),
+ mock.call('mount', self.fake_efi_system_part,
+ self.fake_dir + '/boot/efi'),
+ mock.call('efibootmgr', '-v'),
+ mock.call('efibootmgr', '-v', '-c', '-d', '/dev/sda3',
+ '-p', '3', '-w', '-L', 'ironic1 (RAID, part0)',
+ '-l', '\\EFI\\BOOT\\BOOTX64.EFI'),
+ mock.call('efibootmgr', '-v'),
+ mock.call('efibootmgr', '-v', '-c', '-d', '/dev/sdb3',
+ '-p', '3', '-w', '-L', 'ironic1 (RAID, part1)',
+ '-l', '\\EFI\\BOOT\\BOOTX64.EFI'),
+ mock.call('umount', self.fake_dir + '/boot/efi',
+ attempts=3, delay_on_retry=True),
+ mock.call('sync')]
+
+ result = efi_utils.manage_uefi(self.fake_dev, None)
+ self.assertTrue(result)
+ mkdir_mock.assert_called_once_with(self.fake_dir + '/boot/efi')
+ mock_efi_bl.assert_called_once_with(self.fake_dir + '/boot/efi')
+ mock_execute.assert_has_calls(expected)
diff --git a/ironic_python_agent/tests/unit/test_hardware.py b/ironic_python_agent/tests/unit/test_hardware.py
index 482bf344..7b19931b 100644
--- a/ironic_python_agent/tests/unit/test_hardware.py
+++ b/ironic_python_agent/tests/unit/test_hardware.py
@@ -3660,9 +3660,9 @@ class TestGenericHardwareManager(base.IronicAgentTest):
@mock.patch.object(hardware, '_get_md_uuid', autospec=True)
@mock.patch.object(hardware, 'list_all_block_devices', autospec=True)
@mock.patch.object(il_utils, 'execute', autospec=True)
- def test__get_component_devices(self, mocked_execute,
- mocked_list_all_block_devices,
- mocked_md_uuid):
+ def test_get_component_devices(self, mocked_execute,
+ mocked_list_all_block_devices,
+ mocked_md_uuid):
raid_device1 = hardware.BlockDevice('/dev/md0', 'RAID-1',
107374182400, True)
sda = hardware.BlockDevice('/dev/sda', 'model12', 21, True)
@@ -3682,7 +3682,7 @@ class TestGenericHardwareManager(base.IronicAgentTest):
[hws.MDADM_EXAMINE_OUTPUT_NON_MEMBER, '_'],
]
- component_devices = hardware._get_component_devices(raid_device1)
+ component_devices = hardware.get_component_devices(raid_device1)
self.assertEqual(['/dev/sda1'], component_devices)
mocked_execute.assert_has_calls([
mock.call('mdadm', '--examine', '/dev/sda',
@@ -3739,7 +3739,7 @@ class TestGenericHardwareManager(base.IronicAgentTest):
self.assertEqual(['/dev/sda'], holder_disks)
@mock.patch.object(hardware, 'get_holder_disks', autospec=True)
- @mock.patch.object(hardware, '_get_component_devices', autospec=True)
+ @mock.patch.object(hardware, 'get_component_devices', autospec=True)
@mock.patch.object(hardware, 'list_all_block_devices', autospec=True)
@mock.patch.object(il_utils, 'execute', autospec=True)
def test_delete_configuration(self, mocked_execute, mocked_list,
@@ -3827,7 +3827,7 @@ class TestGenericHardwareManager(base.IronicAgentTest):
mock.call('mdadm', '--assemble', '--scan', check_exit_code=False),
])
- @mock.patch.object(hardware, '_get_component_devices', autospec=True)
+ @mock.patch.object(hardware, 'get_component_devices', autospec=True)
@mock.patch.object(hardware, 'list_all_block_devices', autospec=True)
@mock.patch.object(il_utils, 'execute', autospec=True)
def test_delete_configuration_partition(self, mocked_execute, mocked_list,
@@ -3852,7 +3852,7 @@ class TestGenericHardwareManager(base.IronicAgentTest):
mock.call('mdadm', '--assemble', '--scan', check_exit_code=False),
])
- @mock.patch.object(hardware, '_get_component_devices', autospec=True)
+ @mock.patch.object(hardware, 'get_component_devices', autospec=True)
@mock.patch.object(hardware, 'list_all_block_devices', autospec=True)
@mock.patch.object(il_utils, 'execute', autospec=True)
def test_delete_configuration_failure_blocks_remaining(
diff --git a/releasenotes/notes/move_swraid_to_efibootmgr-d87c1bfde1661fb5.yaml b/releasenotes/notes/move_swraid_to_efibootmgr-d87c1bfde1661fb5.yaml
new file mode 100644
index 00000000..3fa29284
--- /dev/null
+++ b/releasenotes/notes/move_swraid_to_efibootmgr-d87c1bfde1661fb5.yaml
@@ -0,0 +1,7 @@
+---
+fixes:
+ - |
+ Use efibootmgr instead of grub2-install for software RAID.
+ This fixes an issue with images which include newer versions
+ of grub2-install as they refuse bootloader installations in
+ UEFI boot mode due to the lack of secure boot support.