The option --target-arch allows to set the architecture used to build the image. By default this is the host architecture. Please note, if the specified architecture name does not match the host architecture and is therefore requesting a cross architecture image build, it's important to understand that for this process to work a preparatory step to support the image architecture and binary format on the building host is required and is not considered a responsibility of kiwi. There will be a followup effort on providing a plugin for kiwi which should be used to manage the needed binfmt settings for cross arch image builds
451 lines
16 KiB
Python
451 lines
16 KiB
Python
from mock import (
|
|
patch, call
|
|
)
|
|
from pytest import raises
|
|
import mock
|
|
|
|
from kiwi.bootloader.install.grub2 import BootLoaderInstallGrub2
|
|
from kiwi.defaults import Defaults
|
|
|
|
from kiwi.exceptions import (
|
|
KiwiBootLoaderGrubInstallError,
|
|
KiwiBootLoaderGrubDataError,
|
|
KiwiBootLoaderGrubPlatformError
|
|
)
|
|
|
|
|
|
class TestBootLoaderInstallGrub2:
|
|
def setup(self):
|
|
Defaults.set_platform_name('x86_64')
|
|
|
|
self.firmware = mock.Mock()
|
|
self.firmware.efi_mode = mock.Mock(
|
|
return_value=None
|
|
)
|
|
|
|
self.custom_args = {
|
|
'boot_device': '/dev/mapper/loop0p2',
|
|
'root_device': '/dev/mapper/loop0p1',
|
|
'efi_device': '/dev/mapper/loop0p3',
|
|
'prep_device': '/dev/mapper/loop0p2',
|
|
'system_volumes': {'boot/grub2': {
|
|
'volume_options': 'subvol=@/boot/grub2',
|
|
'volume_device': 'device'
|
|
}},
|
|
'firmware': self.firmware,
|
|
'target_removable': None
|
|
}
|
|
|
|
self.root_mount = mock.Mock()
|
|
self.root_mount.device = self.custom_args['root_device']
|
|
self.root_mount.mountpoint = 'tmp_root'
|
|
|
|
self.volume_mount = mock.Mock()
|
|
self.volume_mount.device = self.custom_args['root_device']
|
|
self.volume_mount.mountpoint = 'tmp_volume'
|
|
|
|
self.boot_mount = mock.Mock()
|
|
self.boot_mount.device = self.custom_args['boot_device']
|
|
self.boot_mount.mountpoint = 'tmp_boot'
|
|
|
|
self.efi_mount = mock.Mock()
|
|
self.efi_mount.device = self.custom_args['efi_device']
|
|
self.efi_mount.mountpoint = 'tmp_efi'
|
|
|
|
self.device_mount = mock.Mock()
|
|
self.device_mount.device = 'devtmpfs'
|
|
self.device_mount.mountpoint = 'dev'
|
|
|
|
self.proc_mount = mock.Mock()
|
|
self.proc_mount.device = 'proc'
|
|
self.proc_mount.mountpoint = 'proc'
|
|
|
|
self.sysfs_mount = mock.Mock()
|
|
self.sysfs_mount.device = 'sysfs'
|
|
self.sysfs_mount.mountpoint = 'sys'
|
|
|
|
# the order of mount manager is reverse the order in the code
|
|
self.mount_managers = [
|
|
self.sysfs_mount,
|
|
self.proc_mount,
|
|
self.device_mount,
|
|
self.volume_mount,
|
|
self.efi_mount,
|
|
self.boot_mount,
|
|
self.root_mount
|
|
]
|
|
|
|
device_provider = mock.Mock()
|
|
device_provider.get_device = mock.Mock(
|
|
return_value='/dev/some-device'
|
|
)
|
|
|
|
self.bootloader = BootLoaderInstallGrub2(
|
|
'root_dir', device_provider, self.custom_args
|
|
)
|
|
|
|
@patch('kiwi.bootloader.install.grub2.Defaults.get_grub_path')
|
|
def test_post_init_ppc_no_prep_device(self, mock_grub_path):
|
|
self.bootloader.arch = 'ppc64'
|
|
del self.custom_args['prep_device']
|
|
with raises(KiwiBootLoaderGrubInstallError):
|
|
self.bootloader.install()
|
|
|
|
@patch('kiwi.bootloader.install.grub2.Command.run')
|
|
@patch('kiwi.bootloader.install.grub2.MountManager')
|
|
@patch('kiwi.bootloader.install.grub2.Defaults.get_grub_path')
|
|
def test_grub2_bootloader_not_installed(
|
|
self, mock_grub_path, mock_mount_manager, mock_command
|
|
):
|
|
mock_grub_path.return_value = None
|
|
self.bootloader.arch = 'x86_64'
|
|
with raises(KiwiBootLoaderGrubDataError):
|
|
self.bootloader.install()
|
|
|
|
@patch('kiwi.bootloader.install.grub2.Defaults.get_grub_path')
|
|
def test_unsupported_platform(self, mock_grub_path):
|
|
self.bootloader.arch = 'unsupported'
|
|
with raises(KiwiBootLoaderGrubPlatformError):
|
|
self.bootloader.install()
|
|
|
|
def test_post_init_no_boot_device(self):
|
|
with raises(KiwiBootLoaderGrubInstallError):
|
|
self.bootloader.post_init({})
|
|
|
|
def test_post_init_no_root_device(self):
|
|
with raises(KiwiBootLoaderGrubInstallError):
|
|
self.bootloader.post_init({'boot_device': 'a'})
|
|
|
|
def test_post_init_secure_boot_no_efi_device(self):
|
|
self.firmware.efi_mode.return_value = 'uefi'
|
|
del self.custom_args['efi_device']
|
|
with raises(KiwiBootLoaderGrubInstallError):
|
|
self.bootloader.post_init(self.custom_args)
|
|
|
|
def test_install_required(self):
|
|
assert self.bootloader.install_required() is True
|
|
|
|
def test_install_required_ppc_opal(self):
|
|
self.bootloader.arch = 'ppc64'
|
|
self.bootloader.firmware = mock.Mock()
|
|
self.bootloader.firmware.opal_mode = mock.Mock(
|
|
return_value=True
|
|
)
|
|
assert self.bootloader.install_required() is False
|
|
|
|
def test_install_required_arm64(self):
|
|
self.bootloader.arch = 'arm64'
|
|
assert self.bootloader.install_required() is False
|
|
|
|
def test_install_required_riscv64(self):
|
|
self.bootloader.arch = 'riscv64'
|
|
assert self.bootloader.install_required() is False
|
|
|
|
@patch('kiwi.bootloader.install.grub2.Path.wipe')
|
|
@patch('kiwi.bootloader.install.grub2.Path.which')
|
|
@patch('kiwi.bootloader.install.grub2.Command.run')
|
|
@patch('kiwi.bootloader.install.grub2.MountManager')
|
|
@patch('kiwi.bootloader.install.grub2.Defaults.get_grub_path')
|
|
@patch('kiwi.bootloader.install.grub2.glob.glob')
|
|
def test_install_with_extra_boot_partition(
|
|
self, mock_glob, mock_grub_path, mock_mount_manager,
|
|
mock_command, mock_which, mock_wipe
|
|
):
|
|
mock_glob.return_value = ['tmp_root/boot/grub2/grubenv']
|
|
mock_grub_path.return_value = \
|
|
self.root_mount.mountpoint + '/usr/lib/grub2/i386-pc'
|
|
|
|
def side_effect(device, mountpoint=None):
|
|
return self.mount_managers.pop()
|
|
|
|
mock_mount_manager.side_effect = side_effect
|
|
|
|
self.bootloader.install()
|
|
self.bootloader.root_mount.mount.assert_called_once_with()
|
|
self.bootloader.boot_mount.mount.assert_called_once_with()
|
|
mock_glob.assert_called_once_with(
|
|
'tmp_root/boot/*/grubenv'
|
|
)
|
|
mock_wipe.assert_called_once_with(
|
|
'tmp_root/boot/grub2/grubenv'
|
|
)
|
|
mock_which.assert_called_once_with(
|
|
root_dir='tmp_root', filename='grub2-install'
|
|
)
|
|
mock_command.assert_called_once_with(
|
|
[
|
|
'chroot', 'tmp_root', 'grub2-install', '--skip-fs-probe',
|
|
'--directory', '/usr/lib/grub2/i386-pc',
|
|
'--boot-directory', '/boot',
|
|
'--target', 'i386-pc',
|
|
'--modules', ' '.join(
|
|
Defaults.get_grub_bios_modules(multiboot=True)
|
|
),
|
|
'/dev/some-device'
|
|
]
|
|
)
|
|
|
|
@patch('kiwi.bootloader.install.grub2.Path.wipe')
|
|
@patch('kiwi.bootloader.install.grub2.Path.which')
|
|
@patch('kiwi.bootloader.install.grub2.Command.run')
|
|
@patch('kiwi.bootloader.install.grub2.MountManager')
|
|
@patch('kiwi.bootloader.install.grub2.Defaults.get_grub_path')
|
|
@patch('kiwi.bootloader.install.grub2.glob.glob')
|
|
@patch('os.path.exists')
|
|
def test_install_on_dasd_disk(
|
|
self, mock_os_path_exists, mock_glob, mock_grub_path,
|
|
mock_mount_manager, mock_command, mock_which, mock_wipe
|
|
):
|
|
mock_os_path_exists.return_value = True
|
|
self.firmware.get_partition_table_type = mock.Mock(
|
|
return_value='dasd'
|
|
)
|
|
|
|
def side_effect(device, mountpoint=None):
|
|
return self.mount_managers.pop()
|
|
|
|
mock_mount_manager.side_effect = side_effect
|
|
|
|
self.bootloader.install()
|
|
self.bootloader.root_mount.mount.assert_called_once_with()
|
|
self.bootloader.boot_mount.mount.assert_called_once_with()
|
|
assert mock_command.call_args_list == [
|
|
call(
|
|
[
|
|
'chroot', 'tmp_root', 'grub2-zipl-setup', '--keep'
|
|
]
|
|
),
|
|
call(
|
|
[
|
|
'mv',
|
|
'tmp_root/etc/default/zipl2grub.conf.in.orig',
|
|
'tmp_root/etc/default/zipl2grub.conf.in'
|
|
]
|
|
),
|
|
call(
|
|
[
|
|
'mv',
|
|
'tmp_root/boot/zipl/config',
|
|
'tmp_root/boot/zipl/config.kiwi'
|
|
]
|
|
)
|
|
]
|
|
|
|
@patch('kiwi.bootloader.install.grub2.Path.wipe')
|
|
@patch('kiwi.bootloader.install.grub2.Path.which')
|
|
@patch('kiwi.bootloader.install.grub2.Command.run')
|
|
@patch('kiwi.bootloader.install.grub2.MountManager')
|
|
@patch('kiwi.bootloader.install.grub2.Defaults.get_grub_path')
|
|
@patch('kiwi.bootloader.install.grub2.glob.glob')
|
|
def test_install_ppc_ieee1275(
|
|
self, mock_glob, mock_grub_path, mock_mount_manager,
|
|
mock_command, mock_which, mock_wipe
|
|
):
|
|
mock_glob.return_value = ['tmp_root/boot/grub2/grubenv']
|
|
mock_grub_path.return_value = \
|
|
self.root_mount.mountpoint + '/usr/lib/grub2/powerpc-ieee1275'
|
|
self.bootloader.arch = 'ppc64'
|
|
|
|
def side_effect(device, mountpoint=None):
|
|
return self.mount_managers.pop()
|
|
|
|
mock_mount_manager.side_effect = side_effect
|
|
|
|
self.bootloader.install()
|
|
self.bootloader.root_mount.mount.assert_called_once_with()
|
|
self.bootloader.boot_mount.mount.assert_called_once_with()
|
|
mock_wipe.assert_called_once_with(
|
|
'tmp_root/boot/grub2/grubenv'
|
|
)
|
|
mock_command.assert_called_once_with(
|
|
[
|
|
'chroot', 'tmp_root', 'grub2-install', '--skip-fs-probe',
|
|
'--no-nvram', '--directory', '/usr/lib/grub2/powerpc-ieee1275',
|
|
'--boot-directory', '/boot',
|
|
'--target', 'powerpc-ieee1275',
|
|
'--modules', ' '.join(
|
|
Defaults.get_grub_ofw_modules()
|
|
),
|
|
self.custom_args['prep_device']
|
|
]
|
|
)
|
|
|
|
@patch('kiwi.bootloader.install.grub2.Path.wipe')
|
|
@patch('kiwi.bootloader.install.grub2.Path.which')
|
|
@patch('kiwi.bootloader.install.grub2.Command.run')
|
|
@patch('kiwi.bootloader.install.grub2.MountManager')
|
|
@patch('kiwi.bootloader.install.grub2.Defaults.get_grub_path')
|
|
@patch('kiwi.bootloader.install.grub2.glob.glob')
|
|
def test_install_s390_emu(
|
|
self, mock_glob, mock_grub_path, mock_mount_manager,
|
|
mock_command, mock_which, mock_wipe
|
|
):
|
|
mock_glob.return_value = ['tmp_root/boot/grub2/grubenv']
|
|
mock_grub_path.return_value = \
|
|
self.root_mount.mountpoint + '/usr/lib/grub2/s390x-emu'
|
|
self.bootloader.arch = 's390x'
|
|
|
|
def side_effect(device, mountpoint=None):
|
|
return self.mount_managers.pop()
|
|
|
|
mock_mount_manager.side_effect = side_effect
|
|
|
|
self.bootloader.install()
|
|
self.bootloader.root_mount.mount.assert_called_once_with()
|
|
self.bootloader.boot_mount.mount.assert_called_once_with()
|
|
mock_wipe.assert_called_once_with(
|
|
'tmp_root/boot/grub2/grubenv'
|
|
)
|
|
mock_command.assert_called_once_with(
|
|
[
|
|
'chroot', 'tmp_root', 'grub2-install', '--skip-fs-probe',
|
|
'--no-nvram', '--directory', '/usr/lib/grub2/s390x-emu',
|
|
'--boot-directory', '/boot',
|
|
'--target', 's390x-emu',
|
|
'--modules', ' '.join(
|
|
Defaults.get_grub_s390_modules()
|
|
),
|
|
'/dev/some-device'
|
|
]
|
|
)
|
|
|
|
@patch('kiwi.bootloader.install.grub2.Path.wipe')
|
|
@patch('kiwi.bootloader.install.grub2.Path.which')
|
|
@patch('kiwi.bootloader.install.grub2.Command.run')
|
|
@patch('kiwi.bootloader.install.grub2.MountManager')
|
|
@patch('kiwi.bootloader.install.grub2.Defaults.get_grub_path')
|
|
@patch('kiwi.bootloader.install.grub2.glob.glob')
|
|
def test_install(
|
|
self, mock_glob, mock_grub_path, mock_mount_manager,
|
|
mock_command, mock_which, mock_wipe
|
|
):
|
|
mock_which.return_value = None
|
|
mock_glob.return_value = ['tmp_root/boot/grub2/grubenv']
|
|
mock_grub_path.return_value = \
|
|
self.root_mount.mountpoint + '/usr/lib/grub2/i386-pc'
|
|
self.boot_mount.device = self.root_mount.device
|
|
|
|
def side_effect(device, mountpoint=None):
|
|
return self.mount_managers.pop()
|
|
|
|
mock_mount_manager.side_effect = side_effect
|
|
self.bootloader.target_removable = True
|
|
|
|
self.bootloader.install()
|
|
self.root_mount.mount.assert_called_once_with()
|
|
self.volume_mount.mount.assert_called_once_with(
|
|
options=['subvol=@/boot/grub2']
|
|
)
|
|
mock_wipe.assert_called_once_with(
|
|
'tmp_root/boot/grub2/grubenv'
|
|
)
|
|
mock_command.assert_called_once_with(
|
|
[
|
|
'chroot', 'tmp_root', 'grub2-install',
|
|
'--removable', '--skip-fs-probe',
|
|
'--directory', '/usr/lib/grub2/i386-pc',
|
|
'--boot-directory', '/boot',
|
|
'--target', 'i386-pc',
|
|
'--modules', ' '.join(
|
|
Defaults.get_grub_bios_modules(multiboot=True)
|
|
),
|
|
'/dev/some-device'
|
|
])
|
|
|
|
@patch('kiwi.bootloader.install.grub2.Command.run')
|
|
@patch('kiwi.bootloader.install.grub2.MountManager')
|
|
@patch('os.path.exists')
|
|
@patch('os.access')
|
|
def test_secure_boot_install(
|
|
self, mock_access, mock_exists,
|
|
mock_mount_manager, mock_command
|
|
):
|
|
mock_access.return_value = True
|
|
mock_exists.return_value = True
|
|
self.firmware.efi_mode.return_value = 'uefi'
|
|
self.boot_mount.device = self.root_mount.device
|
|
|
|
def side_effect(device, mountpoint=None):
|
|
return self.mount_managers.pop()
|
|
|
|
mock_mount_manager.side_effect = side_effect
|
|
|
|
self.bootloader.secure_boot_install()
|
|
|
|
assert mock_command.call_args_list == [
|
|
call([
|
|
'cp', '-p', 'tmp_root/usr/sbin/grub2-install',
|
|
'tmp_root/usr/sbin/grub2-install.orig'
|
|
]),
|
|
call([
|
|
'cp', 'tmp_root/bin/true', 'tmp_root/usr/sbin/grub2-install'
|
|
]),
|
|
call([
|
|
'chroot', 'tmp_root', 'shim-install', '--removable',
|
|
'/dev/some-device'
|
|
]),
|
|
call([
|
|
'mv', 'tmp_root/usr/sbin/grub2-install.orig',
|
|
'tmp_root/usr/sbin/grub2-install'
|
|
])
|
|
]
|
|
self.root_mount.mount.assert_called_once_with()
|
|
self.volume_mount.mount.assert_called_once_with(
|
|
options=['subvol=@/boot/grub2']
|
|
)
|
|
self.device_mount.bind_mount.assert_called_once_with()
|
|
self.proc_mount.bind_mount.assert_called_once_with()
|
|
self.sysfs_mount.bind_mount.assert_called_once_with()
|
|
self.efi_mount.mount.assert_called_once_with()
|
|
|
|
@patch('kiwi.bootloader.install.grub2.Path.which')
|
|
@patch('kiwi.bootloader.install.grub2.MountManager')
|
|
def test_secure_boot_install_no_shim_install(
|
|
self, mock_mount_manager, mock_which
|
|
):
|
|
mock_which.return_value = None
|
|
self.firmware.efi_mode.return_value = 'uefi'
|
|
|
|
def side_effect(device, mountpoint=None):
|
|
return self.mount_managers.pop()
|
|
|
|
mock_mount_manager.side_effect = side_effect
|
|
|
|
self.bootloader.secure_boot_install()
|
|
self.root_mount.mount.assert_called_once_with()
|
|
self.volume_mount.mount.assert_called_once_with(
|
|
options=['subvol=@/boot/grub2']
|
|
)
|
|
self.device_mount.bind_mount.assert_called_once_with()
|
|
self.proc_mount.bind_mount.assert_called_once_with()
|
|
self.sysfs_mount.bind_mount.assert_called_once_with()
|
|
self.efi_mount.mount.assert_called_once_with()
|
|
mock_which.assert_called_once_with(
|
|
filename='shim-install', root_dir='tmp_root'
|
|
)
|
|
|
|
@patch('kiwi.bootloader.install.grub2.Command.run')
|
|
@patch('kiwi.bootloader.install.grub2.MountManager')
|
|
@patch('kiwi.bootloader.install.grub2.Defaults.get_grub_path')
|
|
@patch('os.path.exists')
|
|
def test_destructor(
|
|
self, mock_exists, mock_grub_path, mock_mount_manager, mock_command
|
|
):
|
|
mock_exists.return_value = True
|
|
self.firmware.efi_mode.return_value = 'uefi'
|
|
|
|
def side_effect(device, mountpoint=None):
|
|
return self.mount_managers.pop()
|
|
|
|
mock_mount_manager.side_effect = side_effect
|
|
|
|
self.bootloader.install()
|
|
self.bootloader.__del__()
|
|
|
|
self.device_mount.umount.assert_called_once_with()
|
|
self.proc_mount.umount.assert_called_once_with()
|
|
self.sysfs_mount.umount.assert_called_once_with()
|
|
self.efi_mount.umount.assert_called_once_with()
|
|
self.boot_mount.umount.assert_called_once_with()
|
|
self.root_mount.umount.assert_called_once_with()
|