Source

stacklet / src / stacklet / task / image / kernel.py

Full commit
# Copyright (C) 2009, dfn@stacklet.com
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License version 2 as
# published by the Free Software Foundation.

# This program 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.

"""Tasks for configuring a kernel.

Please see docstring of each class for usage.

"""
import os
import re

from stacklet.util.objectify import _XO_
from stacklet.util.objectify import *

from stacklet.task.stacktask import *
from stacklet.task.stackerror import *
from stacklet.util import fileutil

class _XO_kernel(_XO_, StackTask):
    """This task handles miscellaneous tasks for kernels, all of which are optional:
      1. Installation, if the asset parameter is set
      2. Generate an initrd, if the initrd parameter is set
      3. Add a grub entry, if the grubConfig parameter is set

    Task Arguments:
    asset -- (optional) a tar archive in buildContext.get_global_asset_dir() containing a kernel & modules;
             will be extracted to buildContext.mountPoint
    name -- the file name of the kernel, may contain wildcard characters (only the first match will be configured)
    options -- (optional) options passed to the kernel at boot time
    initrd -- (optional) options passed to mkinitrd, no initrd will be generated if absent
    grubConfig -- (optional) the location of the grub config file inside the image.  Task will create the file if
                  it does not exist in the image.  If the argument itself is missing no grub configuration will occur.
    """
    _TASK_NAME = 'kernel'

    def __init__(self):
        pass

    def process(self, buildContext):
        try:
            try:
                self._buildContext = buildContext
                self.log_info(buildContext, 'entering')
                self.precheck(buildContext)

                if not self.is_empty(self._asset):
                    tarball = buildContext.get_global_asset_dir() + 'kernel/' + self._asset
                    cmd = 'tar -xvjf  ' + tarball + ' -C ' + buildContext.mountPoint
                    self.exec_command(buildContext, cmd)

                p = re.compile(self._name)

                vers = ''
                kernel = ''
                bootFiles = os.listdir(buildContext.mountPoint + '/boot')
                for bootFile in bootFiles:
                    if p.match(bootFile):
                        kernel = bootFile
                        vers = bootFile.replace('vmlinuz-', '')

                if kernel == '':
                    raise FieldError(self._TASK_NAME, TaskError.ABORT_TASK, 'could not find kernel matching ' +  self._name)

                self.log_info(buildContext, 'configuring ' + kernel)

                initrd = ''
                if not self.is_empty(self._initrd):
                    initrd = 'initrd-' + vers + '.img'
                    cmds = list()
                    cmds.append('cd /boot && /sbin/mkinitrd -f ' + self._initrd + ' ' + initrd + ' ' + vers)
                    self.exec_command_chroot(buildContext, cmds)
                elif os.access(buildContext.mountPoint + '/boot/initrd.img-' + vers, os.F_OK):
                    initrd = 'initrd.img-' + vers
                elif os.access(buildContext.mountPoint + '/boot/initrd-' + vers + '.img', os.F_OK):
                    initrd = 'initrd-' + vers + '.img'
                elif os.access(buildContext.mountPoint + '/boot/initramfs-' + vers + '.img', os.F_OK):
                    initrd = 'initramfs-' + vers + '.img'
                elif os.access(buildContext.mountPoint + '/boot/initrd-' + vers, os.F_OK):
                    initrd = 'initrd-' + vers
                elif os.access(buildContext.mountPoint + '/boot/initrd', os.F_OK):
                    initrd = 'initrd'
                elif os.access(buildContext.mountPoint + '/boot/initrd.gz', os.F_OK):
                    initrd = 'initrd.gz'

                if not self.is_empty(self._grubConfig):
                    grubLines = list()
                    grubConfigFullPath = buildContext.mountPoint + self._grubConfig
                    if not os.access(grubConfigFullPath, os.F_OK):
                        grubLines.append('default=0')
                        grubLines.append('timeout=10')
                    grubLines.append('title ' + kernel)
                    grubLines.append('  root (hd0,0)')
                    grubLines.append('  kernel /boot/' + kernel + ' ' + self._options)
                    if not self.is_empty(initrd):
                        grubLines.append('  initrd /boot/' + initrd)
                    fileutil.append_lines(buildContext, grubLines, self._grubConfig, 'title ' + kernel)

            except TaskError, taskErr:
                if taskErr.criticality == TaskError.ABORT_BUILD:
                    raise
                self.log_error(buildContext, taskErr)
        finally:
            self.log_info(buildContext, 'leaving')


    def precheck(self, buildContext):
        self.is_valid_build_context(buildContext)

        self._asset = self.get_value('asset')
        self._name = self.get_value('name')
        self._options = self.get_value('options')
        self._initrd = self.get_value('initrd')
        self._grubConfig = self.get_value('grubConfig')

        if self.is_empty(self._name):
            raise FieldError(self._TASK_NAME, TaskError.ABORT_TASK, 'name is required')


stacklet.util.objectify._XO_kernel = _XO_kernel
stacklet.util.objectify._XO_stk_kernel = _XO_kernel