In an OEM deployment that requested the creation of a swap partition via <oem-swap> that swap partition was created at first boot and was always the last partition on the disk. This was required because it could not be placed before any other partition without destroying those partition contents. This process leaves the system in an inflexible condition if the storage device can change its geometry dynamicly as it's the case for SAN systems. The typical deployment target for OEM images are SAN storage clusters and it's cumbersome to resize the root partition if swap is last. This commit Fixes #1231 and changes the handling of swap if requested via <oem-swap> as follows: 1. The swap space is created as part of the image build process and no longer on first boot of the image via dracut code. This increases the size of the non compressed .raw disk image by the configured swap space size or the default. The compressed versions are not affected since zero initialized swap space compresses to almost no space. Deployment of the image however also deploys the swap partition which increases deployment time. For big swap configurations it's advisable to switch off image verification via oem-skip-verify. For very big swap configurations it's also recommended to prevent kiwi from adding them as part of the image and let them be created on first boot via a systemd service that e.g places a swap file, or creates a swap volume when possible such that the fexibility to resize the rootfs is still available. 2. The setup of the swap space is now explicit. It's no longer calculated by twice times RAM size because on newer machines this could lead to huge numbers. Either the kiwi encoded default swap size applies or the user configured value. 3. LVM based oem disks creates the swap space as logical volume. The volume is created as part of the image build process and no longer on first boot. The swap volume at build time of the image is of a minimal size and gets resized on first boot. 4. The move of the swap creation into the builder code also handles swap per configured device persistency schema like any other devices. This means by default swap is mounted via by-uuid name and thus also Fixes #1259
255 lines
9.3 KiB
Python
255 lines
9.3 KiB
Python
import logging
|
|
from mock import (
|
|
patch, mock_open
|
|
)
|
|
from pytest import fixture
|
|
|
|
import mock
|
|
|
|
from kiwi.storage.disk import Disk
|
|
|
|
|
|
class TestDisk:
|
|
@fixture(autouse=True)
|
|
def inject_fixtures(self, caplog):
|
|
self._caplog = caplog
|
|
|
|
@patch('kiwi.storage.disk.Partitioner')
|
|
def setup(self, mock_partitioner):
|
|
self.tempfile = mock.Mock()
|
|
self.tempfile.name = 'tempfile'
|
|
|
|
self.partitioner = mock.Mock()
|
|
self.partitioner.create = mock.Mock()
|
|
self.partitioner.get_id = mock.Mock(
|
|
return_value=1
|
|
)
|
|
mock_partitioner.return_value = self.partitioner
|
|
self.storage_provider = mock.Mock()
|
|
self.storage_provider.is_loop = mock.Mock(
|
|
return_value=True
|
|
)
|
|
self.storage_provider.get_device = mock.Mock(
|
|
return_value='/dev/loop0'
|
|
)
|
|
self.disk = Disk('gpt', self.storage_provider)
|
|
|
|
@patch('os.path.exists')
|
|
def test_get_device(self, mock_exists):
|
|
mock_exists.return_value = True
|
|
self.disk.partition_map['root'] = '/dev/root-device'
|
|
assert self.disk.get_device()['root'].get_device() == '/dev/root-device'
|
|
|
|
def test_is_loop(self):
|
|
self.disk.is_loop()
|
|
self.storage_provider.is_loop.called_once_with()
|
|
|
|
def test_create_root_partition(self):
|
|
self.disk.create_root_partition(100)
|
|
self.partitioner.create.assert_called_once_with(
|
|
'p.lxroot', 100, 't.linux'
|
|
)
|
|
|
|
def test_create_root_which_is_also_boot_partition(self):
|
|
self.disk.create_root_partition(200)
|
|
self.partitioner.create.assert_called_once_with(
|
|
'p.lxroot', 200, 't.linux'
|
|
)
|
|
assert self.disk.public_partition_id_map['kiwi_RootPart'] == 1
|
|
assert self.disk.public_partition_id_map['kiwi_BootPart'] == 1
|
|
|
|
def test_create_root_which_is_also_read_write_partition(self):
|
|
self.disk.public_partition_id_map['kiwi_ROPart'] = 1
|
|
self.disk.create_root_partition(200)
|
|
self.partitioner.create.assert_called_once_with(
|
|
'p.lxroot', 200, 't.linux'
|
|
)
|
|
assert self.disk.public_partition_id_map['kiwi_RootPart'] == 1
|
|
assert self.disk.public_partition_id_map['kiwi_RWPart'] == 1
|
|
|
|
def test_create_root_lvm_partition(self):
|
|
self.disk.create_root_lvm_partition(100)
|
|
self.partitioner.create.assert_called_once_with(
|
|
'p.lxlvm', 100, 't.lvm'
|
|
)
|
|
assert self.disk.public_partition_id_map['kiwi_RootPart'] == 1
|
|
assert self.disk.public_partition_id_map['kiwi_RootPartVol'] == 'LVRoot'
|
|
|
|
def test_create_root_raid_partition(self):
|
|
self.disk.create_root_raid_partition(100)
|
|
self.partitioner.create.assert_called_once_with(
|
|
'p.lxraid', 100, 't.raid'
|
|
)
|
|
assert self.disk.public_partition_id_map['kiwi_RootPart'] == 1
|
|
assert self.disk.public_partition_id_map['kiwi_RaidPart'] == 1
|
|
|
|
def test_create_root_readonly_partition(self):
|
|
self.disk.create_root_readonly_partition(100)
|
|
self.partitioner.create.assert_called_once_with(
|
|
'p.lxreadonly', 100, 't.linux'
|
|
)
|
|
assert self.disk.public_partition_id_map['kiwi_ROPart'] == 1
|
|
|
|
def test_create_boot_partition(self):
|
|
self.disk.create_boot_partition(100)
|
|
self.partitioner.create.assert_called_once_with(
|
|
'p.lxboot', 100, 't.linux'
|
|
)
|
|
assert self.disk.public_partition_id_map['kiwi_BootPart'] == 1
|
|
|
|
def test_create_efi_csm_partition(self):
|
|
self.disk.create_efi_csm_partition(100)
|
|
self.partitioner.create.assert_called_once_with(
|
|
'p.legacy', 100, 't.csm'
|
|
)
|
|
assert self.disk.public_partition_id_map['kiwi_BiosGrub'] == 1
|
|
|
|
def test_create_efi_partition(self):
|
|
self.disk.create_efi_partition(100)
|
|
self.partitioner.create.assert_called_once_with(
|
|
'p.UEFI', 100, 't.efi'
|
|
)
|
|
assert self.disk.public_partition_id_map['kiwi_EfiPart'] == 1
|
|
|
|
def test_create_spare_partition(self):
|
|
self.disk.create_spare_partition(42)
|
|
self.partitioner.create.assert_called_once_with(
|
|
'p.spare', 42, 't.linux'
|
|
)
|
|
assert self.disk.public_partition_id_map['kiwi_SparePart'] == 1
|
|
|
|
def test_create_swap_partition(self):
|
|
self.disk.create_swap_partition(42)
|
|
self.partitioner.create.assert_called_once_with(
|
|
'p.swap', 42, 't.swap'
|
|
)
|
|
assert self.disk.public_partition_id_map['kiwi_SwapPart'] == 1
|
|
|
|
@patch('kiwi.storage.disk.Command.run')
|
|
def test_create_prep_partition(self, mock_command):
|
|
self.disk.create_prep_partition(8)
|
|
self.partitioner.create.assert_called_once_with(
|
|
'p.prep', 8, 't.prep'
|
|
)
|
|
assert self.disk.public_partition_id_map['kiwi_PrepPart'] == 1
|
|
|
|
@patch('kiwi.storage.disk.Command.run')
|
|
def test_device_map_efi_partition(self, mock_command):
|
|
self.disk.create_efi_partition(100)
|
|
self.disk.map_partitions()
|
|
assert self.disk.partition_map == {'efi': '/dev/mapper/loop0p1'}
|
|
self.disk.is_mapped = False
|
|
|
|
@patch('kiwi.storage.disk.Command.run')
|
|
def test_device_map_prep_partition(self, mock_command):
|
|
self.disk.create_prep_partition(8)
|
|
self.disk.map_partitions()
|
|
assert self.disk.partition_map == {'prep': '/dev/mapper/loop0p1'}
|
|
self.disk.is_mapped = False
|
|
|
|
@patch('kiwi.storage.disk.Command.run')
|
|
def test_device_map_linux_dev_sda(self, mock_command):
|
|
self.storage_provider.is_loop.return_value = False
|
|
self.storage_provider.get_device = mock.Mock(
|
|
return_value='/dev/sda'
|
|
)
|
|
self.disk.create_efi_partition(100)
|
|
self.disk.map_partitions()
|
|
assert self.disk.partition_map == {'efi': '/dev/sda1'}
|
|
self.disk.is_mapped = False
|
|
|
|
@patch('kiwi.storage.disk.Command.run')
|
|
def test_device_map_linux_dev_c0d0(self, mock_command):
|
|
self.storage_provider.is_loop.return_value = False
|
|
self.storage_provider.get_device = mock.Mock(
|
|
return_value='/dev/c0d0'
|
|
)
|
|
self.disk.create_efi_partition(100)
|
|
self.disk.map_partitions()
|
|
assert self.disk.partition_map == {'efi': '/dev/c0d0p1'}
|
|
self.disk.is_mapped = False
|
|
|
|
@patch('kiwi.storage.disk.Command.run')
|
|
def test_activate_boot_partition_is_boot_partition(self, mock_command):
|
|
self.disk.create_boot_partition(100)
|
|
self.disk.create_root_partition(100)
|
|
self.disk.activate_boot_partition()
|
|
self.partitioner.set_flag(1, 'f.active')
|
|
|
|
@patch('kiwi.storage.disk.Command.run')
|
|
def test_activate_boot_partition_is_root_partition(self, mock_command):
|
|
self.disk.create_root_partition(100)
|
|
self.disk.activate_boot_partition()
|
|
self.partitioner.set_flag(1, 'f.active')
|
|
|
|
@patch('kiwi.storage.disk.Command.run')
|
|
def test_activate_boot_partition_is_prep_partition(self, mock_command):
|
|
self.disk.create_prep_partition(8)
|
|
self.disk.activate_boot_partition()
|
|
self.partitioner.set_flag(1, 'f.active')
|
|
|
|
@patch('kiwi.storage.disk.Command.run')
|
|
def test_wipe_gpt(self, mock_command):
|
|
self.disk.wipe()
|
|
mock_command.assert_called_once_with(
|
|
['sgdisk', '--zap-all', '/dev/loop0']
|
|
)
|
|
|
|
@patch('kiwi.storage.disk.Command.run')
|
|
@patch('kiwi.storage.disk.NamedTemporaryFile')
|
|
def test_wipe_dasd(self, mock_temp, mock_command):
|
|
mock_command.side_effect = Exception
|
|
self.disk.table_type = 'dasd'
|
|
mock_temp.return_value = self.tempfile
|
|
|
|
m_open = mock_open()
|
|
with patch('builtins.open', m_open, create=True):
|
|
self.disk.wipe()
|
|
|
|
m_open.return_value.write.assert_called_once_with(
|
|
'y\n\nw\nq\n'
|
|
)
|
|
with self._caplog.at_level(logging.DEBUG):
|
|
mock_command.assert_called_once_with(
|
|
['bash', '-c', 'cat tempfile | fdasd -f /dev/loop0']
|
|
)
|
|
|
|
@patch('kiwi.storage.disk.Command.run')
|
|
def test_map_partitions_loop(self, mock_command):
|
|
self.disk.map_partitions()
|
|
mock_command.assert_called_once_with(
|
|
['kpartx', '-s', '-a', '/dev/loop0']
|
|
)
|
|
self.disk.is_mapped = False
|
|
|
|
@patch('kiwi.storage.disk.Command.run')
|
|
def test_map_partitions_other(self, mock_command):
|
|
self.storage_provider.is_loop.return_value = False
|
|
self.disk.map_partitions()
|
|
mock_command.assert_called_once_with(
|
|
['partprobe', '/dev/loop0']
|
|
)
|
|
|
|
@patch('kiwi.storage.disk.Command.run')
|
|
def test_destructor(self, mock_command):
|
|
self.disk.is_mapped = True
|
|
self.disk.partition_map = {'root': '/dev/mapper/loop0p1'}
|
|
mock_command.side_effect = Exception
|
|
self.disk.__del__()
|
|
with self._caplog.at_level(logging.WARNING):
|
|
mock_command.assert_called_once_with(
|
|
['dmsetup', 'remove', '/dev/mapper/loop0p1']
|
|
)
|
|
self.disk.is_mapped = False
|
|
|
|
def test_get_public_partition_id_map(self):
|
|
assert self.disk.get_public_partition_id_map() == {}
|
|
|
|
def test_create_hybrid_mbr(self):
|
|
self.disk.create_hybrid_mbr()
|
|
self.partitioner.set_hybrid_mbr.assert_called_once_with()
|
|
|
|
def test_create_mbr(self):
|
|
self.disk.create_mbr()
|
|
self.partitioner.set_mbr.assert_called_once_with()
|