diff --git a/kiwi/bootloader_config.py b/kiwi/bootloader_config.py
index 3a18113c..f91805ad 100644
--- a/kiwi/bootloader_config.py
+++ b/kiwi/bootloader_config.py
@@ -17,6 +17,7 @@
#
# project
from bootloader_config_grub2 import BootLoaderConfigGrub2
+from bootloader_config_isolinux import BootLoaderConfigIsoLinux
from exceptions import (
KiwiBootLoaderConfigSetupError
@@ -33,6 +34,10 @@ class BootLoaderConfig(object):
return BootLoaderConfigGrub2(
xml_state, source_dir
)
+ elif name == 'isolinux':
+ return BootLoaderConfigIsoLinux(
+ xml_state, source_dir
+ )
else:
raise KiwiBootLoaderConfigSetupError(
'Support for %s bootloader config not implemented' % name
diff --git a/kiwi/bootloader_config_grub2.py b/kiwi/bootloader_config_grub2.py
index fac4f97e..ff0ac4a8 100644
--- a/kiwi/bootloader_config_grub2.py
+++ b/kiwi/bootloader_config_grub2.py
@@ -200,7 +200,7 @@ class BootLoaderConfigGrub2(BootLoaderConfigBase):
self.source_dir + '/boot/mbrid'
)
- self.__copy_unicode_font_to_boot_directory(lookup_path)
+ self.__copy_theme_data_to_boot_directory(lookup_path)
if self.firmware.efi_mode() == 'uefi':
log.info('--> Using signed secure boot efi image')
@@ -226,7 +226,7 @@ class BootLoaderConfigGrub2(BootLoaderConfigBase):
if self.firmware.efi_mode():
self.efi_boot_path = self.create_efi_path()
- self.__copy_unicode_font_to_boot_directory(lookup_path)
+ self.__copy_theme_data_to_boot_directory(lookup_path)
if self.firmware.efi_mode() == 'efi':
log.info('--> Creating unsigned efi image')
@@ -468,11 +468,11 @@ class BootLoaderConfigGrub2(BootLoaderConfigBase):
selected_gfxmode = gfxmode[requested_gfxmode]
return selected_gfxmode
- def __copy_unicode_font_to_boot_directory(self, lookup_path):
+ def __copy_theme_data_to_boot_directory(self, lookup_path):
+ if not lookup_path:
+ lookup_path = self.source_dir
boot_unicode_font = self.source_dir + '/boot/unicode.pf2'
if not os.path.exists(boot_unicode_font):
- if not lookup_path:
- lookup_path = self.source_dir
unicode_font = lookup_path + '/usr/share/grub2/unicode.pf2'
try:
Command.run(
@@ -483,6 +483,18 @@ class BootLoaderConfigGrub2(BootLoaderConfigBase):
'Unicode font %s not found' % unicode_font
)
+ boot_theme_dir = self.source_dir + '/boot/grub2/themes'
+ if self.theme and not os.path.exists(boot_theme_dir):
+ Path.create(boot_theme_dir)
+ theme_dir = \
+ lookup_path + '/usr/share/grub2/themes/' + self.theme
+ if os.path.exists(theme_dir):
+ Command.run(
+ ['rsync', '-zav', theme_dir, boot_theme_dir],
+ )
+ else:
+ log.warning('Theme %s not found', theme_dir)
+
def __copy_efi_modules_to_boot_directory(self, lookup_path):
self.__copy_modules_to_boot_directory_from(
self.__get_efi_modules_path(lookup_path)
diff --git a/kiwi/bootloader_config_isolinux.py b/kiwi/bootloader_config_isolinux.py
new file mode 100644
index 00000000..f4779302
--- /dev/null
+++ b/kiwi/bootloader_config_isolinux.py
@@ -0,0 +1,155 @@
+# Copyright (c) 2015 SUSE Linux GmbH. All rights reserved.
+#
+# This file is part of kiwi.
+#
+# kiwi is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# kiwi is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with kiwi. If not, see
+#
+import os
+import platform
+
+# project
+from logger import log
+from bootloader_config_base import BootLoaderConfigBase
+from bootloader_template_isolinux import BootLoaderTemplateIsoLinux
+from command import Command
+from path import Path
+
+from exceptions import (
+ KiwiTemplateError,
+ KiwiBootLoaderIsoLinuxPlatformError
+)
+
+
+class BootLoaderConfigIsoLinux(BootLoaderConfigBase):
+ """
+ isolinux bootloader configuration.
+ """
+ def post_init(self):
+ arch = platform.machine()
+ if arch == 'x86_64':
+ self.arch = arch
+ else:
+ raise KiwiBootLoaderIsoLinuxPlatformError(
+ 'host architecture %s not supported for isolinux setup' % arch
+ )
+
+ self.gfxmode = self.xml_state.build_type.get_vga()
+ self.timeout = self.get_boot_timeout_seconds()
+ self.cmdline = self.get_boot_cmdline()
+ self.cmdline_failsafe = self.get_failsafe_boot_cmdline()
+ self.failsafe_boot = self.failsafe_boot_entry_requested()
+ self.hypervisor_domain = self.get_hypervisor_domain()
+
+ self.multiboot = False
+ if self.hypervisor_domain:
+ if self.hypervisor_domain == 'dom0':
+ self.multiboot = True
+ elif self.hypervisor_domain == 'domU':
+ self.multiboot = False
+
+ self.isolinux = BootLoaderTemplateIsoLinux()
+ self.config = None
+ self.config_message = None
+
+ def write(self):
+ """
+ Write isolinux.cfg and isolinux.msg file
+ """
+ log.info('Writing isolinux.cfg file')
+ config_dir = self.__get_iso_boot_path()
+ config_file = config_dir + '/isolinux.cfg'
+ if self.config:
+ Path.create(config_dir)
+ with open(config_file, 'w') as config:
+ config.write(self.config)
+
+ config_file_message = config_dir + '/isolinux.msg'
+ if self.config_message:
+ with open(config_file_message, 'w') as config:
+ config.write(self.config_message)
+
+ def setup_install_image_config(
+ self, mbrid, hypervisor='xen.gz', kernel='linux', initrd='initrd'
+ ):
+ """
+ Create isolinux.cfg in memory from a template suitable to boot
+ from an ISO image in BIOS boot mode
+ """
+ # mbrid parameter is not used, the information is placed as the
+ # application id when creating the iso filesystem. Thus not part
+ # of the configuration file
+ log.info('Creating install config file from template')
+ parameters = {
+ 'default_boot': 'Boot_from_Hard_Disk',
+ 'kernel_file': kernel,
+ 'initrd_file': initrd,
+ 'boot_options': self.cmdline,
+ 'failsafe_boot_options': self.cmdline_failsafe,
+ 'gfxmode': self.gfxmode,
+ 'boot_timeout': self.timeout,
+ 'title': self.get_menu_entry_install_title()
+ }
+ if self.multiboot:
+ log.info('--> Using multiboot install template')
+ parameters['hypervisor'] = hypervisor
+ template = self.isolinux.get_multiboot_install_template(
+ self.failsafe_boot, self.__have_theme()
+ )
+ else:
+ log.info('--> Using install template')
+ template = self.isolinux.get_install_template(
+ self.failsafe_boot, self.__have_theme()
+ )
+ try:
+ self.config = template.substitute(parameters)
+ template = self.isolinux.get_install_message_template()
+ self.config_message = template.substitute(parameters)
+ except Exception as e:
+ raise KiwiTemplateError(
+ '%s: %s' % (type(e).__name__, format(e))
+ )
+
+ def setup_live_image_config(
+ self, mbrid, hypervisor='xen.gz', kernel='linux', initrd='initrd'
+ ):
+ # TODO
+ pass
+
+ def setup_install_boot_images(self, mbrid, lookup_path=None):
+ # mbrid parameter is not used, because only isolinux loader
+ # binary and possible theming files are copied
+ self.__copy_loader_data_to_boot_directory(lookup_path)
+
+ def setup_live_boot_images(self, mbrid, lookup_path=None):
+ # same action as for install media
+ self.setup_install_boot_images(None, lookup_path)
+
+ def __copy_loader_data_to_boot_directory(self, lookup_path):
+ if not lookup_path:
+ lookup_path = self.source_dir
+ loader_data = lookup_path + '/image/loader/'
+ Path.create(self.__get_iso_boot_path())
+ Command.run(
+ [
+ 'rsync', '-zav', loader_data, self.__get_iso_boot_path()
+ ]
+ )
+
+ def __get_iso_boot_path(self):
+ return self.source_dir + '/boot/' + self.arch + '/loader'
+
+ def __have_theme(self):
+ if os.path.exists(self.__get_iso_boot_path() + '/bootlogo'):
+ return True
+ return False
diff --git a/kiwi/bootloader_template_grub2.py b/kiwi/bootloader_template_grub2.py
index 09ac4f66..59027189 100644
--- a/kiwi/bootloader_template_grub2.py
+++ b/kiwi/bootloader_template_grub2.py
@@ -45,25 +45,20 @@ class BootLoaderTemplateGrub2(object):
''').strip() + self.cr
self.header_gfxterm = dedent('''
- set font=($$root)${bootpath}/unicode.pf2
- if loadfont $$font ;then
- set gfxmode=${gfxmode}
- insmod all_video
- insmod gfxterm
- terminal_output gfxterm
- fi
+ set gfxmode=${gfxmode}
+ insmod all_video
+ insmod gfxterm
+ terminal_output gfxterm
''').strip() + self.cr
self.header_serial = dedent('''
- set font=${bootpath}/unicode.pf2
- if loadfont $$font ;then
- serial --speed=9600 --unit=0 --word=8 --parity=no --stop=1
- terminal_input serial
- terminal_output serial
- fi
+ serial --speed=9600 --unit=0 --word=8 --parity=no --stop=1
+ terminal_input serial
+ terminal_output serial
''').strip() + self.cr
self.header_theme = dedent('''
+ set font=($$root)${bootpath}/unicode.pf2
if loadfont ($$root)${bootpath}/grub2/themes/${theme}/ascii.pf2;then
loadfont ($$root)${bootpath}/grub2/themes/${theme}/DejaVuSans-Bold14.pf2
loadfont ($$root)${bootpath}/grub2/themes/${theme}/DejaVuSans10.pf2
@@ -73,6 +68,17 @@ class BootLoaderTemplateGrub2(object):
fi
''').strip() + self.cr
+ self.header_theme_iso = dedent('''
+ set font=($$root)/boot/unicode.pf2
+ if loadfont ($$root)/boot/grub2/themes/${theme}/ascii.pf2;then
+ loadfont ($$root)/boot/grub2/themes/${theme}/DejaVuSans-Bold14.pf2
+ loadfont ($$root)/boot/grub2/themes/${theme}/DejaVuSans10.pf2
+ loadfont ($$root)/boot/grub2/themes/${theme}/DejaVuSans12.pf2
+ loadfont ($$root)/boot/grub2/themes/${theme}/ascii.pf2
+ set theme=($$root)/boot/grub2/themes/${theme}/theme.txt
+ fi
+ ''').strip() + self.cr
+
self.menu_entry_hybrid = dedent('''
menuentry "${title}" --class os {
echo Loading kernel...
@@ -263,7 +269,7 @@ class BootLoaderTemplateGrub2(object):
template_data += self.header_gfxterm
else:
template_data += self.header_serial
- template_data += self.header_theme
+ template_data += self.header_theme_iso
template_data += self.menu_install_harddisk_entry
if hybrid:
template_data += self.menu_install_entry_hybrid
@@ -287,7 +293,7 @@ class BootLoaderTemplateGrub2(object):
template_data += self.header_gfxterm
else:
template_data += self.header_serial
- template_data += self.header_theme
+ template_data += self.header_theme_iso
template_data += self.menu_install_harddisk_entry
template_data += self.menu_install_entry_multiboot
if failsafe:
diff --git a/kiwi/bootloader_template_isolinux.py b/kiwi/bootloader_template_isolinux.py
new file mode 100644
index 00000000..d54edebd
--- /dev/null
+++ b/kiwi/bootloader_template_isolinux.py
@@ -0,0 +1,165 @@
+# Copyright (c) 2015 SUSE Linux GmbH. All rights reserved.
+#
+# This file is part of kiwi.
+#
+# kiwi is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# kiwi is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with kiwi. If not, see
+#
+from string import Template
+from textwrap import dedent
+
+
+class BootLoaderTemplateIsoLinux(object):
+ """
+ isolinux configuraton file templates
+ """
+ def __init__(self):
+ self.cr = '\n'
+
+ self.install_message = dedent('''
+ Welcome !
+
+ Boot_from_Hard_Disk
+ Install_${title}
+ Failsafe_--_Install_${title}
+
+
+ Have a lot of fun...
+ ''').strip() + self.cr
+
+ self.message = dedent('''
+ Welcome !
+
+ ${title}
+ Failsafe_${title}
+
+
+ Have a lot of fun...
+ ''').strip() + self.cr
+
+ self.header = dedent('''
+ # kiwi generated isolinux config file
+ implicit 1
+ prompt 1
+ timeout ${boot_timeout}
+ display isolinux.msg
+ default ${default_boot}
+ ui gfxboot bootlogo isolinux.msg
+ ''').strip() + self.cr
+
+ self.ui_theme = dedent('''
+ ui gfxboot bootlogo isolinux.msg
+ ''').strip() + self.cr
+
+ self.ui_plain = dedent('''
+ ui menu.c32
+ ''').strip() + self.cr
+
+ self.menu_install_harddisk_entry = dedent('''
+ label Boot_from_Hard_Disk
+ localboot 0x80
+ ''').strip() + self.cr
+
+ self.menu_install_entry_multiboot = dedent('''
+ label Install_${title}
+ kernel mboot.c32
+ append ${hypervisor} --- ${kernel_file} vga=${gfxmode} ${boot_options} cdinst=1 kiwi_hybrid=1 showopts --- ${initrd_file} showopts
+ ''').strip() + self.cr
+
+ self.menu_install_entry_failsafe_multiboot = dedent('''
+ label Failsafe_--_Install_${title}
+ kernel mboot.c32
+ append ${hypervisor} --- ${kernel_file} vga=${gfxmode} ${failsafe_boot_options} cdinst=1 kiwi_hybrid=1 showopts --- ${initrd_file} showopts
+ ''').strip() + self.cr
+
+ self.menu_entry_multiboot = dedent('''
+ label ${title}
+ kernel mboot.c32
+ append ${hypervisor} --- ${kernel_file} vga=${gfxmode} ${boot_options} cdinst=1 kiwi_hybrid=1 showopts --- ${initrd_file} showopts
+ ''').strip() + self.cr
+
+ self.menu_entry_failsafe_multiboot = dedent('''
+ label Failsafe_--_${title}
+ kernel mboot.c32
+ append ${hypervisor} --- ${kernel_file} vga=${gfxmode} ${failsafe_boot_options} cdinst=1 kiwi_hybrid=1 showopts --- ${initrd_file} showopts
+ ''').strip() + self.cr
+
+ self.menu_install_entry = dedent('''
+ label Install_${title}
+ kernel ${kernel_file}
+ append initrd=${initrd_file} vga=${gfxmode} ${boot_options} cdinst=1 kiwi_hybrid=1 showopts
+ ''').strip() + self.cr
+
+ self.menu_install_entry_failsafe = dedent('''
+ label Failsafe_--_Install_${title}
+ kernel ${kernel_file}
+ append initrd=${initrd_file} vga=${gfxmode} ${failsafe_boot_options} cdinst=1 kiwi_hybrid=1 showopts
+ ''').strip() + self.cr
+
+ self.menu_entry = dedent('''
+ label ${title}
+ kernel ${kernel_file}
+ append initrd=${initrd_file} vga=${gfxmode} ${boot_options} cdinst=1 kiwi_hybrid=1 showopts
+ ''').strip() + self.cr
+
+ self.menu_entry_failsafe = dedent('''
+ label Failsafe_--_${title}
+ kernel ${kernel_file}
+ append initrd=${initrd_file} vga=${gfxmode} ${failsafe_boot_options} cdinst=1 kiwi_hybrid=1 showopts
+ ''').strip() + self.cr
+
+ def get_install_message_template(self):
+ """
+ bootloader template for text message file in install mode.
+ isolinux displays this as menu if no graphics mode can be
+ initialized
+ """
+ return Template(self.install_message)
+
+ def get_message_template(self):
+ """
+ bootloader template for text message file. isolinux
+ displays this as menu if no graphics mode can be initialized
+ """
+ return Template(self.message)
+
+ def get_install_template(self, failsafe=True, with_theme=True):
+ """
+ bootloader configuration template for install media
+ """
+ template_data = self.header
+ if with_theme:
+ self.ui_theme
+ else:
+ self.ui_plain
+ template_data += self.menu_install_harddisk_entry
+ template_data += self.menu_install_entry
+ if failsafe:
+ template_data += self.menu_install_entry_failsafe
+ return Template(template_data)
+
+ def get_multiboot_install_template(self, failsafe=True, with_theme=True):
+ """
+ bootloader configuration template for install media with
+ hypervisor, e.g Xen dom0
+ """
+ template_data = self.header
+ if with_theme:
+ self.ui_theme
+ else:
+ self.ui_plain
+ template_data += self.menu_install_harddisk_entry
+ template_data += self.menu_install_entry_multiboot
+ if failsafe:
+ template_data += self.menu_install_entry_failsafe_multiboot
+ return Template(template_data)
diff --git a/kiwi/command_process.py b/kiwi/command_process.py
index b3007014..00621b69 100644
--- a/kiwi/command_process.py
+++ b/kiwi/command_process.py
@@ -121,6 +121,10 @@ class CommandProcess(object):
result = namedtuple(
'result', ['stderr', 'returncode']
)
+ if watch:
+ log.debug(command_error_output)
+ else:
+ log.debug('%s: %s', self.log_topic, command_error_output)
return result(
stderr=command_error_output,
returncode=self.command.process.returncode
diff --git a/kiwi/exceptions.py b/kiwi/exceptions.py
index 5d4704fc..ea6c31a2 100644
--- a/kiwi/exceptions.py
+++ b/kiwi/exceptions.py
@@ -29,10 +29,6 @@ class KiwiError(Exception):
return format(self.message)
-class KiwiBootLoaderTargetError(KiwiError):
- pass
-
-
class KiwiBootLoaderConfigSetupError(KiwiError):
pass
@@ -57,6 +53,14 @@ class KiwiBootLoaderInstallSetupError(KiwiError):
pass
+class KiwiBootLoaderIsoLinuxPlatformError(KiwiError):
+ pass
+
+
+class KiwiBootLoaderTargetError(KiwiError):
+ pass
+
+
class KiwiBootStrapPhaseFailed(KiwiError):
pass
@@ -129,6 +133,10 @@ class KiwiInvalidVolumeName(KiwiError):
pass
+class KiwiIsoLoaderError(KiwiError):
+ pass
+
+
class KiwiLoadCommandUndefined(KiwiError):
pass
diff --git a/kiwi/filesystem_isofs.py b/kiwi/filesystem_isofs.py
new file mode 100644
index 00000000..023394be
--- /dev/null
+++ b/kiwi/filesystem_isofs.py
@@ -0,0 +1,41 @@
+# Copyright (c) 2015 SUSE Linux GmbH. All rights reserved.
+#
+# This file is part of kiwi.
+#
+# kiwi is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# kiwi is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with kiwi. If not, see
+#
+# project
+from iso import Iso
+from command import Command
+from filesystem_base import FileSystemBase
+
+
+class FileSystemIsoFs(FileSystemBase):
+ """
+ Implements creation of iso filesystem
+ """
+ def post_init(self, custom_args):
+ self.custom_args = custom_args
+
+ def create_on_file(self, filename, label=None):
+ # there is no label which could be set for an iso filesystem
+ # thus this parameter is not used
+ iso = Iso(self.source_dir)
+ iso.init_iso_creation_parameters(self.custom_args)
+ iso.add_efi_loader_parameters()
+ Command.run(
+ ['genisoimage'] + iso.get_iso_creation_parameters() + [
+ '-o', filename, self.source_dir
+ ]
+ )
diff --git a/kiwi/install_image_builder.py b/kiwi/install_image_builder.py
index 1873a317..3b70a6e4 100644
--- a/kiwi/install_image_builder.py
+++ b/kiwi/install_image_builder.py
@@ -22,6 +22,7 @@ import os
from command import Command
from bootloader_config import BootLoaderConfig
from filesystem_squashfs import FileSystemSquashFs
+from filesystem_isofs import FileSystemIsoFs
from image_identifier import ImageIdentifier
from path import Path
from checksum import Checksum
@@ -42,11 +43,21 @@ class InstallImageBuilder(object):
):
self.target_dir = target_dir
self.disk_image = disk_image
+ self.machine = xml_state.get_build_type_machine_section()
self.boot_image_task = boot_image_task
self.xml_state = xml_state
+ self.isoname = ''.join(
+ [
+ target_dir, '/',
+ xml_state.xml_data.get_name(), '.install.iso'
+ ]
+ )
+
self.mbrid = ImageIdentifier()
self.mbrid.calculate_id()
+
self.media_dir = None
+ self.custom_iso_args = None
def create_install_iso(self):
"""
@@ -56,6 +67,12 @@ class InstallImageBuilder(object):
self.media_dir = mkdtemp(
prefix='install-media.', dir=self.target_dir
)
+ # custom iso metadata
+ self.custom_iso_args = [
+ '-V', '"KIWI Installation System"',
+ '-A', self.mbrid.get_id()
+ ]
+
# the install image transfer is checked against a checksum
log.info('Creating disk image checksum')
checksum = Checksum(self.disk_image)
@@ -77,26 +94,43 @@ class InstallImageBuilder(object):
['mv', squashed_image_file, self.media_dir]
)
+ # setup bootloader config to boot the ISO via isolinux
+ bootloader_config_isolinux = BootLoaderConfig.new(
+ 'isolinux', self.xml_state, self.media_dir
+ )
+ bootloader_config_isolinux.setup_install_boot_images(
+ mbrid=None,
+ lookup_path=self.boot_image_task.boot_root_directory
+ )
+ bootloader_config_isolinux.setup_install_image_config(
+ mbrid=None
+ )
+ bootloader_config_isolinux.write()
+
# setup bootloader config to boot the ISO via EFI
- self.bootloader_config_grub = BootLoaderConfig.new(
+ bootloader_config_grub = BootLoaderConfig.new(
'grub2', self.xml_state, self.media_dir
)
- self.bootloader_config_grub.setup_install_boot_images(
+ bootloader_config_grub.setup_install_boot_images(
mbrid=self.mbrid,
lookup_path=self.boot_image_task.boot_root_directory
)
- self.bootloader_config_grub.setup_install_image_config(
- self.mbrid
+ bootloader_config_grub.setup_install_image_config(
+ mbrid=self.mbrid
)
- self.bootloader_config_grub.write()
-
- # setup bootloader config to boot the ISO via isolinux
- # TODO
+ bootloader_config_grub.write()
+ # create initrd for install image
self.__create_iso_install_kernel_and_initrd()
# TODO
# create iso filesystem from self.media_dir and make it hybrid
+ iso_image = FileSystemIsoFs(
+ device_provider=None,
+ source_dir=self.media_dir,
+ custom_args=self.custom_iso_args
+ )
+ iso_image.create_on_file(self.isoname)
def create_install_pxe_archive(self):
# TODO
@@ -113,7 +147,14 @@ class InstallImageBuilder(object):
'No kernel in boot image tree %s found' %
self.boot_image_task.boot_root_directory
)
- # TODO: for xen dom0 boot the hypervisor needs to be copied too
+ if self.machine and self.machine.get_domain() == 'dom0':
+ if kernel.get_xen_hypervisor():
+ kernel.copy_xen_hypervisor(boot_path, '/xen.gz')
+ else:
+ raise KiwiInstallBootImageError(
+ 'No hypervisor in boot image tree %s found' %
+ self.boot_image_task.boot_root_directory
+ )
self.boot_image_task.create_initrd(self.mbrid)
Command.run(
[
@@ -133,6 +174,6 @@ class InstallImageBuilder(object):
iso_system.write('IMAGE="%s"\n' % diskname)
def __del__(self):
- # if self.media_dir:
- # Path.wipe(self.media_dir)
- pass
+ if self.media_dir:
+ log.info('Cleaning up %s instance', type(self).__name__)
+ Path.wipe(self.media_dir)
diff --git a/kiwi/internal_boot_image_task.py b/kiwi/internal_boot_image_task.py
index 7a848b1a..e47a6b2f 100644
--- a/kiwi/internal_boot_image_task.py
+++ b/kiwi/internal_boot_image_task.py
@@ -157,9 +157,6 @@ class BootImageTask(object):
compress = Compress(initrd_file_name)
compress.xz()
self.initrd_filename = compress.compressed_filename
- log.info(
- '--> created %s', self.initrd_filename
- )
def __import_system_description_elements(self):
self.xml_state.copy_displayname(
diff --git a/kiwi/iso.py b/kiwi/iso.py
new file mode 100644
index 00000000..535eefed
--- /dev/null
+++ b/kiwi/iso.py
@@ -0,0 +1,114 @@
+# Copyright (c) 2015 SUSE Linux GmbH. All rights reserved.
+#
+# This file is part of kiwi.
+#
+# kiwi is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# kiwi is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with kiwi. If not, see
+#
+import os
+import platform
+from tempfile import NamedTemporaryFile
+
+# project
+from command import Command
+from exceptions import (
+ KiwiIsoLoaderError
+)
+
+
+class Iso(object):
+ """
+ Implements helper methods around the creation of an iso filesystem
+ """
+ def __init__(self, source_dir):
+ self.header_id = '7984fc91-a43f-4e45-bf27-6d3aa08b24cf'
+ self.header_end_name = 'header_end'
+ self.arch = platform.machine()
+ self.source_dir = source_dir
+ self.boot_path = 'boot/' + self.arch
+ self.iso_sortfile = NamedTemporaryFile()
+ self.iso_parameters = []
+ self.iso_loaders = []
+
+ def init_iso_creation_parameters(self, custom_args=None):
+ loader_file = self.boot_path + '/loader/isolinux.bin'
+ catalog_file = self.boot_path + '/boot.catalog'
+ with open(self.source_dir + '/' + self.header_end_name, 'w') as marker:
+ marker.write('%s\n' % self.header_id)
+ if not os.path.exists(self.source_dir + '/' + loader_file):
+ raise KiwiIsoLoaderError(
+ 'No isolinux loader found in %s' %
+ self.source_dir + '/loader'
+ )
+ if custom_args:
+ self.iso_parameters = custom_args
+ self.iso_parameters += [
+ '-R', '-J', '-f', '-pad', '-joliet-long',
+ '-sort', self.iso_sortfile.name,
+ '-no-emul-boot', '-boot-load-size', '4', '-boot-info-table',
+ '-hide', catalog_file,
+ '-hide-joliet', catalog_file,
+ ]
+ self.iso_loaders += [
+ '-b', loader_file, '-c', catalog_file
+ ]
+ Command.run(
+ [
+ 'isolinux-config', '--base', self.boot_path + '/loader',
+ self.source_dir + '/' + loader_file
+ ]
+ )
+ self.__create_sortfile()
+
+ def add_efi_loader_parameters(self):
+ loader_file = self.boot_path + '/efi'
+ if os.path.exists(self.source_dir + '/' + loader_file):
+ self.iso_loaders += [
+ '-eltorito-alt-boot', '-b', loader_file,
+ '-no-emul-boot', '-joliet-long'
+ ]
+
+ def get_iso_creation_parameters(self):
+ return self.iso_parameters + self.iso_loaders
+
+ def add_iso_header_end_marker(self):
+ # TODO: see the glump file creation in the old kiwi
+ pass
+
+ def relocate_boot_catalog(self, isofile):
+ # TODO
+ pass
+
+ def fix_boot_catalog(self, isofile):
+ # TODO
+ pass
+
+ def __create_sortfile(self):
+ catalog_file = \
+ self.source_dir + '/' + self.boot_path + '/boot.catalog'
+ loader_file = \
+ self.source_dir + '/' + self.boot_path + '/loader/isolinux.bin'
+ with open(self.iso_sortfile.name, 'w') as sortfile:
+ sortfile.write('%s 3\n' % catalog_file)
+ sortfile.write('%s 2\n' % loader_file)
+
+ for basedir, dirnames, filenames in os.walk(self.source_dir):
+ for filename in filenames:
+ if filename == 'efi':
+ sortfile.write('%s/%s 1000001\n' % (basedir, filename))
+ elif filename == self.header_end_name:
+ sortfile.write('%s/%s 1000000\n' % (basedir, filename))
+ else:
+ sortfile.write('%s/%s 1\n' % (basedir, filename))
+ for dirname in dirnames:
+ sortfile.write('%s/%s 1\n' % (basedir, dirname))
diff --git a/kiwi/system.py b/kiwi/system.py
index fe985eca..ad774274 100644
--- a/kiwi/system.py
+++ b/kiwi/system.py
@@ -300,15 +300,15 @@ class System(object):
self, manager, packages, collections=None, products=None
):
if packages:
- for package in packages:
+ for package in sorted(packages):
log.info('--> package: %s', package)
manager.request_package(package)
if collections:
- for collection in collections:
+ for collection in sorted(collections):
log.info('--> collection: %s', collection)
manager.request_collection(collection)
if products:
- for product in products:
+ for product in sorted(products):
log.info('--> product: %s', product)
manager.request_product(product)
return \
diff --git a/kiwi/system_create_task.py b/kiwi/system_create_task.py
index f7a73a71..646524aa 100644
--- a/kiwi/system_create_task.py
+++ b/kiwi/system_create_task.py
@@ -90,6 +90,10 @@ class SystemCreateTask(CliTask):
result.add(
'disk_image', disk.diskname
)
+ if disk.install_image.media_dir:
+ result.add(
+ 'installation_image', disk.install_image.isoname
+ )
elif requested_image_type in Defaults.get_live_image_types():
# TODO
raise KiwiNotImplementedError(
diff --git a/test/unit/bootloader_config_grub2_test.py b/test/unit/bootloader_config_grub2_test.py
index f8080a42..b8c6bbec 100644
--- a/test/unit/bootloader_config_grub2_test.py
+++ b/test/unit/bootloader_config_grub2_test.py
@@ -49,6 +49,10 @@ class TestBootLoaderConfigGrub2(object):
self.bootloader = BootLoaderConfigGrub2(
self.state, 'source_dir'
)
+ self.bootloader.get_hypervisor_domain = mock.Mock(
+ return_value='domU'
+ )
+ self.bootloader.theme = None
@raises(KiwiBootLoaderGrubPlatformError)
@patch('platform.machine')
@@ -56,13 +60,12 @@ class TestBootLoaderConfigGrub2(object):
mock_machine.return_value = 'unsupported-arch'
BootLoaderConfigGrub2(mock.Mock(), 'source_dir')
- @patch('kiwi.bootloader_config_base.BootLoaderConfigBase.get_hypervisor_domain')
@patch('os.path.exists')
- def test_post_init_dom0(self, mock_exists, mock_domain):
- mock_domain.return_value = 'dom0'
+ def test_post_init_dom0(self, mock_exists):
+ self.bootloader.get_hypervisor_domain.return_value = 'dom0'
mock_exists.return_value = True
self.bootloader.post_init()
- assert self.bootloader.hypervisor_domain == 'dom0'
+ assert self.bootloader.multiboot is True
@patch('__builtin__.open')
@patch('os.path.exists')
@@ -423,6 +426,39 @@ class TestBootLoaderConfigGrub2(object):
'source_dir//EFI/BOOT'
])
+ @patch('kiwi.bootloader_config_grub2.Command.run')
+ @patch('__builtin__.open')
+ @patch('os.path.exists')
+ @patch('kiwi.logger.log.warning')
+ def test_setup_install_boot_images_with_theme(
+ self, mock_warn, mock_exists, mock_open, mock_command
+ ):
+ self.bootloader.theme = 'some-theme'
+ exists_results = [False, True, False, False]
+
+ def side_effect(arg):
+ return exists_results.pop()
+
+ mock_exists.side_effect = side_effect
+ self.bootloader.setup_install_boot_images(self.mbrid)
+ assert mock_command.call_args_list[1] == call([
+ 'rsync', '-zav',
+ 'source_dir/usr/share/grub2/themes/some-theme',
+ 'source_dir/boot/grub2/themes'
+ ])
+
+ @patch('kiwi.bootloader_config_grub2.Command.run')
+ @patch('__builtin__.open')
+ @patch('os.path.exists')
+ @patch('kiwi.logger.log.warning')
+ def test_setup_install_boot_images_with_theme_not_existing(
+ self, mock_warn, mock_exists, mock_open, mock_command
+ ):
+ self.bootloader.theme = 'some-theme'
+ mock_exists.return_value = False
+ self.bootloader.setup_install_boot_images(self.mbrid)
+ assert mock_warn.called
+
def test_setup_live_image_config(self):
# TODO
self.bootloader.setup_live_image_config('mbrid')
diff --git a/test/unit/bootloader_config_isolinux_test.py b/test/unit/bootloader_config_isolinux_test.py
new file mode 100644
index 00000000..f806e42d
--- /dev/null
+++ b/test/unit/bootloader_config_isolinux_test.py
@@ -0,0 +1,139 @@
+from nose.tools import *
+from mock import patch
+from mock import call
+
+import mock
+
+import kiwi
+
+import nose_helper
+
+from kiwi.xml_state import XMLState
+from kiwi.xml_description import XMLDescription
+from kiwi.exceptions import *
+from kiwi.bootloader_config_isolinux import BootLoaderConfigIsoLinux
+
+
+class TestBootLoaderConfigIsoLinux(object):
+ @patch('os.path.exists')
+ @patch('platform.machine')
+ def setup(self, mock_machine, mock_exists):
+ mock_machine.return_value = 'x86_64'
+ mock_exists.return_value = True
+ description = XMLDescription(
+ '../data/example_config.xml'
+ )
+ self.state = XMLState(
+ description.load()
+ )
+ kiwi.bootloader_config_isolinux.Path = mock.Mock()
+ kiwi.bootloader_config_base.Path = mock.Mock()
+ self.isolinux = mock.Mock()
+ kiwi.bootloader_config_isolinux.BootLoaderTemplateIsoLinux = mock.Mock(
+ return_value=self.isolinux
+ )
+ self.bootloader = BootLoaderConfigIsoLinux(
+ self.state, 'source_dir'
+ )
+ self.bootloader.get_hypervisor_domain = mock.Mock(
+ return_value='domU'
+ )
+
+ @raises(KiwiBootLoaderIsoLinuxPlatformError)
+ @patch('platform.machine')
+ def test_post_init_invalid_platform(self, mock_machine):
+ mock_machine.return_value = 'unsupported-arch'
+ BootLoaderConfigIsoLinux(mock.Mock(), 'source_dir')
+
+ @patch('os.path.exists')
+ def test_post_init_dom0(self, mock_exists):
+ self.bootloader.get_hypervisor_domain.return_value = 'dom0'
+ mock_exists.return_value = True
+
+ self.bootloader.post_init()
+ assert self.bootloader.multiboot is True
+
+ @patch('__builtin__.open')
+ @patch('os.path.exists')
+ def test_write(self, mock_exists, mock_open):
+ mock_exists.return_value = True
+ 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.config = 'some-data'
+ self.bootloader.config_message = 'some-message-data'
+
+ self.bootloader.write()
+ assert mock_open.call_args_list == [
+ call('source_dir/boot/x86_64/loader/isolinux.cfg', 'w'),
+ call('source_dir/boot/x86_64/loader/isolinux.msg', 'w')
+ ]
+ assert file_mock.write.call_args_list == [
+ call('some-data'),
+ call('some-message-data')
+ ]
+
+ def test_setup_install_image_config(self):
+ template_cfg = mock.Mock()
+ template_msg = mock.Mock()
+ self.isolinux.get_install_template.return_value = template_cfg
+ self.isolinux.get_install_message_template.return_value = template_msg
+
+ self.bootloader.setup_install_image_config(mbrid=None)
+ self.isolinux.get_install_template.assert_called_once_with(True, False)
+ self.isolinux.get_install_message_template.assert_called_once_with()
+ assert template_cfg.substitute.called
+ assert template_msg.substitute.called
+
+ def test_setup_install_image_config_multiboot(self):
+ self.bootloader.multiboot = True
+
+ self.bootloader.setup_install_image_config(mbrid=None)
+ self.isolinux.get_multiboot_install_template.assert_called_once_with(
+ True, False
+ )
+
+ @patch('os.path.exists')
+ def test_setup_install_image_config_with_theme(self, mock_exists):
+ mock_exists.return_value = True
+
+ self.bootloader.setup_install_image_config(mbrid=None)
+ self.isolinux.get_install_template.assert_called_once_with(True, True)
+
+ @raises(KiwiTemplateError)
+ def test_setup_install_image_config_invalid_template(self):
+ self.isolinux.get_install_message_template.side_effect = Exception
+ self.bootloader.setup_install_image_config(mbrid=None)
+
+ @patch('kiwi.bootloader_config_isolinux.Command.run')
+ def test_setup_install_boot_images(self, mock_command):
+ self.bootloader.setup_install_boot_images(
+ mbrid=None, lookup_path='lookup_dir'
+ )
+ mock_command.assert_called_once_with(
+ [
+ 'rsync', '-zav', 'lookup_dir/image/loader/',
+ 'source_dir/boot/x86_64/loader'
+ ]
+ )
+
+ @patch('kiwi.bootloader_config_isolinux.Command.run')
+ def test_setup_live_boot_images(self, mock_command):
+ self.bootloader.setup_live_boot_images(
+ mbrid=None
+ )
+ mock_command.assert_called_once_with(
+ [
+ 'rsync', '-zav', 'source_dir/image/loader/',
+ 'source_dir/boot/x86_64/loader'
+ ]
+ )
+
+ def test_setup_live_image_config(self):
+ # TODO
+ self.bootloader.setup_live_image_config(mbrid=None)
diff --git a/test/unit/bootloader_config_test.py b/test/unit/bootloader_config_test.py
index bf1896d3..7f43e573 100644
--- a/test/unit/bootloader_config_test.py
+++ b/test/unit/bootloader_config_test.py
@@ -19,3 +19,9 @@ class TestBootLoaderConfig(object):
xml_state = mock.Mock()
BootLoaderConfig.new('grub2', xml_state, 'source_dir')
mock_grub2.assert_called_once_with(xml_state, 'source_dir')
+
+ @patch('kiwi.bootloader_config.BootLoaderConfigIsoLinux')
+ def test_bootloader_config_isolinux(self, mock_isolinux):
+ xml_state = mock.Mock()
+ BootLoaderConfig.new('isolinux', xml_state, 'source_dir')
+ mock_isolinux.assert_called_once_with(xml_state, 'source_dir')
diff --git a/test/unit/bootloader_template_isolinux_test.py b/test/unit/bootloader_template_isolinux_test.py
new file mode 100644
index 00000000..d10019b2
--- /dev/null
+++ b/test/unit/bootloader_template_isolinux_test.py
@@ -0,0 +1,83 @@
+from nose.tools import *
+from mock import patch
+
+import mock
+
+import nose_helper
+
+from kiwi.bootloader_template_isolinux import BootLoaderTemplateIsoLinux
+
+
+class TestBootLoaderTemplateIsoLinux(object):
+ def setup(self):
+ self.isolinux = BootLoaderTemplateIsoLinux()
+
+ def test_get_multiboot_install_template(self):
+ assert self.isolinux.get_multiboot_install_template().substitute(
+ default_boot='0',
+ kernel_file='linux.vmx',
+ initrd_file='initrd.vmx',
+ boot_options='splash',
+ failsafe_boot_options='splash',
+ gfxmode='800x600',
+ theme='SLE',
+ boot_timeout='10',
+ title='LimeJeOS-SLE12-Community [ VMX ]',
+ bootpath='/boot',
+ hypervisor='xen.gz'
+ )
+
+ def test_get_install_template(self):
+ assert self.isolinux.get_install_template().substitute(
+ default_boot='0',
+ kernel_file='boot/linux.vmx',
+ initrd_file='boot/initrd.vmx',
+ boot_options='cdinst=1 splash',
+ failsafe_boot_options='cdinst=1 splash',
+ gfxmode='800x600',
+ theme='SLE',
+ boot_timeout='10',
+ title='LimeJeOS-SLE12-Community [ VMX ]',
+ bootpath='/boot'
+ )
+
+ def test_get_multiboot_install_template_plain_ui(self):
+ assert self.isolinux.get_multiboot_install_template(
+ with_theme=False
+ ).substitute(
+ default_boot='0',
+ kernel_file='linux.vmx',
+ initrd_file='initrd.vmx',
+ boot_options='splash',
+ failsafe_boot_options='splash',
+ gfxmode='800x600',
+ theme='SLE',
+ boot_timeout='10',
+ title='LimeJeOS-SLE12-Community [ VMX ]',
+ bootpath='/boot',
+ hypervisor='xen.gz'
+ )
+
+ def test_get_install_template_plan_ui(self):
+ assert self.isolinux.get_install_template(with_theme=False).substitute(
+ default_boot='0',
+ kernel_file='boot/linux.vmx',
+ initrd_file='boot/initrd.vmx',
+ boot_options='cdinst=1 splash',
+ failsafe_boot_options='cdinst=1 splash',
+ gfxmode='800x600',
+ theme='SLE',
+ boot_timeout='10',
+ title='LimeJeOS-SLE12-Community [ VMX ]',
+ bootpath='/boot'
+ )
+
+ def test_get_message_template(self):
+ assert self.isolinux.get_message_template().substitute(
+ title='LimeJeOS-SLE12-Community [ VMX ]'
+ )
+
+ def test_get_install_message_template(self):
+ assert self.isolinux.get_install_message_template().substitute(
+ title='LimeJeOS-SLE12-Community [ VMX ]'
+ )
diff --git a/test/unit/command_process_test.py b/test/unit/command_process_test.py
index 839bd060..c29c7075 100644
--- a/test/unit/command_process_test.py
+++ b/test/unit/command_process_test.py
@@ -1,5 +1,6 @@
from nose.tools import *
from mock import patch
+from mock import call
from collections import namedtuple
import mock
@@ -60,9 +61,10 @@ class TestCommandProcess(object):
process.command.error.read = self.flow_err
process.command.process.returncode = 0
process.poll_show_progress(['a', 'b'], match_method)
- mock_log_debug.assert_called_once_with(
- '%s: %s', 'system', 'data'
- )
+ assert mock_log_debug.call_args_list == [
+ call('%s: %s', 'system', 'data'),
+ call('%s: %s', 'system', 'error')
+ ]
@raises(KiwiCommandError)
@patch('kiwi.command.Command')
@@ -90,9 +92,10 @@ class TestCommandProcess(object):
process.command.error.read = self.flow_err
process.command.process.returncode = 0
process.poll()
- mock_log_debug.assert_called_once_with(
- '%s: %s', 'system', 'data'
- )
+ assert mock_log_debug.call_args_list == [
+ call('%s: %s', 'system', 'data'),
+ call('%s: %s', 'system', 'error')
+ ]
@raises(KiwiCommandError)
@patch('kiwi.command.Command')
diff --git a/test/unit/filesystem_isofs_test.py b/test/unit/filesystem_isofs_test.py
new file mode 100644
index 00000000..98d82bb3
--- /dev/null
+++ b/test/unit/filesystem_isofs_test.py
@@ -0,0 +1,35 @@
+from nose.tools import *
+from mock import patch
+
+import mock
+
+import nose_helper
+
+from kiwi.exceptions import *
+from kiwi.filesystem_isofs import FileSystemIsoFs
+
+
+class TestFileSystemIsoFs(object):
+ @patch('os.path.exists')
+ def setup(self, mock_exists):
+ mock_exists.return_value = True
+ self.isofs = FileSystemIsoFs(mock.Mock(), 'source_dir')
+
+ def test_post_init(self):
+ self.isofs.post_init(['args'])
+ assert self.isofs.custom_args == ['args']
+
+ @patch('kiwi.filesystem_isofs.Command.run')
+ @patch('kiwi.filesystem_isofs.Iso')
+ def test_create_on_file(self, mock_iso, mock_command):
+ iso = mock.Mock()
+ iso.get_iso_creation_parameters = mock.Mock(
+ return_value=['args']
+ )
+ mock_iso.return_value = iso
+ self.isofs.create_on_file('myimage', None)
+ iso.init_iso_creation_parameters.assert_called_once_with(None)
+ iso.add_efi_loader_parameters.assert_called_once_with()
+ mock_command.assert_called_once_with(
+ ['genisoimage', 'args', '-o', 'myimage', 'source_dir']
+ )
diff --git a/test/unit/install_image_builder_test.py b/test/unit/install_image_builder_test.py
index 0bdc06e1..30e5beaa 100644
--- a/test/unit/install_image_builder_test.py
+++ b/test/unit/install_image_builder_test.py
@@ -20,6 +20,10 @@ class TestInstallImageBuilder(object):
kiwi.install_image_builder.FileSystemSquashFs = mock.Mock(
return_value=self.squashed_image
)
+ self.iso_image = mock.Mock()
+ kiwi.install_image_builder.FileSystemIsoFs = mock.Mock(
+ return_value=self.iso_image
+ )
self.mbrid = mock.Mock()
self.mbrid.get_id = mock.Mock(
return_value='0xffffffff'
@@ -34,17 +38,26 @@ class TestInstallImageBuilder(object):
)
self.kernel = mock.Mock()
self.kernel.get_kernel = mock.Mock()
+ self.kernel.get_xen_hypervisor = mock.Mock()
self.kernel.copy_kernel = mock.Mock()
+ self.kernel.copy_xen_hypervisor = mock.Mock()
kiwi.install_image_builder.Kernel = mock.Mock(
return_value=self.kernel
)
self.xml_state = mock.Mock()
+ self.xml_state.xml_data.get_name = mock.Mock(
+ return_value='result-image'
+ )
self.boot_image_task = mock.Mock()
self.boot_image_task.boot_root_directory = 'initrd_dir'
self.boot_image_task.initrd_filename = 'initrd'
self.install_image = InstallImageBuilder(
self.xml_state, 'target_dir', 'some-diskimage', self.boot_image_task
)
+ self.install_image.machine = mock.Mock()
+ self.install_image.machine.get_domain = mock.Mock(
+ return_value='dom0'
+ )
@patch('kiwi.install_image_builder.mkdtemp')
@patch('__builtin__.open')
@@ -76,23 +89,37 @@ class TestInstallImageBuilder(object):
self.squashed_image.create_on_file.assert_called_once_with(
'some-diskimage.squashfs'
)
- self.bootloader.setup_install_boot_images.assert_called_once_with(
- lookup_path='initrd_dir', mbrid=self.mbrid
- )
- self.bootloader.setup_install_image_config.assert_called_once_with(
- self.mbrid
- )
- self.bootloader.write.assert_called_once_with()
+ assert self.bootloader.setup_install_boot_images.call_args_list == [
+ call(lookup_path='initrd_dir', mbrid=None),
+ call(lookup_path='initrd_dir', mbrid=self.mbrid)
+ ]
+ assert self.bootloader.setup_install_boot_images.call_args_list == [
+ call(lookup_path='initrd_dir', mbrid=None),
+ call(lookup_path='initrd_dir', mbrid=self.mbrid)
+ ]
+ assert self.bootloader.setup_install_image_config.call_args_list == [
+ call(mbrid=None),
+ call(mbrid=self.mbrid)
+ ]
+ assert self.bootloader.write.call_args_list == [
+ call(), call()
+ ]
self.boot_image_task.create_initrd.assert_called_once_with(
self.mbrid
)
self.kernel.copy_kernel.assert_called_once_with(
'tmpdir/boot/x86_64/loader', '/linux'
)
+ self.kernel.copy_xen_hypervisor.assert_called_once_with(
+ 'tmpdir/boot/x86_64/loader', '/xen.gz'
+ )
assert mock_command.call_args_list == [
call(['mv', 'some-diskimage.squashfs', 'tmpdir']),
call(['mv', 'initrd', 'tmpdir/boot/x86_64/loader/initrd'])
]
+ self.iso_image.create_on_file.assert_called_once_with(
+ 'target_dir/result-image.install.iso'
+ )
@patch('kiwi.install_image_builder.mkdtemp')
@patch('__builtin__.open')
@@ -104,10 +131,23 @@ class TestInstallImageBuilder(object):
self.kernel.get_kernel.return_value = False
self.install_image.create_install_iso()
+ @patch('kiwi.install_image_builder.mkdtemp')
+ @patch('__builtin__.open')
+ @patch('kiwi.install_image_builder.Command.run')
+ @raises(KiwiInstallBootImageError)
+ def test_create_install_iso_no_hypervisor_found(
+ self, mock_command, mock_open, mock_dtemp
+ ):
+ self.kernel.get_xen_hypervisor.return_value = False
+ self.install_image.create_install_iso()
+
def test_create_install_pxe_archive(self):
# TODO
self.install_image.create_install_pxe_archive()
- def test_destructor(self):
- # TODO
+ @patch('kiwi.install_image_builder.Path.wipe')
+ def test_destructor(self, mock_wipe):
+ self.install_image.media_dir = 'media-dir'
self.install_image.__del__()
+ mock_wipe.assert_called_once_with('media-dir')
+ self.install_image.media_dir = None
diff --git a/test/unit/iso_test.py b/test/unit/iso_test.py
new file mode 100644
index 00000000..cebc9298
--- /dev/null
+++ b/test/unit/iso_test.py
@@ -0,0 +1,110 @@
+from nose.tools import *
+from mock import patch
+from mock import call
+import mock
+
+import nose_helper
+
+from kiwi.exceptions import *
+
+from kiwi.iso import Iso
+from collections import namedtuple
+
+
+class TestIso(object):
+ @patch('kiwi.iso.NamedTemporaryFile')
+ @patch('platform.machine')
+ def setup(self, mock_machine, mock_tempfile):
+ temp_type = namedtuple(
+ 'temp_type', ['name']
+ )
+ mock_machine.return_value = 'x86_64'
+ mock_tempfile.return_value = temp_type(
+ name='sortfile'
+ )
+ self.iso = Iso('source-dir')
+
+ @patch('__builtin__.open')
+ @patch('os.path.exists')
+ @raises(KiwiIsoLoaderError)
+ def test_init_iso_creation_parameters_no_loader(
+ self, mock_exists, mock_open
+ ):
+ mock_exists.return_value = False
+ self.iso.init_iso_creation_parameters()
+
+ @patch('__builtin__.open')
+ @patch('kiwi.iso.Command.run')
+ @patch('os.path.exists')
+ @patch('os.walk')
+ def test_init_iso_creation_parameters(
+ self, mock_walk, mock_exists, mock_command, mock_open
+ ):
+ mock_walk.return_value = [
+ ('source-dir', ('bar', 'baz'), ('efi', 'eggs', 'header_end'))
+ ]
+ mock_exists.return_value = True
+ 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.iso.init_iso_creation_parameters(['custom_arg'])
+
+ assert file_mock.write.call_args_list == [
+ call('7984fc91-a43f-4e45-bf27-6d3aa08b24cf\n'),
+ call('source-dir/boot/x86_64/boot.catalog 3\n'),
+ call('source-dir/boot/x86_64/loader/isolinux.bin 2\n'),
+ call('source-dir/efi 1000001\n'),
+ call('source-dir/eggs 1\n'),
+ call('source-dir/header_end 1000000\n'),
+ call('source-dir/bar 1\n'),
+ call('source-dir/baz 1\n')
+ ]
+ assert self.iso.iso_parameters == [
+ 'custom_arg', '-R', '-J', '-f', '-pad', '-joliet-long',
+ '-sort', 'sortfile', '-no-emul-boot', '-boot-load-size', '4',
+ '-boot-info-table',
+ '-hide', 'boot/x86_64/boot.catalog',
+ '-hide-joliet', 'boot/x86_64/boot.catalog',
+ ]
+ assert self.iso.iso_loaders == [
+ '-b', 'boot/x86_64/loader/isolinux.bin',
+ '-c', 'boot/x86_64/boot.catalog'
+ ]
+ mock_command.assert_called_once_with(
+ [
+ 'isolinux-config', '--base', 'boot/x86_64/loader',
+ 'source-dir/boot/x86_64/loader/isolinux.bin'
+ ]
+ )
+
+ @patch('os.path.exists')
+ def test_add_efi_loader_parameters(self, mock_exists):
+ mock_exists.return_value = True
+ self.iso.add_efi_loader_parameters()
+ assert self.iso.iso_loaders == [
+ '-eltorito-alt-boot', '-b', 'boot/x86_64/efi',
+ '-no-emul-boot', '-joliet-long'
+ ]
+
+ def test_get_iso_creation_parameters(self):
+ self.iso.iso_parameters = ['a']
+ self.iso.iso_loaders = ['b']
+ assert self.iso.get_iso_creation_parameters() == ['a', 'b']
+
+ def test_add_iso_header_end_marker(self):
+ # TODO
+ self.iso.add_iso_header_end_marker()
+
+ def test_relocate_boot_catalog(self):
+ # TODO
+ self.iso.relocate_boot_catalog('isofile')
+
+ def test_fix_boot_catalog(self):
+ # TODO
+ self.iso.fix_boot_catalog('isofile')