Source code for kiwi.bootloader.config.zipl

# 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 <http://www.gnu.org/licenses/>
#
import logging
import re

# project
from kiwi.bootloader.config.base import BootLoaderConfigBase
from kiwi.bootloader.template.zipl import BootLoaderTemplateZipl
from kiwi.command import Command
from kiwi.path import Path
from kiwi.firmware import FirmWare
from kiwi.defaults import Defaults

from kiwi.exceptions import (
    KiwiTemplateError,
    KiwiBootLoaderZiplPlatformError,
    KiwiBootLoaderZiplSetupError,
    KiwiDiskGeometryError
)

log = logging.getLogger('kiwi')


[docs]class BootLoaderConfigZipl(BootLoaderConfigBase): """ **zipl bootloader configuration.** """
[docs] def post_init(self, custom_args): """ zipl post initialization method :param dict custom_args: Contains zipl config arguments .. code:: python {'targetbase': 'device_name'} """ self.custom_args = custom_args arch = Defaults.get_platform_name() if 's390' in arch: self.arch = arch else: raise KiwiBootLoaderZiplPlatformError( 'host architecture %s not supported for zipl setup' % arch ) if not custom_args or 'targetbase' not in custom_args: raise KiwiBootLoaderZiplSetupError( 'targetbase device name is required for zipl setup' ) self.bootpath = '.' self.timeout = self.get_boot_timeout_seconds() self.cmdline = self.get_boot_cmdline() self.cmdline_failsafe = ' '.join( [self.cmdline, Defaults.get_failsafe_kernel_options()] ) self.target_blocksize = \ self.xml_state.build_type.get_target_blocksize() if not self.target_blocksize: self.target_blocksize = Defaults.get_s390_disk_block_size() self.target_type = \ self.xml_state.get_build_type_bootloader_targettype() if not self.target_type: self.target_type = Defaults.get_s390_disk_type() self.failsafe_boot = self.failsafe_boot_entry_requested() self.target_device = custom_args['targetbase'] self.firmware = FirmWare(self.xml_state) self.target_table_type = self.firmware.get_partition_table_type() self.zipl = BootLoaderTemplateZipl() self.config = None
[docs] def write(self): """ Write zipl config file """ log.info('Writing zipl config file') config_dir = self._get_zipl_boot_path() config_file = config_dir + '/config' if self.config: Path.create(config_dir) with open(config_file, 'w') as config: config.write(self.config)
[docs] def setup_disk_image_config( self, boot_uuid=None, root_uuid=None, hypervisor=None, kernel='image', initrd='initrd', boot_options={} ): """ Create the zipl config in memory from a template suitable to boot from a disk image. :param string boot_uuid: unused :param string root_uuid: unused :param string hypervisor: unused :param string kernel: kernel name :param string initrd: initrd name :param dict boot_options: unused """ log.info('Creating zipl config file from template') parameters = { 'device': self.target_device, 'target_type': self.target_type, 'blocksize': self.target_blocksize, 'offset': self._get_target_offset(), 'geometry': self._get_target_geometry(), 'default_boot': '1', 'bootpath': self.bootpath, 'boot_timeout': self.timeout, 'title': self.quote_title(self.get_menu_entry_title()), 'kernel_file': kernel, 'initrd_file': initrd, 'boot_options': self.cmdline, 'failsafe_boot_options': self.cmdline_failsafe } log.info('--> Using standard disk boot template') template = self.zipl.get_template(self.failsafe_boot, self.target_type) try: self.config = template.substitute(parameters) except Exception as e: raise KiwiTemplateError( '%s: %s' % (type(e).__name__, format(e)) )
[docs] def setup_disk_boot_images(self, boot_uuid, lookup_path=None): """ On s390 no bootloader images needs to be created Thus this method does nothing :param string boot_uuid: boot device UUID :param string lookup_path: custom module lookup path """ pass
def _get_zipl_boot_path(self): return self.boot_dir + '/boot/zipl' def _get_target_geometry(self): if self.target_table_type == 'dasd': return '%d,%d,%d' % ( self._read_dasd_disk_geometry('cylinders'), self._read_dasd_disk_geometry('tracks per cylinder'), self._read_dasd_disk_geometry('blocks per track') ) else: return '%d,%d,%d' % ( self._read_msdos_disk_geometry('cylinders'), self._read_msdos_disk_geometry('tracks per cylinder'), self._read_msdos_disk_geometry('blocks per track') ) def _get_target_offset(self): if self.target_table_type == 'dasd': blocks = self._read_dasd_disk_geometry('blocks per track') bash_command = [ 'fdasd', '-f', '-s', '-p', self.target_device, '|', 'head', '-n', '1', '|', 'tr', '-s', '" "' ] fdasd_call = Command.run( ['bash', '-c', ' '.join(bash_command)] ) fdasd_output = fdasd_call.output try: start_track = int(fdasd_output.split(' ')[2].lstrip()) except Exception: raise KiwiDiskGeometryError( 'unknown partition format: %s' % fdasd_output ) return start_track * blocks else: blocks = self._read_msdos_disk_geometry('blocks per track') parted_call = Command.run( ['parted', '-m', self.target_device, 'unit', 's', 'print'] ) parted_output = parted_call.output.lstrip() first_partition_format = re.search('1:(.*?)s', parted_output) if not first_partition_format: raise KiwiDiskGeometryError( 'unknown partition format: %s' % parted_output ) start_track = int(first_partition_format.group(1)) return start_track * blocks def _read_msdos_disk_geometry(self, value): sfdisk_call = Command.run( ['sfdisk', '-g', self.target_device] ) sfdisk_output = sfdisk_call.output.lstrip() geometry_format = re.search( '/dev.*: (.*) cylinders, (.*) heads, (.*) sectors/track', sfdisk_output ) if not geometry_format: raise KiwiDiskGeometryError( 'unknown format for geometry: %s' % sfdisk_output ) result = { 'cylinders': geometry_format.group(1), 'tracks per cylinder': geometry_format.group(2), 'blocks per track': geometry_format.group(3) } if value in result: return int(result[value]) def _read_dasd_disk_geometry(self, value): fdasd = ['fdasd', '-f', '-p', self.target_device] bash_command = fdasd + ['|', 'grep', '"' + value + '"'] fdasd_call = Command.run( ['bash', '-c', ' '.join(bash_command)] ) fdasd_output = fdasd_call.output try: return int(fdasd_output.split(':')[1].lstrip()) except Exception: raise KiwiDiskGeometryError( 'unknown format for disk geometry: %s' % fdasd_output )