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