Add support for discoverable partitions
Set PARTUUID according to systemd-id128 if applicable This Fixes #1385
This commit is contained in:
parent
6dc4ef2570
commit
2540d56602
@ -98,6 +98,17 @@ class PartitionerBase:
|
||||
"""
|
||||
raise NotImplementedError
|
||||
|
||||
def set_uuid(self, partition_id: int, uuid: str):
|
||||
"""
|
||||
Set partition UUID
|
||||
|
||||
Implementation in specialized partitioner class
|
||||
|
||||
:param int partition_id: unused
|
||||
:param string uuid: unused
|
||||
"""
|
||||
raise NotImplementedError
|
||||
|
||||
def set_hybrid_mbr(self):
|
||||
"""
|
||||
Turn partition table into hybrid table if supported
|
||||
|
||||
@ -83,6 +83,17 @@ class PartitionerDasd(PartitionerBase):
|
||||
# that point.
|
||||
log.debug('potential fdasd errors were ignored')
|
||||
|
||||
def set_uuid(self, partition_id: int, uuid: str) -> None:
|
||||
"""
|
||||
Set partition UUID
|
||||
|
||||
Nothing to be done here for DASD devices
|
||||
|
||||
:param int partition_id: unused
|
||||
:param string uuid: unused
|
||||
"""
|
||||
pass # pragma: nocover
|
||||
|
||||
def resize_table(self, entries: int = None) -> None:
|
||||
"""
|
||||
Resize partition table
|
||||
|
||||
@ -114,6 +114,21 @@ class PartitionerGpt(PartitionerBase):
|
||||
else:
|
||||
log.warning('Flag %s ignored on GPT', flag_name)
|
||||
|
||||
def set_uuid(self, partition_id: int, uuid: str) -> None:
|
||||
"""
|
||||
Set partition UUID (GUID)
|
||||
|
||||
:param int partition_id: partition number
|
||||
:param string uuid: UUID
|
||||
"""
|
||||
Command.run(
|
||||
[
|
||||
'sgdisk',
|
||||
'--partition-guid', f'{partition_id}:{uuid}',
|
||||
self.disk_device
|
||||
]
|
||||
)
|
||||
|
||||
def set_hybrid_mbr(self) -> None:
|
||||
"""
|
||||
Turn partition table into hybrid GPT/MBR table
|
||||
|
||||
@ -121,6 +121,17 @@ class PartitionerMsDos(PartitionerBase):
|
||||
"""
|
||||
pass
|
||||
|
||||
def set_uuid(self, partition_id: int, uuid: str) -> None:
|
||||
"""
|
||||
Set partition UUID
|
||||
|
||||
Nothing to be done here for MSDOS devices
|
||||
|
||||
:param int partition_id: unused
|
||||
:param string uuid: unused
|
||||
"""
|
||||
pass # pragma: nocover
|
||||
|
||||
def set_start_sector(self, start_sector: int):
|
||||
"""
|
||||
Set start sector of first partition as configured.
|
||||
|
||||
@ -29,7 +29,11 @@ from kiwi.storage.device_provider import DeviceProvider
|
||||
from kiwi.storage.mapped_device import MappedDevice
|
||||
from kiwi.partitioner import Partitioner
|
||||
from kiwi.runtime_config import RuntimeConfig
|
||||
from kiwi.exceptions import KiwiCustomPartitionConflictError
|
||||
from kiwi.exceptions import (
|
||||
KiwiCustomPartitionConflictError,
|
||||
KiwiCommandError,
|
||||
KiwiCommandNotFound
|
||||
)
|
||||
|
||||
ptable_entry_type = NamedTuple(
|
||||
'ptable_entry_type', [
|
||||
@ -86,6 +90,9 @@ class Disk(DeviceProvider):
|
||||
'efi'
|
||||
]
|
||||
|
||||
#: Unified partition UUIDs according to systemd
|
||||
self.gUID = self.get_discoverable_partition_ids()
|
||||
|
||||
self.partition_map: Dict[str, str] = {}
|
||||
self.public_partition_id_map: Dict[str, str] = {}
|
||||
self.partition_id_map: Dict[str, str] = {}
|
||||
@ -161,6 +168,11 @@ class Disk(DeviceProvider):
|
||||
)
|
||||
self._add_to_map(map_name)
|
||||
self._add_to_public_id_map(id_name)
|
||||
part_uuid = self.gUID.get(entry.partition_name)
|
||||
if part_uuid:
|
||||
self.partitioner.set_uuid(
|
||||
self.partition_id_map[map_name], part_uuid
|
||||
)
|
||||
|
||||
def create_root_partition(self, mbsize: str, clone: int = 0):
|
||||
"""
|
||||
@ -182,6 +194,11 @@ class Disk(DeviceProvider):
|
||||
self._add_to_public_id_map('kiwi_RWPart')
|
||||
if 'kiwi_BootPart' not in self.public_partition_id_map:
|
||||
self._add_to_public_id_map('kiwi_BootPart')
|
||||
root_uuid = self.gUID.get('root')
|
||||
if root_uuid:
|
||||
self.partitioner.set_uuid(
|
||||
self.partition_id_map['root'], root_uuid
|
||||
)
|
||||
|
||||
def create_root_lvm_partition(self, mbsize: str, clone: int = 0):
|
||||
"""
|
||||
@ -198,6 +215,11 @@ class Disk(DeviceProvider):
|
||||
self.partitioner.create('p.lxlvm', mbsize, 't.lvm')
|
||||
self._add_to_map('root')
|
||||
self._add_to_public_id_map('kiwi_RootPart')
|
||||
root_uuid = self.gUID.get('root')
|
||||
if root_uuid:
|
||||
self.partitioner.set_uuid(
|
||||
self.partition_id_map['root'], root_uuid
|
||||
)
|
||||
|
||||
def create_root_raid_partition(self, mbsize: str, clone: int = 0):
|
||||
"""
|
||||
@ -217,6 +239,11 @@ class Disk(DeviceProvider):
|
||||
self._add_to_map('root')
|
||||
self._add_to_public_id_map('kiwi_RootPart')
|
||||
self._add_to_public_id_map('kiwi_RaidPart')
|
||||
root_uuid = self.gUID.get('root')
|
||||
if root_uuid:
|
||||
self.partitioner.set_uuid(
|
||||
self.partition_id_map['root'], root_uuid
|
||||
)
|
||||
|
||||
def create_root_readonly_partition(self, mbsize: str, clone: int = 0):
|
||||
"""
|
||||
@ -236,6 +263,11 @@ class Disk(DeviceProvider):
|
||||
self.partitioner.create('p.lxreadonly', mbsize, 't.linux')
|
||||
self._add_to_map('readonly')
|
||||
self._add_to_public_id_map('kiwi_ROPart')
|
||||
root_uuid = self.gUID.get('root')
|
||||
if root_uuid:
|
||||
self.partitioner.set_uuid(
|
||||
self.partition_id_map['readonly'], root_uuid
|
||||
)
|
||||
|
||||
def create_boot_partition(self, mbsize: str, clone: int = 0):
|
||||
"""
|
||||
@ -252,6 +284,11 @@ class Disk(DeviceProvider):
|
||||
self.partitioner.create('p.lxboot', mbsize, 't.linux')
|
||||
self._add_to_map('boot')
|
||||
self._add_to_public_id_map('kiwi_BootPart')
|
||||
boot_uuid = self.gUID.get('xbootldr')
|
||||
if boot_uuid:
|
||||
self.partitioner.set_uuid(
|
||||
self.partition_id_map['boot'], boot_uuid
|
||||
)
|
||||
|
||||
def create_prep_partition(self, mbsize: str):
|
||||
"""
|
||||
@ -291,6 +328,11 @@ class Disk(DeviceProvider):
|
||||
self.partitioner.create('p.swap', mbsize, 't.swap')
|
||||
self._add_to_map('swap')
|
||||
self._add_to_public_id_map('kiwi_SwapPart')
|
||||
swap_uuid = self.gUID.get('swap')
|
||||
if swap_uuid:
|
||||
self.partitioner.set_uuid(
|
||||
self.partition_id_map['swap'], swap_uuid
|
||||
)
|
||||
|
||||
def create_efi_csm_partition(self, mbsize: str):
|
||||
"""
|
||||
@ -317,6 +359,11 @@ class Disk(DeviceProvider):
|
||||
self.partitioner.create('p.UEFI', mbsize, 't.efi')
|
||||
self._add_to_map('efi')
|
||||
self._add_to_public_id_map('kiwi_EfiPart')
|
||||
esp_uuid = self.gUID.get('esp')
|
||||
if esp_uuid:
|
||||
self.partitioner.set_uuid(
|
||||
self.partition_id_map['efi'], esp_uuid
|
||||
)
|
||||
|
||||
def activate_boot_partition(self):
|
||||
"""
|
||||
@ -424,6 +471,37 @@ class Disk(DeviceProvider):
|
||||
sorted(self.public_partition_id_map.items())
|
||||
)
|
||||
|
||||
def get_discoverable_partition_ids(self) -> Dict[str, str]:
|
||||
"""
|
||||
Ask systemd for a list of standardized GUIDs for the
|
||||
current architecture and return them in a dictionary.
|
||||
If there is no such information available an empty
|
||||
dictionary is returned
|
||||
|
||||
:return: key:value dict from systemd-id128
|
||||
|
||||
:rtype: dict
|
||||
"""
|
||||
discoverable_ids = {}
|
||||
try:
|
||||
raw_lines = Command.run(
|
||||
['systemd-id128', 'show']
|
||||
).output.split(os.linesep)[1:]
|
||||
for line in raw_lines:
|
||||
if line:
|
||||
line = ' '.join(line.split())
|
||||
partition_name, uuid = line.split(' ')
|
||||
discoverable_ids[partition_name] = uuid
|
||||
except KiwiCommandNotFound as issue:
|
||||
log.warning(
|
||||
f'Failed to call systemd-id128: {issue}'
|
||||
)
|
||||
except KiwiCommandError as issue:
|
||||
log.warning(
|
||||
f'Failed to obtain discoverable partition IDs: {issue}'
|
||||
)
|
||||
return discoverable_ids
|
||||
|
||||
def _create_clones(
|
||||
self, name: str, clone: int, type_flag: str, mbsize: str
|
||||
) -> None:
|
||||
|
||||
46
test/data/systemd-id128.out
Normal file
46
test/data/systemd-id128.out
Normal file
@ -0,0 +1,46 @@
|
||||
NAME ID
|
||||
root-x86 44479540f29741b29af7d131d5f0458a
|
||||
root-x86-verity d13c5d3bb5d1422ab29f9454fdc89d76
|
||||
root-x86-64 4f68bce3e8cd4db196e7fbcaf984b709
|
||||
root-x86-64-verity 2c7357edebd246d9aec123d437ec2bf5
|
||||
root-arm 69dad7102ce44e3cb16c21a1d49abed3
|
||||
root-arm-verity 7386cdf2203c47a9a498f2ecce45a2d6
|
||||
root-arm64 b921b0451df041c3af444c6f280d3fae
|
||||
root-arm64-verity df3300ced69f4c92978c9bfb0f38d820
|
||||
root-ia64 993d8d3df80e4225855a9daf8ed7ea97
|
||||
root-ia64-verity 86ed10d5b60745bb8957d350f23d0571
|
||||
root-riscv32 60d5a7fe8e7d435cb7143dd8162144e1
|
||||
root-riscv32-verity ae0253be11674007ac6843926c14c5de
|
||||
root-riscv64 72ec70a6cf7440e6bd494bda08e8f224
|
||||
root-riscv64-verity b6ed5582440b4209b8da5ff7c419ea3d
|
||||
root 4f68bce3e8cd4db196e7fbcaf984b709
|
||||
root-verity 2c7357edebd246d9aec123d437ec2bf5
|
||||
root-secondary 44479540f29741b29af7d131d5f0458a
|
||||
root-secondary-verity d13c5d3bb5d1422ab29f9454fdc89d76
|
||||
usr-x86 75250d768cc6458ebd66bd47cc81a812
|
||||
usr-x86-verity 8f461b0d14ee4e819aa9049b6fb97abd
|
||||
usr-x86-64 8484680c952148c69c11b0720656f69e
|
||||
usr-x86-64-verity 77ff5f63e7b64633acf41565b864c0e6
|
||||
usr-arm 7d0359a302b34f0a865c654403e70625
|
||||
usr-arm-verity c215d7517bcd4649be906627490a4c05
|
||||
usr-arm64 b0e01050ee5f4390949a9101b17104e9
|
||||
usr-arm64-verity 6e11a4e7fbca4dedb9e9e1a512bb664e
|
||||
usr-ia64 4301d2a64e3b4b2abb949e0b2c4225ea
|
||||
usr-ia64-verity 6a491e033be745458e3883320e0ea880
|
||||
usr-riscv32 b933fb225c3f4f91af90e2bb0fa50702
|
||||
usr-riscv32-verity cb1ee4e38cd04136a0a4aa61a32e8730
|
||||
usr-riscv64 beaec34b8442439ba40b984381ed097d
|
||||
usr-riscv64-verity 8f1056be9b0547c481d6be53128e5b54
|
||||
usr 8484680c952148c69c11b0720656f69e
|
||||
usr-verity 77ff5f63e7b64633acf41565b864c0e6
|
||||
usr-secondary 75250d768cc6458ebd66bd47cc81a812
|
||||
usr-secondary-verity 8f461b0d14ee4e819aa9049b6fb97abd
|
||||
esp c12a7328f81f11d2ba4b00a0c93ec93b
|
||||
xbootldr bc13c2ff59e64262a352b275fd6f7172
|
||||
swap 0657fd6da4ab43c484e50933c84b4f4f
|
||||
home 933ac7e12eb44f13b8440e14e2aef915
|
||||
srv 3b8f842520e04f3b907f1a25a76f98e8
|
||||
var 4d21b016b53445c2a9fb5c16e091fd2d
|
||||
tmp 7ec6f5573bc54acab29316ef5df639d1
|
||||
user-home 773f91ef66d449b5bd83d683bf40ad16
|
||||
linux-generic 0fc63daf848347728e793d69d8477de4
|
||||
@ -18,6 +18,10 @@ class TestPartitionerBase:
|
||||
def test_get_id(self):
|
||||
assert self.partitioner.get_id() == 0
|
||||
|
||||
def test_set_uuid(self):
|
||||
with raises(NotImplementedError):
|
||||
self.partitioner.set_uuid(100, 'ID')
|
||||
|
||||
def test_create(self):
|
||||
with raises(NotImplementedError):
|
||||
self.partitioner.create('name', 100, 'type', ['flag'])
|
||||
|
||||
@ -116,3 +116,10 @@ class TestPartitionerGpt:
|
||||
mock_command.assert_called_once_with(
|
||||
['sgdisk', '--resize-table', '42', '/dev/loop0']
|
||||
)
|
||||
|
||||
@patch('kiwi.partitioner.gpt.Command.run')
|
||||
def test_set_uuid(self, mock_Command_run):
|
||||
self.partitioner.set_uuid(42, 'ID')
|
||||
mock_Command_run.assert_called_once_with(
|
||||
['sgdisk', '--partition-guid', '42:ID', '/dev/loop0']
|
||||
)
|
||||
|
||||
@ -10,7 +10,11 @@ import unittest.mock as mock
|
||||
|
||||
from kiwi.storage.disk import ptable_entry_type
|
||||
from kiwi.storage.disk import Disk
|
||||
from kiwi.exceptions import KiwiCustomPartitionConflictError
|
||||
from kiwi.exceptions import (
|
||||
KiwiCustomPartitionConflictError,
|
||||
KiwiCommandError,
|
||||
KiwiCommandNotFound
|
||||
)
|
||||
|
||||
|
||||
class TestDisk:
|
||||
@ -18,9 +22,13 @@ class TestDisk:
|
||||
def inject_fixtures(self, caplog):
|
||||
self._caplog = caplog
|
||||
|
||||
@patch.object(Disk, 'get_discoverable_partition_ids')
|
||||
@patch('kiwi.storage.disk.Partitioner.new')
|
||||
@patch('kiwi.storage.disk.RuntimeConfig')
|
||||
def setup(self, mock_RuntimeConfig, mock_partitioner):
|
||||
def setup(
|
||||
self, mock_RuntimeConfig, mock_partitioner,
|
||||
mock_get_discoverable_partition_ids
|
||||
):
|
||||
runtime_config = Mock()
|
||||
runtime_config.get_mapper_tool.return_value = 'partx'
|
||||
mock_RuntimeConfig.return_value = runtime_config
|
||||
@ -304,8 +312,11 @@ class TestDisk:
|
||||
['partprobe', '/dev/loop0']
|
||||
)
|
||||
|
||||
@patch.object(Disk, 'get_discoverable_partition_ids')
|
||||
@patch('kiwi.storage.disk.Command.run')
|
||||
def test_destructor_partx_loop_cleanup_failed(self, mock_command):
|
||||
def test_context_manager_exit_partx_loop_cleanup_failed(
|
||||
self, mock_command, mock_get_discoverable_partition_ids
|
||||
):
|
||||
mock_command.side_effect = Exception
|
||||
with Disk('gpt', self.storage_provider) as disk:
|
||||
disk.is_mapped = True
|
||||
@ -315,8 +326,11 @@ class TestDisk:
|
||||
['partx', '--delete', '/dev/loop0']
|
||||
)
|
||||
|
||||
@patch.object(Disk, 'get_discoverable_partition_ids')
|
||||
@patch('kiwi.storage.disk.Command.run')
|
||||
def test_destructor_dm_loop_cleanup_failed(self, mock_command):
|
||||
def test_context_manager_exit_dm_loop_cleanup_failed(
|
||||
self, mock_command, mock_get_discoverable_partition_ids
|
||||
):
|
||||
mock_command.side_effect = Exception
|
||||
with Disk('gpt', self.storage_provider) as disk:
|
||||
disk.partition_mapper = 'kpartx'
|
||||
@ -327,8 +341,11 @@ class TestDisk:
|
||||
['dmsetup', 'remove', '/dev/mapper/loop0p1']
|
||||
)
|
||||
|
||||
@patch.object(Disk, 'get_discoverable_partition_ids')
|
||||
@patch('kiwi.storage.disk.Command.run')
|
||||
def test_destructor_partx(self, mock_command):
|
||||
def test_context_manager_exit_partx(
|
||||
self, mock_command, mock_get_discoverable_partition_ids
|
||||
):
|
||||
with Disk('gpt', self.storage_provider) as disk:
|
||||
disk.is_mapped = True
|
||||
disk.partition_map = {'root': '/dev/loop0p1'}
|
||||
@ -336,8 +353,11 @@ class TestDisk:
|
||||
call(['partx', '--delete', '/dev/loop0'])
|
||||
]
|
||||
|
||||
@patch.object(Disk, 'get_discoverable_partition_ids')
|
||||
@patch('kiwi.storage.disk.Command.run')
|
||||
def test_destructor_kpartx(self, mock_command):
|
||||
def test_context_manager_exit_kpartx(
|
||||
self, mock_command, mock_get_discoverable_partition_ids
|
||||
):
|
||||
with Disk('gpt', self.storage_provider) as disk:
|
||||
disk.partition_mapper = 'kpartx'
|
||||
disk.is_mapped = True
|
||||
@ -371,3 +391,16 @@ class TestDisk:
|
||||
(size, clone_size) = self.disk._parse_size('clone:100:all_free')
|
||||
assert size == '100'
|
||||
assert clone_size == 'all_free'
|
||||
|
||||
@patch('kiwi.storage.disk.Command.run')
|
||||
def test_get_discoverable_partition_ids(self, mock_Command_run):
|
||||
command = Mock()
|
||||
with open('../data/systemd-id128.out') as ids:
|
||||
command.output = ids.read()
|
||||
mock_Command_run.return_value = command
|
||||
assert self.disk.get_discoverable_partition_ids()['root'] == \
|
||||
'4f68bce3e8cd4db196e7fbcaf984b709'
|
||||
mock_Command_run.side_effect = KiwiCommandError('issue')
|
||||
assert self.disk.get_discoverable_partition_ids().get('root') is None
|
||||
mock_Command_run.side_effect = KiwiCommandNotFound('issue')
|
||||
assert self.disk.get_discoverable_partition_ids().get('root') is None
|
||||
|
||||
Loading…
Reference in New Issue
Block a user