change the layout of the kickstart module
authorJF Ding <jian-feng.ding@intel.com>
Fri, 19 Aug 2011 08:39:54 +0000 (16:39 +0800)
committerJF Ding <jian-feng.ding@intel.com>
Fri, 19 Aug 2011 08:39:54 +0000 (16:39 +0800)
mic/kickstart/__init__.py
mic/kickstart/kickstart.py [deleted file]

index a74d927..b957719 100644 (file)
@@ -1,3 +1,814 @@
+#
+# kickstart.py : Apply kickstart configuration to a system
+#
+# Copyright 2007, Red Hat  Inc.
+#
+# 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; version 2 of the License.
+#
+# 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 Library 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
 import os, sys
+import shutil
+import subprocess
+import time
+import logging
+import string
+
+from mic.utils import errors
+from mic.utils import misc
+from mic.utils import fs_related as fs
+from mic import msger
+
 sys.path.append(os.path.dirname(__file__) or '.')
 import pykickstart
+
+import pykickstart.commands as kscommands
+import pykickstart.constants as ksconstants
+import pykickstart.errors as kserrors
+import pykickstart.parser as ksparser
+import pykickstart.version as ksversion
+from pykickstart.handlers.control import commandMap
+from pykickstart.handlers.control import dataMap
+
+import custom_commands.desktop as desktop
+import custom_commands.moblinrepo as moblinrepo
+import custom_commands.micboot as micboot
+
+def read_kickstart(path):
+    """Parse a kickstart file and return a KickstartParser instance.
+
+    This is a simple utility function which takes a path to a kickstart file,
+    parses it and returns a pykickstart KickstartParser instance which can
+    be then passed to an ImageCreator constructor.
+
+    If an error occurs, a CreatorError exception is thrown.
+
+    """
+    #version = ksversion.makeVersion()
+    #ks = ksparser.KickstartParser(version)
+
+    using_version = ksversion.DEVEL
+    commandMap[using_version]["desktop"] = desktop.Moblin_Desktop
+    commandMap[using_version]["repo"] = moblinrepo.Moblin_Repo
+    commandMap[using_version]["bootloader"] = micboot.Moblin_Bootloader
+    dataMap[using_version]["RepoData"] = moblinrepo.Moblin_RepoData
+    superclass = ksversion.returnClassForVersion(version=using_version)
+
+    class KSHandlers(superclass):
+        def __init__(self, mapping={}):
+            superclass.__init__(self, mapping=commandMap[using_version])
+
+    ks = ksparser.KickstartParser(KSHandlers())
+
+    try:
+        ks.readKickstart(path)
+    except IOError, (err, msg):
+        raise errors.KickstartError("Failed to read kickstart file "
+                                    "'%s' : %s" % (path, msg))
+    except kserrors.KickstartError, e:
+        raise errors.KickstartError("Failed to parse kickstart file "
+                                    "'%s' : %s" % (path, e))
+    return ks
+
+def build_name(kscfg, prefix = None, suffix = None, maxlen = None):
+    """Construct and return an image name string.
+
+    This is a utility function to help create sensible name and fslabel
+    strings. The name is constructed using the sans-prefix-and-extension
+    kickstart filename and the supplied prefix and suffix.
+
+    If the name exceeds the maxlen length supplied, the prefix is first dropped
+    and then the kickstart filename portion is reduced until it fits. In other
+    words, the suffix takes precedence over the kickstart portion and the
+    kickstart portion takes precedence over the prefix.
+
+    kscfg -- a path to a kickstart file
+    prefix -- a prefix to prepend to the name; defaults to None, which causes
+              no prefix to be used
+    suffix -- a suffix to append to the name; defaults to None, which causes
+              a YYYYMMDDHHMM suffix to be used
+    maxlen -- the maximum length for the returned string; defaults to None,
+              which means there is no restriction on the name length
+
+    Note, if maxlen is less then the len(suffix), you get to keep both pieces.
+
+    """
+    name = os.path.basename(kscfg)
+    idx = name.rfind('.')
+    if idx >= 0:
+        name = name[:idx]
+
+    if prefix is None:
+        prefix = ""
+    if suffix is None:
+        suffix = time.strftime("%Y%m%d%H%M")
+
+    if name.startswith(prefix):
+        name = name[len(prefix):]
+
+    ret = prefix + name + "-" + suffix
+    if not maxlen is None and len(ret) > maxlen:
+        ret = name[:maxlen - len(suffix) - 1] + "-" + suffix
+
+    return ret
+
+class KickstartConfig(object):
+    """A base class for applying kickstart configurations to a system."""
+    def __init__(self, instroot):
+        self.instroot = instroot
+
+    def path(self, subpath):
+        return self.instroot + subpath
+
+    def chroot(self):
+        os.chroot(self.instroot)
+        os.chdir("/")
+
+    def call(self, args):
+        if not os.path.exists("%s/%s" %(self.instroot, args[0])):
+            msger.warning("%s/%s" %(self.instroot, args[0]))
+            raise errors.KickstartError("Unable to run %s!" %(args))
+        subprocess.call(args, preexec_fn = self.chroot)
+
+    def apply(self):
+        pass
+
+class LanguageConfig(KickstartConfig):
+    """A class to apply a kickstart language configuration to a system."""
+    def apply(self, kslang):
+        lang = kslang.lang or "en_US.UTF-8"
+
+        f = open(self.path("/etc/sysconfig/i18n"), "w+")
+        f.write("LANG=\"" + lang + "\"\n")
+        f.close()
+
+class KeyboardConfig(KickstartConfig):
+    """A class to apply a kickstart keyboard configuration to a system."""
+    def apply(self, kskeyboard):
+        #
+        # FIXME:
+        #   should this impact the X keyboard config too?
+        #   or do we want to make X be able to do this mapping?
+        #
+        #k = rhpl.keyboard.Keyboard()
+        #if kskeyboard.keyboard:
+        #   k.set(kskeyboard.keyboard)
+        #k.write(self.instroot)
+        pass
+
+class TimezoneConfig(KickstartConfig):
+    """A class to apply a kickstart timezone configuration to a system."""
+    def apply(self, kstimezone):
+        tz = kstimezone.timezone or "America/New_York"
+        utc = str(kstimezone.isUtc)
+
+        f = open(self.path("/etc/sysconfig/clock"), "w+")
+        f.write("ZONE=\"" + tz + "\"\n")
+        f.write("UTC=" + utc + "\n")
+        f.close()
+        try:
+            shutil.copyfile(self.path("/usr/share/zoneinfo/%s" %(tz,)),
+                            self.path("/etc/localtime"))
+        except (IOError, OSError), (errno, msg):
+            raise errors.KickstartError("Error copying timezone info: %s" %(msg,))
+
+
+class AuthConfig(KickstartConfig):
+    """A class to apply a kickstart authconfig configuration to a system."""
+    def apply(self, ksauthconfig):
+        auth = ksauthconfig.authconfig or "--useshadow --enablemd5"
+        args = ["/usr/share/authconfig/authconfig.py", "--update", "--nostart"]
+        self.call(args + auth.split())
+
+class FirewallConfig(KickstartConfig):
+    """A class to apply a kickstart firewall configuration to a system."""
+    def apply(self, ksfirewall):
+        #
+        # FIXME: should handle the rest of the options
+        #
+        if not os.path.exists(self.path("/usr/sbin/lokkit")):
+            return
+        if ksfirewall.enabled:
+            status = "--enabled"
+        else:
+            status = "--disabled"
+
+        self.call(["/usr/sbin/lokkit",
+                   "-f", "--quiet", "--nostart", status])
+
+class RootPasswordConfig(KickstartConfig):
+    """A class to apply a kickstart root password configuration to a system."""
+    def unset(self):
+        self.call(["/usr/bin/passwd", "-d", "root"])
+
+    def set_encrypted(self, password):
+        self.call(["/usr/sbin/usermod", "-p", password, "root"])
+
+    def set_unencrypted(self, password):
+        for p in ("/bin/echo", "/usr/sbin/chpasswd"):
+            if not os.path.exists("%s/%s" %(self.instroot, p)):
+                raise errors.KickstartError("Unable to set unencrypted password due to lack of %s" % p)
+
+        p1 = subprocess.Popen(["/bin/echo", "root:%s" %password],
+                              stdout = subprocess.PIPE,
+                              preexec_fn = self.chroot)
+        p2 = subprocess.Popen(["/usr/sbin/chpasswd", "-m"],
+                              stdin = p1.stdout,
+                              stdout = subprocess.PIPE,
+                              preexec_fn = self.chroot)
+        p2.communicate()
+
+    def apply(self, ksrootpw):
+        if ksrootpw.isCrypted:
+            self.set_encrypted(ksrootpw.password)
+        elif ksrootpw.password != "":
+            self.set_unencrypted(ksrootpw.password)
+        else:
+            self.unset()
+
+class UserConfig(KickstartConfig):
+    def set_empty_passwd(self, user):
+        self.call(["/usr/bin/passwd", "-d", user])
+
+    def set_encrypted_passwd(self, user, password):
+        self.call(["/usr/sbin/usermod", "-p", "%s" % password, user])
+
+    def set_unencrypted_passwd(self, user, password):
+        for p in ("/bin/echo", "/usr/sbin/chpasswd"):
+            if not os.path.exists("%s/%s" %(self.instroot, p)):
+                raise errors.KickstartError("Unable to set unencrypted password due to lack of %s" % p)
+
+        p1 = subprocess.Popen(["/bin/echo", "%s:%s" %(user, password)],
+                              stdout = subprocess.PIPE,
+                              preexec_fn = self.chroot)
+        p2 = subprocess.Popen(["/usr/sbin/chpasswd", "-m"],
+                              stdin = p1.stdout,
+                              stdout = subprocess.PIPE,
+                              preexec_fn = self.chroot)
+        p2.communicate()
+
+    def addUser(self, userconfig):
+        args = [ "/usr/sbin/useradd" ]
+        if userconfig.groups:
+            args += [ "--groups", string.join(userconfig.groups, ",") ]
+        if userconfig.name:
+            args.append(userconfig.name)
+            dev_null = os.open("/dev/null", os.O_WRONLY)
+            subprocess.call(args,
+                             stdout = dev_null,
+                             stderr = dev_null,
+                             preexec_fn = self.chroot)
+            os.close(dev_null)
+            if userconfig.password not in (None, ""):
+                if userconfig.isCrypted:
+                    self.set_encrypted_passwd(userconfig.name, userconfig.password)
+                else:
+                    self.set_unencrypted_passwd(userconfig.name, userconfig.password)
+            else:
+                self.set_empty_passwd(userconfig.name)
+        else:
+            raise errors.KickstartError("Invalid kickstart command: %s" % userconfig.__str__())
+
+    def apply(self, user):
+        for userconfig in user.userList:
+            try:
+                self.addUser(userconfig)
+            except:
+                raise
+
+class ServicesConfig(KickstartConfig):
+    """A class to apply a kickstart services configuration to a system."""
+    def apply(self, ksservices):
+        if not os.path.exists(self.path("/sbin/chkconfig")):
+            return
+        for s in ksservices.enabled:
+            self.call(["/sbin/chkconfig", s, "on"])
+        for s in ksservices.disabled:
+            self.call(["/sbin/chkconfig", s, "off"])
+
+class XConfig(KickstartConfig):
+    """A class to apply a kickstart X configuration to a system."""
+    def apply(self, ksxconfig):
+        if ksxconfig.startX:
+            f = open(self.path("/etc/inittab"), "rw+")
+            buf = f.read()
+            buf = buf.replace("id:3:initdefault", "id:5:initdefault")
+            f.seek(0)
+            f.write(buf)
+            f.close()
+        if ksxconfig.defaultdesktop:
+            f = open(self.path("/etc/sysconfig/desktop"), "w")
+            f.write("DESKTOP="+ksxconfig.defaultdesktop+"\n")
+            f.close()
+
+class DesktopConfig(KickstartConfig):
+    """A class to apply a kickstart desktop configuration to a system."""
+    def apply(self, ksdesktop):
+        if ksdesktop.defaultdesktop:
+            f = open(self.path("/etc/sysconfig/desktop"), "w")
+            f.write("DESKTOP="+ksdesktop.defaultdesktop+"\n")
+            f.close()
+            if os.path.exists(self.path("/etc/gdm/custom.conf")):
+                f = open(self.path("/etc/skel/.dmrc"), "w")
+                f.write("[Desktop]\n")
+                f.write("Session="+ksdesktop.defaultdesktop.lower()+"\n")
+                f.close()
+        if ksdesktop.session:
+            if os.path.exists(self.path("/etc/sysconfig/uxlaunch")):
+                f = open(self.path("/etc/sysconfig/uxlaunch"), "a+")
+                f.write("session="+ksdesktop.session.lower()+"\n")
+                f.close()
+        if ksdesktop.autologinuser:
+            f = open(self.path("/etc/sysconfig/desktop"), "a+")
+            f.write("AUTOLOGIN_USER=" + ksdesktop.autologinuser + "\n")
+            f.close()
+            if ksdesktop.session:
+                if os.path.exists(self.path("/etc/sysconfig/uxlaunch")):
+                    f = open(self.path("/etc/sysconfig/uxlaunch"), "a+")
+                    f.write("user="+ksdesktop.autologinuser+"\n")
+                    f.close()
+            if os.path.exists(self.path("/etc/gdm/custom.conf")):
+                f = open(self.path("/etc/gdm/custom.conf"), "w")
+                f.write("[daemon]\n")
+                f.write("AutomaticLoginEnable=true\n")
+                f.write("AutomaticLogin=" + ksdesktop.autologinuser + "\n")
+                f.close()
+
+class MoblinRepoConfig(KickstartConfig):
+    """A class to apply a kickstart desktop configuration to a system."""
+    def __create_repo_section(self, repo, type, fd):
+        baseurl = None
+        mirrorlist = None
+        reposuffix = {"base":"", "debuginfo":"-debuginfo", "source":"-source"}
+        reponame = repo.name + reposuffix[type]
+        if type == "base":
+            if repo.baseurl:
+                baseurl = repo.baseurl
+            if repo.mirrorlist:
+                mirrorlist = repo.mirrorlist
+        elif type == "debuginfo":
+            if repo.baseurl:
+                if repo.baseurl.endswith("/"):
+                    baseurl = os.path.dirname(os.path.dirname(repo.baseurl))
+                else:
+                    baseurl = os.path.dirname(repo.baseurl)
+                baseurl += "/debug"
+            if repo.mirrorlist:
+                variant = repo.mirrorlist[repo.mirrorlist.find("$"):]
+                mirrorlist = repo.mirrorlist[0:repo.mirrorlist.find("$")]
+                mirrorlist += "debug" + "-" + variant
+        elif type == "source":
+            if repo.baseurl:
+                if repo.baseurl.endswith("/"):
+                    baseurl = os.path.dirname(os.path.dirname(os.path.dirname(repo.baseurl)))
+                else:
+                    baseurl = os.path.dirname(os.path.dirname(repo.baseurl))
+                baseurl += "/source"
+            if repo.mirrorlist:
+                variant = repo.mirrorlist[repo.mirrorlist.find("$"):]
+                mirrorlist = repo.mirrorlist[0:repo.mirrorlist.find("$")]
+                mirrorlist += "source" + "-" + variant
+
+        fd.write("[" + reponame + "]\n")
+        fd.write("name=" + reponame + "\n")
+        fd.write("failovermethod=priority\n")
+        if baseurl:
+            fd.write("baseurl=" + baseurl + "\n")
+        if mirrorlist:
+            fd.write("mirrorlist=" + mirrorlist + "\n")
+        """ Skip saving proxy settings """
+        #if repo.proxy:
+        #    fd.write("proxy=" + repo.proxy + "\n")
+        #if repo.proxy_username:
+        #    fd.write("proxy_username=" + repo.proxy_username + "\n")
+        #if repo.proxy_password:
+        #    fd.write("proxy_password=" + repo.proxy_password + "\n")
+        if repo.gpgkey:
+            fd.write("gpgkey=" + repo.gpgkey + "\n")
+            fd.write("gpgcheck=1\n")
+        else:
+            fd.write("gpgcheck=0\n")
+        if type == "source" or type == "debuginfo" or repo.disable:
+            fd.write("enabled=0\n")
+        else:
+            fd.write("enabled=1\n")
+        fd.write("\n")
+
+    def __create_repo_file(self, repo, repodir):
+        if not os.path.exists(self.path(repodir)):
+            fs.makedirs(self.path(repodir))
+        f = open(self.path(repodir + "/" + repo.name + ".repo"), "w")
+        self.__create_repo_section(repo, "base", f)
+        if repo.debuginfo:
+            self.__create_repo_section(repo, "debuginfo", f)
+        if repo.source:
+            self.__create_repo_section(repo, "source", f)
+        f.close()
+
+    def apply(self, ksrepo, repodata):
+        for repo in ksrepo.repoList:
+            if repo.save:
+                #self.__create_repo_file(repo, "/etc/yum.repos.d")
+                self.__create_repo_file(repo, "/etc/zypp/repos.d")
+        """ Import repo gpg keys """
+        if repodata:
+            dev_null = os.open("/dev/null", os.O_WRONLY)
+            for repo in repodata:
+                if repo['repokey']:
+                    subprocess.call([fs.find_binary_path("rpm"), "--root=%s" % self.instroot, "--import", repo['repokey']],
+                                    stdout = dev_null, stderr = dev_null)
+            os.close(dev_null)
+
+class RPMMacroConfig(KickstartConfig):
+    """A class to apply the specified rpm macros to the filesystem"""
+    def apply(self, ks):
+        if not ks:
+            return
+        if not os.path.exists(self.path("/etc/rpm")):
+            os.mkdir(self.path("/etc/rpm"))
+        f = open(self.path("/etc/rpm/macros.imgcreate"), "w+")
+        if exclude_docs(ks):
+            f.write("%_excludedocs 1\n")
+        f.write("%__file_context_path %{nil}\n")
+        if inst_langs(ks) != None:
+            f.write("%_install_langs ")
+            f.write(inst_langs(ks))
+            f.write("\n")
+        f.close()
+
+class NetworkConfig(KickstartConfig):
+    """A class to apply a kickstart network configuration to a system."""
+    def write_ifcfg(self, network):
+        p = self.path("/etc/sysconfig/network-scripts/ifcfg-" + network.device)
+
+        f = file(p, "w+")
+        os.chmod(p, 0644)
+
+        f.write("DEVICE=%s\n" % network.device)
+        f.write("BOOTPROTO=%s\n" % network.bootProto)
+
+        if network.bootProto.lower() == "static":
+            if network.ip:
+                f.write("IPADDR=%s\n" % network.ip)
+            if network.netmask:
+                f.write("NETMASK=%s\n" % network.netmask)
+
+        if network.onboot:
+            f.write("ONBOOT=on\n")
+        else:
+            f.write("ONBOOT=off\n")
+
+        if network.essid:
+            f.write("ESSID=%s\n" % network.essid)
+
+        if network.ethtool:
+            if network.ethtool.find("autoneg") == -1:
+                network.ethtool = "autoneg off " + network.ethtool
+            f.write("ETHTOOL_OPTS=%s\n" % network.ethtool)
+
+        if network.bootProto.lower() == "dhcp":
+            if network.hostname:
+                f.write("DHCP_HOSTNAME=%s\n" % network.hostname)
+            if network.dhcpclass:
+                f.write("DHCP_CLASSID=%s\n" % network.dhcpclass)
+
+        if network.mtu:
+            f.write("MTU=%s\n" % network.mtu)
+
+        f.close()
+
+    def write_wepkey(self, network):
+        if not network.wepkey:
+            return
+
+        p = self.path("/etc/sysconfig/network-scripts/keys-" + network.device)
+        f = file(p, "w+")
+        os.chmod(p, 0600)
+        f.write("KEY=%s\n" % network.wepkey)
+        f.close()
+
+    def write_sysconfig(self, useipv6, hostname, gateway):
+        path = self.path("/etc/sysconfig/network")
+        f = file(path, "w+")
+        os.chmod(path, 0644)
+
+        f.write("NETWORKING=yes\n")
+
+        if useipv6:
+            f.write("NETWORKING_IPV6=yes\n")
+        else:
+            f.write("NETWORKING_IPV6=no\n")
+
+        if hostname:
+            f.write("HOSTNAME=%s\n" % hostname)
+        else:
+            f.write("HOSTNAME=localhost.localdomain\n")
+
+        if gateway:
+            f.write("GATEWAY=%s\n" % gateway)
+
+        f.close()
+
+    def write_hosts(self, hostname):
+        localline = ""
+        if hostname and hostname != "localhost.localdomain":
+            localline += hostname + " "
+            l = hostname.split(".")
+            if len(l) > 1:
+                localline += l[0] + " "
+        localline += "localhost.localdomain localhost"
+
+        path = self.path("/etc/hosts")
+        f = file(path, "w+")
+        os.chmod(path, 0644)
+        f.write("127.0.0.1\t\t%s\n" % localline)
+        f.write("::1\t\tlocalhost6.localdomain6 localhost6\n")
+        f.close()
+
+    def write_resolv(self, nodns, nameservers):
+        if nodns or not nameservers:
+            return
+
+        path = self.path("/etc/resolv.conf")
+        f = file(path, "w+")
+        os.chmod(path, 0644)
+
+        for ns in (nameservers):
+            if ns:
+                f.write("nameserver %s\n" % ns)
+
+        f.close()
+
+    def apply(self, ksnet):
+        fs.makedirs(self.path("/etc/sysconfig/network-scripts"))
+
+        useipv6 = False
+        nodns = False
+        hostname = None
+        gateway = None
+        nameservers = None
+
+        for network in ksnet.network:
+            if not network.device:
+                raise errors.KickstartError("No --device specified with "
+                                            "network kickstart command")
+
+            if (network.onboot and network.bootProto.lower() != "dhcp" and
+                not (network.ip and network.netmask)):
+                raise errors.KickstartError("No IP address and/or netmask "
+                                            "specified with static "
+                                            "configuration for '%s'" %
+                                            network.device)
+
+            self.write_ifcfg(network)
+            self.write_wepkey(network)
+
+            if network.ipv6:
+                useipv6 = True
+            if network.nodns:
+                nodns = True
+
+            if network.hostname:
+                hostname = network.hostname
+            if network.gateway:
+                gateway = network.gateway
+
+            if network.nameserver:
+                nameservers = network.nameserver.split(",")
+
+        self.write_sysconfig(useipv6, hostname, gateway)
+        self.write_hosts(hostname)
+        self.write_resolv(nodns, nameservers)
+
+
+def get_image_size(ks, default = None):
+    __size = 0
+    for p in ks.handler.partition.partitions:
+        if p.mountpoint == "/" and p.size:
+            __size = p.size
+    if __size > 0:
+        return int(__size) * 1024L * 1024L
+    else:
+        return default
+
+def get_image_fstype(ks, default = None):
+    for p in ks.handler.partition.partitions:
+        if p.mountpoint == "/" and p.fstype:
+            return p.fstype
+    return default
+
+def get_image_fsopts(ks, default = None):
+    for p in ks.handler.partition.partitions:
+        if p.mountpoint == "/" and p.fsopts:
+            return p.fstype
+    return default
+
+def get_modules(ks):
+    devices = []
+    if isinstance(ks.handler.device, kscommands.device.FC3_Device):
+        devices.append(ks.handler.device)
+    else:
+        devices.extend(ks.handler.device.deviceList)
+
+    modules = []
+    for device in devices:
+        if not device.moduleName:
+            continue
+        modules.extend(device.moduleName.split(":"))
+
+    return modules
+
+def get_timeout(ks, default = None):
+    if not hasattr(ks.handler.bootloader, "timeout"):
+        return default
+    if ks.handler.bootloader.timeout is None:
+        return default
+    return int(ks.handler.bootloader.timeout)
+
+def get_kernel_args(ks, default = "ro liveimg"):
+    if not hasattr(ks.handler.bootloader, "appendLine"):
+        return default
+    if ks.handler.bootloader.appendLine is None:
+        return default
+    return "%s %s" %(default, ks.handler.bootloader.appendLine)
+
+def get_menu_args(ks, default = "liveinst"):
+    if not hasattr(ks.handler.bootloader, "menus"):
+        return default
+    if ks.handler.bootloader.menus in (None, ""):
+        return default
+    return "%s" % ks.handler.bootloader.menus
+
+def get_default_kernel(ks, default = None):
+    if not hasattr(ks.handler.bootloader, "default"):
+        return default
+    if not ks.handler.bootloader.default:
+        return default
+    return ks.handler.bootloader.default
+
+def get_repos(ks, repo_urls = {}):
+    repos = {}
+    for repo in ks.handler.repo.repoList:
+        inc = []
+        if hasattr(repo, "includepkgs"):
+            inc.extend(repo.includepkgs)
+
+        exc = []
+        if hasattr(repo, "excludepkgs"):
+            exc.extend(repo.excludepkgs)
+
+        baseurl = repo.baseurl
+        mirrorlist = repo.mirrorlist
+
+        if repo.name in repo_urls:
+            baseurl = repo_urls[repo.name]
+            mirrorlist = None
+
+        if repos.has_key(repo.name):
+            logging.warn("Overriding already specified repo %s" %(repo.name,))
+
+        proxy = None
+        if hasattr(repo, "proxy"):
+            proxy = repo.proxy
+        proxy_username = None
+        if hasattr(repo, "proxy_username"):
+            proxy_username = repo.proxy_username
+        proxy_password = None
+        if hasattr(repo, "proxy_password"):
+            proxy_password = repo.proxy_password
+        if hasattr(repo, "debuginfo"):
+            debuginfo = repo.debuginfo
+        if hasattr(repo, "source"):
+            source = repo.source
+        if hasattr(repo, "gpgkey"):
+            gpgkey = repo.gpgkey
+        if hasattr(repo, "disable"):
+            disable = repo.disable
+
+        repos[repo.name] = (repo.name, baseurl, mirrorlist, inc, exc, proxy, proxy_username, proxy_password, debuginfo, source, gpgkey, disable)
+
+    return repos.values()
+
+def convert_method_to_repo(ks):
+    try:
+        ks.handler.repo.methodToRepo()
+    except (AttributeError, kserrors.KickstartError):
+        pass
+
+def get_packages(ks, required = []):
+    return ks.handler.packages.packageList + required
+
+def get_groups(ks, required = []):
+    return ks.handler.packages.groupList + required
+
+def get_excluded(ks, required = []):
+    return ks.handler.packages.excludedList + required
+
+def get_partitions(ks, required = []):
+    return ks.handler.partition.partitions
+
+def ignore_missing(ks):
+    return ks.handler.packages.handleMissing == ksconstants.KS_MISSING_IGNORE
+
+def exclude_docs(ks):
+    return ks.handler.packages.excludeDocs
+
+def inst_langs(ks):
+    if hasattr(ks.handler.packages, "instLange"):
+        return ks.handler.packages.instLange
+    elif hasattr(ks.handler.packages, "instLangs"):
+        return ks.handler.packages.instLangs
+    return ""
+
+def get_post_scripts(ks):
+    scripts = []
+    for s in ks.handler.scripts:
+        if s.type != ksparser.KS_SCRIPT_POST:
+            continue
+        scripts.append(s)
+    return scripts
+
+def add_repo(ks, repostr):
+    args = repostr.split()
+    repoobj = ks.handler.repo.parse(args[1:])
+    if repoobj and repoobj not in ks.handler.repo.repoList:
+        ks.handler.repo.repoList.append(repoobj)
+
+def remove_all_repos(ks):
+    while len(ks.handler.repo.repoList) != 0:
+        del ks.handler.repo.repoList[0]
+
+def remove_duplicate_repos(ks):
+    i = 0
+    j = i + 1
+    while True:
+        if len(ks.handler.repo.repoList) < 2:
+            break
+        if i >= len(ks.handler.repo.repoList) - 1:
+            break
+        name = ks.handler.repo.repoList[i].name
+        baseurl = ks.handler.repo.repoList[i].baseurl
+        if j < len(ks.handler.repo.repoList):
+            if (ks.handler.repo.repoList[j].name == name or \
+                ks.handler.repo.repoList[j].baseurl == baseurl):
+                del ks.handler.repo.repoList[j]
+            else:
+                j += 1
+            if j >= len(ks.handler.repo.repoList):
+                i += 1
+                j = i + 1
+        else:
+            i += 1
+            j = i + 1
+
+def resolve_groups(creator, repometadata, use_comps = False):
+    pkgmgr = creator.pkgmgr.get_default_pkg_manager
+    iszypp = False
+    if creator.pkgmgr.managers.has_key("zypp") and creator.pkgmgr.managers['zypp'] == pkgmgr:
+        iszypp = True
+    ks = creator.ks
+
+    for repo in repometadata:
+        """ Mustn't replace group with package list if repo is ready for the corresponding package manager """
+        if iszypp and repo["patterns"] and not use_comps:
+            continue
+        if not iszypp and repo["comps"] and use_comps:
+            continue
+
+        """
+            But we also must handle such cases, use zypp but repo only has comps,
+            use yum but repo only has patterns, use zypp but use_comps is true,
+            use yum but use_comps is false.
+        """
+        groupfile = None
+        if iszypp:
+            if (use_comps and repo["comps"]) or (not repo["patterns"] and repo["comps"]):
+                groupfile = repo["comps"]
+                get_pkglist_handler = misc.get_pkglist_in_comps
+        if not iszypp:
+            if (not use_comps and repo["patterns"]) or (not repo["comps"] and repo["patterns"]):
+                groupfile = repo["patterns"]
+                get_pkglist_handler = misc.get_pkglist_in_patterns
+
+        if groupfile:
+            i = 0
+            while True:
+                if i >= len(ks.handler.packages.groupList):
+                    break
+                pkglist = get_pkglist_handler(ks.handler.packages.groupList[i].name, groupfile)
+                if pkglist:
+                    del ks.handler.packages.groupList[i]
+                    for pkg in pkglist:
+                        if pkg not in ks.handler.packages.packageList:
+                            ks.handler.packages.packageList.append(pkg)
+                else:
+                    i = i + 1
diff --git a/mic/kickstart/kickstart.py b/mic/kickstart/kickstart.py
deleted file mode 100644 (file)
index 78a254a..0000000
+++ /dev/null
@@ -1,811 +0,0 @@
-#
-# kickstart.py : Apply kickstart configuration to a system
-#
-# Copyright 2007, Red Hat  Inc.
-#
-# 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; version 2 of the License.
-#
-# 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 Library 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
-
-import os, sys
-import shutil
-import subprocess
-import time
-import logging
-import string
-
-import errors
-import misc
-import fs_related as fs
-from mic import msger
-
-import pykickstart.commands as kscommands
-import pykickstart.constants as ksconstants
-import pykickstart.errors as kserrors
-import pykickstart.parser as ksparser
-import pykickstart.version as ksversion
-from pykickstart.handlers.control import commandMap
-from pykickstart.handlers.control import dataMap
-
-import custom_commands.desktop as desktop
-import custom_commands.moblinrepo as moblinrepo
-import custom_commands.micboot as micboot
-
-def read_kickstart(path):
-    """Parse a kickstart file and return a KickstartParser instance.
-
-    This is a simple utility function which takes a path to a kickstart file,
-    parses it and returns a pykickstart KickstartParser instance which can
-    be then passed to an ImageCreator constructor.
-
-    If an error occurs, a CreatorError exception is thrown.
-
-    """
-    #version = ksversion.makeVersion()
-    #ks = ksparser.KickstartParser(version)
-
-    using_version = ksversion.DEVEL
-    commandMap[using_version]["desktop"] = desktop.Moblin_Desktop
-    commandMap[using_version]["repo"] = moblinrepo.Moblin_Repo
-    commandMap[using_version]["bootloader"] = micboot.Moblin_Bootloader
-    dataMap[using_version]["RepoData"] = moblinrepo.Moblin_RepoData
-    superclass = ksversion.returnClassForVersion(version=using_version)
-
-    class KSHandlers(superclass):
-        def __init__(self, mapping={}):
-            superclass.__init__(self, mapping=commandMap[using_version])
-
-    ks = ksparser.KickstartParser(KSHandlers())
-
-    try:
-        ks.readKickstart(path)
-    except IOError, (err, msg):
-        raise errors.KickstartError("Failed to read kickstart file "
-                                    "'%s' : %s" % (path, msg))
-    except kserrors.KickstartError, e:
-        raise errors.KickstartError("Failed to parse kickstart file "
-                                    "'%s' : %s" % (path, e))
-    return ks
-
-def build_name(kscfg, prefix = None, suffix = None, maxlen = None):
-    """Construct and return an image name string.
-
-    This is a utility function to help create sensible name and fslabel
-    strings. The name is constructed using the sans-prefix-and-extension
-    kickstart filename and the supplied prefix and suffix.
-
-    If the name exceeds the maxlen length supplied, the prefix is first dropped
-    and then the kickstart filename portion is reduced until it fits. In other
-    words, the suffix takes precedence over the kickstart portion and the
-    kickstart portion takes precedence over the prefix.
-
-    kscfg -- a path to a kickstart file
-    prefix -- a prefix to prepend to the name; defaults to None, which causes
-              no prefix to be used
-    suffix -- a suffix to append to the name; defaults to None, which causes
-              a YYYYMMDDHHMM suffix to be used
-    maxlen -- the maximum length for the returned string; defaults to None,
-              which means there is no restriction on the name length
-
-    Note, if maxlen is less then the len(suffix), you get to keep both pieces.
-
-    """
-    name = os.path.basename(kscfg)
-    idx = name.rfind('.')
-    if idx >= 0:
-        name = name[:idx]
-
-    if prefix is None:
-        prefix = ""
-    if suffix is None:
-        suffix = time.strftime("%Y%m%d%H%M")
-
-    if name.startswith(prefix):
-        name = name[len(prefix):]
-
-    ret = prefix + name + "-" + suffix
-    if not maxlen is None and len(ret) > maxlen:
-        ret = name[:maxlen - len(suffix) - 1] + "-" + suffix
-
-    return ret
-
-class KickstartConfig(object):
-    """A base class for applying kickstart configurations to a system."""
-    def __init__(self, instroot):
-        self.instroot = instroot
-
-    def path(self, subpath):
-        return self.instroot + subpath
-
-    def chroot(self):
-        os.chroot(self.instroot)
-        os.chdir("/")
-
-    def call(self, args):
-        if not os.path.exists("%s/%s" %(self.instroot, args[0])):
-            msger.warning("%s/%s" %(self.instroot, args[0]))
-            raise errors.KickstartError("Unable to run %s!" %(args))
-        subprocess.call(args, preexec_fn = self.chroot)
-
-    def apply(self):
-        pass
-
-class LanguageConfig(KickstartConfig):
-    """A class to apply a kickstart language configuration to a system."""
-    def apply(self, kslang):
-        lang = kslang.lang or "en_US.UTF-8"
-
-        f = open(self.path("/etc/sysconfig/i18n"), "w+")
-        f.write("LANG=\"" + lang + "\"\n")
-        f.close()
-
-class KeyboardConfig(KickstartConfig):
-    """A class to apply a kickstart keyboard configuration to a system."""
-    def apply(self, kskeyboard):
-        #
-        # FIXME:
-        #   should this impact the X keyboard config too?
-        #   or do we want to make X be able to do this mapping?
-        #
-        #k = rhpl.keyboard.Keyboard()
-        #if kskeyboard.keyboard:
-        #   k.set(kskeyboard.keyboard)
-        #k.write(self.instroot)
-        pass
-
-class TimezoneConfig(KickstartConfig):
-    """A class to apply a kickstart timezone configuration to a system."""
-    def apply(self, kstimezone):
-        tz = kstimezone.timezone or "America/New_York"
-        utc = str(kstimezone.isUtc)
-
-        f = open(self.path("/etc/sysconfig/clock"), "w+")
-        f.write("ZONE=\"" + tz + "\"\n")
-        f.write("UTC=" + utc + "\n")
-        f.close()
-        try:
-            shutil.copyfile(self.path("/usr/share/zoneinfo/%s" %(tz,)),
-                            self.path("/etc/localtime"))
-        except (IOError, OSError), (errno, msg):
-            raise errors.KickstartError("Error copying timezone info: %s" %(msg,))
-
-
-class AuthConfig(KickstartConfig):
-    """A class to apply a kickstart authconfig configuration to a system."""
-    def apply(self, ksauthconfig):
-        auth = ksauthconfig.authconfig or "--useshadow --enablemd5"
-        args = ["/usr/share/authconfig/authconfig.py", "--update", "--nostart"]
-        self.call(args + auth.split())
-
-class FirewallConfig(KickstartConfig):
-    """A class to apply a kickstart firewall configuration to a system."""
-    def apply(self, ksfirewall):
-        #
-        # FIXME: should handle the rest of the options
-        #
-        if not os.path.exists(self.path("/usr/sbin/lokkit")):
-            return
-        if ksfirewall.enabled:
-            status = "--enabled"
-        else:
-            status = "--disabled"
-
-        self.call(["/usr/sbin/lokkit",
-                   "-f", "--quiet", "--nostart", status])
-
-class RootPasswordConfig(KickstartConfig):
-    """A class to apply a kickstart root password configuration to a system."""
-    def unset(self):
-        self.call(["/usr/bin/passwd", "-d", "root"])
-
-    def set_encrypted(self, password):
-        self.call(["/usr/sbin/usermod", "-p", password, "root"])
-
-    def set_unencrypted(self, password):
-        for p in ("/bin/echo", "/usr/sbin/chpasswd"):
-            if not os.path.exists("%s/%s" %(self.instroot, p)):
-                raise errors.KickstartError("Unable to set unencrypted password due to lack of %s" % p)
-
-        p1 = subprocess.Popen(["/bin/echo", "root:%s" %password],
-                              stdout = subprocess.PIPE,
-                              preexec_fn = self.chroot)
-        p2 = subprocess.Popen(["/usr/sbin/chpasswd", "-m"],
-                              stdin = p1.stdout,
-                              stdout = subprocess.PIPE,
-                              preexec_fn = self.chroot)
-        p2.communicate()
-
-    def apply(self, ksrootpw):
-        if ksrootpw.isCrypted:
-            self.set_encrypted(ksrootpw.password)
-        elif ksrootpw.password != "":
-            self.set_unencrypted(ksrootpw.password)
-        else:
-            self.unset()
-
-class UserConfig(KickstartConfig):
-    def set_empty_passwd(self, user):
-        self.call(["/usr/bin/passwd", "-d", user])
-
-    def set_encrypted_passwd(self, user, password):
-        self.call(["/usr/sbin/usermod", "-p", "%s" % password, user])
-
-    def set_unencrypted_passwd(self, user, password):
-        for p in ("/bin/echo", "/usr/sbin/chpasswd"):
-            if not os.path.exists("%s/%s" %(self.instroot, p)):
-                raise errors.KickstartError("Unable to set unencrypted password due to lack of %s" % p)
-
-        p1 = subprocess.Popen(["/bin/echo", "%s:%s" %(user, password)],
-                              stdout = subprocess.PIPE,
-                              preexec_fn = self.chroot)
-        p2 = subprocess.Popen(["/usr/sbin/chpasswd", "-m"],
-                              stdin = p1.stdout,
-                              stdout = subprocess.PIPE,
-                              preexec_fn = self.chroot)
-        p2.communicate()
-
-    def addUser(self, userconfig):
-        args = [ "/usr/sbin/useradd" ]
-        if userconfig.groups:
-            args += [ "--groups", string.join(userconfig.groups, ",") ]
-        if userconfig.name:
-            args.append(userconfig.name)
-            dev_null = os.open("/dev/null", os.O_WRONLY)
-            subprocess.call(args,
-                             stdout = dev_null,
-                             stderr = dev_null,
-                             preexec_fn = self.chroot)
-            os.close(dev_null)
-            if userconfig.password not in (None, ""):
-                if userconfig.isCrypted:
-                    self.set_encrypted_passwd(userconfig.name, userconfig.password)
-                else:
-                    self.set_unencrypted_passwd(userconfig.name, userconfig.password)
-            else:
-                self.set_empty_passwd(userconfig.name)
-        else:
-            raise errors.KickstartError("Invalid kickstart command: %s" % userconfig.__str__())
-
-    def apply(self, user):
-        for userconfig in user.userList:
-            try:
-                self.addUser(userconfig)
-            except:
-                raise
-
-class ServicesConfig(KickstartConfig):
-    """A class to apply a kickstart services configuration to a system."""
-    def apply(self, ksservices):
-        if not os.path.exists(self.path("/sbin/chkconfig")):
-            return
-        for s in ksservices.enabled:
-            self.call(["/sbin/chkconfig", s, "on"])
-        for s in ksservices.disabled:
-            self.call(["/sbin/chkconfig", s, "off"])
-
-class XConfig(KickstartConfig):
-    """A class to apply a kickstart X configuration to a system."""
-    def apply(self, ksxconfig):
-        if ksxconfig.startX:
-            f = open(self.path("/etc/inittab"), "rw+")
-            buf = f.read()
-            buf = buf.replace("id:3:initdefault", "id:5:initdefault")
-            f.seek(0)
-            f.write(buf)
-            f.close()
-        if ksxconfig.defaultdesktop:
-            f = open(self.path("/etc/sysconfig/desktop"), "w")
-            f.write("DESKTOP="+ksxconfig.defaultdesktop+"\n")
-            f.close()
-
-class DesktopConfig(KickstartConfig):
-    """A class to apply a kickstart desktop configuration to a system."""
-    def apply(self, ksdesktop):
-        if ksdesktop.defaultdesktop:
-            f = open(self.path("/etc/sysconfig/desktop"), "w")
-            f.write("DESKTOP="+ksdesktop.defaultdesktop+"\n")
-            f.close()
-            if os.path.exists(self.path("/etc/gdm/custom.conf")):
-                f = open(self.path("/etc/skel/.dmrc"), "w")
-                f.write("[Desktop]\n")
-                f.write("Session="+ksdesktop.defaultdesktop.lower()+"\n")
-                f.close()
-        if ksdesktop.session:
-            if os.path.exists(self.path("/etc/sysconfig/uxlaunch")):
-                f = open(self.path("/etc/sysconfig/uxlaunch"), "a+")
-                f.write("session="+ksdesktop.session.lower()+"\n")
-                f.close()
-        if ksdesktop.autologinuser:
-            f = open(self.path("/etc/sysconfig/desktop"), "a+")
-            f.write("AUTOLOGIN_USER=" + ksdesktop.autologinuser + "\n")
-            f.close()
-            if ksdesktop.session:
-                if os.path.exists(self.path("/etc/sysconfig/uxlaunch")):
-                    f = open(self.path("/etc/sysconfig/uxlaunch"), "a+")
-                    f.write("user="+ksdesktop.autologinuser+"\n")
-                    f.close()
-            if os.path.exists(self.path("/etc/gdm/custom.conf")):
-                f = open(self.path("/etc/gdm/custom.conf"), "w")
-                f.write("[daemon]\n")
-                f.write("AutomaticLoginEnable=true\n")
-                f.write("AutomaticLogin=" + ksdesktop.autologinuser + "\n")
-                f.close()
-
-class MoblinRepoConfig(KickstartConfig):
-    """A class to apply a kickstart desktop configuration to a system."""
-    def __create_repo_section(self, repo, type, fd):
-        baseurl = None
-        mirrorlist = None
-        reposuffix = {"base":"", "debuginfo":"-debuginfo", "source":"-source"}
-        reponame = repo.name + reposuffix[type]
-        if type == "base":
-            if repo.baseurl:
-                baseurl = repo.baseurl
-            if repo.mirrorlist:
-                mirrorlist = repo.mirrorlist
-        elif type == "debuginfo":
-            if repo.baseurl:
-                if repo.baseurl.endswith("/"):
-                    baseurl = os.path.dirname(os.path.dirname(repo.baseurl))
-                else:
-                    baseurl = os.path.dirname(repo.baseurl)
-                baseurl += "/debug"
-            if repo.mirrorlist:
-                variant = repo.mirrorlist[repo.mirrorlist.find("$"):]
-                mirrorlist = repo.mirrorlist[0:repo.mirrorlist.find("$")]
-                mirrorlist += "debug" + "-" + variant
-        elif type == "source":
-            if repo.baseurl:
-                if repo.baseurl.endswith("/"):
-                    baseurl = os.path.dirname(os.path.dirname(os.path.dirname(repo.baseurl)))
-                else:
-                    baseurl = os.path.dirname(os.path.dirname(repo.baseurl))
-                baseurl += "/source"
-            if repo.mirrorlist:
-                variant = repo.mirrorlist[repo.mirrorlist.find("$"):]
-                mirrorlist = repo.mirrorlist[0:repo.mirrorlist.find("$")]
-                mirrorlist += "source" + "-" + variant
-
-        fd.write("[" + reponame + "]\n")
-        fd.write("name=" + reponame + "\n")
-        fd.write("failovermethod=priority\n")
-        if baseurl:
-            fd.write("baseurl=" + baseurl + "\n")
-        if mirrorlist:
-            fd.write("mirrorlist=" + mirrorlist + "\n")
-        """ Skip saving proxy settings """
-        #if repo.proxy:
-        #    fd.write("proxy=" + repo.proxy + "\n")
-        #if repo.proxy_username:
-        #    fd.write("proxy_username=" + repo.proxy_username + "\n")
-        #if repo.proxy_password:
-        #    fd.write("proxy_password=" + repo.proxy_password + "\n")
-        if repo.gpgkey:
-            fd.write("gpgkey=" + repo.gpgkey + "\n")
-            fd.write("gpgcheck=1\n")
-        else:
-            fd.write("gpgcheck=0\n")
-        if type == "source" or type == "debuginfo" or repo.disable:
-            fd.write("enabled=0\n")
-        else:
-            fd.write("enabled=1\n")
-        fd.write("\n")
-
-    def __create_repo_file(self, repo, repodir):
-        if not os.path.exists(self.path(repodir)):
-            fs.makedirs(self.path(repodir))
-        f = open(self.path(repodir + "/" + repo.name + ".repo"), "w")
-        self.__create_repo_section(repo, "base", f)
-        if repo.debuginfo:
-            self.__create_repo_section(repo, "debuginfo", f)
-        if repo.source:
-            self.__create_repo_section(repo, "source", f)
-        f.close()
-
-    def apply(self, ksrepo, repodata):
-        for repo in ksrepo.repoList:
-            if repo.save:
-                #self.__create_repo_file(repo, "/etc/yum.repos.d")
-                self.__create_repo_file(repo, "/etc/zypp/repos.d")
-        """ Import repo gpg keys """
-        if repodata:
-            dev_null = os.open("/dev/null", os.O_WRONLY)
-            for repo in repodata:
-                if repo['repokey']:
-                    subprocess.call([fs.find_binary_path("rpm"), "--root=%s" % self.instroot, "--import", repo['repokey']],
-                                    stdout = dev_null, stderr = dev_null)
-            os.close(dev_null)
-
-class RPMMacroConfig(KickstartConfig):
-    """A class to apply the specified rpm macros to the filesystem"""
-    def apply(self, ks):
-        if not ks:
-            return
-        if not os.path.exists(self.path("/etc/rpm")):
-            os.mkdir(self.path("/etc/rpm"))
-        f = open(self.path("/etc/rpm/macros.imgcreate"), "w+")
-        if exclude_docs(ks):
-            f.write("%_excludedocs 1\n")
-        f.write("%__file_context_path %{nil}\n")
-        if inst_langs(ks) != None:
-            f.write("%_install_langs ")
-            f.write(inst_langs(ks))
-            f.write("\n")
-        f.close()
-
-class NetworkConfig(KickstartConfig):
-    """A class to apply a kickstart network configuration to a system."""
-    def write_ifcfg(self, network):
-        p = self.path("/etc/sysconfig/network-scripts/ifcfg-" + network.device)
-
-        f = file(p, "w+")
-        os.chmod(p, 0644)
-
-        f.write("DEVICE=%s\n" % network.device)
-        f.write("BOOTPROTO=%s\n" % network.bootProto)
-
-        if network.bootProto.lower() == "static":
-            if network.ip:
-                f.write("IPADDR=%s\n" % network.ip)
-            if network.netmask:
-                f.write("NETMASK=%s\n" % network.netmask)
-
-        if network.onboot:
-            f.write("ONBOOT=on\n")
-        else:
-            f.write("ONBOOT=off\n")
-
-        if network.essid:
-            f.write("ESSID=%s\n" % network.essid)
-
-        if network.ethtool:
-            if network.ethtool.find("autoneg") == -1:
-                network.ethtool = "autoneg off " + network.ethtool
-            f.write("ETHTOOL_OPTS=%s\n" % network.ethtool)
-
-        if network.bootProto.lower() == "dhcp":
-            if network.hostname:
-                f.write("DHCP_HOSTNAME=%s\n" % network.hostname)
-            if network.dhcpclass:
-                f.write("DHCP_CLASSID=%s\n" % network.dhcpclass)
-
-        if network.mtu:
-            f.write("MTU=%s\n" % network.mtu)
-
-        f.close()
-
-    def write_wepkey(self, network):
-        if not network.wepkey:
-            return
-
-        p = self.path("/etc/sysconfig/network-scripts/keys-" + network.device)
-        f = file(p, "w+")
-        os.chmod(p, 0600)
-        f.write("KEY=%s\n" % network.wepkey)
-        f.close()
-
-    def write_sysconfig(self, useipv6, hostname, gateway):
-        path = self.path("/etc/sysconfig/network")
-        f = file(path, "w+")
-        os.chmod(path, 0644)
-
-        f.write("NETWORKING=yes\n")
-
-        if useipv6:
-            f.write("NETWORKING_IPV6=yes\n")
-        else:
-            f.write("NETWORKING_IPV6=no\n")
-
-        if hostname:
-            f.write("HOSTNAME=%s\n" % hostname)
-        else:
-            f.write("HOSTNAME=localhost.localdomain\n")
-
-        if gateway:
-            f.write("GATEWAY=%s\n" % gateway)
-
-        f.close()
-
-    def write_hosts(self, hostname):
-        localline = ""
-        if hostname and hostname != "localhost.localdomain":
-            localline += hostname + " "
-            l = hostname.split(".")
-            if len(l) > 1:
-                localline += l[0] + " "
-        localline += "localhost.localdomain localhost"
-
-        path = self.path("/etc/hosts")
-        f = file(path, "w+")
-        os.chmod(path, 0644)
-        f.write("127.0.0.1\t\t%s\n" % localline)
-        f.write("::1\t\tlocalhost6.localdomain6 localhost6\n")
-        f.close()
-
-    def write_resolv(self, nodns, nameservers):
-        if nodns or not nameservers:
-            return
-
-        path = self.path("/etc/resolv.conf")
-        f = file(path, "w+")
-        os.chmod(path, 0644)
-
-        for ns in (nameservers):
-            if ns:
-                f.write("nameserver %s\n" % ns)
-
-        f.close()
-
-    def apply(self, ksnet):
-        fs.makedirs(self.path("/etc/sysconfig/network-scripts"))
-
-        useipv6 = False
-        nodns = False
-        hostname = None
-        gateway = None
-        nameservers = None
-
-        for network in ksnet.network:
-            if not network.device:
-                raise errors.KickstartError("No --device specified with "
-                                            "network kickstart command")
-
-            if (network.onboot and network.bootProto.lower() != "dhcp" and
-                not (network.ip and network.netmask)):
-                raise errors.KickstartError("No IP address and/or netmask "
-                                            "specified with static "
-                                            "configuration for '%s'" %
-                                            network.device)
-
-            self.write_ifcfg(network)
-            self.write_wepkey(network)
-
-            if network.ipv6:
-                useipv6 = True
-            if network.nodns:
-                nodns = True
-
-            if network.hostname:
-                hostname = network.hostname
-            if network.gateway:
-                gateway = network.gateway
-
-            if network.nameserver:
-                nameservers = network.nameserver.split(",")
-
-        self.write_sysconfig(useipv6, hostname, gateway)
-        self.write_hosts(hostname)
-        self.write_resolv(nodns, nameservers)
-
-
-def get_image_size(ks, default = None):
-    __size = 0
-    for p in ks.handler.partition.partitions:
-        if p.mountpoint == "/" and p.size:
-            __size = p.size
-    if __size > 0:
-        return int(__size) * 1024L * 1024L
-    else:
-        return default
-
-def get_image_fstype(ks, default = None):
-    for p in ks.handler.partition.partitions:
-        if p.mountpoint == "/" and p.fstype:
-            return p.fstype
-    return default
-
-def get_image_fsopts(ks, default = None):
-    for p in ks.handler.partition.partitions:
-        if p.mountpoint == "/" and p.fsopts:
-            return p.fstype
-    return default
-
-def get_modules(ks):
-    devices = []
-    if isinstance(ks.handler.device, kscommands.device.FC3_Device):
-        devices.append(ks.handler.device)
-    else:
-        devices.extend(ks.handler.device.deviceList)
-
-    modules = []
-    for device in devices:
-        if not device.moduleName:
-            continue
-        modules.extend(device.moduleName.split(":"))
-
-    return modules
-
-def get_timeout(ks, default = None):
-    if not hasattr(ks.handler.bootloader, "timeout"):
-        return default
-    if ks.handler.bootloader.timeout is None:
-        return default
-    return int(ks.handler.bootloader.timeout)
-
-def get_kernel_args(ks, default = "ro liveimg"):
-    if not hasattr(ks.handler.bootloader, "appendLine"):
-        return default
-    if ks.handler.bootloader.appendLine is None:
-        return default
-    return "%s %s" %(default, ks.handler.bootloader.appendLine)
-
-def get_menu_args(ks, default = "liveinst"):
-    if not hasattr(ks.handler.bootloader, "menus"):
-        return default
-    if ks.handler.bootloader.menus in (None, ""):
-        return default
-    return "%s" % ks.handler.bootloader.menus
-
-def get_default_kernel(ks, default = None):
-    if not hasattr(ks.handler.bootloader, "default"):
-        return default
-    if not ks.handler.bootloader.default:
-        return default
-    return ks.handler.bootloader.default
-
-def get_repos(ks, repo_urls = {}):
-    repos = {}
-    for repo in ks.handler.repo.repoList:
-        inc = []
-        if hasattr(repo, "includepkgs"):
-            inc.extend(repo.includepkgs)
-
-        exc = []
-        if hasattr(repo, "excludepkgs"):
-            exc.extend(repo.excludepkgs)
-
-        baseurl = repo.baseurl
-        mirrorlist = repo.mirrorlist
-
-        if repo.name in repo_urls:
-            baseurl = repo_urls[repo.name]
-            mirrorlist = None
-
-        if repos.has_key(repo.name):
-            logging.warn("Overriding already specified repo %s" %(repo.name,))
-
-        proxy = None
-        if hasattr(repo, "proxy"):
-            proxy = repo.proxy
-        proxy_username = None
-        if hasattr(repo, "proxy_username"):
-            proxy_username = repo.proxy_username
-        proxy_password = None
-        if hasattr(repo, "proxy_password"):
-            proxy_password = repo.proxy_password
-        if hasattr(repo, "debuginfo"):
-            debuginfo = repo.debuginfo
-        if hasattr(repo, "source"):
-            source = repo.source
-        if hasattr(repo, "gpgkey"):
-            gpgkey = repo.gpgkey
-        if hasattr(repo, "disable"):
-            disable = repo.disable
-
-        repos[repo.name] = (repo.name, baseurl, mirrorlist, inc, exc, proxy, proxy_username, proxy_password, debuginfo, source, gpgkey, disable)
-
-    return repos.values()
-
-def convert_method_to_repo(ks):
-    try:
-        ks.handler.repo.methodToRepo()
-    except (AttributeError, kserrors.KickstartError):
-        pass
-
-def get_packages(ks, required = []):
-    return ks.handler.packages.packageList + required
-
-def get_groups(ks, required = []):
-    return ks.handler.packages.groupList + required
-
-def get_excluded(ks, required = []):
-    return ks.handler.packages.excludedList + required
-
-def get_partitions(ks, required = []):
-    return ks.handler.partition.partitions
-
-def ignore_missing(ks):
-    return ks.handler.packages.handleMissing == ksconstants.KS_MISSING_IGNORE
-
-def exclude_docs(ks):
-    return ks.handler.packages.excludeDocs
-
-def inst_langs(ks):
-    if hasattr(ks.handler.packages, "instLange"):
-        return ks.handler.packages.instLange
-    elif hasattr(ks.handler.packages, "instLangs"):
-        return ks.handler.packages.instLangs
-    return ""
-
-def get_post_scripts(ks):
-    scripts = []
-    for s in ks.handler.scripts:
-        if s.type != ksparser.KS_SCRIPT_POST:
-            continue
-        scripts.append(s)
-    return scripts
-
-def add_repo(ks, repostr):
-    args = repostr.split()
-    repoobj = ks.handler.repo.parse(args[1:])
-    if repoobj and repoobj not in ks.handler.repo.repoList:
-        ks.handler.repo.repoList.append(repoobj)
-
-def remove_all_repos(ks):
-    while len(ks.handler.repo.repoList) != 0:
-        del ks.handler.repo.repoList[0]
-
-def remove_duplicate_repos(ks):
-    i = 0
-    j = i + 1
-    while True:
-        if len(ks.handler.repo.repoList) < 2:
-            break
-        if i >= len(ks.handler.repo.repoList) - 1:
-            break
-        name = ks.handler.repo.repoList[i].name
-        baseurl = ks.handler.repo.repoList[i].baseurl
-        if j < len(ks.handler.repo.repoList):
-            if (ks.handler.repo.repoList[j].name == name or \
-                ks.handler.repo.repoList[j].baseurl == baseurl):
-                del ks.handler.repo.repoList[j]
-            else:
-                j += 1
-            if j >= len(ks.handler.repo.repoList):
-                i += 1
-                j = i + 1
-        else:
-            i += 1
-            j = i + 1
-
-def resolve_groups(creator, repometadata, use_comps = False):
-    pkgmgr = creator.pkgmgr.get_default_pkg_manager
-    iszypp = False
-    if creator.pkgmgr.managers.has_key("zypp") and creator.pkgmgr.managers['zypp'] == pkgmgr:
-        iszypp = True
-    ks = creator.ks
-
-    for repo in repometadata:
-        """ Mustn't replace group with package list if repo is ready for the corresponding package manager """
-        if iszypp and repo["patterns"] and not use_comps:
-            continue
-        if not iszypp and repo["comps"] and use_comps:
-            continue
-
-        """
-            But we also must handle such cases, use zypp but repo only has comps,
-            use yum but repo only has patterns, use zypp but use_comps is true,
-            use yum but use_comps is false.
-        """
-        groupfile = None
-        if iszypp:
-            if (use_comps and repo["comps"]) or (not repo["patterns"] and repo["comps"]):
-                groupfile = repo["comps"]
-                get_pkglist_handler = misc.get_pkglist_in_comps
-        if not iszypp:
-            if (not use_comps and repo["patterns"]) or (not repo["comps"] and repo["patterns"]):
-                groupfile = repo["patterns"]
-                get_pkglist_handler = misc.get_pkglist_in_patterns
-
-        if groupfile:
-            i = 0
-            while True:
-                if i >= len(ks.handler.packages.groupList):
-                    break
-                pkglist = get_pkglist_handler(ks.handler.packages.groupList[i].name, groupfile)
-                if pkglist:
-                    del ks.handler.packages.groupList[i]
-                    for pkg in pkglist:
-                        if pkg not in ks.handler.packages.packageList:
-                            ks.handler.packages.packageList.append(pkg)
-                else:
-                    i = i + 1