initial import code into git
[platform/upstream/mic.git] / micng / utils / kickstart.py
1 #
2 # kickstart.py : Apply kickstart configuration to a system
3 #
4 # Copyright 2007, Red Hat  Inc.
5 #
6 # This program is free software; you can redistribute it and/or modify
7 # it under the terms of the GNU General Public License as published by
8 # the Free Software Foundation; version 2 of the License.
9 #
10 # This program is distributed in the hope that it will be useful,
11 # but WITHOUT ANY WARRANTY; without even the implied warranty of
12 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13 # GNU Library General Public License for more details.
14 #
15 # You should have received a copy of the GNU General Public License
16 # along with this program; if not, write to the Free Software
17 # Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
18
19 import os
20 import os.path
21 import shutil
22 import subprocess
23 import time
24 import logging
25 import string
26
27 #import rhpl.keyboard
28
29 import pykickstart.commands as kscommands
30 import pykickstart.constants as ksconstants
31 import pykickstart.errors as kserrors
32 import pykickstart.parser as ksparser
33 import pykickstart.version as ksversion
34 from pykickstart.handlers.control import commandMap
35 from pykickstart.handlers.control import dataMap
36
37 import errors as errors
38 import fs_related as fs
39 import kscommands.desktop as desktop
40 import kscommands.moblinrepo as moblinrepo
41 import kscommands.micboot as micboot
42
43 import sys
44 sys.path.append("~/0509/mic")
45 import misc as misc
46
47 def read_kickstart(path):
48     """Parse a kickstart file and return a KickstartParser instance.
49
50     This is a simple utility function which takes a path to a kickstart file,
51     parses it and returns a pykickstart KickstartParser instance which can
52     be then passed to an ImageCreator constructor.
53
54     If an error occurs, a CreatorError exception is thrown.
55
56     """
57     #version = ksversion.makeVersion()
58     #ks = ksparser.KickstartParser(version)
59
60     using_version = ksversion.DEVEL
61     commandMap[using_version]["desktop"] = desktop.Moblin_Desktop
62     commandMap[using_version]["repo"] = moblinrepo.Moblin_Repo
63     commandMap[using_version]["bootloader"] = micboot.Moblin_Bootloader
64     dataMap[using_version]["RepoData"] = moblinrepo.Moblin_RepoData
65     superclass = ksversion.returnClassForVersion(version=using_version)
66
67     class KSHandlers(superclass):
68         def __init__(self, mapping={}):
69             superclass.__init__(self, mapping=commandMap[using_version])
70
71     ks = ksparser.KickstartParser(KSHandlers())
72
73     try:
74         ks.readKickstart(path)
75     except IOError, (err, msg):
76         raise errors.KickstartError("Failed to read kickstart file "
77                                     "'%s' : %s" % (path, msg))
78     except kserrors.KickstartError, e:
79         raise errors.KickstartError("Failed to parse kickstart file "
80                                     "'%s' : %s" % (path, e))
81     return ks
82
83 def build_name(kscfg, prefix = None, suffix = None, maxlen = None):
84     """Construct and return an image name string.
85
86     This is a utility function to help create sensible name and fslabel
87     strings. The name is constructed using the sans-prefix-and-extension
88     kickstart filename and the supplied prefix and suffix.
89
90     If the name exceeds the maxlen length supplied, the prefix is first dropped
91     and then the kickstart filename portion is reduced until it fits. In other
92     words, the suffix takes precedence over the kickstart portion and the
93     kickstart portion takes precedence over the prefix.
94
95     kscfg -- a path to a kickstart file
96     prefix -- a prefix to prepend to the name; defaults to None, which causes
97               no prefix to be used
98     suffix -- a suffix to append to the name; defaults to None, which causes
99               a YYYYMMDDHHMM suffix to be used
100     maxlen -- the maximum length for the returned string; defaults to None,
101               which means there is no restriction on the name length
102
103     Note, if maxlen is less then the len(suffix), you get to keep both pieces.
104
105     """
106     name = os.path.basename(kscfg)
107     idx = name.rfind('.')
108     if idx >= 0:
109         name = name[:idx]
110
111     if prefix is None:
112         prefix = ""
113     if suffix is None:
114         suffix = time.strftime("%Y%m%d%H%M")
115
116     if name.startswith(prefix):
117         name = name[len(prefix):]
118
119     ret = prefix + name + "-" + suffix
120     if not maxlen is None and len(ret) > maxlen:
121         ret = name[:maxlen - len(suffix) - 1] + "-" + suffix
122
123     return ret
124
125 class KickstartConfig(object):
126     """A base class for applying kickstart configurations to a system."""
127     def __init__(self, instroot):
128         self.instroot = instroot
129
130     def path(self, subpath):
131         return self.instroot + subpath
132
133     def chroot(self):
134         os.chroot(self.instroot)
135         os.chdir("/")
136
137     def call(self, args):
138         if not os.path.exists("%s/%s" %(self.instroot, args[0])):
139             print "%s/%s" %(self.instroot, args[0])
140             raise errors.KickstartError("Unable to run %s!" %(args))
141         subprocess.call(args, preexec_fn = self.chroot)
142
143     def apply(self):
144         pass
145
146 class LanguageConfig(KickstartConfig):
147     """A class to apply a kickstart language configuration to a system."""
148     def apply(self, kslang):
149         lang = kslang.lang or "en_US.UTF-8"
150
151         f = open(self.path("/etc/sysconfig/i18n"), "w+")
152         f.write("LANG=\"" + lang + "\"\n")
153         f.close()
154
155 class KeyboardConfig(KickstartConfig):
156     """A class to apply a kickstart keyboard configuration to a system."""
157     def apply(self, kskeyboard):
158         #
159         # FIXME:
160         #   should this impact the X keyboard config too?
161         #   or do we want to make X be able to do this mapping?
162         #
163         #k = rhpl.keyboard.Keyboard()
164         #if kskeyboard.keyboard:
165         #   k.set(kskeyboard.keyboard)
166         #k.write(self.instroot)
167         pass
168
169 class TimezoneConfig(KickstartConfig):
170     """A class to apply a kickstart timezone configuration to a system."""
171     def apply(self, kstimezone):
172         tz = kstimezone.timezone or "America/New_York"
173         utc = str(kstimezone.isUtc)
174
175         f = open(self.path("/etc/sysconfig/clock"), "w+")
176         f.write("ZONE=\"" + tz + "\"\n")
177         f.write("UTC=" + utc + "\n")
178         f.close()
179         try:
180             shutil.copyfile(self.path("/usr/share/zoneinfo/%s" %(tz,)),
181                             self.path("/etc/localtime"))
182         except (IOError, OSError), (errno, msg):
183             raise errors.KickstartError("Error copying timezone info: %s" %(msg,))
184
185
186 class AuthConfig(KickstartConfig):
187     """A class to apply a kickstart authconfig configuration to a system."""
188     def apply(self, ksauthconfig):
189         auth = ksauthconfig.authconfig or "--useshadow --enablemd5"
190         args = ["/usr/share/authconfig/authconfig.py", "--update", "--nostart"]
191         self.call(args + auth.split())
192
193 class FirewallConfig(KickstartConfig):
194     """A class to apply a kickstart firewall configuration to a system."""
195     def apply(self, ksfirewall):
196         #
197         # FIXME: should handle the rest of the options
198         #
199         if not os.path.exists(self.path("/usr/sbin/lokkit")):
200             return
201         if ksfirewall.enabled:
202             status = "--enabled"
203         else:
204             status = "--disabled"
205
206         self.call(["/usr/sbin/lokkit",
207                    "-f", "--quiet", "--nostart", status])
208
209 class RootPasswordConfig(KickstartConfig):
210     """A class to apply a kickstart root password configuration to a system."""
211     def unset(self):
212         self.call(["/usr/bin/passwd", "-d", "root"])
213
214     def set_encrypted(self, password):
215         self.call(["/usr/sbin/usermod", "-p", password, "root"])
216
217     def set_unencrypted(self, password):        
218         for p in ("/bin/echo", "/usr/sbin/chpasswd"):
219             if not os.path.exists("%s/%s" %(self.instroot, p)):
220                 raise errors.KickstartError("Unable to set unencrypted password due to lack of %s" % p) 
221         
222         p1 = subprocess.Popen(["/bin/echo", "root:%s" %password],
223                               stdout = subprocess.PIPE,
224                               preexec_fn = self.chroot)
225         p2 = subprocess.Popen(["/usr/sbin/chpasswd", "-m"],
226                               stdin = p1.stdout,
227                               stdout = subprocess.PIPE,
228                               preexec_fn = self.chroot)
229         p2.communicate()
230
231     def apply(self, ksrootpw):
232         if ksrootpw.isCrypted:
233             self.set_encrypted(ksrootpw.password)
234         elif ksrootpw.password != "":
235             self.set_unencrypted(ksrootpw.password)
236         else:
237             self.unset()
238
239 class UserConfig(KickstartConfig):
240     def set_empty_passwd(self, user):
241         self.call(["/usr/bin/passwd", "-d", user])
242
243     def set_encrypted_passwd(self, user, password):
244         self.call(["/usr/sbin/usermod", "-p", "%s" % password, user])
245
246     def set_unencrypted_passwd(self, user, password):
247         for p in ("/bin/echo", "/usr/sbin/chpasswd"):
248             if not os.path.exists("%s/%s" %(self.instroot, p)):
249                 raise errors.KickstartError("Unable to set unencrypted password due to lack of %s" % p)
250
251         p1 = subprocess.Popen(["/bin/echo", "%s:%s" %(user, password)],
252                               stdout = subprocess.PIPE,
253                               preexec_fn = self.chroot)
254         p2 = subprocess.Popen(["/usr/sbin/chpasswd", "-m"],
255                               stdin = p1.stdout,
256                               stdout = subprocess.PIPE,
257                               preexec_fn = self.chroot)
258         p2.communicate()
259
260     def addUser(self, userconfig):
261         args = [ "/usr/sbin/useradd" ]
262         if userconfig.groups:
263             args += [ "--groups", string.join(userconfig.groups, ",") ]
264         if userconfig.name:
265             args.append(userconfig.name)
266             dev_null = os.open("/dev/null", os.O_WRONLY)
267             subprocess.call(args,
268                              stdout = dev_null,
269                              stderr = dev_null,
270                              preexec_fn = self.chroot)
271             os.close(dev_null)
272             if userconfig.password not in (None, ""):
273                 if userconfig.isCrypted:
274                     self.set_encrypted_passwd(userconfig.name, userconfig.password)
275                 else:
276                     self.set_unencrypted_passwd(userconfig.name, userconfig.password)
277             else:
278                 self.set_empty_passwd(userconfig.name)
279         else:
280             raise errors.KickstartError("Invalid kickstart command: %s" % userconfig.__str__())
281
282     def apply(self, user):
283         for userconfig in user.userList:
284             try:
285                 self.addUser(userconfig)
286             except:
287                 raise
288
289 class ServicesConfig(KickstartConfig):
290     """A class to apply a kickstart services configuration to a system."""
291     def apply(self, ksservices):
292         if not os.path.exists(self.path("/sbin/chkconfig")):
293             return
294         for s in ksservices.enabled:
295             self.call(["/sbin/chkconfig", s, "on"])
296         for s in ksservices.disabled:
297             self.call(["/sbin/chkconfig", s, "off"])
298
299 class XConfig(KickstartConfig):
300     """A class to apply a kickstart X configuration to a system."""
301     def apply(self, ksxconfig):
302         if ksxconfig.startX:
303             f = open(self.path("/etc/inittab"), "rw+")
304             buf = f.read()
305             buf = buf.replace("id:3:initdefault", "id:5:initdefault")
306             f.seek(0)
307             f.write(buf)
308             f.close()
309         if ksxconfig.defaultdesktop:
310             f = open(self.path("/etc/sysconfig/desktop"), "w")
311             f.write("DESKTOP="+ksxconfig.defaultdesktop+"\n")
312             f.close()
313
314 class DesktopConfig(KickstartConfig):
315     """A class to apply a kickstart desktop configuration to a system."""
316     def apply(self, ksdesktop):
317         if ksdesktop.defaultdesktop:
318             f = open(self.path("/etc/sysconfig/desktop"), "w")
319             f.write("DESKTOP="+ksdesktop.defaultdesktop+"\n")
320             f.close()
321             if os.path.exists(self.path("/etc/gdm/custom.conf")):
322                 f = open(self.path("/etc/skel/.dmrc"), "w")
323                 f.write("[Desktop]\n")
324                 f.write("Session="+ksdesktop.defaultdesktop.lower()+"\n")
325                 f.close()
326         if ksdesktop.session:
327             if os.path.exists(self.path("/etc/sysconfig/uxlaunch")):
328                 f = open(self.path("/etc/sysconfig/uxlaunch"), "a+")
329                 f.write("session="+ksdesktop.session.lower()+"\n")
330                 f.close()
331         if ksdesktop.autologinuser:
332             f = open(self.path("/etc/sysconfig/desktop"), "a+")
333             f.write("AUTOLOGIN_USER=" + ksdesktop.autologinuser + "\n")
334             f.close()
335             if ksdesktop.session:
336                 if os.path.exists(self.path("/etc/sysconfig/uxlaunch")):
337                     f = open(self.path("/etc/sysconfig/uxlaunch"), "a+")
338                     f.write("user="+ksdesktop.autologinuser+"\n")
339                     f.close()
340             if os.path.exists(self.path("/etc/gdm/custom.conf")):
341                 f = open(self.path("/etc/gdm/custom.conf"), "w")
342                 f.write("[daemon]\n")
343                 f.write("AutomaticLoginEnable=true\n")
344                 f.write("AutomaticLogin=" + ksdesktop.autologinuser + "\n")
345                 f.close()
346
347 class MoblinRepoConfig(KickstartConfig):
348     """A class to apply a kickstart desktop configuration to a system."""
349     def __create_repo_section(self, repo, type, fd):
350         baseurl = None
351         mirrorlist = None
352         reposuffix = {"base":"", "debuginfo":"-debuginfo", "source":"-source"}
353         reponame = repo.name + reposuffix[type]
354         if type == "base":
355             if repo.baseurl:
356                 baseurl = repo.baseurl
357             if repo.mirrorlist:
358                 mirrorlist = repo.mirrorlist
359         elif type == "debuginfo":
360             if repo.baseurl:
361                 if repo.baseurl.endswith("/"):
362                     baseurl = os.path.dirname(os.path.dirname(repo.baseurl))
363                 else:
364                     baseurl = os.path.dirname(repo.baseurl)
365                 baseurl += "/debug"
366             if repo.mirrorlist:
367                 variant = repo.mirrorlist[repo.mirrorlist.find("$"):]
368                 mirrorlist = repo.mirrorlist[0:repo.mirrorlist.find("$")]
369                 mirrorlist += "debug" + "-" + variant
370         elif type == "source":
371             if repo.baseurl:
372                 if repo.baseurl.endswith("/"):
373                     baseurl = os.path.dirname(os.path.dirname(os.path.dirname(repo.baseurl)))
374                 else:
375                     baseurl = os.path.dirname(os.path.dirname(repo.baseurl))
376                 baseurl += "/source"
377             if repo.mirrorlist:
378                 variant = repo.mirrorlist[repo.mirrorlist.find("$"):]
379                 mirrorlist = repo.mirrorlist[0:repo.mirrorlist.find("$")]
380                 mirrorlist += "source" + "-" + variant
381
382         fd.write("[" + reponame + "]\n")
383         fd.write("name=" + reponame + "\n")
384         fd.write("failovermethod=priority\n")
385         if baseurl:
386             fd.write("baseurl=" + baseurl + "\n")
387         if mirrorlist:
388             fd.write("mirrorlist=" + mirrorlist + "\n")
389         """ Skip saving proxy settings """
390         #if repo.proxy:
391         #    fd.write("proxy=" + repo.proxy + "\n")
392         #if repo.proxy_username:
393         #    fd.write("proxy_username=" + repo.proxy_username + "\n")
394         #if repo.proxy_password:
395         #    fd.write("proxy_password=" + repo.proxy_password + "\n")
396         if repo.gpgkey:
397             fd.write("gpgkey=" + repo.gpgkey + "\n")
398             fd.write("gpgcheck=1\n")
399         else:
400             fd.write("gpgcheck=0\n")
401         if type == "source" or type == "debuginfo" or repo.disable:
402             fd.write("enabled=0\n")
403         else:
404             fd.write("enabled=1\n")
405         fd.write("\n")
406
407     def __create_repo_file(self, repo, repodir):
408         if not os.path.exists(self.path(repodir)):
409             fs.makedirs(self.path(repodir))
410         f = open(self.path(repodir + "/" + repo.name + ".repo"), "w")
411         self.__create_repo_section(repo, "base", f)
412         if repo.debuginfo:
413             self.__create_repo_section(repo, "debuginfo", f)
414         if repo.source:
415             self.__create_repo_section(repo, "source", f)
416         f.close()
417
418     def apply(self, ksrepo, repodata):
419         for repo in ksrepo.repoList:
420             if repo.save:
421                 #self.__create_repo_file(repo, "/etc/yum.repos.d")
422                 self.__create_repo_file(repo, "/etc/zypp/repos.d")
423         """ Import repo gpg keys """
424         if repodata:
425             dev_null = os.open("/dev/null", os.O_WRONLY)
426             for repo in repodata:
427                 if repo['repokey']:
428                     subprocess.call([fs.find_binary_path("rpm"), "--root=%s" % self.instroot, "--import", repo['repokey']],
429                                     stdout = dev_null, stderr = dev_null)
430             os.close(dev_null)
431
432 class RPMMacroConfig(KickstartConfig):
433     """A class to apply the specified rpm macros to the filesystem"""
434     def apply(self, ks):
435         if not ks:
436             return
437         if not os.path.exists(self.path("/etc/rpm")):
438             os.mkdir(self.path("/etc/rpm"))
439         f = open(self.path("/etc/rpm/macros.imgcreate"), "w+")
440         if exclude_docs(ks):
441             f.write("%_excludedocs 1\n")
442         f.write("%__file_context_path %{nil}\n")
443         if inst_langs(ks) != None:
444             f.write("%_install_langs ")
445             f.write(inst_langs(ks))
446             f.write("\n")
447         f.close()
448
449 class NetworkConfig(KickstartConfig):
450     """A class to apply a kickstart network configuration to a system."""
451     def write_ifcfg(self, network):
452         p = self.path("/etc/sysconfig/network-scripts/ifcfg-" + network.device)
453
454         f = file(p, "w+")
455         os.chmod(p, 0644)
456
457         f.write("DEVICE=%s\n" % network.device)
458         f.write("BOOTPROTO=%s\n" % network.bootProto)
459
460         if network.bootProto.lower() == "static":
461             if network.ip:
462                 f.write("IPADDR=%s\n" % network.ip)
463             if network.netmask:
464                 f.write("NETMASK=%s\n" % network.netmask)
465
466         if network.onboot:
467             f.write("ONBOOT=on\n")
468         else:
469             f.write("ONBOOT=off\n")
470
471         if network.essid:
472             f.write("ESSID=%s\n" % network.essid)
473
474         if network.ethtool:
475             if network.ethtool.find("autoneg") == -1:
476                 network.ethtool = "autoneg off " + network.ethtool
477             f.write("ETHTOOL_OPTS=%s\n" % network.ethtool)
478
479         if network.bootProto.lower() == "dhcp":
480             if network.hostname:
481                 f.write("DHCP_HOSTNAME=%s\n" % network.hostname)
482             if network.dhcpclass:
483                 f.write("DHCP_CLASSID=%s\n" % network.dhcpclass)
484
485         if network.mtu:
486             f.write("MTU=%s\n" % network.mtu)
487
488         f.close()
489
490     def write_wepkey(self, network):
491         if not network.wepkey:
492             return
493
494         p = self.path("/etc/sysconfig/network-scripts/keys-" + network.device)
495         f = file(p, "w+")
496         os.chmod(p, 0600)
497         f.write("KEY=%s\n" % network.wepkey)
498         f.close()
499
500     def write_sysconfig(self, useipv6, hostname, gateway):
501         path = self.path("/etc/sysconfig/network")
502         f = file(path, "w+")
503         os.chmod(path, 0644)
504
505         f.write("NETWORKING=yes\n")
506
507         if useipv6:
508             f.write("NETWORKING_IPV6=yes\n")
509         else:
510             f.write("NETWORKING_IPV6=no\n")
511
512         if hostname:
513             f.write("HOSTNAME=%s\n" % hostname)
514         else:
515             f.write("HOSTNAME=localhost.localdomain\n")
516
517         if gateway:
518             f.write("GATEWAY=%s\n" % gateway)
519
520         f.close()
521
522     def write_hosts(self, hostname):
523         localline = ""
524         if hostname and hostname != "localhost.localdomain":
525             localline += hostname + " "
526             l = hostname.split(".")
527             if len(l) > 1:
528                 localline += l[0] + " "
529         localline += "localhost.localdomain localhost"
530
531         path = self.path("/etc/hosts")
532         f = file(path, "w+")
533         os.chmod(path, 0644)
534         f.write("127.0.0.1\t\t%s\n" % localline)
535         f.write("::1\t\tlocalhost6.localdomain6 localhost6\n")
536         f.close()
537
538     def write_resolv(self, nodns, nameservers):
539         if nodns or not nameservers:
540             return
541
542         path = self.path("/etc/resolv.conf")
543         f = file(path, "w+")
544         os.chmod(path, 0644)
545
546         for ns in (nameservers):
547             if ns:
548                 f.write("nameserver %s\n" % ns)
549
550         f.close()
551
552     def apply(self, ksnet):
553         fs.makedirs(self.path("/etc/sysconfig/network-scripts"))
554
555         useipv6 = False
556         nodns = False
557         hostname = None
558         gateway = None
559         nameservers = None
560
561         for network in ksnet.network:
562             if not network.device:
563                 raise errors.KickstartError("No --device specified with "
564                                             "network kickstart command")
565
566             if (network.onboot and network.bootProto.lower() != "dhcp" and
567                 not (network.ip and network.netmask)):
568                 raise errors.KickstartError("No IP address and/or netmask "
569                                             "specified with static "
570                                             "configuration for '%s'" %
571                                             network.device)
572
573             self.write_ifcfg(network)
574             self.write_wepkey(network)
575
576             if network.ipv6:
577                 useipv6 = True
578             if network.nodns:
579                 nodns = True
580
581             if network.hostname:
582                 hostname = network.hostname
583             if network.gateway:
584                 gateway = network.gateway
585
586             if network.nameserver:
587                 nameservers = network.nameserver.split(",")
588
589         self.write_sysconfig(useipv6, hostname, gateway)
590         self.write_hosts(hostname)
591         self.write_resolv(nodns, nameservers)
592
593
594 def get_image_size(ks, default = None):
595     __size = 0
596     for p in ks.handler.partition.partitions:
597         if p.mountpoint == "/" and p.size:
598             __size = p.size
599     if __size > 0:
600         return int(__size) * 1024L * 1024L
601     else:
602         return default
603
604 def get_image_fstype(ks, default = None):
605     for p in ks.handler.partition.partitions:
606         if p.mountpoint == "/" and p.fstype:
607             return p.fstype
608     return default
609
610 def get_image_fsopts(ks, default = None):
611     for p in ks.handler.partition.partitions:
612         if p.mountpoint == "/" and p.fsopts:
613             return p.fstype
614     return default
615
616 def get_modules(ks):
617     devices = []
618     if isinstance(ks.handler.device, kscommands.device.FC3_Device):
619         devices.append(ks.handler.device)
620     else:
621         devices.extend(ks.handler.device.deviceList)
622
623     modules = []
624     for device in devices:
625         if not device.moduleName:
626             continue
627         modules.extend(device.moduleName.split(":"))
628
629     return modules
630
631 def get_timeout(ks, default = None):
632     if not hasattr(ks.handler.bootloader, "timeout"):
633         return default
634     if ks.handler.bootloader.timeout is None:
635         return default
636     return int(ks.handler.bootloader.timeout)
637
638 def get_kernel_args(ks, default = "ro liveimg"):
639     if not hasattr(ks.handler.bootloader, "appendLine"):
640         return default
641     if ks.handler.bootloader.appendLine is None:
642         return default
643     return "%s %s" %(default, ks.handler.bootloader.appendLine)
644
645 def get_menu_args(ks, default = "bootinstall"):
646     if not hasattr(ks.handler.bootloader, "menus"):
647         return default
648     if ks.handler.bootloader.menus is None:
649         return default
650     return "%s %s" %(default, ks.handler.bootloader.menus)
651
652 def get_default_kernel(ks, default = None):
653     if not hasattr(ks.handler.bootloader, "default"):
654         return default
655     if not ks.handler.bootloader.default:
656         return default
657     return ks.handler.bootloader.default
658
659 def get_repos(ks, repo_urls = {}):
660     repos = {}
661     for repo in ks.handler.repo.repoList:
662         inc = []
663         if hasattr(repo, "includepkgs"):
664             inc.extend(repo.includepkgs)
665
666         exc = []
667         if hasattr(repo, "excludepkgs"):
668             exc.extend(repo.excludepkgs)
669
670         baseurl = repo.baseurl
671         mirrorlist = repo.mirrorlist
672
673         if repo.name in repo_urls:
674             baseurl = repo_urls[repo.name]
675             mirrorlist = None
676
677         if repos.has_key(repo.name):
678             logging.warn("Overriding already specified repo %s" %(repo.name,))
679
680         proxy = None
681         if hasattr(repo, "proxy"):
682             proxy = repo.proxy
683         proxy_username = None
684         if hasattr(repo, "proxy_username"):
685             proxy_username = repo.proxy_username
686         proxy_password = None
687         if hasattr(repo, "proxy_password"):
688             proxy_password = repo.proxy_password
689         if hasattr(repo, "debuginfo"):
690             debuginfo = repo.debuginfo
691         if hasattr(repo, "source"):
692             source = repo.source
693         if hasattr(repo, "gpgkey"):
694             gpgkey = repo.gpgkey
695         if hasattr(repo, "disable"):
696             disable = repo.disable
697
698         repos[repo.name] = (repo.name, baseurl, mirrorlist, inc, exc, proxy, proxy_username, proxy_password, debuginfo, source, gpgkey, disable)
699
700     return repos.values()
701
702 def convert_method_to_repo(ks):
703     try:
704         ks.handler.repo.methodToRepo()
705     except (AttributeError, kserrors.KickstartError):
706         pass
707
708 def get_packages(ks, required = []):
709     return ks.handler.packages.packageList + required
710
711 def get_groups(ks, required = []):
712     return ks.handler.packages.groupList + required
713
714 def get_excluded(ks, required = []):
715     return ks.handler.packages.excludedList + required
716
717 def get_partitions(ks, required = []):
718     return ks.handler.partition.partitions
719
720 def ignore_missing(ks):
721     return ks.handler.packages.handleMissing == ksconstants.KS_MISSING_IGNORE
722
723 def exclude_docs(ks):
724     return ks.handler.packages.excludeDocs
725
726 def inst_langs(ks):
727     if hasattr(ks.handler.packages, "instLange"):
728         return ks.handler.packages.instLange
729     elif hasattr(ks.handler.packages, "instLangs"):
730         return ks.handler.packages.instLangs
731     return ""
732
733 def get_post_scripts(ks):
734     scripts = []
735     for s in ks.handler.scripts:
736         if s.type != ksparser.KS_SCRIPT_POST:
737             continue
738         scripts.append(s)
739     return scripts
740
741 def add_repo(ks, repostr):
742     args = repostr.split()
743     repoobj = ks.handler.repo.parse(args[1:])
744     if repoobj and repoobj not in ks.handler.repo.repoList:
745         ks.handler.repo.repoList.append(repoobj) 
746
747 def remove_all_repos(ks):
748     while len(ks.handler.repo.repoList) != 0:
749         del ks.handler.repo.repoList[0]
750
751 def remove_duplicate_repos(ks):
752     i = 0
753     j = i + 1
754     while True:
755         if len(ks.handler.repo.repoList) < 2:
756             break
757         if i >= len(ks.handler.repo.repoList) - 1:
758             break
759         name = ks.handler.repo.repoList[i].name
760         baseurl = ks.handler.repo.repoList[i].baseurl
761         if j < len(ks.handler.repo.repoList):
762             if (ks.handler.repo.repoList[j].name == name or \
763                 ks.handler.repo.repoList[j].baseurl == baseurl):
764                 del ks.handler.repo.repoList[j]
765             else:
766                 j += 1
767             if j >= len(ks.handler.repo.repoList):
768                 i += 1
769                 j = i + 1
770         else:
771             i += 1
772             j = i + 1
773
774 def resolve_groups(creator, repometadata, use_comps = False):
775     pkgmgr = creator.pkgmgr.get_default_pkg_manager
776     iszypp = False
777     if creator.pkgmgr.managers.has_key("zypp") and creator.pkgmgr.managers['zypp'] == pkgmgr:
778         iszypp = True
779     ks = creator.ks
780
781     for repo in repometadata:
782         """ Mustn't replace group with package list if repo is ready for the corresponding package manager """
783         if iszypp and repo["patterns"] and not use_comps:
784             continue
785         if not iszypp and repo["comps"] and use_comps:
786             continue
787
788         """
789             But we also must handle such cases, use zypp but repo only has comps, 
790             use yum but repo only has patterns, use zypp but use_comps is true,
791             use yum but use_comps is false.
792         """
793         groupfile = None
794         if iszypp:
795             if (use_comps and repo["comps"]) or (not repo["patterns"] and repo["comps"]):
796                 groupfile = repo["comps"]
797                 get_pkglist_handler = misc.get_pkglist_in_comps
798         if not iszypp:
799             if (not use_comps and repo["patterns"]) or (not repo["comps"] and repo["patterns"]):
800                 groupfile = repo["patterns"]
801                 get_pkglist_handler = misc.get_pkglist_in_patterns
802             
803         if groupfile:
804             i = 0
805             while True:
806                 if i >= len(ks.handler.packages.groupList):
807                     break
808                 pkglist = get_pkglist_handler(ks.handler.packages.groupList[i].name, groupfile)
809                 if pkglist:
810                     del ks.handler.packages.groupList[i]
811                     for pkg in pkglist:
812                         if pkg not in ks.handler.packages.packageList:
813                             ks.handler.packages.packageList.append(pkg)
814                 else:
815                     i = i + 1