import os, shutil, copy, pickle, re, glob, time, logging
from autotest_lib.client.bin import kernel_config, os_dep, kernelexpand, test
from autotest_lib.client.bin import utils
from autotest_lib.client.common_lib import log, error, packages


def tee_output_logdir_mark(fn):
    def tee_logdir_mark_wrapper(self, *args, **dargs):
        mark = self.__class__.__name__ + "." + fn.__name__
        logging.info("--- START %s ---", mark)
        self.job.logging.tee_redirect_debug_dir(self.log_dir)
        try:
            result = fn(self, *args, **dargs)
        finally:
            self.job.logging.restore()
            logging.info("--- END %s ---", mark)

        return result

    tee_logdir_mark_wrapper.__name__ = fn.__name__
    return tee_logdir_mark_wrapper


def _add_kernel_to_bootloader(bootloader, base_args, tag, args, image, initrd):
    """
    Add a kernel with the specified tag to the boot config using the given
    bootloader object. Also process the base_args and args kernel arguments
    by removing all root= options and give the last root= option value to
    the bootloader as a root device.

    @param bootloader: bootloader object
    @param base_args: base cmdline kernel arguments
    @param tag: kernel tag
    @param args: kernel cmdline arguments that are merged with base_args; a
            root= option in "args" will override any from base_args
    @param image: kernel image file
    @param initrd: initrd file
    """
    # remove existing entry if present
    bootloader.remove_kernel(tag)

    if base_args:
        args = ' '.join((base_args, args))

    root_prefix = 'root='
    # stores the last root= value
    root = None
    # a list with all arguments that don't start with root= so we give them
    # later to bootloader.add_kernel()
    arglist = []

    for arg in args.split():
        if arg.startswith(root_prefix):
            # set the current root value with the one from the argument
            # thus after processing all the arguments we keep the last
            # root value (so root= options from args overrides any from
            # base_args)
            root = arg[len(root_prefix):]
        else:
            arglist.append(arg)

    # Add the kernel entry. it will keep all arguments from the default entry.
    # args='_dummy_' is used to workaround a boottool limitation of not being
    # able to add arguments to a kernel that does not already have any of its
    # own by way of its own append= section below the image= line in lilo.conf.
    bootloader.add_kernel(image, tag, initrd=initrd, root=root, args='_dummy_')
    # Now, for each argument in arglist, try to add it to the kernel that was
    # just added. In each step, if the arg already existed on the args string,
    # that particular arg will be skipped
    for a in arglist:
        bootloader.add_args(kernel=tag, args=a)
    bootloader.remove_args(kernel=tag, args='_dummy_')


class BootableKernel(object):

    def __init__(self, job):
        self.job = job
        self.installed_as = None  # kernel choice in bootloader menu
        self.image = None
        self.initrd = ''


    def _boot_kernel(self, args, ident_check, expected_ident, subdir, notes):
        """
        Boot a kernel, with post-boot kernel id check

        @param args:  kernel cmdline arguments
        @param ident_check: check kernel id after boot
        @param expected_ident:
        @param subdir: job-step qualifier in status log
        @param notes:  additional comment in status log
        """
        # If we can check the kernel identity do so.
        if ident_check:
            when = int(time.time())
            args += " IDENT=%d" % when
            self.job.next_step_prepend(["job.end_reboot_and_verify", when,
                                        expected_ident, subdir, notes])
        else:
            self.job.next_step_prepend(["job.end_reboot", subdir,
                                        expected_ident, notes])

        self.add_to_bootloader(args)

        # defer fsck for next reboot, to avoid reboots back to default kernel
        utils.system('touch /fastboot')  # this file is removed automatically

        # Boot it.
        self.job.start_reboot()
        self.job.reboot(tag=self.installed_as)


    def add_to_bootloader(self, args=''):
        # Point bootloader to the selected tag.
        _add_kernel_to_bootloader(self.job.bootloader,
                                  self.job.config_get('boot.default_args'),
                                  self.installed_as, args, self.image,
                                  self.initrd)


