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