From c826e7db4c44cc2c6e7648a9c8394881c14989a4 Mon Sep 17 00:00:00 2001 From: mvpnitesh Date: Wed, 12 Jun 2019 10:36:21 +0000 Subject: [PATCH] Returns disk_identifier for UEFI boot mode nodes Returns the disk_identifer for the block device images which will be needed in pxe_grub_config.template to boot wholedisk images in UEFI boot mode. Change-Id: I9882a81ae6d476fd26f3fe0dc00f6072454e3e5a Story: 2005532 Task: 33673 --- ironic_lib/disk_utils.py | 35 ++++++++++++++++ ironic_lib/tests/test_disk_utils.py | 62 +++++++++++++++++++++++++++++ 2 files changed, 97 insertions(+) diff --git a/ironic_lib/disk_utils.py b/ironic_lib/disk_utils.py index f4273c7f..6122d0ea 100644 --- a/ironic_lib/disk_utils.py +++ b/ironic_lib/disk_utils.py @@ -159,6 +159,41 @@ def get_disk_identifier(dev): return disk_identifier[0] +def get_uefi_disk_identifier(dev): + """Get the uuid from the disk being exposed by the ramdisk. + + This uuid is appended to the pxe config which will then be set as the root + and load the bootx64.efi file using chainloader and boot the machine. + This is helpful in deployments to nodes with multiple disks. + + https://wiki.gentoo.org/wiki/GRUB2/Chainloading + + :param dev: Path for the already populated disk device. + :raises InstanceDeployFailure: Image is not UEFI bootable. + :returns: The UUID of the partition. + """ + partition_id = None + try: + report, _ = utils.execute('fdisk', '-l', dev, run_as_root=True) + except processutils.ProcessExecutionError as e: + msg = _('Failed to find the partition on the disk %s ') % e + LOG.error(msg) + raise exception.InstanceDeployFailure(msg) + for line in report.splitlines(): + if line.startswith(dev) and 'EFI System' in line: + vals = line.split() + partition_id = vals[0] + try: + lsblk_output, _ = utils.execute('lsblk', '-PbioUUID', partition_id, + run_as_root=True) + disk_identifier = lsblk_output.split("=")[1].strip() + disk_identifier = disk_identifier.strip('"') + except processutils.ProcessExecutionError as e: + raise exception.InstanceDeployFailure("Image is not UEFI bootable. " + "Error: %s " % e) + return disk_identifier + + def is_iscsi_device(dev, node_uuid): """check whether the device path belongs to an iscsi device. """ diff --git a/ironic_lib/tests/test_disk_utils.py b/ironic_lib/tests/test_disk_utils.py index c531d300..f0200bc0 100644 --- a/ironic_lib/tests/test_disk_utils.py +++ b/ironic_lib/tests/test_disk_utils.py @@ -428,6 +428,68 @@ class WorkOnDiskTestCase(base.IronicLibTestCase): conv_flags='sparse') +class GetUEFIDiskIdentifierTestCase(base.IronicLibTestCase): + + def setUp(self): + super(GetUEFIDiskIdentifierTestCase, self).setUp() + self.dev = '/dev/fake' + + @mock.patch.object(utils, 'execute', autospec=True) + def test_get_uefi_disk_identifier_uefi_bootable_image(self, mock_execute): + mock_execute.return_value = ('', '') + fdisk_output = """ +Disk /dev/sda: 931.5 GiB, 1000171331584 bytes, 1953459632 sectors +Units: sectors of 1 * 512 = 512 bytes +Sector size (logical/physical): 512 bytes / 512 bytes +I/O size (minimum/optimal): 262144 bytes / 262144 bytes +Disklabel type: gpt +Disk identifier: 73457A6C-3595-4965-8D83-2EA1BD85F327 + +Device Start End Sectors Size Type +/dev/fake-part1 2048 1050623 1048576 512M EFI System +/dev/fake-part2 1050624 1920172031 1919121408 915.1G Linux filesystem +/dev/fake-part3 1920172032 1953458175 33286144 15.9G Linux swap +""" + partition_id = '/dev/fake-part1' + lsblk_output = 'UUID="ABCD-B05B"\n' + part_result = 'ABCD-B05B' + mock_execute.side_effect = [(fdisk_output, ''), (lsblk_output, '')] + result = disk_utils.get_uefi_disk_identifier(self.dev) + self.assertEqual(part_result, result) + execute_calls = [ + mock.call('fdisk', '-l', self.dev, run_as_root=True), + mock.call('lsblk', '-PbioUUID', partition_id, + run_as_root=True) + ] + mock_execute.assert_has_calls(execute_calls) + + @mock.patch.object(utils, 'execute', autospec=True) + def test_get_uefi_disk_identifier_non_uefi_bootable_image(self, + mock_execute): + mock_execute.return_value = ('', '') + fdisk_output = """ +Disk /dev/vda: 50 GiB, 53687091200 bytes, 104857600 sectors +Units: sectors of 1 * 512 = 512 bytes +Sector size (logical/physical): 512 bytes / 512 bytes +I/O size (minimum/optimal): 512 bytes / 512 bytes +Disklabel type: dos +Disk identifier: 0xb82b9faf + +Device Boot Start End Sectors Size Id Type +/dev/fake-part1 * 2048 104857566 104855519 50G 83 Linux +""" + partition_id = None + mock_execute.side_effect = [(fdisk_output, ''), + processutils.ProcessExecutionError()] + self.assertRaises(exception.InstanceDeployFailure, + disk_utils.get_uefi_disk_identifier, self.dev) + execute_calls = [ + mock.call('fdisk', '-l', self.dev, run_as_root=True), + mock.call('lsblk', '-PbioUUID', partition_id, run_as_root=True) + ] + mock_execute.assert_has_calls(execute_calls) + + @mock.patch.object(utils, 'execute', autospec=True) class MakePartitionsTestCase(base.IronicLibTestCase):