diff options
-rw-r--r-- | ironic_python_agent/extensions/image.py | 28 | ||||
-rw-r--r-- | ironic_python_agent/tests/unit/extensions/test_image.py | 40 | ||||
-rw-r--r-- | releasenotes/notes/rescan-before-checking-uefi-64597c937880134d.yaml | 7 |
3 files changed, 59 insertions, 16 deletions
diff --git a/ironic_python_agent/extensions/image.py b/ironic_python_agent/extensions/image.py index bb5801ff..34b10501 100644 --- a/ironic_python_agent/extensions/image.py +++ b/ironic_python_agent/extensions/image.py @@ -36,20 +36,28 @@ BIND_MOUNTS = ('/dev', '/proc', '/run') BOOTLOADERS_EFI = ['bootx64.efi', 'grubaa64.efi', 'winload.efi'] +def _rescan_device(device): + """Force the device to be rescanned + + :param device: device upon which to rescan and update + kernel partition records. + """ + try: + utils.execute('partx', '-u', device, attempts=3, + delay_on_retry=True) + utils.execute('udevadm', 'settle') + except processutils.ProcessExecutionError: + LOG.warning("Couldn't re-read the partition table " + "on device %s", device) + + def _get_partition(device, uuid): """Find the partition of a given device.""" LOG.debug("Find the partition %(uuid)s on device %(dev)s", {'dev': device, 'uuid': uuid}) try: - # Try to tell the kernel to re-read the partition table - try: - utils.execute('partx', '-u', device, attempts=3, - delay_on_retry=True) - utils.execute('udevadm', 'settle') - except processutils.ProcessExecutionError: - LOG.warning("Couldn't re-read the partition table " - "on device %s", device) + _rescan_device(device) lsblk = utils.execute('lsblk', '-PbioKNAME,UUID,PARTUUID,TYPE', device) report = lsblk[0] @@ -162,6 +170,10 @@ def _manage_uefi(device, efi_system_part_uuid=None): efi_mounted = False try: + # Force UEFI to rescan the device. Required if the deployment + # was over iscsi. + _rescan_device(device) + local_path = tempfile.mkdtemp() # Trust the contents on the disk in the event of a whole disk image. efi_partition = utils.get_efi_part_on_device(device) diff --git a/ironic_python_agent/tests/unit/extensions/test_image.py b/ironic_python_agent/tests/unit/extensions/test_image.py index ca838a64..dd193a51 100644 --- a/ironic_python_agent/tests/unit/extensions/test_image.py +++ b/ironic_python_agent/tests/unit/extensions/test_image.py @@ -103,9 +103,13 @@ class TestImageExtension(base.IronicAgentTest): mock_execute.side_effect = iter([('', ''), ('', ''), ('', ''), ('', ''), + ('', ''), ('', ''), ('', ''), ('', '')]) expected = [mock.call('efibootmgr', '--version'), + mock.call('partx', '-u', '/dev/fake', attempts=3, + delay_on_retry=True), + mock.call('udevadm', 'settle'), mock.call('mount', self.fake_efi_system_part, self.fake_dir + '/boot/efi'), mock.call('efibootmgr'), @@ -127,7 +131,7 @@ class TestImageExtension(base.IronicAgentTest): mock_efi_bl.assert_called_once_with(self.fake_dir + '/boot/efi') mock_execute.assert_has_calls(expected) mock_utils_efi_part.assert_called_once_with(self.fake_dev) - self.assertEqual(6, mock_execute.call_count) + self.assertEqual(8, mock_execute.call_count) @mock.patch.object(os.path, 'exists', lambda *_: False) @mock.patch.object(iscsi, 'clean_up', autospec=True) @@ -146,9 +150,13 @@ class TestImageExtension(base.IronicAgentTest): mock_efi_bl.return_value = ['\\EFI\\BOOT\\BOOTX64.EFI'] mock_execute.side_effect = iter([('', ''), ('', ''), ('', ''), ('', ''), + ('', ''), ('', ''), ('', ''), ('', '')]) expected = [mock.call('efibootmgr', '--version'), + mock.call('partx', '-u', '/dev/fake', attempts=3, + delay_on_retry=True), + mock.call('udevadm', 'settle'), mock.call('mount', self.fake_efi_system_part, self.fake_dir + '/boot/efi'), mock.call('efibootmgr'), @@ -170,7 +178,7 @@ class TestImageExtension(base.IronicAgentTest): mock_efi_bl.assert_called_once_with(self.fake_dir + '/boot/efi') mock_execute.assert_has_calls(expected) mock_utils_efi_part.assert_called_once_with(self.fake_dev) - self.assertEqual(6, mock_execute.call_count) + self.assertEqual(8, mock_execute.call_count) @mock.patch.object(os.path, 'exists', lambda *_: False) @mock.patch.object(iscsi, 'clean_up', autospec=True) @@ -192,11 +200,15 @@ efibootmgr: ** Warning ** : Boot0004 has same label ironic1\n efibootmgr: ** Warning ** : Boot0005 has same label ironic1\n """ mock_execute.side_effect = iter([('', ''), ('', ''), + ('', ''), ('', ''), ('', ''), ('', stdeer_msg), ('', ''), ('', ''), ('', ''), ('', '')]) expected = [mock.call('efibootmgr', '--version'), + mock.call('partx', '-u', '/dev/fake', attempts=3, + delay_on_retry=True), + mock.call('udevadm', 'settle'), mock.call('mount', self.fake_efi_system_part, self.fake_dir + '/boot/efi'), mock.call('efibootmgr'), @@ -220,7 +232,7 @@ efibootmgr: ** Warning ** : Boot0005 has same label ironic1\n mock_efi_bl.assert_called_once_with(self.fake_dir + '/boot/efi') mock_execute.assert_has_calls(expected) mock_utils_efi_part.assert_called_once_with(self.fake_dev) - self.assertEqual(8, mock_execute.call_count) + self.assertEqual(10, mock_execute.call_count) @mock.patch.object(os.path, 'exists', lambda *_: False) @mock.patch.object(iscsi, 'clean_up', autospec=True) @@ -242,9 +254,13 @@ efibootmgr: ** Warning ** : Boot0005 has same label ironic1\n mock_execute.side_effect = iter([('', ''), ('', ''), ('', ''), ('', ''), ('', ''), ('', ''), + ('', ''), ('', ''), ('', '')]) expected = [mock.call('efibootmgr', '--version'), + mock.call('partx', '-u', '/dev/fake', attempts=3, + delay_on_retry=True), + mock.call('udevadm', 'settle'), mock.call('mount', self.fake_efi_system_part, self.fake_dir + '/boot/efi'), mock.call('efibootmgr'), @@ -270,7 +286,7 @@ efibootmgr: ** Warning ** : Boot0005 has same label ironic1\n mock_efi_bl.assert_called_once_with(self.fake_dir + '/boot/efi') mock_execute.assert_has_calls(expected) mock_utils_efi_part.assert_called_once_with(self.fake_dev) - self.assertEqual(7, mock_execute.call_count) + self.assertEqual(9, mock_execute.call_count) @mock.patch.object(iscsi, 'clean_up', autospec=True) @mock.patch.object(image, '_install_grub2', autospec=True) @@ -624,9 +640,13 @@ efibootmgr: ** Warning ** : Boot0005 has same label ironic1\n mock_execute.side_effect = iter([('', ''), ('', ''), ('', ''), ('', ''), + ('', ''), ('', ''), ('', '')]) - expected = [mock.call('mount', self.fake_efi_system_part, + expected = [mock.call('partx', '-u', '/dev/fake', attempts=3, + delay_on_retry=True), + mock.call('udevadm', 'settle'), + mock.call('mount', self.fake_efi_system_part, self.fake_dir + '/boot/efi'), mock.call('efibootmgr'), mock.call('efibootmgr', '-c', '-d', self.fake_dev, @@ -642,7 +662,7 @@ efibootmgr: ** Warning ** : Boot0005 has same label ironic1\n 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) - self.assertEqual(5, mock_execute.call_count) + self.assertEqual(7, mock_execute.call_count) @mock.patch.object(os.path, 'exists', lambda *_: False) @mock.patch.object(image, '_get_efi_bootloaders', autospec=True) @@ -660,9 +680,13 @@ efibootmgr: ** Warning ** : Boot0005 has same label ironic1\n mock_execute.side_effect = iter([('', ''), ('', ''), ('', ''), ('', ''), + ('', ''), ('', ''), ('', '')]) - expected = [mock.call('mount', self.fake_efi_system_part, + expected = [mock.call('partx', '-u', '/dev/fake', attempts=3, + delay_on_retry=True), + mock.call('udevadm', 'settle'), + mock.call('mount', self.fake_efi_system_part, self.fake_dir + '/boot/efi'), mock.call('efibootmgr'), mock.call('efibootmgr', '-c', '-d', self.fake_dev, @@ -678,7 +702,7 @@ efibootmgr: ** Warning ** : Boot0005 has same label ironic1\n 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) - self.assertEqual(5, mock_execute.call_count) + self.assertEqual(7, mock_execute.call_count) @mock.patch.object(os, 'walk', autospec=True) @mock.patch.object(os, 'access', autospec=False) diff --git a/releasenotes/notes/rescan-before-checking-uefi-64597c937880134d.yaml b/releasenotes/notes/rescan-before-checking-uefi-64597c937880134d.yaml new file mode 100644 index 00000000..90041f1c --- /dev/null +++ b/releasenotes/notes/rescan-before-checking-uefi-64597c937880134d.yaml @@ -0,0 +1,7 @@ +--- +fixes: + - | + Fixes an issue where the agent was failing to rescan the device deployed + upon before checking uefi contents. This would occur with an iSCSI + based deployment, as partition management operations are performed by + the conductor, and not locally. |