class kernel(BootableKernel):
    """ Class for compiling kernels.

    Data for the object includes the src files
    used to create the kernel, patches applied, config (base + changes),
    the build directory itself, and logged output

    Properties:
            job
                    Backpointer to the job object we're part of
            autodir
                    Path to the top level autotest dir (/usr/local/autotest)
            src_dir
                    <tmp_dir>/src/
            build_dir
                    <tmp_dir>/linux/
            config_dir
                    <results_dir>/config/
            log_dir
                    <results_dir>/debug/
            results_dir
                    <results_dir>/results/
    """

    autodir = ''

    def __init__(self, job, base_tree, subdir, tmp_dir, build_dir, leave=False):
        """Initialize the kernel build environment

        job
                which job this build is part of
        base_tree
                base kernel tree. Can be one of the following:
                        1. A local tarball
                        2. A URL to a tarball
                        3. A local directory (will symlink it)
                        4. A shorthand expandable (eg '2.6.11-git3')
        subdir
                subdir in the results directory (eg "build")
                (holds config/, debug/, results/)
        tmp_dir

        leave
                Boolean, whether to leave existing tmpdir or not
        """
        super(kernel, self).__init__(job)
        self.autodir = job.autodir

        self.src_dir    = os.path.join(tmp_dir, 'src')
        self.build_dir  = os.path.join(tmp_dir, build_dir)
                # created by get_kernel_tree
        self.config_dir = os.path.join(subdir, 'config')
        self.log_dir    = os.path.join(subdir, 'debug')
        self.results_dir = os.path.join(subdir, 'results')
        self.subdir     = os.path.basename(subdir)

        if not leave:
            if os.path.isdir(self.src_dir):
                utils.system('rm -rf ' + self.src_dir)
            if os.path.isdir(self.build_dir):
                utils.system('rm -rf ' + self.build_dir)

        if not os.path.exists(self.src_dir):
            os.mkdir(self.src_dir)
        for path in [self.config_dir, self.log_dir, self.results_dir]:
            if os.path.exists(path):
                utils.system('rm -rf ' + path)
            os.mkdir(path)

        logpath = os.path.join(self.log_dir, 'build_log')
        self.logfile = open(logpath, 'w+')
        self.applied_patches = []

        self.target_arch = None
        self.build_target = 'bzImage'
        self.build_image = None

        arch = utils.get_current_kernel_arch()
        if arch == 's390' or arch == 's390x':
            self.build_target = 'image'
        elif arch == 'ia64':
            self.build_target = 'all'
            self.build_image = 'vmlinux.gz'

        if not leave:
            self.logfile.write('BASE: %s\n' % base_tree)

            # Where we have direct version hint record that
            # for later configuration selection.
            shorthand = re.compile(r'^\d+\.\d+\.\d+')
            if shorthand.match(base_tree):
                self.base_tree_version = base_tree
            else:
                self.base_tree_version = None

            # Actually extract the tree.  Make sure we know it occured
            self.extract(base_tree)


    def kernelexpand(self, kernel):
        # If we have something like a path, just use it as it is
        if '/' in kernel:
            return [kernel]

        # Find the configured mirror list.
        mirrors = self.job.config_get('mirror.mirrors')
        if not mirrors:
            # LEGACY: convert the kernel.org mirror
            mirror = self.job.config_get('mirror.ftp_kernel_org')
            if mirror:
                korg = 'http://www.kernel.org/pub/linux/kernel'
                mirrors = [
                  [ korg + '/v2.6', mirror + '/v2.6' ],
                  [ korg + '/people/akpm/patches/2.6', mirror + '/akpm' ],
                  [ korg + '/people/mbligh', mirror + '/mbligh' ],
                ]

        patches = kernelexpand.expand_classic(kernel, mirrors)
        print patches

        return patches


    @log.record
    @tee_output_logdir_mark
    def extract(self, base_tree):
        if os.path.exists(base_tree):
            self.get_kernel_tree(base_tree)
        else:
            base_components = self.kernelexpand(base_tree)
            print 'kernelexpand: '
            print base_components
            self.get_kernel_tree(base_components.pop(0))
            if base_components:      # apply remaining patches
                self.patch(*base_components)


    @log.record
    @tee_output_logdir_mark
    def patch(self, *patches):
        """Apply a list of patches (in order)"""
        if not patches:
            return
        print 'Applying patches: ', patches
        self.apply_patches(self.get_patches(patches))


    @log.record
    @tee_output_logdir_mark
    def config(self, config_file = '', config_list = None, defconfig = False, make = None):
        self.set_cross_cc()
        config = kernel_config.kernel_config(self.job, self.build_dir,
                 self.config_dir, config_file, config_list,
                 defconfig, self.base_tree_version, make)


    def get_patches(self, patches):
        """fetch the patches to the local src_dir"""
        local_patches = []
        for patch in patches:
            dest = os.path.join(self.src_dir, os.path.basename(patch))
            # FIXME: this isn't unique. Append something to it
            # like wget does if it's not there?
            print "get_file %s %s %s %s" % (patch, dest, self.src_dir,
                                            os.path.basename(patch))
            utils.get_file(patch, dest)
            # probably safer to use the command, not python library
            md5sum = utils.system_output('md5sum ' + dest).split()[0]
            local_patches.append((patch, dest, md5sum))
        return local_patches


    def apply_patches(self, local_patches):
        """apply the list of patches, in order"""
        builddir = self.build_dir
        os.chdir(builddir)

        if not local_patches:
            return None
        for (spec, local, md5sum) in local_patches:
            if local.endswith('.bz2') or local.endswith('.gz'):
                ref = spec
            else:
                ref = utils.force_copy(local, self.results_dir)
                ref = self.job.relative_path(ref)
            patch_id = "%s %s %s" % (spec, ref, md5sum)
            log = "PATCH: " + patch_id + "\n"
            print log
            utils.cat_file_to_cmd(local, 'patch -p1 > /dev/null')
            self.logfile.write(log)
            self.applied_patches.append(patch_id)


    def get_kernel_tree(self, base_tree):
        """Extract/link base_tree to self.build_dir"""

        # if base_tree is a dir, assume uncompressed kernel
        if os.path.isdir(base_tree):
            print 'Symlinking existing kernel source'
            if os.path.islink(self.build_dir):
                os.remove(self.build_dir)
            os.symlink(base_tree, self.build_dir)

        # otherwise, extract tarball
        else:
            os.chdir(os.path.dirname(self.src_dir))
            # Figure out local destination for tarball
            tarball = os.path.join(self.src_dir, os.path.basename(base_tree.split(';')[0]))
            utils.get_file(base_tree, tarball)
            print 'Extracting kernel tarball:', tarball, '...'
            utils.extract_tarball_to_dir(tarball, self.build_dir)


    def extraversion(self, tag, append=True):
        os.chdir(self.build_dir)
        extraversion_sub = r's/^CONFIG_LOCALVERSION=\s*"\(.*\)"/CONFIG_LOCALVERSION='
        cfg = self.build_dir + '/.config'
        if append:
            p = extraversion_sub + '"\\1-%s"/' % tag
        else:
            p = extraversion_sub + '"-%s"/' % tag
        utils.system('mv %s %s.old' % (cfg, cfg))
        utils.system("sed '%s' < %s.old > %s" % (p, cfg, cfg))
        self.config(make='oldconfig')


    @log.record
    @tee_output_logdir_mark
    def build(self, make_opts = '', logfile = '', extraversion='autotest'):
        """build the kernel

        make_opts
                additional options to make, if any
        """
        os_dep.commands('gcc', 'make')
        if logfile == '':
            logfile = os.path.join(self.log_dir, 'kernel_build')
        os.chdir(self.build_dir)
        if extraversion:
            self.extraversion(extraversion)
        self.set_cross_cc()
        # setup_config_file(config_file, config_overrides)

        # Not needed on 2.6, but hard to tell -- handle failure
        utils.system('make dep', ignore_status=True)
        threads = 2 * utils.count_cpus()
        build_string = 'make -j %d %s %s' % (threads, make_opts,
                                     self.build_target)
                                # eg make bzImage, or make zImage
        print build_string
        utils.system(build_string)
        if kernel_config.modules_needed('.config'):
            utils.system('make -j %d modules' % (threads))

        kernel_version = self.get_kernel_build_ver()
        kernel_version = re.sub('-autotest', '', kernel_version)
        self.logfile.write('BUILD VERSION: %s\n' % kernel_version)

        utils.force_copy(self.build_dir+'/System.map',
                                  self.results_dir)


    def build_timed(self, threads, timefile = '/dev/null', make_opts = '',
                                                    output = '/dev/null'):
        """time the bulding of the kernel"""
        os.chdir(self.build_dir)
        self.set_cross_cc()

        self.clean()
        build_string = "/usr/bin/time -o %s make %s -j %s vmlinux" \
                                        % (timefile, make_opts, threads)
        build_string += ' > %s 2>&1' % output
        print build_string
        utils.system(build_string)

        if (not os.path.isfile('vmlinux')):
            errmsg = "no vmlinux found, kernel build failed"
            raise error.TestError(errmsg)


    @log.record
    @tee_output_logdir_mark
    def clean(self):
        """make clean in the kernel tree"""
        os.chdir(self.build_dir)
        print "make clean"
        utils.system('make clean > /dev/null 2> /dev/null')


    @log.record
    @tee_output_logdir_mark
    def mkinitrd(self, version, image, system_map, initrd):
        """Build kernel initrd image.
        Try to use distro specific way to build initrd image.
        Parameters:
                version
                        new kernel version
                image
                        new kernel image file
                system_map
                        System.map file
                initrd
                        initrd image file to build
        """
        vendor = utils.get_os_vendor()

        if os.path.isfile(initrd):
            print "Existing %s file, will remove it." % initrd
            os.remove(initrd)

        args = self.job.config_get('kernel.mkinitrd_extra_args')

        # don't leak 'None' into mkinitrd command
        if not args:
            args = ''

        # It is important to match the version with a real directory inside
        # /lib/modules
        real_version_list = glob.glob('/lib/modules/%s*' % version)
        rl = len(real_version_list)
        if rl == 0:
            logging.error("No directory %s found under /lib/modules. Initramfs"
                          "creation will most likely fail and your new kernel"
                          "will fail to build", version)
        else:
            if rl > 1:
                logging.warning("Found more than one possible match for "
                                "kernel version %s under /lib/modules", version)
            version = os.path.basename(real_version_list[0])

        if vendor in ['Red Hat', 'Fedora Core']:
            try:
                cmd = os_dep.command('dracut')
                full_cmd = '%s -f %s %s' % (cmd, initrd, version)
            except ValueError:
                cmd = os_dep.command('mkinitrd')
                full_cmd = '%s %s %s %s' % (cmd, args, initrd, version)
            utils.system(full_cmd)
        elif vendor in ['SUSE']:
            utils.system('mkinitrd %s -k %s -i %s -M %s' %
                         (args, image, initrd, system_map))
        elif vendor in ['Debian', 'Ubuntu']:
            if os.path.isfile('/usr/sbin/mkinitrd'):
                cmd = '/usr/sbin/mkinitrd'
            elif os.path.isfile('/usr/sbin/mkinitramfs'):
                cmd = '/usr/sbin/mkinitramfs'
            else:
                raise error.TestError('No Debian initrd builder')
            utils.system('%s %s -o %s %s' % (cmd, args, initrd, version))
        else:
            raise error.TestError('Unsupported vendor %s' % vendor)


    def set_build_image(self, image):
        self.build_image = image


    @log.record
    @tee_output_logdir_mark
    def install(self, tag='autotest', prefix = '/'):
        """make install in the kernel tree"""

        # Record that we have installed the kernel, and
        # the tag under which we installed it.
        self.installed_as = tag

        os.chdir(self.build_dir)

        if not os.path.isdir(prefix):
            os.mkdir(prefix)
        self.boot_dir = os.path.join(prefix, 'boot')
        if not os.path.isdir(self.boot_dir):
            os.mkdir(self.boot_dir)

        if not self.build_image:
            images = glob.glob('arch/*/boot/' + self.build_target)
            if len(images):
                self.build_image = images[0]
            else:
                self.build_image = self.build_target

        # remember installed files
        self.vmlinux = self.boot_dir + '/vmlinux-' + tag
        if (self.build_image != 'vmlinux'):
            self.image = self.boot_dir + '/vmlinuz-' + tag
        else:
            self.image = self.vmlinux
        self.system_map = self.boot_dir + '/System.map-' + tag
        self.config_file = self.boot_dir + '/config-' + tag
        self.initrd = ''

        # copy to boot dir
        utils.force_copy('vmlinux', self.vmlinux)
        if (self.build_image != 'vmlinux'):
            utils.force_copy(self.build_image, self.image)
        utils.force_copy('System.map', self.system_map)
        utils.force_copy('.config', self.config_file)

        if not kernel_config.modules_needed('.config'):
            return

        utils.system('make modules_install INSTALL_MOD_PATH=%s' % prefix)
        if prefix == '/':
            self.initrd = self.boot_dir + '/initrd-' + tag
            self.mkinitrd(self.get_kernel_build_ver(), self.image,
                          self.system_map, self.initrd)


    def get_kernel_build_arch(self, arch=None):
        """
        Work out the current kernel architecture (as a kernel arch)
        """
        if not arch:
            arch = utils.get_current_kernel_arch()
        if re.match('i.86', arch):
            return 'i386'
        elif re.match('sun4u', arch):
            return 'sparc64'
        elif re.match('arm.*', arch):
            return 'arm'
        elif re.match('sa110', arch):
            return 'arm'
        elif re.match('s390x', arch):
            return 's390'
        elif re.match('parisc64', arch):
            return 'parisc'
        elif re.match('ppc.*', arch):
            return 'powerpc'
        elif re.match('mips.*', arch):
            return 'mips'
        else:
            return arch


    def get_kernel_build_release(self):
        releasem = re.compile(r'.*UTS_RELEASE\s+"([^"]+)".*');
        versionm = re.compile(r'.*UTS_VERSION\s+"([^"]+)".*');

        release = None
        version = None

        for f in [self.build_dir + "/include/linux/version.h",
                  self.build_dir + "/include/linux/utsrelease.h",
                  self.build_dir + "/include/linux/compile.h",
                  self.build_dir + "/include/generated/utsrelease.h",
                  self.build_dir + "/include/generated/compile.h"]:
            if os.path.exists(f):
                fd = open(f, 'r')
                for line in fd.readlines():
                    m = releasem.match(line)
                    if m:
                        release = m.groups()[0]
                    m = versionm.match(line)
                    if m:
                        version = m.groups()[0]
                fd.close()

        return (release, version)


    def get_kernel_build_ident(self):
        (release, version) = self.get_kernel_build_release()

        if not release or not version:
            raise error.JobError('kernel has no identity')

        return release + '::' + version


    def boot(self, args='', ident=True):
        """ install and boot this kernel, do not care how
            just make it happen.
        """

        # If the kernel has not yet been installed,
        #   install it now as default tag.
        if not self.installed_as:
            self.install()

        expected_ident = self.get_kernel_build_ident()
        self._boot_kernel(args, ident, expected_ident,
                          self.subdir, self.applied_patches)


    def get_kernel_build_ver(self):
        """Check Makefile and .config to return kernel version"""
        version = patchlevel = sublevel = extraversion = localversion = ''

        for line in open(self.build_dir + '/Makefile', 'r').readlines():
            if line.startswith('VERSION'):
                version = line[line.index('=') + 1:].strip()
            if line.startswith('PATCHLEVEL'):
                patchlevel = line[line.index('=') + 1:].strip()
            if line.startswith('SUBLEVEL'):
                sublevel = line[line.index('=') + 1:].strip()
            if line.startswith('EXTRAVERSION'):
                extraversion = line[line.index('=') + 1:].strip()

        for line in open(self.build_dir + '/.config', 'r').readlines():
            if line.startswith('CONFIG_LOCALVERSION='):
                localversion = line.rstrip().split('"')[1]

        return "%s.%s.%s%s%s" %(version, patchlevel, sublevel, extraversion, localversion)


    def set_build_target(self, build_target):
        if build_target:
            self.build_target = build_target
            print 'BUILD TARGET: %s' % self.build_target


    def set_cross_cc(self, target_arch=None, cross_compile=None,
                     build_target='bzImage'):
        """Set up to cross-compile.
                This is broken. We need to work out what the default
                compile produces, and if not, THEN set the cross
                compiler.
        """

        if self.target_arch:
            return

        # if someone has set build_target, don't clobber in set_cross_cc
        # run set_build_target before calling set_cross_cc
        if not self.build_target:
            self.set_build_target(build_target)

        # If no 'target_arch' given assume native compilation
        if target_arch is None:
            target_arch = utils.get_current_kernel_arch()
            if target_arch == 'ppc64':
                if self.build_target == 'bzImage':
                    self.build_target = 'vmlinux'

        if not cross_compile:
            cross_compile = self.job.config_get('kernel.cross_cc')

        if cross_compile:
            os.environ['CROSS_COMPILE'] = cross_compile
        else:
            if os.environ.has_key('CROSS_COMPILE'):
                del os.environ['CROSS_COMPILE']

        return                 # HACK. Crap out for now.

        # At this point I know what arch I *want* to build for
        # but have no way of working out what arch the default
        # compiler DOES build for.

        def install_package(package):
            raise NotImplementedError("I don't exist yet!")

        if target_arch == 'ppc64':
            install_package('ppc64-cross')
            cross_compile = os.path.join(self.autodir, 'sources/ppc64-cross/bin')

        elif target_arch == 'x86_64':
            install_package('x86_64-cross')
            cross_compile = os.path.join(self.autodir, 'sources/x86_64-cross/bin')

        os.environ['ARCH'] = self.target_arch = target_arch

        self.cross_compile = cross_compile
        if self.cross_compile:
            os.environ['CROSS_COMPILE'] = self.cross_compile


    def pickle_dump(self, filename):
        """dump a pickle of ourself out to the specified filename

        we can't pickle the backreference to job (it contains fd's),
        nor would we want to. Same for logfile (fd's).
        """
        temp = copy.copy(self)
        temp.job = None
        temp.logfile = None
        pickle.dump(temp, open(filename, 'w'))


