kiwi-el8/test/unit/storage/clone_device_test.py
Marcus Schäfer 009c88a48b
Added new CloneDevice class
Added CloneDevice class to the storage interface.
The class allows to create clone(s) from a given source
block device into a list of target block devices.
The target block devices are clones of the source but
prevents device naming conflicts for unique identifiers
like the UUID. This is requires to still allow to boot
from images containing device clones and needs to be
handled by tools that might work on top of the cloned
devices.
2022-04-05 17:43:41 +02:00

140 lines
4.9 KiB
Python

import io
from mock import (
patch, call, MagicMock, Mock
)
from pytest import raises
from kiwi.storage.clone_device import CloneDevice
from kiwi.exceptions import KiwiRaidSetupError
class TestCloneDevice:
def setup(self):
self.storage_device = Mock()
self.storage_device.get_device = Mock(
return_value='/dev/source-device'
)
self.target_device = Mock()
self.target_device.get_device = Mock(
return_value='/dev/target-device'
)
self.clone_id = Mock()
self.clone_device = CloneDevice(
self.storage_device, 'root_dir'
)
@patch('kiwi.storage.clone_device.Command.run')
@patch('kiwi.storage.clone_device.BlockID')
@patch('kiwi.storage.clone_device.FileSystem.new')
def test_clone_filesystem(
self, mock_FileSystem_new, mock_BlockID, mock_Command_run
):
self.clone_id.get_filesystem.return_value = 'ext3'
mock_BlockID.return_value = self.clone_id
self.clone_device.clone([self.target_device])
mock_Command_run.assert_called_once_with(
['dd', 'if=/dev/source-device', 'of=/dev/target-device']
)
mock_FileSystem_new.assert_called_once_with(
'ext3', self.target_device
)
mock_FileSystem_new.return_value.set_uuid.assert_called_once_with()
@patch('kiwi.storage.clone_device.Command.run')
@patch('kiwi.storage.clone_device.BlockID')
def test_clone_lvm(self, mock_BlockID, mock_Command_run):
self.clone_id.get_filesystem.return_value = 'LVM2_member'
mock_BlockID.return_value = self.clone_id
self.clone_device.clone([self.target_device])
assert mock_Command_run.call_args_list == [
call(
['dd', 'if=/dev/source-device', 'of=/dev/target-device']
),
call(
['vgimportclone', '/dev/target-device']
)
]
@patch('kiwi.storage.clone_device.Command.run')
@patch('kiwi.storage.clone_device.BlockID')
@patch('uuid.uuid4')
def test_clone_luks(self, mock_uuid4, mock_BlockID, mock_Command_run):
self.clone_id.get_filesystem.return_value = 'crypto_LUKS'
mock_BlockID.return_value = self.clone_id
mock_uuid4.return_value = 'some-UUID'
self.clone_device.clone([self.target_device])
assert mock_Command_run.call_args_list == [
call(
['dd', 'if=/dev/source-device', 'of=/dev/target-device']
),
call(
[
'cryptsetup', '-q', 'luksUUID',
'/dev/target-device', '--uuid', 'some-UUID'
]
)
]
@patch('kiwi.storage.clone_device.Command.run')
@patch('kiwi.storage.clone_device.BlockID')
@patch('kiwi.storage.clone_device.FileSystem.new')
@patch('kiwi.storage.clone_device.MappedDevice')
def test_clone_raid(
self, mock_MappedDevice, mock_FileSystem_new,
mock_BlockID, mock_Command_run
):
self.clone_id.get_filesystem.return_value = 'linux_raid_member'
mock_BlockID.return_value = self.clone_id
with patch('builtins.open', create=True) as mock_open:
mock_open.return_value = MagicMock(spec=io.IOBase)
file_handle = mock_open.return_value.__enter__.return_value
file_handle.readline.return_value = \
'ARRAY /dev/md0 metadata=1.2 name=asterix:0 UUID=...'
self.clone_device.clone([self.target_device])
mock_open.assert_called_once_with('root_dir/etc/mdadm.conf')
mock_FileSystem_new.assert_called_once_with(
mock_BlockID.return_value.get_filesystem.return_value,
mock_MappedDevice.return_value
)
mock_FileSystem_new.return_value.set_uuid.assert_called_once_with()
assert mock_Command_run.call_args_list == [
call(
['dd', 'if=/dev/source-device', 'of=/dev/target-device']
),
call(
['mdadm', '--stop', '/dev/md0']
),
call(
[
'mdadm', '--assemble', '--update=uuid',
'--name', 'asterix:0', '/dev/md0', '/dev/target-device'
]
),
call(
['mdadm', '--stop', '/dev/md0']
),
call(
['mdadm', '--assemble', '/dev/md0', '/dev/source-device']
)
]
@patch('kiwi.storage.clone_device.Command.run')
@patch('kiwi.storage.clone_device.BlockID')
def test_clone_raid_raises(self, mock_BlockID, mock_Command_run):
self.clone_id.get_filesystem.return_value = 'linux_raid_member'
mock_BlockID.return_value = self.clone_id
with patch('builtins.open', create=True) as mock_open:
mock_open.side_effect = Exception
with raises(KiwiRaidSetupError):
self.clone_device.clone([self.target_device])