Timezone setting change
[platform/upstream/mic.git] / mic / kickstart / __init__.py
old mode 100644 (file)
new mode 100755 (executable)
index 4d11cca..76cc525
@@ -1,31 +1,28 @@
+#!/usr/bin/python -tt
 #
-# kickstart.py : Apply kickstart configuration to a system
+# Copyright (c) 2007 Red Hat, Inc.
+# Copyright (c) 2009, 2010, 2011 Intel, Inc.
 #
-# Copyright 2007, Red Hat  Inc.
-# Copyright 2009, 2010, 2011  Intel, 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 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 General Public License
+# for more details.
 #
-# 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.
+# 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 os, sys, re
 import shutil
 import subprocess
-import time
 import string
+import collections
 
-from mic import msger
-from mic.utils import errors, misc, runner, fs_related as fs
-
+import pykickstart.sections as kssections
 import pykickstart.commands as kscommands
 import pykickstart.constants as ksconstants
 import pykickstart.errors as kserrors
@@ -34,9 +31,58 @@ 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
+from mic import msger
+from mic.utils import errors, misc, runner, fs_related as fs
+from custom_commands import desktop, micrepo, micboot, partition, installerfw
+from mic.utils.safeurl import SafeURL
+
+
+AUTH_URL_PTN = r"(?P<scheme>.*)://(?P<username>.*)(:?P<password>.*)?@(?P<url>.*)"
+
+
+class PrepackageSection(kssections.Section):
+    sectionOpen = "%prepackages"
+
+    def handleLine(self, line):
+        if not self.handler:
+            return
+
+        (h, s, t) = line.partition('#')
+        line = h.rstrip()
+
+        self.handler.prepackages.add([line])
+
+    def handleHeader(self, lineno, args):
+        kssections.Section.handleHeader(self, lineno, args)
+
+class AttachmentSection(kssections.Section):
+    sectionOpen = "%attachment"
+
+    def handleLine(self, line):
+        if not self.handler:
+            return
+
+        (h, s, t) = line.partition('#')
+        line = h.rstrip()
+
+        self.handler.attachment.add([line])
+
+    def handleHeader(self, lineno, args):
+        kssections.Section.handleHeader(self, lineno, args)
+
+def apply_wrapper(func):
+    def wrapper(*kargs, **kwargs):
+        try:
+            func(*kargs, **kwargs)
+        except (OSError, IOError, errors.KsError), err:
+            cfgcls = kargs[0].__class__.__name__
+            if msger.ask("Failed to apply %s, skip and continue?" % cfgcls):
+                msger.warning("%s" % err)
+                pass
+            else:
+                # just throw out the exception
+                raise
+    return wrapper
 
 def read_kickstart(path):
     """Parse a kickstart file and return a KickstartParser instance.
@@ -46,73 +92,42 @@ def read_kickstart(path):
     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
+    commandMap[using_version]["desktop"] = desktop.Mic_Desktop
+    commandMap[using_version]["repo"] = micrepo.Mic_Repo
+    commandMap[using_version]["bootloader"] = micboot.Mic_Bootloader
+    commandMap[using_version]["part"] = partition.Mic_Partition
+    commandMap[using_version]["partition"] = partition.Mic_Partition
+    commandMap[using_version]["installerfw_plugins"] = installerfw.Mic_installerfw
+    dataMap[using_version]["RepoData"] = micrepo.Mic_RepoData
+    dataMap[using_version]["PartData"] = partition.Mic_PartData
     superclass = ksversion.returnClassForVersion(version=using_version)
 
     class KSHandlers(superclass):
-        def __init__(self, mapping={}):
+        def __init__(self):
             superclass.__init__(self, mapping=commandMap[using_version])
+            self.prepackages = ksparser.Packages()
+            self.attachment = ksparser.Packages()
 
-    ks = ksparser.KickstartParser(KSHandlers())
+    ks = ksparser.KickstartParser(KSHandlers(), errorsAreFatal=False)
+    ks.registerSection(PrepackageSection(ks.handler))
+    ks.registerSection(AttachmentSection(ks.handler))
 
     try:
         ks.readKickstart(path)
-    except kserrors.KickstartError, e:
-        raise errors.KsError("'%s': %s" % (path, str(e)))
-    except kserrors.KickstartParseError, e:
-        raise errors.KsError("'%s': %s" % (path, str(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
+    except (kserrors.KickstartParseError, kserrors.KickstartError), err:
+        if msger.ask("Errors occured on kickstart file, skip and continue?"):
+            msger.warning("%s" % err)
+            pass
+        else:
+            raise errors.KsError("%s" % err)
 
-    return ret
+    return ks
 
 class KickstartConfig(object):
     """A base class for applying kickstart configurations to a system."""
@@ -122,14 +137,17 @@ class KickstartConfig(object):
     def path(self, subpath):
         return self.instroot + subpath
 
+    def _check_sysconfig(self):
+        if not os.path.exists(self.path("/etc/sysconfig")):
+            fs.makedirs(self.path("/etc/sysconfig"))
+
     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.KsError("Unable to run %s!" %(args))
+            raise errors.KsError("Can't find %s in chroot" % args[0])
         subprocess.call(args, preexec_fn = self.chroot)
 
     def apply(self):
@@ -137,14 +155,27 @@ class KickstartConfig(object):
 
 class LanguageConfig(KickstartConfig):
     """A class to apply a kickstart language configuration to a system."""
+    @apply_wrapper
     def apply(self, kslang):
+        self._check_sysconfig()
         if kslang.lang:
             f = open(self.path("/etc/sysconfig/i18n"), "w+")
             f.write("LANG=\"" + kslang.lang + "\"\n")
             f.close()
 
+            f = open(self.path("/etc/locale.conf"), "w+")
+            f.write("LANG=\"" + kslang.lang + "\"\n")
+            f.close()
+
+            #cp ks lang setting to other file, then can access the file in %post section
+            fs.makedirs(self.path("/etc/config"))
+            f = open(self.path("/etc/config/mic_language"), "w+")
+            f.write("LANG=\"" + kslang.lang + "\"\n")
+            f.close()
+
 class KeyboardConfig(KickstartConfig):
     """A class to apply a kickstart keyboard configuration to a system."""
+    @apply_wrapper
     def apply(self, kskeyboard):
         #
         # FIXME:
@@ -159,7 +190,9 @@ class KeyboardConfig(KickstartConfig):
 
 class TimezoneConfig(KickstartConfig):
     """A class to apply a kickstart timezone configuration to a system."""
+    @apply_wrapper
     def apply(self, kstimezone):
+        self._check_sysconfig()
         tz = kstimezone.timezone or "America/New_York"
         utc = str(kstimezone.isUtc)
 
@@ -167,15 +200,30 @@ class TimezoneConfig(KickstartConfig):
         f.write("ZONE=\"" + tz + "\"\n")
         f.write("UTC=" + utc + "\n")
         f.close()
+        if not os.path.exists("/opt/etc"):
+            fs.makedirs("/opt/etc")
+        tz_source = "/usr/share/zoneinfo/%s" % (tz)
+        tz_midst = "/opt/etc/localtime"
+        tz_dest = "/etc/localtime"
         try:
-            shutil.copyfile(self.path("/usr/share/zoneinfo/%s" %(tz,)),
-                            self.path("/etc/localtime"))
+            lncmd = fs.find_binary_inchroot('ln', self.instroot)
+            if lncmd:
+                self.call([lncmd, "-s", tz_source, tz_midst])
+                self.call([lncmd, "-s", tz_midst, tz_dest])
+            else:
+                lncmd = fs.find_binary_path('ln')
+                subprocess.call([lncmd, "-s",
+                                 self.path(tz_source),
+                                 self.path(tz_midst)])
+                subprocess.call([lncmd, "-s",
+                                 self.path(tz_midst),
+                                 self.path(tz_dest)])
         except (IOError, OSError), (errno, msg):
-            raise errors.KsError("Error copying timezone info: %s" %(msg,))
-
+            raise errors.KsError("Timezone setting error: %s" % msg)
 
 class AuthConfig(KickstartConfig):
     """A class to apply a kickstart authconfig configuration to a system."""
+    @apply_wrapper
     def apply(self, ksauthconfig):
         auth = ksauthconfig.authconfig or "--useshadow --enablemd5"
         args = ["/usr/share/authconfig/authconfig.py", "--update", "--nostart"]
@@ -183,6 +231,7 @@ class AuthConfig(KickstartConfig):
 
 class FirewallConfig(KickstartConfig):
     """A class to apply a kickstart firewall configuration to a system."""
+    @apply_wrapper
     def apply(self, ksfirewall):
         #
         # FIXME: should handle the rest of the options
@@ -208,7 +257,8 @@ class RootPasswordConfig(KickstartConfig):
     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.KsError("Unable to set unencrypted password due to lack of %s" % p)
+                raise errors.KsError("Unable to set unencrypted password due "
+                                     "to lack of %s" % p)
 
         p1 = subprocess.Popen(["/bin/echo", "root:%s" %password],
                               stdout = subprocess.PIPE,
@@ -219,6 +269,7 @@ class RootPasswordConfig(KickstartConfig):
                               preexec_fn = self.chroot)
         p2.communicate()
 
+    @apply_wrapper
     def apply(self, ksrootpw):
         if ksrootpw.isCrypted:
             self.set_encrypted(ksrootpw.password)
@@ -237,7 +288,8 @@ class UserConfig(KickstartConfig):
     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.KsError("Unable to set unencrypted password due to lack of %s" % p)
+                raise errors.KsError("Unable to set unencrypted password due "
+                                     "to lack of %s" % p)
 
         p1 = subprocess.Popen(["/bin/echo", "%s:%s" %(user, password)],
                               stdout = subprocess.PIPE,
@@ -253,32 +305,41 @@ class UserConfig(KickstartConfig):
         if userconfig.groups:
             args += [ "--groups", string.join(userconfig.groups, ",") ]
         if userconfig.name:
+            args += [ "-m"]
+            args += [ "-d", "/home/%s" % 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)
+            try:
+                dev_null = os.open("/dev/null", os.O_WRONLY)
+                msger.debug('adding user with %s' % args)
+                subprocess.call(args,
+                                 stdout = dev_null,
+                                 stderr = dev_null,
+                                 preexec_fn = self.chroot)
+                os.close(dev_null)
+            except:
+                msger.warning('Cannot add user using "useradd"')
+
             if userconfig.password not in (None, ""):
                 if userconfig.isCrypted:
-                    self.set_encrypted_passwd(userconfig.name, userconfig.password)
+                    self.set_encrypted_passwd(userconfig.name,
+                                              userconfig.password)
                 else:
-                    self.set_unencrypted_passwd(userconfig.name, userconfig.password)
+                    self.set_unencrypted_passwd(userconfig.name,
+                                                userconfig.password)
             else:
                 self.set_empty_passwd(userconfig.name)
         else:
-            raise errors.KsError("Invalid kickstart command: %s" % userconfig.__str__())
+            raise errors.KsError("Invalid kickstart command: %s" \
+                                 % userconfig.__str__())
 
+    @apply_wrapper
     def apply(self, user):
         for userconfig in user.userList:
-            try:
-                self.addUser(userconfig)
-            except:
-                raise
+            self.addUser(userconfig)
 
 class ServicesConfig(KickstartConfig):
     """A class to apply a kickstart services configuration to a system."""
+    @apply_wrapper
     def apply(self, ksservices):
         if not os.path.exists(self.path("/sbin/chkconfig")):
             return
@@ -289,8 +350,9 @@ class ServicesConfig(KickstartConfig):
 
 class XConfig(KickstartConfig):
     """A class to apply a kickstart X configuration to a system."""
+    @apply_wrapper
     def apply(self, ksxconfig):
-        if ksxconfig.startX:
+        if ksxconfig.startX and os.path.exists(self.path("/etc/inittab")):
             f = open(self.path("/etc/inittab"), "rw+")
             buf = f.read()
             buf = buf.replace("id:3:initdefault", "id:5:initdefault")
@@ -298,14 +360,17 @@ class XConfig(KickstartConfig):
             f.write(buf)
             f.close()
         if ksxconfig.defaultdesktop:
+            self._check_sysconfig()
             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."""
