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
This commit is contained in:
parent
e06dd22e78
commit
62c5674a60
@ -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.
|
||||
|
@ -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:
|
||||
|
@ -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
|
||||
|
@ -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',
|
||||
|
@ -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)
|
||||
|
@ -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(
|
||||
|
@ -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.
|
Loading…
Reference in New Issue
Block a user