Move prepare_boot_partitions_for_softraid to raid_utils
prepare_boot_partitions_for_softraid() is used in BIOS and UEFI modes to prepare the partitions for the bootloader. Move it from the image extensions to raid_utils to reflect this and avoid the import of an extension to efi_utils. Follow-up to 62c5674a600baeeef0af3b12baeab486870eb103. Change-Id: I9f5974fbbfea5e8cdfbb7e49bea375e5cbfdd145
This commit is contained in:
parent
b8b1991bea
commit
a83f38479e
@ -20,9 +20,9 @@ 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 raid_utils
|
||||
from ironic_python_agent import utils
|
||||
|
||||
|
||||
@ -112,7 +112,7 @@ def manage_uefi(device, efi_system_part_uuid=None):
|
||||
efi_mounted = False
|
||||
|
||||
holders = hardware.get_holder_disks(device)
|
||||
efi_md_device = image.prepare_boot_partitions_for_softraid(
|
||||
efi_md_device = raid_utils.prepare_boot_partitions_for_softraid(
|
||||
device, holders, efi_device_part, target_boot_mode='uefi'
|
||||
)
|
||||
efi_devices = hardware.get_component_devices(efi_md_device)
|
||||
|
@ -18,8 +18,6 @@ import re
|
||||
import shutil
|
||||
import tempfile
|
||||
|
||||
from ironic_lib import disk_utils
|
||||
from ironic_lib import utils as ilib_utils
|
||||
from oslo_concurrency import processutils
|
||||
from oslo_config import cfg
|
||||
from oslo_log import log
|
||||
@ -104,123 +102,6 @@ def _is_bootloader_loaded(dev):
|
||||
return _find_bootable_device(stdout, dev)
|
||||
|
||||
|
||||
# TODO(rg): handle PreP boot parts relocation as well
|
||||
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
|
||||
RAID, 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 path to the ESP md device when target boot mode is uefi,
|
||||
nothing otherwise.
|
||||
"""
|
||||
# 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 = disk_utils.find_efi_partition(device)
|
||||
if efi_part:
|
||||
efi_part = '{}p{}'.format(device, efi_part['number'])
|
||||
|
||||
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-'
|
||||
efi_partitions = []
|
||||
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]
|
||||
efi_partitions.append(target_part)
|
||||
|
||||
LOG.debug("EFI partition %s created on holder disk %s",
|
||||
target_part, holder)
|
||||
|
||||
# RAID the ESPs, metadata=1.0 is mandatory to be able to boot
|
||||
md_device = raid_utils.get_next_free_raid_device()
|
||||
LOG.debug("Creating md device %(md_device)s for the ESPs "
|
||||
"on %(efi_partitions)s",
|
||||
{'md_device': md_device, 'efi_partitions': efi_partitions})
|
||||
utils.execute('mdadm', '--create', md_device, '--force',
|
||||
'--run', '--metadata=1.0', '--level', '1',
|
||||
'--name', 'esp', '--raid-devices', len(efi_partitions),
|
||||
*efi_partitions)
|
||||
|
||||
disk_utils.trigger_device_rescan(md_device)
|
||||
|
||||
if efi_part:
|
||||
# Blockdev copy the source ESP and erase it
|
||||
LOG.debug("Relocating EFI %s to %s", efi_part, md_device)
|
||||
utils.execute('cp', efi_part, md_device)
|
||||
LOG.debug("Erasing EFI partition %s", efi_part)
|
||||
utils.execute('wipefs', '-a', efi_part)
|
||||
else:
|
||||
fslabel = 'efi-part'
|
||||
ilib_utils.mkfs(fs='vfat', path=md_device, label=fslabel)
|
||||
|
||||
return md_device
|
||||
|
||||
elif target_boot_mode == 'bios':
|
||||
partlabel_prefix = 'bios-boot-part-'
|
||||
for number, holder in enumerate(holders):
|
||||
label = disk_utils.get_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.
|
||||
|
||||
|
||||
def _umount_all_partitions(path, path_variable, umount_warn_msg):
|
||||
"""Umount all partitions we may have mounted"""
|
||||
umount_binds_success = True
|
||||
@ -313,7 +194,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 = raid_utils.prepare_boot_partitions_for_softraid(
|
||||
device, holders, efi_part, target_boot_mode
|
||||
)
|
||||
|
||||
|
@ -13,6 +13,7 @@
|
||||
import copy
|
||||
import re
|
||||
|
||||
from ironic_lib import disk_utils
|
||||
from ironic_lib import utils as il_utils
|
||||
from oslo_concurrency import processutils
|
||||
from oslo_log import log as logging
|
||||
@ -262,3 +263,120 @@ def get_next_free_raid_device():
|
||||
return name
|
||||
|
||||
raise errors.SoftwareRAIDError("No free md (RAID) devices are left")
|
||||
|
||||
|
||||
# TODO(rg): handle PreP boot parts relocation as well
|
||||
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
|
||||
RAID, 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 path to the ESP md device when target boot mode is uefi,
|
||||
nothing otherwise.
|
||||
"""
|
||||
# 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 = disk_utils.find_efi_partition(device)
|
||||
if efi_part:
|
||||
efi_part = '{}p{}'.format(device, efi_part['number'])
|
||||
|
||||
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 = ESP_SIZE_MIB
|
||||
partlabel_prefix = 'uefi-holder-'
|
||||
efi_partitions = []
|
||||
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]
|
||||
efi_partitions.append(target_part)
|
||||
|
||||
LOG.debug("EFI partition %s created on holder disk %s",
|
||||
target_part, holder)
|
||||
|
||||
# RAID the ESPs, metadata=1.0 is mandatory to be able to boot
|
||||
md_device = get_next_free_raid_device()
|
||||
LOG.debug("Creating md device %(md_device)s for the ESPs "
|
||||
"on %(efi_partitions)s",
|
||||
{'md_device': md_device, 'efi_partitions': efi_partitions})
|
||||
utils.execute('mdadm', '--create', md_device, '--force',
|
||||
'--run', '--metadata=1.0', '--level', '1',
|
||||
'--name', 'esp', '--raid-devices', len(efi_partitions),
|
||||
*efi_partitions)
|
||||
|
||||
disk_utils.trigger_device_rescan(md_device)
|
||||
|
||||
if efi_part:
|
||||
# Blockdev copy the source ESP and erase it
|
||||
LOG.debug("Relocating EFI %s to %s", efi_part, md_device)
|
||||
utils.execute('cp', efi_part, md_device)
|
||||
LOG.debug("Erasing EFI partition %s", efi_part)
|
||||
utils.execute('wipefs', '-a', efi_part)
|
||||
else:
|
||||
fslabel = 'efi-part'
|
||||
il_utils.mkfs(fs='vfat', path=md_device, label=fslabel)
|
||||
|
||||
return md_device
|
||||
|
||||
elif target_boot_mode == 'bios':
|
||||
partlabel_prefix = 'bios-boot-part-'
|
||||
for number, holder in enumerate(holders):
|
||||
label = disk_utils.get_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.
|
||||
|
@ -1654,212 +1654,6 @@ Boot0004* ironic1 HD(1,GPT,55db8d03-c8f6-4a5b-9155-790dddc348fa,0x800,0x640
|
||||
uuid=self.fake_root_uuid)
|
||||
self.assertFalse(mock_dispatch.called)
|
||||
|
||||
@mock.patch.object(disk_utils, 'trigger_device_rescan', autospec=True)
|
||||
@mock.patch.object(raid_utils, 'get_next_free_raid_device', autospec=True,
|
||||
return_value='/dev/md42')
|
||||
@mock.patch.object(disk_utils, 'find_efi_partition', autospec=True)
|
||||
def test_prepare_boot_partitions_for_softraid_uefi_gpt(
|
||||
self, mock_efi_part, mock_free_raid_device, mock_rescan,
|
||||
mock_execute, mock_dispatch):
|
||||
mock_efi_part.return_value = {'number': '12'}
|
||||
mock_execute.side_effect = [
|
||||
('451', None), # sgdisk -F
|
||||
(None, None), # sgdisk create part
|
||||
(None, None), # partprobe
|
||||
(None, None), # blkid
|
||||
('/dev/sda12: dsfkgsdjfg', None), # blkid
|
||||
('452', None), # sgdisk -F
|
||||
(None, None), # sgdisk create part
|
||||
(None, None), # partprobe
|
||||
(None, None), # blkid
|
||||
('/dev/sdb14: whatever', None), # blkid
|
||||
(None, None), # mdadm
|
||||
(None, None), # cp
|
||||
(None, None), # wipefs
|
||||
]
|
||||
|
||||
efi_part = image.prepare_boot_partitions_for_softraid(
|
||||
'/dev/md0', ['/dev/sda', '/dev/sdb'], None,
|
||||
target_boot_mode='uefi')
|
||||
|
||||
mock_efi_part.assert_called_once_with('/dev/md0')
|
||||
expected = [
|
||||
mock.call('sgdisk', '-F', '/dev/sda'),
|
||||
mock.call('sgdisk', '-n', '0:451s:+550MiB', '-t', '0:ef00', '-c',
|
||||
'0:uefi-holder-0', '/dev/sda'),
|
||||
mock.call('partprobe'),
|
||||
mock.call('blkid'),
|
||||
mock.call('blkid', '-l', '-t', 'PARTLABEL=uefi-holder-0',
|
||||
'/dev/sda'),
|
||||
mock.call('sgdisk', '-F', '/dev/sdb'),
|
||||
mock.call('sgdisk', '-n', '0:452s:+550MiB', '-t', '0:ef00', '-c',
|
||||
'0:uefi-holder-1', '/dev/sdb'),
|
||||
mock.call('partprobe'),
|
||||
mock.call('blkid'),
|
||||
mock.call('blkid', '-l', '-t', 'PARTLABEL=uefi-holder-1',
|
||||
'/dev/sdb'),
|
||||
mock.call('mdadm', '--create', '/dev/md42', '--force', '--run',
|
||||
'--metadata=1.0', '--level', '1', '--name', 'esp',
|
||||
'--raid-devices', 2, '/dev/sda12', '/dev/sdb14'),
|
||||
mock.call('cp', '/dev/md0p12', '/dev/md42'),
|
||||
mock.call('wipefs', '-a', '/dev/md0p12')
|
||||
]
|
||||
mock_execute.assert_has_calls(expected, any_order=False)
|
||||
self.assertEqual(efi_part, '/dev/md42')
|
||||
mock_rescan.assert_called_once_with('/dev/md42')
|
||||
|
||||
@mock.patch.object(disk_utils, 'trigger_device_rescan', autospec=True)
|
||||
@mock.patch.object(raid_utils, 'get_next_free_raid_device', autospec=True,
|
||||
return_value='/dev/md42')
|
||||
@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(
|
||||
self, mock_mkfs, mock_efi_part, mock_free_raid_device,
|
||||
mock_rescan, mock_execute, mock_dispatch):
|
||||
mock_efi_part.return_value = None
|
||||
mock_execute.side_effect = [
|
||||
('451', None), # sgdisk -F
|
||||
(None, None), # sgdisk create part
|
||||
(None, None), # partprobe
|
||||
(None, None), # blkid
|
||||
('/dev/sda12: dsfkgsdjfg', None), # blkid
|
||||
('452', None), # sgdisk -F
|
||||
(None, None), # sgdisk create part
|
||||
(None, None), # partprobe
|
||||
(None, None), # blkid
|
||||
('/dev/sdb14: whatever', None), # blkid
|
||||
(None, None), # mdadm
|
||||
]
|
||||
|
||||
efi_part = image.prepare_boot_partitions_for_softraid(
|
||||
'/dev/md0', ['/dev/sda', '/dev/sdb'], None,
|
||||
target_boot_mode='uefi')
|
||||
|
||||
mock_efi_part.assert_called_once_with('/dev/md0')
|
||||
expected = [
|
||||
mock.call('sgdisk', '-F', '/dev/sda'),
|
||||
mock.call('sgdisk', '-n', '0:451s:+550MiB', '-t', '0:ef00', '-c',
|
||||
'0:uefi-holder-0', '/dev/sda'),
|
||||
mock.call('partprobe'),
|
||||
mock.call('blkid'),
|
||||
mock.call('blkid', '-l', '-t', 'PARTLABEL=uefi-holder-0',
|
||||
'/dev/sda'),
|
||||
mock.call('sgdisk', '-F', '/dev/sdb'),
|
||||
mock.call('sgdisk', '-n', '0:452s:+550MiB', '-t', '0:ef00', '-c',
|
||||
'0:uefi-holder-1', '/dev/sdb'),
|
||||
mock.call('partprobe'),
|
||||
mock.call('blkid'),
|
||||
mock.call('blkid', '-l', '-t', 'PARTLABEL=uefi-holder-1',
|
||||
'/dev/sdb'),
|
||||
]
|
||||
mock_execute.assert_has_calls(expected, any_order=False)
|
||||
mock_mkfs.assert_has_calls([
|
||||
mock.call(path='/dev/md42', label='efi-part', fs='vfat'),
|
||||
], any_order=False)
|
||||
self.assertEqual(efi_part, '/dev/md42')
|
||||
mock_rescan.assert_called_once_with('/dev/md42')
|
||||
|
||||
@mock.patch.object(disk_utils, 'trigger_device_rescan', autospec=True)
|
||||
@mock.patch.object(raid_utils, 'get_next_free_raid_device', autospec=True,
|
||||
return_value='/dev/md42')
|
||||
def test_prepare_boot_partitions_for_softraid_uefi_gpt_efi_provided(
|
||||
self, mock_free_raid_device, mock_rescan,
|
||||
mock_execute, mock_dispatch):
|
||||
mock_execute.side_effect = [
|
||||
('451', None), # sgdisk -F
|
||||
(None, None), # sgdisk create part
|
||||
(None, None), # partprobe
|
||||
(None, None), # blkid
|
||||
('/dev/sda12: dsfkgsdjfg', None), # blkid
|
||||
('452', None), # sgdisk -F
|
||||
(None, None), # sgdisk create part
|
||||
(None, None), # partprobe
|
||||
(None, None), # blkid
|
||||
('/dev/sdb14: whatever', None), # blkid
|
||||
(None, None), # mdadm create
|
||||
(None, None), # cp
|
||||
(None, None), # wipefs
|
||||
]
|
||||
|
||||
efi_part = image.prepare_boot_partitions_for_softraid(
|
||||
'/dev/md0', ['/dev/sda', '/dev/sdb'], '/dev/md0p15',
|
||||
target_boot_mode='uefi')
|
||||
|
||||
expected = [
|
||||
mock.call('sgdisk', '-F', '/dev/sda'),
|
||||
mock.call('sgdisk', '-n', '0:451s:+550MiB', '-t', '0:ef00', '-c',
|
||||
'0:uefi-holder-0', '/dev/sda'),
|
||||
mock.call('partprobe'),
|
||||
mock.call('blkid'),
|
||||
mock.call('blkid', '-l', '-t', 'PARTLABEL=uefi-holder-0',
|
||||
'/dev/sda'),
|
||||
mock.call('sgdisk', '-F', '/dev/sdb'),
|
||||
mock.call('sgdisk', '-n', '0:452s:+550MiB', '-t', '0:ef00', '-c',
|
||||
'0:uefi-holder-1', '/dev/sdb'),
|
||||
mock.call('partprobe'),
|
||||
mock.call('blkid'),
|
||||
mock.call('blkid', '-l', '-t', 'PARTLABEL=uefi-holder-1',
|
||||
'/dev/sdb'),
|
||||
mock.call('mdadm', '--create', '/dev/md42', '--force', '--run',
|
||||
'--metadata=1.0', '--level', '1', '--name', 'esp',
|
||||
'--raid-devices', 2, '/dev/sda12', '/dev/sdb14'),
|
||||
mock.call('cp', '/dev/md0p15', '/dev/md42'),
|
||||
mock.call('wipefs', '-a', '/dev/md0p15')
|
||||
]
|
||||
mock_execute.assert_has_calls(expected, any_order=False)
|
||||
self.assertEqual(efi_part, '/dev/md42')
|
||||
|
||||
@mock.patch.object(disk_utils, 'get_partition_table_type', autospec=True,
|
||||
return_value='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(
|
||||
'/dev/md0', ['/dev/sda', '/dev/sdb'], 'notusedanyway',
|
||||
target_boot_mode='bios')
|
||||
|
||||
expected = [
|
||||
mock.call('/dev/sda'),
|
||||
mock.call('/dev/sdb'),
|
||||
]
|
||||
mock_label_scan.assert_has_calls(expected, any_order=False)
|
||||
self.assertIsNone(efi_part)
|
||||
|
||||
@mock.patch.object(disk_utils, 'get_partition_table_type', autospec=True,
|
||||
return_value='gpt')
|
||||
def test_prepare_boot_partitions_for_softraid_bios_gpt(
|
||||
self, mock_label_scan, mock_execute, mock_dispatch):
|
||||
|
||||
mock_execute.side_effect = [
|
||||
('whatever\n314', None), # sgdisk -F
|
||||
(None, None), # bios boot grub
|
||||
('warning message\n914', None), # sgdisk -F
|
||||
(None, None), # bios boot grub
|
||||
]
|
||||
|
||||
efi_part = image.prepare_boot_partitions_for_softraid(
|
||||
'/dev/md0', ['/dev/sda', '/dev/sdb'], 'notusedanyway',
|
||||
target_boot_mode='bios')
|
||||
|
||||
expected_scan = [
|
||||
mock.call('/dev/sda'),
|
||||
mock.call('/dev/sdb'),
|
||||
]
|
||||
|
||||
mock_label_scan.assert_has_calls(expected_scan, any_order=False)
|
||||
|
||||
expected_exec = [
|
||||
mock.call('sgdisk', '-F', '/dev/sda'),
|
||||
mock.call('sgdisk', '-n', '0:314s:+2MiB', '-t', '0:ef02', '-c',
|
||||
'0:bios-boot-part-0', '/dev/sda'),
|
||||
mock.call('sgdisk', '-F', '/dev/sdb'),
|
||||
mock.call('sgdisk', '-n', '0:914s:+2MiB', '-t', '0:ef02', '-c',
|
||||
'0:bios-boot-part-1', '/dev/sdb'),
|
||||
]
|
||||
|
||||
mock_execute.assert_has_calls(expected_exec, any_order=False)
|
||||
self.assertIsNone(efi_part)
|
||||
|
||||
@mock.patch.object(image, '_is_bootloader_loaded', lambda *_: True)
|
||||
@mock.patch.object(hardware, 'is_md_device', autospec=True)
|
||||
@mock.patch.object(hardware, 'md_restart', autospec=True)
|
||||
@ -1869,7 +1663,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(raid_utils, 'prepare_boot_partitions_for_softraid',
|
||||
autospec=True,
|
||||
return_value='/dev/md/esp')
|
||||
@mock.patch.object(image, '_has_dracut',
|
||||
@ -1987,7 +1781,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(raid_utils, 'prepare_boot_partitions_for_softraid',
|
||||
autospec=True,
|
||||
return_value=[])
|
||||
@mock.patch.object(image, '_has_dracut',
|
||||
|
@ -19,9 +19,9 @@ 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 import raid_utils
|
||||
from ironic_python_agent.tests.unit import base
|
||||
from ironic_python_agent import utils
|
||||
|
||||
@ -321,7 +321,7 @@ Boot0002: VENDMAGIC FvFile(9f3c6294-bf9b-4208-9808-be45dfc34b51)
|
||||
|
||||
@mock.patch.object(os.path, 'exists', lambda *_: False)
|
||||
@mock.patch.object(hardware, 'get_component_devices', autospec=True)
|
||||
@mock.patch.object(image,
|
||||
@mock.patch.object(raid_utils,
|
||||
'prepare_boot_partitions_for_softraid',
|
||||
autospec=True)
|
||||
@mock.patch.object(hardware, 'get_holder_disks', autospec=True)
|
||||
|
@ -12,6 +12,8 @@
|
||||
|
||||
from unittest import mock
|
||||
|
||||
from ironic_lib import disk_utils
|
||||
from ironic_lib import utils as ilib_utils
|
||||
from oslo_concurrency import processutils
|
||||
|
||||
from ironic_python_agent import errors
|
||||
@ -115,6 +117,222 @@ class TestRaidUtils(base.IronicAgentTest):
|
||||
raid_utils.create_raid_device, 0,
|
||||
logical_disk)
|
||||
|
||||
@mock.patch.object(disk_utils, 'trigger_device_rescan', autospec=True)
|
||||
@mock.patch.object(raid_utils, 'get_next_free_raid_device', autospec=True,
|
||||
return_value='/dev/md42')
|
||||
@mock.patch.object(hardware, 'dispatch_to_managers', autospec=True)
|
||||
@mock.patch.object(ilib_utils, 'execute', autospec=True)
|
||||
@mock.patch.object(disk_utils, 'find_efi_partition', autospec=True)
|
||||
def test_prepare_boot_partitions_for_softraid_uefi_gpt(
|
||||
self, mock_efi_part, mock_execute, mock_dispatch,
|
||||
mock_free_raid_device, mock_rescan):
|
||||
mock_efi_part.return_value = {'number': '12'}
|
||||
mock_execute.side_effect = [
|
||||
('451', None), # sgdisk -F
|
||||
(None, None), # sgdisk create part
|
||||
(None, None), # partprobe
|
||||
(None, None), # blkid
|
||||
('/dev/sda12: dsfkgsdjfg', None), # blkid
|
||||
('452', None), # sgdisk -F
|
||||
(None, None), # sgdisk create part
|
||||
(None, None), # partprobe
|
||||
(None, None), # blkid
|
||||
('/dev/sdb14: whatever', None), # blkid
|
||||
(None, None), # mdadm
|
||||
(None, None), # cp
|
||||
(None, None), # wipefs
|
||||
]
|
||||
|
||||
efi_part = raid_utils.prepare_boot_partitions_for_softraid(
|
||||
'/dev/md0', ['/dev/sda', '/dev/sdb'], None,
|
||||
target_boot_mode='uefi')
|
||||
|
||||
mock_efi_part.assert_called_once_with('/dev/md0')
|
||||
expected = [
|
||||
mock.call('sgdisk', '-F', '/dev/sda'),
|
||||
mock.call('sgdisk', '-n', '0:451s:+550MiB', '-t', '0:ef00', '-c',
|
||||
'0:uefi-holder-0', '/dev/sda'),
|
||||
mock.call('partprobe'),
|
||||
mock.call('blkid'),
|
||||
mock.call('blkid', '-l', '-t', 'PARTLABEL=uefi-holder-0',
|
||||
'/dev/sda'),
|
||||
mock.call('sgdisk', '-F', '/dev/sdb'),
|
||||
mock.call('sgdisk', '-n', '0:452s:+550MiB', '-t', '0:ef00', '-c',
|
||||
'0:uefi-holder-1', '/dev/sdb'),
|
||||
mock.call('partprobe'),
|
||||
mock.call('blkid'),
|
||||
mock.call('blkid', '-l', '-t', 'PARTLABEL=uefi-holder-1',
|
||||
'/dev/sdb'),
|
||||
mock.call('mdadm', '--create', '/dev/md42', '--force', '--run',
|
||||
'--metadata=1.0', '--level', '1', '--name', 'esp',
|
||||
'--raid-devices', 2, '/dev/sda12', '/dev/sdb14'),
|
||||
mock.call('cp', '/dev/md0p12', '/dev/md42'),
|
||||
mock.call('wipefs', '-a', '/dev/md0p12')
|
||||
]
|
||||
mock_execute.assert_has_calls(expected, any_order=False)
|
||||
self.assertEqual(efi_part, '/dev/md42')
|
||||
mock_rescan.assert_called_once_with('/dev/md42')
|
||||
|
||||
@mock.patch.object(disk_utils, 'trigger_device_rescan', autospec=True)
|
||||
@mock.patch.object(raid_utils, 'get_next_free_raid_device', autospec=True,
|
||||
return_value='/dev/md42')
|
||||
@mock.patch.object(hardware, 'dispatch_to_managers', autospec=True)
|
||||
@mock.patch.object(ilib_utils, 'execute', autospec=True)
|
||||
@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(
|
||||
self, mock_mkfs, mock_efi_part, mock_execute, mock_dispatch,
|
||||
mock_free_raid_device, mock_rescan):
|
||||
mock_efi_part.return_value = None
|
||||
mock_execute.side_effect = [
|
||||
('451', None), # sgdisk -F
|
||||
(None, None), # sgdisk create part
|
||||
(None, None), # partprobe
|
||||
(None, None), # blkid
|
||||
('/dev/sda12: dsfkgsdjfg', None), # blkid
|
||||
('452', None), # sgdisk -F
|
||||
(None, None), # sgdisk create part
|
||||
(None, None), # partprobe
|
||||
(None, None), # blkid
|
||||
('/dev/sdb14: whatever', None), # blkid
|
||||
(None, None), # mdadm
|
||||
]
|
||||
|
||||
efi_part = raid_utils.prepare_boot_partitions_for_softraid(
|
||||
'/dev/md0', ['/dev/sda', '/dev/sdb'], None,
|
||||
target_boot_mode='uefi')
|
||||
|
||||
mock_efi_part.assert_called_once_with('/dev/md0')
|
||||
expected = [
|
||||
mock.call('sgdisk', '-F', '/dev/sda'),
|
||||
mock.call('sgdisk', '-n', '0:451s:+550MiB', '-t', '0:ef00', '-c',
|
||||
'0:uefi-holder-0', '/dev/sda'),
|
||||
mock.call('partprobe'),
|
||||
mock.call('blkid'),
|
||||
mock.call('blkid', '-l', '-t', 'PARTLABEL=uefi-holder-0',
|
||||
'/dev/sda'),
|
||||
mock.call('sgdisk', '-F', '/dev/sdb'),
|
||||
mock.call('sgdisk', '-n', '0:452s:+550MiB', '-t', '0:ef00', '-c',
|
||||
'0:uefi-holder-1', '/dev/sdb'),
|
||||
mock.call('partprobe'),
|
||||
mock.call('blkid'),
|
||||
mock.call('blkid', '-l', '-t', 'PARTLABEL=uefi-holder-1',
|
||||
'/dev/sdb'),
|
||||
]
|
||||
mock_execute.assert_has_calls(expected, any_order=False)
|
||||
mock_mkfs.assert_has_calls([
|
||||
mock.call(path='/dev/md42', label='efi-part', fs='vfat'),
|
||||
], any_order=False)
|
||||
self.assertEqual(efi_part, '/dev/md42')
|
||||
mock_rescan.assert_called_once_with('/dev/md42')
|
||||
|
||||
@mock.patch.object(disk_utils, 'trigger_device_rescan', autospec=True)
|
||||
@mock.patch.object(raid_utils, 'get_next_free_raid_device', autospec=True,
|
||||
return_value='/dev/md42')
|
||||
@mock.patch.object(hardware, 'dispatch_to_managers', autospec=True)
|
||||
@mock.patch.object(ilib_utils, 'execute', autospec=True)
|
||||
def test_prepare_boot_partitions_for_softraid_uefi_gpt_efi_provided(
|
||||
self, mock_execute, mock_dispatch, mock_free_raid_device,
|
||||
mock_rescan):
|
||||
mock_execute.side_effect = [
|
||||
('451', None), # sgdisk -F
|
||||
(None, None), # sgdisk create part
|
||||
(None, None), # partprobe
|
||||
(None, None), # blkid
|
||||
('/dev/sda12: dsfkgsdjfg', None), # blkid
|
||||
('452', None), # sgdisk -F
|
||||
(None, None), # sgdisk create part
|
||||
(None, None), # partprobe
|
||||
(None, None), # blkid
|
||||
('/dev/sdb14: whatever', None), # blkid
|
||||
(None, None), # mdadm create
|
||||
(None, None), # cp
|
||||
(None, None), # wipefs
|
||||
]
|
||||
|
||||
efi_part = raid_utils.prepare_boot_partitions_for_softraid(
|
||||
'/dev/md0', ['/dev/sda', '/dev/sdb'], '/dev/md0p15',
|
||||
target_boot_mode='uefi')
|
||||
|
||||
expected = [
|
||||
mock.call('sgdisk', '-F', '/dev/sda'),
|
||||
mock.call('sgdisk', '-n', '0:451s:+550MiB', '-t', '0:ef00', '-c',
|
||||
'0:uefi-holder-0', '/dev/sda'),
|
||||
mock.call('partprobe'),
|
||||
mock.call('blkid'),
|
||||
mock.call('blkid', '-l', '-t', 'PARTLABEL=uefi-holder-0',
|
||||
'/dev/sda'),
|
||||
mock.call('sgdisk', '-F', '/dev/sdb'),
|
||||
mock.call('sgdisk', '-n', '0:452s:+550MiB', '-t', '0:ef00', '-c',
|
||||
'0:uefi-holder-1', '/dev/sdb'),
|
||||
mock.call('partprobe'),
|
||||
mock.call('blkid'),
|
||||
mock.call('blkid', '-l', '-t', 'PARTLABEL=uefi-holder-1',
|
||||
'/dev/sdb'),
|
||||
mock.call('mdadm', '--create', '/dev/md42', '--force', '--run',
|
||||
'--metadata=1.0', '--level', '1', '--name', 'esp',
|
||||
'--raid-devices', 2, '/dev/sda12', '/dev/sdb14'),
|
||||
mock.call('cp', '/dev/md0p15', '/dev/md42'),
|
||||
mock.call('wipefs', '-a', '/dev/md0p15')
|
||||
]
|
||||
mock_execute.assert_has_calls(expected, any_order=False)
|
||||
self.assertEqual(efi_part, '/dev/md42')
|
||||
|
||||
@mock.patch.object(hardware, 'dispatch_to_managers', autospec=True)
|
||||
@mock.patch.object(ilib_utils, 'execute', autospec=True)
|
||||
@mock.patch.object(disk_utils, 'get_partition_table_type', autospec=True,
|
||||
return_value='msdos')
|
||||
def test_prepare_boot_partitions_for_softraid_bios_msdos(
|
||||
self, mock_label_scan, mock_execute, mock_dispatch):
|
||||
|
||||
efi_part = raid_utils.prepare_boot_partitions_for_softraid(
|
||||
'/dev/md0', ['/dev/sda', '/dev/sdb'], 'notusedanyway',
|
||||
target_boot_mode='bios')
|
||||
|
||||
expected = [
|
||||
mock.call('/dev/sda'),
|
||||
mock.call('/dev/sdb'),
|
||||
]
|
||||
mock_label_scan.assert_has_calls(expected, any_order=False)
|
||||
self.assertIsNone(efi_part)
|
||||
|
||||
@mock.patch.object(hardware, 'dispatch_to_managers', autospec=True)
|
||||
@mock.patch.object(ilib_utils, 'execute', autospec=True)
|
||||
@mock.patch.object(disk_utils, 'get_partition_table_type', autospec=True,
|
||||
return_value='gpt')
|
||||
def test_prepare_boot_partitions_for_softraid_bios_gpt(
|
||||
self, mock_label_scan, mock_execute, mock_dispatch):
|
||||
|
||||
mock_execute.side_effect = [
|
||||
('whatever\n314', None), # sgdisk -F
|
||||
(None, None), # bios boot grub
|
||||
('warning message\n914', None), # sgdisk -F
|
||||
(None, None), # bios boot grub
|
||||
]
|
||||
|
||||
efi_part = raid_utils.prepare_boot_partitions_for_softraid(
|
||||
'/dev/md0', ['/dev/sda', '/dev/sdb'], 'notusedanyway',
|
||||
target_boot_mode='bios')
|
||||
|
||||
expected_scan = [
|
||||
mock.call('/dev/sda'),
|
||||
mock.call('/dev/sdb'),
|
||||
]
|
||||
|
||||
mock_label_scan.assert_has_calls(expected_scan, any_order=False)
|
||||
|
||||
expected_exec = [
|
||||
mock.call('sgdisk', '-F', '/dev/sda'),
|
||||
mock.call('sgdisk', '-n', '0:314s:+2MiB', '-t', '0:ef02', '-c',
|
||||
'0:bios-boot-part-0', '/dev/sda'),
|
||||
mock.call('sgdisk', '-F', '/dev/sdb'),
|
||||
mock.call('sgdisk', '-n', '0:914s:+2MiB', '-t', '0:ef02', '-c',
|
||||
'0:bios-boot-part-1', '/dev/sdb'),
|
||||
]
|
||||
|
||||
mock_execute.assert_has_calls(expected_exec, any_order=False)
|
||||
self.assertIsNone(efi_part)
|
||||
|
||||
|
||||
@mock.patch.object(hardware, 'dispatch_to_managers', autospec=True)
|
||||
class TestGetNextFreeRaidDevice(base.IronicAgentTest):
|
||||
|
Loading…
x
Reference in New Issue
Block a user