+    @apply_wrapper
     def apply(self, ksdesktop):
         if ksdesktop.defaultdesktop:
+            self._check_sysconfig()
             f = open(self.path("/etc/sysconfig/desktop"), "w")
             f.write("DESKTOP="+ksdesktop.defaultdesktop+"\n")
             f.close()
@@ -320,14 +385,10 @@ class DesktopConfig(KickstartConfig):
                 f.write("session="+ksdesktop.session.lower()+"\n")
                 f.close()
         if ksdesktop.autologinuser:
+            self._check_sysconfig()
             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")
@@ -347,6 +408,7 @@ class MoblinRepoConfig(KickstartConfig):
                 baseurl = repo.baseurl
             if repo.mirrorlist:
                 mirrorlist = repo.mirrorlist
+
         elif type == "debuginfo":
             if repo.baseurl:
                 if repo.baseurl.endswith("/"):
@@ -354,17 +416,22 @@ class MoblinRepoConfig(KickstartConfig):
                 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)))
+                    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("$")]
@@ -374,6 +441,10 @@ class MoblinRepoConfig(KickstartConfig):
         fd.write("name=" + reponame + "\n")
         fd.write("failovermethod=priority\n")
         if baseurl:
+            auth_url = re.compile(AUTH_URL_PTN)
+            m = auth_url.match(baseurl)
+            if m:
+                baseurl = "%s://%s" % (m.group('scheme'), m.group('url'))
             fd.write("baseurl=" + baseurl + "\n")
         if mirrorlist:
             fd.write("mirrorlist=" + mirrorlist + "\n")