class rpm_kernel(BootableKernel):
    """
    Class for installing a binary rpm kernel package
    """

    def __init__(self, job, rpm_package, subdir):
        super(rpm_kernel, self).__init__(job)
        self.rpm_package = rpm_package
        self.log_dir = os.path.join(subdir, 'debug')
        self.subdir = os.path.basename(subdir)
        if os.path.exists(self.log_dir):
            utils.system('rm -rf ' + self.log_dir)
        os.mkdir(self.log_dir)


    def build(self, *args, **dargs):
        """
        Dummy function, binary kernel so nothing to build.
        """
        pass


    @log.record
    @tee_output_logdir_mark
    def install(self, tag='autotest', install_vmlinux=True):
        self.installed_as = tag

        self.image = None
        self.initrd = ''
        for rpm_pack in self.rpm_package:
            rpm_name = utils.system_output('rpm -qp ' + rpm_pack)

            # install
            utils.system('rpm -i --force ' + rpm_pack)

            # get file list
            files = utils.system_output('rpm -ql ' + rpm_name).splitlines()

            # search for vmlinuz
            for file in files:
                if file.startswith('/boot/vmlinuz'):
                    self.full_version = file[len('/boot/vmlinuz-'):]
                    self.image = file
                    self.rpm_flavour = rpm_name.split('-')[1]

                    # get version and release number
                    self.version, self.release = utils.system_output(
                            'rpm --queryformat="%{VERSION}\\n%{RELEASE}\\n" -q '
                            + rpm_name).splitlines()[0:2]

                    # prefer /boot/kernel-version before /boot/kernel
                    if self.full_version:
                        break

            # search for initrd
            for file in files:
                if file.startswith('/boot/init'):
                    self.initrd = file
                    # prefer /boot/initrd-version before /boot/initrd
                    if len(file) > len('/boot/initrd'):
                        break

        if self.image == None:
            errmsg = "specified rpm file(s) don't contain /boot/vmlinuz"
            raise error.TestError(errmsg)

        # install vmlinux
        if install_vmlinux:
            for rpm_pack in self.rpm_package:
                vmlinux = utils.system_output(
                        'rpm -q -l -p %s | grep /boot/vmlinux' % rpm_pack)
            utils.system('cd /; rpm2cpio %s | cpio -imuv .%s 2>&1'
                         % (rpm_pack, vmlinux))
            if not os.path.exists(vmlinux):
                raise error.TestError('%s does not exist after installing %s'
                                      % (vmlinux, rpm_pack))


    def boot(self, args='', ident=True):
        """ install and boot this kernel
        """

        # If the kernel has not yet been installed,
        #   install it now as default tag.
        if not self.installed_as:
            self.install()

        expected_ident = self.full_version
        if not expected_ident:
            expected_ident = '-'.join([self.version,
                                       self.rpm_flavour,
                                       self.release])

        self._boot_kernel(args, ident, expected_ident,
                          None, 'rpm')


