Refactor grub2 bootloader installation

Make use of grub2-install to install the bootloader
This commit is contained in:
Marcus Schäfer 2016-02-25 17:18:31 +01:00
parent f43546fd59
commit 147c0706eb
No known key found for this signature in database
GPG Key ID: AD11DD02B44996EF
8 changed files with 299 additions and 255 deletions

View File

@ -53,6 +53,7 @@ class BootLoaderConfigGrub2(BootLoaderConfigBase):
'host architecture %s not supported for grub2 setup' % arch
)
self.gfxmode = '800x600'
self.terminal = 'gfxterm'
self.bootpath = self.get_boot_path()
self.gfxmode = self.__get_gfxmode()
@ -260,8 +261,8 @@ class BootLoaderConfigGrub2(BootLoaderConfigBase):
self.__setup_secure_boot_efi_image(lookup_path)
else:
log.info('--> Creating unsigned efi image')
self.__create_efi_image(mbrid=mbrid, lookup_path=lookup_path)
self.__copy_efi_modules_to_boot_directory(lookup_path)
self.__create_efi_image(mbrid=mbrid)
self.__create_embedded_fat_efi_image()
@ -271,8 +272,9 @@ class BootLoaderConfigGrub2(BootLoaderConfigBase):
def setup_disk_boot_images(self, boot_uuid, lookup_path=None):
"""
EFI and bios images needs to be build or used if provided
by the distribution
EFI images needs to be build or used if provided
by the distribution. The bios core image is created
when grub2-install is called
"""
log.info('Creating grub bootloader images')
@ -283,15 +285,14 @@ class BootLoaderConfigGrub2(BootLoaderConfigBase):
if self.firmware.efi_mode() == 'efi':
log.info('--> Creating unsigned efi image')
self.__create_efi_image(uuid=boot_uuid, lookup_path=lookup_path)
self.__copy_efi_modules_to_boot_directory(lookup_path)
self.__create_efi_image(uuid=boot_uuid)
elif self.firmware.efi_mode() == 'uefi':
log.info('--> Using signed secure boot efi image')
self.__setup_secure_boot_efi_image(lookup_path)
log.info('--> Creating bios core image')
self.__copy_bios_modules_to_boot_directory(lookup_path)
self.__create_bios_boot_image(boot_uuid)
def __setup_secure_boot_efi_image(self, lookup_path):
"""
@ -335,7 +336,7 @@ class BootLoaderConfigGrub2(BootLoaderConfigBase):
]
)
def __create_efi_image(self, uuid=None, mbrid=None):
def __create_efi_image(self, uuid=None, mbrid=None, lookup_path=None):
"""
create efi image
"""
@ -355,28 +356,8 @@ class BootLoaderConfigGrub2(BootLoaderConfigBase):
'-o', self.__get_efi_image_name(),
'-c', early_boot_script,
'-p', self.get_boot_path() + '/' + self.boot_directory_name,
'-d',
self.__get_grub_boot_path() + '/' + self.__get_efi_format()
] + self.__get_efi_modules()
)
def __create_bios_boot_image(self, uuid):
"""
create bios image
"""
early_boot_script = self.__get_grub_boot_path() + '/earlyboot.cfg'
self.__create_early_boot_script_for_uuid_search(
early_boot_script, uuid
)
Command.run(
[
'grub2-mkimage', '-O', self.__get_bios_format(),
'-o', self.__get_bios_image_name(),
'-c', early_boot_script,
'-p', self.get_boot_path() + '/' + self.boot_directory_name,
'-d',
self.__get_grub_boot_path() + '/' + self.__get_bios_format()
] + self.__get_bios_modules()
'-d', self.__get_efi_modules_path(lookup_path)
] + Defaults.get_grub_efi_modules()
)
def __create_early_boot_script_for_uuid_search(self, filename, uuid):
@ -402,73 +383,8 @@ class BootLoaderConfigGrub2(BootLoaderConfigBase):
def __get_grub_boot_path(self):
return self.root_dir + '/boot/' + self.boot_directory_name
def __get_basic_modules(self):
modules = [
'ext2',
'iso9660',
'linux',
'echo',
'configfile',
'search_label',
'search_fs_file',
'search',
'search_fs_uuid',
'ls',
'normal',
'gzio',
'png',
'fat',
'gettext',
'font',
'minicmd',
'gfxterm',
'gfxmenu',
'video',
'video_fb',
'xfs',
'btrfs',
'lvm',
'multiboot'
]
return modules
def __get_efi_modules(self):
modules = self.__get_basic_modules() + [
'part_gpt',
'efi_gop',
'efi_uga',
'linuxefi'
]
return modules
def __get_bios_modules(self):
modules = self.__get_basic_modules() + [
'part_gpt',
'part_msdos',
'biosdisk',
'vga',
'vbe',
'chain',
'boot'
]
return modules
def __get_efi_image_name(self):
efi_image_name = None
if self.arch == 'x86_64':
efi_image_name = 'bootx64.efi'
if efi_image_name:
return ''.join(
[self.efi_boot_path, '/', efi_image_name]
)
def __get_bios_image_name(self):
return ''.join(
[
self.__get_grub_boot_path(), '/',
self.__get_bios_format(), '/core.img'
]
)
return self.efi_boot_path + '/bootx64.efi'
def __get_efi_format(self):
return 'x86_64-efi'
@ -499,29 +415,11 @@ class BootLoaderConfigGrub2(BootLoaderConfigBase):
)
def __get_gfxmode(self):
selected_gfxmode = '800x600'
gfxmode = {
'0x301': '640x480',
'0x310': '640x480',
'0x311': '640x480',
'0x312': '640x480',
'0x303': '800x600',
'0x313': '800x600',
'0x314': '800x600',
'0x315': '800x600',
'0x305': '1024x768',
'0x316': '1024x768',
'0x317': '1024x768',
'0x318': '1024x768',
'0x307': '1280x1024',
'0x319': '1280x1024',
'0x31a': '1280x1024',
'0x31b': '1280x1024',
}
gfxmode = Defaults.get_video_mode_map()
requested_gfxmode = self.xml_state.build_type.get_vga()
if requested_gfxmode in gfxmode:
selected_gfxmode = gfxmode[requested_gfxmode]
return selected_gfxmode
self.gfxmode = gfxmode[requested_gfxmode].grub2
return self.gfxmode
def __copy_theme_data_to_boot_directory(self, lookup_path):
if not lookup_path:
@ -547,7 +445,7 @@ class BootLoaderConfigGrub2(BootLoaderConfigBase):
'/themes/' + self.theme
if os.path.exists(theme_dir):
Command.run(
['rsync', '-zav', theme_dir, boot_theme_dir],
['rsync', '-za', theme_dir, boot_theme_dir],
)
else:
log.warning('Theme %s not found', theme_dir)
@ -569,15 +467,14 @@ class BootLoaderConfigGrub2(BootLoaderConfigBase):
def __copy_modules_to_boot_directory_from(self, module_path):
boot_module_path = \
self.__get_grub_boot_path() + '/' + os.path.basename(module_path)
if not os.path.exists(boot_module_path):
try:
Command.run(
['cp', '-a', module_path, boot_module_path]
)
except Exception:
raise KiwiBootLoaderGrubModulesError(
'grub2 modules %s not found' % module_path
)
try:
Command.run(
['rsync', '-za', module_path + '/', boot_module_path]
)
except Exception as e:
raise KiwiBootLoaderGrubModulesError(
'Module synchronisation failed with: %s' % format(e)
)
def __find_grub_data(self, lookup_path):
"""