@@ -405,8 +476,11 @@ class MoblinRepoConfig(KickstartConfig):
             self.__create_repo_section(repo, "source", f)
         f.close()
 
-    def apply(self, ksrepo, repodata):
+    @apply_wrapper
+    def apply(self, ksrepo, repodata, repourl):
         for repo in ksrepo.repoList:
+            if repo.name in repourl:
+                repo.baseurl = repourl[repo.name]
             if repo.save:
                 #self.__create_repo_file(repo, "/etc/yum.repos.d")
                 self.__create_repo_file(repo, "/etc/zypp/repos.d")
@@ -414,10 +488,14 @@ class MoblinRepoConfig(KickstartConfig):
         if repodata:
             for repo in repodata:
                 if repo['repokey']:
-                    runner.quiet(['rpm', "--root=%s" % self.instroot, "--import", repo['repokey']])
+                    runner.quiet(['rpm',
+                                  "--root=%s" % self.instroot,
+                                  "--import",
+                                  repo['repokey']])
 
 class RPMMacroConfig(KickstartConfig):
     """A class to apply the specified rpm macros to the filesystem"""
+    @apply_wrapper
     def apply(self, ks):
         if not ks:
             return
@@ -536,6 +614,7 @@ class NetworkConfig(KickstartConfig):
 
         f.close()
 
