Merge "Delete EFI boot entry duplicate labels first" into stable/xena
This commit is contained in:
commit
38b8ec7510
|
@ -274,12 +274,10 @@ def _run_efibootmgr(valid_efi_bootloaders, device, efi_partition,
|
||||||
|
|
||||||
# Before updating let's get information about the bootorder
|
# Before updating let's get information about the bootorder
|
||||||
LOG.debug("Getting information about boot order.")
|
LOG.debug("Getting information about boot order.")
|
||||||
utils.execute('efibootmgr', '-v')
|
original_efi_output = utils.execute('efibootmgr', '-v')
|
||||||
# NOTE(iurygregory): regex used to identify the Warning in the stderr after
|
# NOTE(TheJulia): regex used to identify entries in the efibootmgr
|
||||||
# we add the new entry. Example:
|
# output on stdout.
|
||||||
# "efibootmgr: ** Warning ** : Boot0004 has same label ironic"
|
entry_label = re.compile(r'Boot([0-9a-f-A-F]+):\s(.*).*$')
|
||||||
duplicated_label = re.compile(r'^.*:\s\*\*.*\*\*\s:\s.*'
|
|
||||||
r'Boot([0-9a-f-A-F]+)\s.*$')
|
|
||||||
label_id = 1
|
label_id = 1
|
||||||
for v_bl in valid_efi_bootloaders:
|
for v_bl in valid_efi_bootloaders:
|
||||||
if 'csv' in v_bl.lower():
|
if 'csv' in v_bl.lower():
|
||||||
|
@ -298,20 +296,26 @@ def _run_efibootmgr(valid_efi_bootloaders, device, efi_partition,
|
||||||
v_efi_bl_path = '\\' + v_bl.replace('/', '\\')
|
v_efi_bl_path = '\\' + v_bl.replace('/', '\\')
|
||||||
label = 'ironic' + str(label_id)
|
label = 'ironic' + str(label_id)
|
||||||
|
|
||||||
|
# Iterate through standard out, and look for duplicates
|
||||||
|
for line in original_efi_output[0].split('\n'):
|
||||||
|
match = entry_label.match(line)
|
||||||
|
# Look for the base label in the string if a line match
|
||||||
|
# occurs, so we can identify if we need to eliminate the
|
||||||
|
# entry.
|
||||||
|
if match and label in match.group(2):
|
||||||
|
boot_num = match.group(1)
|
||||||
|
LOG.debug("Found bootnum %s matching label", boot_num)
|
||||||
|
utils.execute('efibootmgr', '-b', boot_num, '-B')
|
||||||
|
|
||||||
LOG.debug("Adding loader %(path)s on partition %(part)s of device "
|
LOG.debug("Adding loader %(path)s on partition %(part)s of device "
|
||||||
" %(dev)s", {'path': v_efi_bl_path, 'part': efi_partition,
|
" %(dev)s", {'path': v_efi_bl_path, 'part': efi_partition,
|
||||||
'dev': device})
|
'dev': device})
|
||||||
# Update the nvram using efibootmgr
|
# Update the nvram using efibootmgr
|
||||||
# https://linux.die.net/man/8/efibootmgr
|
# https://linux.die.net/man/8/efibootmgr
|
||||||
cmd = utils.execute('efibootmgr', '-v', '-c', '-d', device,
|
utils.execute('efibootmgr', '-v', '-c', '-d', device,
|
||||||
'-p', efi_partition, '-w', '-L', label,
|
'-p', efi_partition, '-w', '-L', label,
|
||||||
'-l', v_efi_bl_path)
|
'-l', v_efi_bl_path)
|
||||||
for line in cmd[1].split('\n'):
|
# Increment the ID in case the loop runs again.
|
||||||
match = duplicated_label.match(line)
|
|
||||||
if match:
|
|
||||||
boot_num = match.group(1)
|
|
||||||
LOG.debug("Found bootnum %s matching label", boot_num)
|
|
||||||
utils.execute('efibootmgr', '-b', boot_num, '-B')
|
|
||||||
label_id += 1
|
label_id += 1
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -319,13 +319,17 @@ class TestImageExtension(base.IronicAgentTest):
|
||||||
mock_partition.return_value = self.fake_dev
|
mock_partition.return_value = self.fake_dev
|
||||||
mock_utils_efi_part.return_value = '1'
|
mock_utils_efi_part.return_value = '1'
|
||||||
mock_efi_bl.return_value = ['EFI/BOOT/BOOTX64.EFI']
|
mock_efi_bl.return_value = ['EFI/BOOT/BOOTX64.EFI']
|
||||||
stdeer_msg = """
|
stdout_msg = """
|
||||||
efibootmgr: ** Warning ** : Boot0004 has same label ironic1\n
|
BootCurrent: 0001
|
||||||
efibootmgr: ** Warning ** : Boot0005 has same label ironic1\n
|
Timeout: 0 seconds
|
||||||
"""
|
BootOrder: 0000,00001
|
||||||
|
Boot0000: ironic1 HD(1, GPT,4f3c6294-bf9b-4208-9808-be45dfc34b5c)File(\EFI\Boot\BOOTX64.EFI)
|
||||||
|
Boot0001: ironic2 HD(1, GPT,4f3c6294-bf9b-4208-9808-111111111112)File(\EFI\Boot\BOOTX64.EFI)
|
||||||
|
Boot0002: VENDMAGIC FvFile(9f3c6294-bf9b-4208-9808-be45dfc34b51)
|
||||||
|
""" # noqa This is a giant literal string for testing.
|
||||||
mock_execute.side_effect = iter([('', ''), ('', ''),
|
mock_execute.side_effect = iter([('', ''), ('', ''),
|
||||||
('', ''), ('', ''),
|
('', ''), ('', ''),
|
||||||
('', ''), ('', stdeer_msg),
|
(stdout_msg, ''), ('', ''),
|
||||||
('', ''), ('', ''),
|
('', ''), ('', ''),
|
||||||
('', ''), ('', '')])
|
('', ''), ('', '')])
|
||||||
|
|
||||||
|
@ -336,12 +340,11 @@ efibootmgr: ** Warning ** : Boot0005 has same label ironic1\n
|
||||||
mock.call('mount', self.fake_efi_system_part,
|
mock.call('mount', self.fake_efi_system_part,
|
||||||
self.fake_dir + '/boot/efi'),
|
self.fake_dir + '/boot/efi'),
|
||||||
mock.call('efibootmgr', '-v'),
|
mock.call('efibootmgr', '-v'),
|
||||||
|
mock.call('efibootmgr', '-b', '0000', '-B'),
|
||||||
mock.call('efibootmgr', '-v', '-c', '-d', self.fake_dev,
|
mock.call('efibootmgr', '-v', '-c', '-d', self.fake_dev,
|
||||||
'-p', '1', '-w',
|
'-p', '1', '-w',
|
||||||
'-L', 'ironic1', '-l',
|
'-L', 'ironic1', '-l',
|
||||||
'\\EFI\\BOOT\\BOOTX64.EFI'),
|
'\\EFI\\BOOT\\BOOTX64.EFI'),
|
||||||
mock.call('efibootmgr', '-b', '0004', '-B'),
|
|
||||||
mock.call('efibootmgr', '-b', '0005', '-B'),
|
|
||||||
mock.call('umount', self.fake_dir + '/boot/efi',
|
mock.call('umount', self.fake_dir + '/boot/efi',
|
||||||
attempts=3, delay_on_retry=True),
|
attempts=3, delay_on_retry=True),
|
||||||
mock.call('sync')]
|
mock.call('sync')]
|
||||||
|
@ -356,7 +359,7 @@ efibootmgr: ** Warning ** : Boot0005 has same label ironic1\n
|
||||||
mock_efi_bl.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_execute.assert_has_calls(expected)
|
||||||
mock_utils_efi_part.assert_called_once_with(self.fake_dev)
|
mock_utils_efi_part.assert_called_once_with(self.fake_dev)
|
||||||
self.assertEqual(10, mock_execute.call_count)
|
self.assertEqual(9, mock_execute.call_count)
|
||||||
|
|
||||||
@mock.patch.object(hardware, 'is_md_device', lambda *_: False)
|
@mock.patch.object(hardware, 'is_md_device', lambda *_: False)
|
||||||
@mock.patch.object(os.path, 'exists', lambda *_: False)
|
@mock.patch.object(os.path, 'exists', lambda *_: False)
|
||||||
|
@ -2259,8 +2262,19 @@ efibootmgr: ** Warning ** : Boot0005 has same label ironic1\n
|
||||||
# Mild difference, Ubuntu ships a file without a 0xFEFF delimiter
|
# Mild difference, Ubuntu ships a file without a 0xFEFF delimiter
|
||||||
# at the start of the file, where as Red Hat *does*
|
# at the start of the file, where as Red Hat *does*
|
||||||
csv_file_data = u'shimx64.efi,Vendor String,,Grub2MadeUSDoThis\n'
|
csv_file_data = u'shimx64.efi,Vendor String,,Grub2MadeUSDoThis\n'
|
||||||
|
# This test also handles deleting a pre-existing matching vendor
|
||||||
|
# string in advance.
|
||||||
|
dupe_entry = """
|
||||||
|
BootCurrent: 0001
|
||||||
|
Timeout: 0 seconds
|
||||||
|
BootOrder: 0000,00001
|
||||||
|
Boot0000: Vendor String HD(1, GPT,4f3c6294-bf9b-4208-9808-be45dfc34b5c)File(\EFI\Boot\BOOTX64.EFI)
|
||||||
|
Boot0001: Vendor String HD(2, GPT,4f3c6294-bf9b-4208-9808-be45dfc34b5c)File(\EFI\Boot\BOOTX64.EFI)
|
||||||
|
Boot0002: VENDMAGIC FvFile(9f3c6294-bf9b-4208-9808-be45dfc34b51)
|
||||||
|
""" # noqa This is a giant literal string for testing.
|
||||||
|
|
||||||
mock_execute.side_effect = iter([('', ''), ('', ''),
|
mock_execute.side_effect = iter([('', ''), ('', ''),
|
||||||
|
('', ''), (dupe_entry, ''),
|
||||||
('', ''), ('', ''),
|
('', ''), ('', ''),
|
||||||
('', ''), ('', ''),
|
('', ''), ('', ''),
|
||||||
('', '')])
|
('', '')])
|
||||||
|
@ -2271,6 +2285,8 @@ efibootmgr: ** Warning ** : Boot0005 has same label ironic1\n
|
||||||
mock.call('mount', self.fake_efi_system_part,
|
mock.call('mount', self.fake_efi_system_part,
|
||||||
self.fake_dir + '/boot/efi'),
|
self.fake_dir + '/boot/efi'),
|
||||||
mock.call('efibootmgr', '-v'),
|
mock.call('efibootmgr', '-v'),
|
||||||
|
mock.call('efibootmgr', '-b', '0000', '-B'),
|
||||||
|
mock.call('efibootmgr', '-b', '0001', '-B'),
|
||||||
mock.call('efibootmgr', '-v', '-c', '-d', self.fake_dev,
|
mock.call('efibootmgr', '-v', '-c', '-d', self.fake_dev,
|
||||||
'-p', '1', '-w',
|
'-p', '1', '-w',
|
||||||
'-L', 'Vendor String', '-l',
|
'-L', 'Vendor String', '-l',
|
||||||
|
@ -2285,7 +2301,7 @@ efibootmgr: ** Warning ** : Boot0005 has same label ironic1\n
|
||||||
mkdir_mock.assert_called_once_with(self.fake_dir + '/boot/efi')
|
mkdir_mock.assert_called_once_with(self.fake_dir + '/boot/efi')
|
||||||
mock_efi_bl.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_execute.assert_has_calls(expected)
|
||||||
self.assertEqual(7, mock_execute.call_count)
|
self.assertEqual(9, mock_execute.call_count)
|
||||||
|
|
||||||
@mock.patch.object(os.path, 'exists', lambda *_: False)
|
@mock.patch.object(os.path, 'exists', lambda *_: False)
|
||||||
@mock.patch.object(image, '_get_efi_bootloaders', autospec=True)
|
@mock.patch.object(image, '_get_efi_bootloaders', autospec=True)
|
||||||
|
@ -2453,6 +2469,7 @@ efibootmgr: ** Warning ** : Boot0005 has same label ironic1\n
|
||||||
mock_execute.assert_has_calls(expected)
|
mock_execute.assert_has_calls(expected)
|
||||||
|
|
||||||
def test__run_efibootmgr(self, mock_execute, mock_dispatch):
|
def test__run_efibootmgr(self, mock_execute, mock_dispatch):
|
||||||
|
mock_execute.return_value = ('', '')
|
||||||
result = image._run_efibootmgr(['EFI/BOOT/BOOTX64.EFI'],
|
result = image._run_efibootmgr(['EFI/BOOT/BOOTX64.EFI'],
|
||||||
self.fake_dev,
|
self.fake_dev,
|
||||||
self.fake_efi_system_part,
|
self.fake_efi_system_part,
|
||||||
|
|
|
@ -0,0 +1,6 @@
|
||||||
|
---
|
||||||
|
fixes:
|
||||||
|
- |
|
||||||
|
Fixes cases where duplicates may not be found in the UEFI
|
||||||
|
firmware NVRAM boot entry table by explicitly looking for, and deleting
|
||||||
|
for matching labels in advance of creating the EFI boot loader entry.
|
Loading…
Reference in New Issue