View File

@ -15,55 +15,114 @@
# You should have received a copy of the GNU General Public License
# along with kiwi. If not, see <http://www.gnu.org/licenses/>
#
from tempfile import NamedTemporaryFile
from tempfile import mkdtemp
import time
# project
from .bootloader_install_base import BootLoaderInstallBase
from .command import Command
from .logger import log
from .path import Path
from .defaults import Defaults
from .exceptions import(
KiwiBootLoaderGrubInstallError
)
class BootLoaderInstallGrub2(BootLoaderInstallBase):
"""
grub2 bootloader installation
grub2 bootloader installation for x86 bios platform
"""
def post_init(self, custom_args):
self.custom_args = custom_args
self.temporary_boot_dir = None
if not custom_args or 'boot_device' not in custom_args:
raise KiwiBootLoaderGrubInstallError(
'boot device node name required for grub2 installation'
)
if not custom_args or 'root_device' not in custom_args:
raise KiwiBootLoaderGrubInstallError(
'root device node name required for grub2 installation'
)
self.mountpoint_root = mkdtemp()
self.mountpoint_boot = mkdtemp()
self.grub2_boot_device = custom_args['boot_device']
self.grub2_root_device = custom_args['root_device']
self.extra_boot_partition = False
if not self.grub2_boot_device == self.grub2_root_device:
self.extra_boot_partition = True
def install(self):
"""
install bootloader on self.device
"""
log.info('Installing grub2 on disk %s', self.device)
device_map_file = NamedTemporaryFile()
with open(device_map_file.name, 'w') as device_map:
device_map.write('(hd0) %s\n' % self.device)
# The following copy action is only needed because grub2-probe
# is not able to resolve the canonical path of the boot directory
# if it lives on e.g a tmpfs. However building an image in a tmpfs
# is done pretty often to increase the build performance. In order
# to make grub happy we have to copy out the boot data with the
# hope that /boot of the build host system is not on a filesystem
# which causes grub2-probe to fail again
self.temporary_boot_dir = mkdtemp(prefix='kiwi_bootloader.')
Command.run(
['cp', '-a', self.root_dir + '/boot/', self.temporary_boot_dir]
)
if self.extra_boot_partition:
self.__mount_boot_partition()
self.__mount_root_partition()
module_directory = self.mountpoint_root + '/usr/lib/grub2/i386-pc'
boot_directory = self.mountpoint_boot
else:
self.__mount_root_partition()
module_directory = self.mountpoint_root + '/usr/lib/grub2/i386-pc'
boot_directory = self.mountpoint_root + '/boot'
Command.run(
[
'grub2-bios-setup', '-f',
'-d', self.temporary_boot_dir + '/boot/grub2/i386-pc',
'-m', device_map_file.name,
'grub2-install',
'--skip-fs-probe',
'--directory', module_directory,
'--boot-directory', boot_directory,
'--target', 'i386-pc',
'--modules', ' '.join(Defaults.get_grub_bios_modules()),
self.device
]
)
def __mount_boot_partition(self):
self.__mount(self.grub2_boot_device, self.mountpoint_boot)
def __mount_root_partition(self):
self.__mount(self.grub2_root_device, self.mountpoint_root)
def __is_mounted(self, mountpoint):
try:
Command.run(['mountpoint', mountpoint])
return True
except Exception:
return False
def __mount(self, device, mountpoint):
Command.run(['mount', device, mountpoint])
return True
def __umount(self, mountpoint):
if self.__is_mounted(mountpoint):
umounted_successfully = False
for busy in [1, 2, 3]:
try:
Command.run(['umount', mountpoint])
umounted_successfully = True
break
except Exception:
log.warning(
'%d umount of %s failed, try again in 1sec',
busy, mountpoint
)
time.sleep(1)
if not umounted_successfully:
log.warning(
'%s still busy at %s', mountpoint, type(self).__name__
)
# skip removing the mountpoint directory
return
Path.remove(mountpoint)
def __del__(self):
if self.temporary_boot_dir:
log.info('Cleaning up %s instance', type(self).__name__)
Path.wipe(self.temporary_boot_dir)
log.info('Cleaning up %s instance', type(self).__name__)
self.__umount(self.mountpoint_root)
self.__umount(self.mountpoint_boot)