+    @apply_wrapper
     def apply(self, ksnet):
         fs.makedirs(self.path("/etc/sysconfig/network-scripts"))
 
@@ -577,6 +656,15 @@ class NetworkConfig(KickstartConfig):
         self.write_hosts(hostname)
         self.write_resolv(nodns, nameservers)
 
+def use_installerfw(ks, feature):
+    """ Check if the installer framework has to be used for a feature
+    "feature". """
+
+    features = ks.handler.installerfw.features
+    if features:
+        if feature in features or "all" in features:
+            return True
+    return False
 
 def get_image_size(ks, default = None):
     __size = 0
@@ -597,7 +685,7 @@ def get_image_fstype(ks, default = None):
 def get_image_fsopts(ks, default = None):
     for p in ks.handler.partition.partitions:
         if p.mountpoint == "/" and p.fsopts:
-            return p.fstype
+            return p.fsopts
     return default
 
 def get_modules(ks):
@@ -622,14 +710,14 @@ def get_timeout(ks, default = None):
         return default
     return int(ks.handler.bootloader.timeout)
 
-def get_kernel_args(ks, default = "ro liveimg"):
+def get_kernel_args(ks, default = "ro rd.live.image"):
     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"):
+def get_menu_args(ks, default = ""):
     if not hasattr(ks.handler.bootloader, "menus"):
         return default
     if ks.handler.bootloader.menus in (None, ""):
@@ -643,46 +731,47 @@ def get_default_kernel(ks, default = None):
         return default
     return ks.handler.bootloader.default
 
