#! /usr/bin/python2.4
# -*- coding: utf-8 mode: python -*-
# kmdl.py - plugin for handling kmdls
# Copyright (C) 2006 A. Thimm
#
# This program 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 2
# of the License, or (at your option) any later version.
#
# 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.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
#
# by Troy Dawson <dawson@fnal.gov>
#
# This is a modification of A. Thimm's kmdl.py plugin
#  The modification is that is works with kernel-module-<module name>-<uname -r>
#  instead of <module name>-kmdl-<uname -r>
#  Another modification is that it also installs all kernel modules for all
#  of your installed kernels.
# $Id$

try:
    set = set
except:
    from sets import Set as set

import re
import rpm

from yum.plugins import TYPE_CORE

requires_api_version = '2.1'
plugin_type = (TYPE_CORE,)

KERNELS=["kernel", "kernel-smp", "kernel-bigmem", "kernel-hugemem", "kernel-largesmp", "kernel-xen0", "kernel-xenU", "kernel-kdump", "kernel-xen", "kernel-PAE"]

def uname_r(name, version, release):
    if name == 'kernel':
        return "%s-%s" % (version, release)
    else:
        (dummy, flavour) = name.split('-')
        return "%s-%s%s" % (version, release, flavour)

def old_kmdls(conduit):
    conduit.info(4, "---> WE ARE IN THE OLD_KMDLS FUNCTION")
    kmdls=[]
    for hdr in conduit.getRpmDB().getHdrList():
        m=re.match('(.*)-kmdl-.*', hdr[rpm.RPMTAG_NAME])
        if m:
            conduit.info(6, '----> this is a kmdl package from getHdrList %s' % m.group(1))
            kmdls.append(m.group(1))
        else:
            mkm=re.match('kernel-module-.*', hdr[rpm.RPMTAG_NAME])
            if mkm:
                conduit.info(6, '----> this is a kernel module from getHdrList %s' % mkm.group(0))
                tmp=mkm.group(0).split('-')
                if len(tmp) > 3:
                    km = tmp[2]
                    conduit.info(6, '----> this is the package from getHdrList %s' % km)
                    kmdls.append(km)
    conduit.info(4, '-----> old kmds are %s' % kmdls)
    return kmdls

def new_kmdls(conduit):
    conduit.info(4, "---> WE ARE IN THE NEW_KMDLS FUNCTION")
    kmdls=[]
    tsInfo=conduit.getTsInfo()
    for txmbr in tsInfo.getMembers():
        m=re.match('(.*)-kmdl-.*', txmbr.name)
        if m and txmbr.ts_state in ('i', 'u'):
            conduit.info(6, '----> this is a kmdl package from getMembers %s' % m.group(1))
            kmdls.append(m.group(1))
        else:
            mkm=re.match('kernel-module-.*', txmbr.name)
            if mkm and txmbr.ts_state in ('i', 'u'):
                conduit.info(6, '----> this is a kernel module from getMembers %s' % mkm.group(0))
                tmp=mkm.group(0).split('-')
                if len(tmp) > 3:
                    km = tmp[2]
                    conduit.info(6, '----> this is the package from getMembers %s' % km)
                    kmdls.append(km)
    conduit.info(4, '-----> new kmds are %s' % kmdls)
    return kmdls

def old_kernels(conduit):
    conduit.info(4, "---> WE ARE IN THE OLD_KERNELS FUNCTION")
    kernels=[]
    for hdr in conduit.getRpmDB().getHdrList():
        if hdr[rpm.RPMTAG_NAME] in KERNELS:
            kernels.append([uname_r(hdr[rpm.RPMTAG_NAME],
                                    hdr[rpm.RPMTAG_VERSION],
                                    hdr[rpm.RPMTAG_RELEASE]),
                             hdr[rpm.RPMTAG_ARCH]])
    return kernels

def new_kernels(conduit):
    conduit.info(4, "---> WE ARE IN THE NEW_KERNELS FUNCTION")
    kernels=[]
    tsInfo=conduit.getTsInfo()
    for txmbr in tsInfo.getMembers():
        if txmbr.name in KERNELS and txmbr.ts_state in ('i', 'u'):
            kernels.append([uname_r(txmbr.name, txmbr.version, txmbr.release),
                             txmbr.arch])
    return kernels

def kmdl_install(conduit, kernels, kmdls):
    conduit.info(4, "---> WE ARE IN THE KMDL_INSTALL FUNCTION")
    conduit.info(4, '-----> we have these kernels %s' % kernels)
    conduit.info(4, '-----> we have these kmdls %s' % kmdls)
    tsInfo = conduit.getTsInfo()
    for kernel in kernels:
        conduit.info(6, '------> working on kernel %s' % kernel)
        for kmdl in kmdls:
            conduit.info(6, '--------> working on kernel_module for package %s' % kmdl)
            kmpkgname="kernel-module-%s-%s" % (kmdl, kernel[0])
            kmdlpkgname="%s-kmdl-%s" % (kmdl, kernel[0])
            pkgfound=None
            for pkg in conduit.getPackages():
                if pkg.name == kmpkgname and pkg.arch == kernel[1]:
                    if not pkgfound or pkgfound.returnEVR() < pkg.returnEVR():
                        pkgfound=pkg
                elif pkg.name == kmdlpkgname and pkg.arch == kernel[1]:
                    if not pkgfound or pkgfound.returnEVR() < pkg.returnEVR():
                        pkgfound=pkg
            if pkgfound and not conduit.getRpmDB().installed(pkgfound.name, pkgfound.arch, pkgfound.epoch, pkgfound.version, pkgfound.release):
                (n, a, e, v, r) = pkgfound.pkgtup
                conduit.info(2, '---> Package %s.%s %s:%s-%s set to be %s' % (n, a, e, v, r,'installed'))
                tsInfo.addInstall(pkgfound)

def postresolve_hook(conduit):
    conduit.info(2, 'Beginning Kernel Module Plugin')
    kernels = new_kernels(conduit)
    kmdls = new_kmdls(conduit)
    if kernels or kmdls:
    	kernels = kernels + old_kernels(conduit)
    	kmdls = kmdls + old_kmdls(conduit)
    	kmdls = set(kmdls)
    	kmdl_install(conduit, kernels, kmdls)
    conduit.info(2, 'Finished Kernel Module Plugin')