View File

@ -15,6 +15,7 @@
# You should have received a copy of the GNU General Public License
# along with kiwi. If not, see <http://www.gnu.org/licenses/>
#
from collections import namedtuple
import platform
import re
from pkg_resources import resource_filename
@ -49,6 +50,83 @@ class Defaults(object):
'kiwi_revision'
]
@classmethod
def get_video_mode_map(self):
video_type = namedtuple(
'video_type', ['grub2']
)
return {
'0x301': video_type(grub2='640x480'),
'0x310': video_type(grub2='640x480'),
'0x311': video_type(grub2='640x480'),
'0x312': video_type(grub2='640x480'),
'0x303': video_type(grub2='800x600'),
'0x313': video_type(grub2='800x600'),
'0x314': video_type(grub2='800x600'),
'0x315': video_type(grub2='800x600'),
'0x305': video_type(grub2='1024x768'),
'0x316': video_type(grub2='1024x768'),
'0x317': video_type(grub2='1024x768'),
'0x318': video_type(grub2='1024x768'),
'0x307': video_type(grub2='1280x1024'),
'0x319': video_type(grub2='1280x1024'),
'0x31a': video_type(grub2='1280x1024'),
'0x31b': video_type(grub2='1280x1024'),
}
@classmethod
def get_grub_basic_modules(self):
return [
'ext2',
'iso9660',
'linux',
'echo',
'configfile',
'search_label',
'search_fs_file',
'search',
'search_fs_uuid',
'ls',
'normal',
'gzio',
'png',
'fat',
'gettext',
'font',
'minicmd',
'gfxterm',
'gfxmenu',
'video',
'video_fb',
'xfs',
'btrfs',
'lvm',
'multiboot'
]
@classmethod
def get_grub_efi_modules(self):
modules = Defaults.get_grub_basic_modules() + [
'part_gpt',
'efi_gop',
'efi_uga',
'linuxefi'
]
return modules
@classmethod
def get_grub_bios_modules(self):
modules = Defaults.get_grub_basic_modules() + [
'part_gpt',
'part_msdos',
'biosdisk',
'vga',
'vbe',
'chain',
'boot'
]
return modules
@classmethod
def get_preparer(self):
return 'KIWI - http://suse.github.com/kiwi'

View File

@ -485,11 +485,15 @@ class DiskBuilder(object):
)
def __install_bootloader(self, device_map):
boot_device = device_map['root']
custom_install_arguments = {}
root_device = device_map['root']
boot_device = root_device
if 'boot' in device_map:
boot_device = device_map['boot']
custom_install_arguments['boot_device'] = boot_device.get_device()
custom_install_arguments = {
'boot_device': boot_device.get_device(),
'root_device': root_device.get_device()
}
bootloader = BootLoaderInstall(
self.bootloader, self.root_dir, self.disk.storage_provider,

View File

@ -49,6 +49,10 @@ class KiwiBootLoaderGrubFontError(KiwiError):
pass
class KiwiBootLoaderGrubInstallError(KiwiError):
pass
class KiwiBootLoaderGrubModulesError(KiwiError):
pass

View File

@ -316,13 +316,10 @@ class TestBootLoaderConfigGrub2(object):
setattr(context_manager_mock, '__exit__', exit_mock)
self.bootloader.setup_disk_boot_images('0815')
assert mock_open.call_args_list == [
call('root_dir/boot/efi/EFI/BOOT/earlyboot.cfg', 'w'),
call('root_dir/boot/grub2/earlyboot.cfg', 'w')
]
mock_open.assert_called_once_with(
'root_dir/boot/efi/EFI/BOOT/earlyboot.cfg', 'w'
)
assert file_mock.write.call_args_list == [
call('search --fs-uuid --set=root 0815\n'),
call('set prefix=($root)//grub2\n'),
call('search --fs-uuid --set=root 0815\n'),
call('set prefix=($root)//grub2\n')
]
@ -331,16 +328,12 @@ class TestBootLoaderConfigGrub2(object):
'cp', 'root_dir/usr/share/grub2/unicode.pf2',
'root_dir/boot/unicode.pf2'
]),
call([
'cp', '-a', 'root_dir/usr/lib/grub2/x86_64-efi',
'root_dir/boot/grub2/x86_64-efi'
]),
call([
'grub2-mkimage', '-O', 'x86_64-efi',
'-o', 'root_dir/boot/efi/EFI/BOOT/bootx64.efi',
'-c', 'root_dir/boot/efi/EFI/BOOT/earlyboot.cfg',
'-p', '//grub2',
'-d', 'root_dir/boot/grub2/x86_64-efi',
'-d', 'root_dir/usr/lib/grub2/x86_64-efi',
'ext2', 'iso9660', 'linux', 'echo', 'configfile',
'search_label', 'search_fs_file', 'search', 'search_fs_uuid',
'ls', 'normal', 'gzio', 'png', 'fat', 'gettext', 'font',
@ -349,31 +342,21 @@ class TestBootLoaderConfigGrub2(object):
'efi_uga', 'linuxefi'
]),
call([
'cp', '-a', 'root_dir/usr/lib/grub2/i386-pc',
'root_dir/boot/grub2/i386-pc'
'rsync', '-za', 'root_dir/usr/lib/grub2/x86_64-efi/',
'root_dir/boot/grub2/x86_64-efi'
]),
call([
'grub2-mkimage', '-O', 'i386-pc',
'-o', 'root_dir/boot/grub2/i386-pc/core.img',
'-c', 'root_dir/boot/grub2/earlyboot.cfg',
'-p', '//grub2',
'-d', 'root_dir/boot/grub2/i386-pc',
'ext2', 'iso9660', 'linux', 'echo', 'configfile',
'search_label', 'search_fs_file', 'search', 'search_fs_uuid',
'ls', 'normal', 'gzio', 'png', 'fat', 'gettext', 'font',
'minicmd', 'gfxterm', 'gfxmenu', 'video', 'video_fb',
'xfs', 'btrfs', 'lvm', 'multiboot', 'part_gpt',
'part_msdos', 'biosdisk', 'vga', 'vbe', 'chain',
'boot'
'rsync', '-za', 'root_dir/usr/lib/grub2/i386-pc/',
'root_dir/boot/grub2/i386-pc'
])
]
@patch('kiwi.bootloader_config_grub2.Command.run')
@patch('builtins.open')
#@patch('builtins.open')
@patch('os.path.exists')
@patch('platform.machine')
def test_setup_disk_boot_images_xen_guest(
self, mock_machine, mock_exists, mock_open, mock_command
self, mock_machine, mock_exists, mock_command
):
mock_machine.return_value = 'x86_64'
self.firmware.efi_mode = mock.Mock(
@ -386,49 +369,22 @@ class TestBootLoaderConfigGrub2(object):
return self.os_exists[arg]
mock_exists.side_effect = side_effect
context_manager_mock = mock.Mock()
mock_open.return_value = context_manager_mock
file_mock = mock.Mock()
enter_mock = mock.Mock()
exit_mock = mock.Mock()
enter_mock.return_value = file_mock
setattr(context_manager_mock, '__enter__', enter_mock)
setattr(context_manager_mock, '__exit__', exit_mock)
self.bootloader.setup_disk_boot_images('0815')
mock_open.assert_called_once_with(
'root_dir/boot/grub2/earlyboot.cfg', 'w'
)
assert file_mock.write.call_args_list == [
call('search --fs-uuid --set=root 0815\n'),
call('set prefix=($root)//grub2\n'),
]
assert mock_command.call_args_list == [
call([
'cp', 'root_dir/usr/share/grub2/unicode.pf2',
'root_dir/boot/unicode.pf2'
]),
call([
'cp', '-a', 'root_dir/usr/lib/grub2/i386-pc',
'rsync', '-za', 'root_dir/usr/lib/grub2/i386-pc/',
'root_dir/boot/grub2/i386-pc'
]),
call([
'cp', '-a', 'root_dir/usr/lib/grub2/x86_64-xen',
'root_dir/boot/grub2/x86_64-xen'
]),
call([
'grub2-mkimage', '-O', 'i386-pc',
'-o', 'root_dir/boot/grub2/i386-pc/core.img',
'-c', 'root_dir/boot/grub2/earlyboot.cfg',
'-p', '//grub2',
'-d', 'root_dir/boot/grub2/i386-pc',
'ext2', 'iso9660', 'linux', 'echo', 'configfile',
'search_label', 'search_fs_file', 'search', 'search_fs_uuid',
'ls', 'normal', 'gzio', 'png', 'fat', 'gettext', 'font',
'minicmd', 'gfxterm', 'gfxmenu', 'video', 'video_fb', 'xfs',
'btrfs', 'lvm', 'multiboot', 'part_gpt', 'part_msdos',
'biosdisk', 'vga', 'vbe', 'chain', 'boot'
])
'rsync', '-za', 'root_dir/usr/lib/grub2/x86_64-xen/',
'root_dir/boot/grub2/x86_64-xen']
)
]
@patch('kiwi.bootloader_config_grub2.Command.run')
@ -496,16 +452,12 @@ class TestBootLoaderConfigGrub2(object):
'cp', 'root_dir/usr/share/grub2/unicode.pf2',
'root_dir/boot/unicode.pf2'
]),
call([
'cp', '-a', 'root_dir/usr/lib/grub2/x86_64-efi',
'root_dir/boot/grub2/x86_64-efi'
]),
call([
'grub2-mkimage', '-O', 'x86_64-efi',
'-o', 'root_dir//EFI/BOOT/bootx64.efi',
'-c', 'root_dir//EFI/BOOT/earlyboot.cfg',
'-p', '//grub2',
'-d', 'root_dir/boot/grub2/x86_64-efi',
'-d', 'root_dir/usr/lib/grub2/x86_64-efi',
'ext2', 'iso9660', 'linux', 'echo', 'configfile',
'search_label', 'search_fs_file', 'search', 'search_fs_uuid',
'ls', 'normal', 'gzio', 'png', 'fat', 'gettext', 'font',
@ -513,6 +465,10 @@ class TestBootLoaderConfigGrub2(object):
'btrfs', 'lvm', 'multiboot', 'part_gpt', 'efi_gop',
'efi_uga', 'linuxefi'
]),
call([
'rsync', '-za', 'root_dir/usr/lib/grub2/x86_64-efi/',
'root_dir/boot/grub2/x86_64-efi'
]),
call([
'qemu-img', 'create', 'root_dir/boot/x86_64/efi', '4M'
]),
@ -574,7 +530,7 @@ class TestBootLoaderConfigGrub2(object):
mock_exists.side_effect = side_effect
self.bootloader.setup_install_boot_images(self.mbrid)
assert mock_command.call_args_list[0] == call([
'rsync', '-zav',
'rsync', '-za',
'root_dir/usr/share/grub2/themes/some-theme',
'root_dir/boot/grub2/themes'
])