class rpm_kernel_suse(rpm_kernel):
    """ Class for installing openSUSE/SLE rpm kernel package
    """

    def install(self):
        # do not set the new kernel as the default one
        os.environ['PBL_AUTOTEST'] = '1'

        rpm_kernel.install(self, 'dummy')
        self.installed_as = self.job.bootloader.get_title_for_kernel(self.image)
        if not self.installed_as:
            errmsg = "cannot find installed kernel in bootloader configuration"
            raise error.TestError(errmsg)


    def add_to_bootloader(self, tag='dummy', args=''):
        """ Set parameters of this kernel in bootloader
        """

        # pull the base argument set from the job config
        baseargs = self.job.config_get('boot.default_args')
        if baseargs:
            args = baseargs + ' ' + args

        self.job.bootloader.add_args(tag, args)


def rpm_kernel_vendor(job, rpm_package, subdir):
    vendor = utils.get_os_vendor()
    if vendor == "SUSE":
        return rpm_kernel_suse(job, rpm_package, subdir)
    else:
        return rpm_kernel(job, rpm_package, subdir)


# just make the preprocessor a nop
def _preprocess_path_dummy(path):
    return path.strip()


# pull in some optional site-specific path pre-processing
preprocess_path = utils.import_site_function(__file__,
    "autotest_lib.client.bin.site_kernel", "preprocess_path",
    _preprocess_path_dummy)


def auto_kernel(job, path, subdir, tmp_dir, build_dir, leave=False):
    """
    Create a kernel object, dynamically selecting the appropriate class to use
    based on the path provided.
    """
    kernel_paths = [preprocess_path(path)]
    if kernel_paths[0].endswith('.list'):
    # Fetch the list of packages to install
        kernel_list = os.path.join(tmp_dir, 'kernel.list')
        utils.get_file(kernel_paths[0], kernel_list)
        kernel_paths = [p.strip() for p in open(kernel_list).readlines()]

    if kernel_paths[0].endswith('.rpm'):
        rpm_paths = []
        for kernel_path in kernel_paths:
            if os.path.exists(kernel_path):
                rpm_paths.append(kernel_path)
            else:
                # Fetch the rpm into the job's packages directory and pass it to
                # rpm_kernel
                rpm_name = os.path.basename(kernel_path)

                # If the preprocessed path (kernel_path) is only a name then
                # search for the kernel in all the repositories, else fetch the
                # kernel from that specific path.
                job.pkgmgr.fetch_pkg(rpm_name, os.path.join(job.pkgdir, rpm_name),
                                     repo_url=os.path.dirname(kernel_path))

                rpm_paths.append(os.path.join(job.pkgdir, rpm_name))
        return rpm_kernel_vendor(job, rpm_paths, subdir)
    else:
        if len(kernel_paths) > 1:
            raise error.TestError("don't know what to do with more than one non-rpm kernel file")
        return kernel(job,kernel_paths[0], subdir, tmp_dir, build_dir, leave)
