Ejemplo n.º 1
0
    def _test_scan_partition_table_by_type(self, mocked_execute,
                                           table_type_output,
                                           expected_table_type):

        parted_ret = PARTED_OUTPUT_UNFORMATTED.format(table_type_output)

        mocked_execute.side_effect = [
            (parted_ret, None),
        ]

        ret = utils.scan_partition_table_type('hello')
        mocked_execute.assert_has_calls(
            [mock.call('parted', '-s', 'hello', '--', 'print')])
        self.assertEqual(expected_table_type, ret)
Ejemplo n.º 2
0
def _prepare_boot_partitions_for_softraid(device, holders, efi_part,
                                          target_boot_mode):
    """Prepare boot partitions when relevant.

    Create either efi partitions or bios boot partitions for softraid,
    according to both target boot mode and disk holders partition table types.

    :param device: the softraid device path
    :param holders: the softraid drive members
    :param efi_part: when relevant the efi partition coming from the image
     deployed on softraid device, can be/is often None
    :param target_boot_mode: target boot mode can be bios/uefi/None
     or anything else for unspecified

    :returns: the efi partition paths on softraid disk holders when target
     boot mode is uefi, empty list otherwise.
    """
    efi_partitions = []

    # Actually any fat partition could be a candidate. Let's assume the
    # partition also has the esp flag
    if target_boot_mode == 'uefi':
        if not efi_part:

            LOG.debug(
                "No explicit EFI partition provided. Scanning for any "
                "EFI partition located on software RAID device %s to "
                "be relocated", device)

            # NOTE: for whole disk images, no efi part uuid will be provided.
            # Let's try to scan for esp on the root softraid device. If not
            # found, it's fine in most cases to just create an empty esp and
            # let grub handle the magic.
            efi_part = utils.get_efi_part_on_device(device)
            if efi_part:
                efi_part = '{}p{}'.format(device, efi_part)

        LOG.info("Creating EFI partitions on software RAID holder disks")
        # We know that we kept this space when configuring raid,see
        # hardware.GenericHardwareManager.create_configuration.
        # We could also directly get the EFI partition size.
        partsize_mib = raid_utils.ESP_SIZE_MIB
        partlabel_prefix = 'uefi-holder-'
        for number, holder in enumerate(holders):
            # NOTE: see utils.get_partition_table_type_from_specs
            # for uefi we know that we have setup a gpt partition table,
            # sgdisk can be used to edit table, more user friendly
            # for alignment and relative offsets
            partlabel = '{}{}'.format(partlabel_prefix, number)
            out, _u = utils.execute('sgdisk', '-F', holder)
            start_sector = '{}s'.format(out.splitlines()[-1].strip())
            out, _u = utils.execute(
                'sgdisk', '-n', '0:{}:+{}MiB'.format(start_sector,
                                                     partsize_mib), '-t',
                '0:ef00', '-c', '0:{}'.format(partlabel), holder)

            # Refresh part table
            utils.execute("partprobe")
            utils.execute("blkid")

            target_part, _u = utils.execute("blkid", "-l", "-t",
                                            "PARTLABEL={}".format(partlabel),
                                            holder)

            target_part = target_part.splitlines()[-1].split(':', 1)[0]

            LOG.debug("EFI partition %s created on holder disk %s",
                      target_part, holder)

            if efi_part:
                LOG.debug("Relocating EFI %s to holder part %s", efi_part,
                          target_part)
                # Blockdev copy
                utils.execute("cp", efi_part, target_part)
            else:
                # Creating a label is just to make life easier
                if number == 0:
                    fslabel = 'efi-part'
                else:
                    # bak, label is limited to 11 chars
                    fslabel = 'efi-part-b'
                ilib_utils.mkfs(fs='vfat', path=target_part, label=fslabel)
            efi_partitions.append(target_part)
            # TBD: Would not hurt to destroy source efi part when defined,
            # for clarity.

    elif target_boot_mode == 'bios':
        partlabel_prefix = 'bios-boot-part-'
        for number, holder in enumerate(holders):
            label = utils.scan_partition_table_type(holder)
            if label == 'gpt':
                LOG.debug("Creating bios boot partition on disk holder %s",
                          holder)
                out, _u = utils.execute('sgdisk', '-F', holder)
                start_sector = '{}s'.format(out.splitlines()[-1].strip())
                partlabel = '{}{}'.format(partlabel_prefix, number)
                out, _u = utils.execute('sgdisk', '-n',
                                        '0:{}:+2MiB'.format(start_sector),
                                        '-t', '0:ef02', '-c',
                                        '0:{}'.format(partlabel), holder)

            # Q: MBR case, could we dd the boot code from the softraid
            # (446 first bytes) if we detect a bootloader with
            # _is_bootloader_loaded?
            # A: This won't work. Because it includes the address on the
            # disk, as in virtual disk, where to load the data from.
            # Since there is a structural difference, this means it will
            # fail.

    # Just an empty list if not uefi boot mode, nvm, not used anyway
    return efi_partitions