View File

@ -3,64 +3,106 @@ from mock import patch
from mock import call
import mock
import kiwi
from . import nose_helper
from kiwi.exceptions import *
from kiwi.bootloader_install_grub2 import BootLoaderInstallGrub2
from kiwi.defaults import Defaults
class TestBootLoaderInstallGrub2(object):
def setup(self):
@patch('kiwi.bootloader_install_grub2.mkdtemp')
def setup(self, mock_mkdtemp):
tmpdirs = ['tmp_boot', 'tmp_root']
def side_effect():
return tmpdirs.pop()
mock_mkdtemp.side_effect = side_effect
device_provider = mock.Mock()
device_provider.get_device = mock.Mock(
return_value='/dev/some-device'
)
self.path = mock.Mock()
kiwi.bootloader_install_grub2.Path = self.path
self.bootloader = BootLoaderInstallGrub2(
'root_dir', device_provider
'root_dir', device_provider, {
'boot_device': '/dev/mapper/loop0p2',
'root_device': '/dev/mapper/loop0p1'
}
)
assert self.bootloader.mountpoint_root == 'tmp_root'
assert self.bootloader.mountpoint_boot == 'tmp_boot'
assert self.bootloader.extra_boot_partition is True
def test_post_init(self):
self.bootloader.post_init(None)
assert self.bootloader.temporary_boot_dir is None
@raises(KiwiBootLoaderGrubInstallError)
def test_post_init_no_boot_device(self):
self.bootloader.post_init({})
@raises(KiwiBootLoaderGrubInstallError)
def test_post_init_no_root_device(self):
self.bootloader.post_init({'boot_device': 'a'})
@patch('builtins.open')
@patch('kiwi.bootloader_install_grub2.Command.run')
@patch('kiwi.bootloader_install_grub2.mkdtemp')
@patch('kiwi.bootloader_install_grub2.NamedTemporaryFile')
def test_install(self, mock_tmpfile, mock_mkdtemp, mock_command, mock_open):
mock_mkdtemp.return_value = 'tmpdir'
tmpfile = mock.Mock()
tmpfile.name = 'tmpfile'
mock_tmpfile.return_value = tmpfile
context_manager_mock = mock.Mock()
mock_open.return_value = context_manager_mock
file_mock = mock.Mock()
enter_mock = mock.Mock()
exit_mock = mock.Mock()
enter_mock.return_value = file_mock
setattr(context_manager_mock, '__enter__', enter_mock)
setattr(context_manager_mock, '__exit__', exit_mock)
def test_install_with_extra_boot_partition(self, mock_command):
self.bootloader.install()
mock_open.assert_called_once_with('tmpfile', 'w')
file_mock.write.assert_called_once_with(
'(hd0) /dev/some-device\n'
)
assert mock_command.call_args_list == [
call(['cp', '-a', 'root_dir/boot/', 'tmpdir']),
call(['mount', '/dev/mapper/loop0p2', 'tmp_boot']),
call(['mount', '/dev/mapper/loop0p1', 'tmp_root']),
call([
'grub2-bios-setup', '-f',
'-d', 'tmpdir/boot/grub2/i386-pc',
'-m', 'tmpfile',
'grub2-install', '--skip-fs-probe',
'--directory', 'tmp_root/usr/lib/grub2/i386-pc',
'--boot-directory', 'tmp_boot',
'--target', 'i386-pc',
'--modules', ' '.join(Defaults.get_grub_bios_modules()),
'/dev/some-device'
])
]
@patch('kiwi.bootloader_install_grub2.Path.wipe')
def test_desstructor(self, mock_wipe):
self.bootloader.temporary_boot_dir = 'tmpdir'
@patch('kiwi.bootloader_install_grub2.Command.run')
def test_install(self, mock_command):
self.bootloader.extra_boot_partition = False
self.bootloader.install()
assert mock_command.call_args_list == [
call(['mount', '/dev/mapper/loop0p1', 'tmp_root']),
call([
'grub2-install', '--skip-fs-probe',
'--directory', 'tmp_root/usr/lib/grub2/i386-pc',
'--boot-directory', 'tmp_root/boot',
'--target', 'i386-pc',
'--modules', ' '.join(Defaults.get_grub_bios_modules()),
'/dev/some-device'
])
]
@patch('kiwi.bootloader_install_grub2.Command.run')
@patch('kiwi.logger.log.warning')
@patch('time.sleep')
def test_desstructor(self, mock_sleep, mock_warn, mock_command):
command_return_values = [False, False, False, True, True, True]
def side_effect(arg):
if not command_return_values.pop():
raise Exception
mock_command.side_effect = side_effect
self.bootloader.__del__()
mock_wipe.assert_called_once_with('tmpdir')
self.bootloader.temporary_boot_dir = None
self.path.remove.assert_called_once_with('tmp_root')
assert mock_command.call_args_list == [
call(['mountpoint', 'tmp_root']),
call(['umount', 'tmp_root']),
call(['mountpoint', 'tmp_boot']),
call(['umount', 'tmp_boot']),
call(['umount', 'tmp_boot']),
call(['umount', 'tmp_boot'])
]
@patch('kiwi.bootloader_install_grub2.Command.run')
def test_desstructor_nothing_mounted(self, mock_command):
mock_command.side_effect = Exception
self.bootloader.__del__()
assert mock_command.call_args_list == [
call(['mountpoint', 'tmp_root']),
call(['mountpoint', 'tmp_boot'])
]

View File

@ -354,12 +354,16 @@ class TestDiskBuilder(object):
@patch('kiwi.disk_builder.VolumeManager')
@patch('builtins.open')
@patch('kiwi.disk_builder.Command.run')
@patch('os.path.exists')
def test_create_volume_managed_root(
self, mock_command, mock_open, mock_volume_manager, mock_fs
self, mock_exists, mock_command, mock_open, mock_volume_manager, mock_fs
):
mock_exists.return_value = True
volume_manager = mock.Mock()
volume_manager.get_device = mock.Mock(
return_value={'root': '/dev/systemVG/LVRoot'}
return_value={
'root': MappedDevice('/dev/systemVG/LVRoot', mock.Mock())
}
)
mock_volume_manager.return_value = volume_manager
filesystem = mock.Mock()