-def get_repos(ks, repo_urls = {}):
+RepoType = collections.namedtuple("Repo",
+               "name, baseurl, mirrorlist, includepkgs, excludepkgs, proxy, \
+               proxy_username, proxy_password, debuginfo, \
+               source, gpgkey, disable, ssl_verify, nocache, \
+               cost, priority")
+
+def Repo(name, baseurl, mirrorlist=None, includepkgs=[], excludepkgs=[], proxy=None,
+         proxy_username=None, proxy_password=None, debuginfo=None,
+         source=None, gpgkey=None, disable=None, ssl_verify=None,
+         nocache=False, cost=None, priority=None):
+    return RepoType(name, baseurl, mirrorlist, includepkgs, excludepkgs, proxy,
+                    proxy_username, proxy_password, debuginfo,
+                    source, gpgkey, disable, ssl_verify, nocache,
+                    cost, priority)
+
+
+def get_repos(ks, repo_urls=None, ignore_ksrepo=False):
     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):
-            msger.warning("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)
+    for repodata in ks.handler.repo.repoList:
+        repo = {}
+        for field in RepoType._fields:
+            if hasattr(repodata, field) and getattr(repodata, field):
+                repo[field] = getattr(repodata, field)
+
+        if hasattr(repodata, 'baseurl') and getattr(repodata, 'baseurl'):
+            repo['baseurl'] = SafeURL(getattr(repodata, 'baseurl'),
+                                      getattr(repodata, 'user', None),
+                                      getattr(repodata, 'passwd', None))
+
+        if 'name' in repo:
+            repos[repo['name']] = Repo(**repo)
+
+    if repo_urls:
+        if ignore_ksrepo:
+            repos = {}
+        for name, repo in repo_urls.items():
+            if 'baseurl' in repo:
+                repo['baseurl'] = SafeURL(repo.get('baseurl'),
+                                          repo.get('user', None),
+                                          repo.get('passwd', None))
+            repos[name] = Repo(**repo)
 
     return repos.values()
 
@@ -692,16 +781,22 @@ def convert_method_to_repo(ks):
     except (AttributeError, kserrors.KickstartError):
         pass
 
-def get_packages(ks, required = []):
-    return ks.handler.packages.packageList + required
+def get_attachment(ks, required=()):
+    return ks.handler.attachment.packageList + list(required)
+
+def get_pre_packages(ks, required=()):
+    return ks.handler.prepackages.packageList + list(required)
+
+def get_packages(ks, required=()):
+    return ks.handler.packages.packageList + list(required)
 
-def get_groups(ks, required = []):
-    return ks.handler.packages.groupList + required
+def get_groups(ks, required=()):
+    return ks.handler.packages.groupList + list(required)
 
-def get_excluded(ks, required = []):
-    return ks.handler.packages.excludedList + required
+def get_excluded(ks, required=()):
+    return ks.handler.packages.excludedList + list(required)
 
-def get_partitions(ks, required = []):
+def get_partitions(ks):
     return ks.handler.partition.partitions
 
 def ignore_missing(ks):
@@ -725,6 +820,13 @@ def get_post_scripts(ks):
         scripts.append(s)
     return scripts
 
+def get_sign_scripts(ks):
+    scripts = []
+    for s in ks.handler.scripts:
+        if s.type != ksparser.KS_SCRIPT_RUN:
+            continue
+        scripts.append(s)
+    return scripts
 def add_repo(ks, repostr):
     args = repostr.split()
     repoobj = ks.handler.repo.parse(args[1:])
@@ -758,41 +860,41 @@ def remove_duplicate_repos(ks):
             i += 1
             j = i + 1
 
-def resolve_groups(creator, repometadata, use_comps = False):
-    pkgmgr = creator.pkgmgr.get_default_pkg_manager
+def resolve_groups(creatoropts, repometadata):
     iszypp = False
-    if creator.pkgmgr.managers.has_key("zypp") and creator.pkgmgr.managers['zypp'] == pkgmgr:
+    if 'zypp' == creatoropts['pkgmgr']:
         iszypp = True
-    ks = creator.ks
+    ks = creatoropts['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:
+        """ Mustn't replace group with package list if repo is ready for the
+            corresponding package manager.
+        """
+
+        if iszypp and repo["patterns"]:
             continue
-        if not iszypp and repo["comps"] and use_comps:
+        if not iszypp and repo["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.
-        """
+        # 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 iszypp and repo["comps"]:
+            groupfile = repo["comps"]
+            get_pkglist_handler = misc.get_pkglist_in_comps
+        if not iszypp 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)
+                pkglist = get_pkglist_handler(
+                                        ks.handler.packages.groupList[i].name,
+                                        groupfile)
                 if pkglist:
                     del ks.handler.packages.groupList[i]
                     for pkg in pkglist: