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