/[smeserver]/cdrom.image/updates/kickstart.py
ViewVC logotype

Contents of /cdrom.image/updates/kickstart.py

Parent Directory Parent Directory | Revision Log Revision Log | View Revision Graph Revision Graph


Revision 1.5 - (show annotations) (download) (as text)
Fri Jun 9 05:03:00 2006 UTC (18 years, 6 months ago) by gordonr
Branch: MAIN
CVS Tags: HEAD
Changes since 1.4: +0 -0 lines
Content type: text/x-python
FILE REMOVED
See bug 1510 - all changes should be in the anaconda CVS repository

1 #
2 # kickstart.py: kickstart install support
3 #
4 # Copyright 1999-2004 Red Hat, Inc.
5 #
6 # This software may be freely redistributed under the terms of the GNU
7 # library public license.
8 #
9 # You should have received a copy of the GNU Library Public License
10 # along with this program; if not, write to the Free Software
11 # Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
12 #
13
14 import iutil
15 import isys
16 import os
17 from installclass import BaseInstallClass
18 from partitioning import *
19 from autopart import *
20 from fsset import *
21 from flags import flags
22 from constants import *
23 import sys
24 import raid
25 import string
26 import partRequests
27 import urllib2
28 import lvm
29
30 from rhpl.translate import _
31 from rhpl.log import log
32
33 KS_MISSING_PROMPT = 0
34 KS_MISSING_IGNORE = 1
35
36 class KickstartError(Exception):
37 def __init__(self, val = ""):
38 self.value = val
39
40 def __str__ (self):
41 return self.value
42
43 class KickstartValueError(KickstartError):
44 def __init__(self, val = ""):
45 self.value = val
46
47 def __str__ (self):
48 return self.value
49
50 class KSAppendException(KickstartError):
51 def __init__(self, s=""):
52 self.str = s
53
54 def __str__(self):
55 return self.str
56
57 class Script:
58 def __repr__(self):
59 str = ("(s: '%s' i: %s c: %d)") % \
60 (self.script, self.interp, self.inChroot)
61 return string.replace(str, "\n", "|")
62
63 def __init__(self, script, interp, inChroot, logfile = None):
64 self.script = script
65 self.interp = interp
66 self.inChroot = inChroot
67 self.logfile = logfile
68
69 def run(self, chroot, serial):
70 scriptRoot = "/"
71 if self.inChroot:
72 scriptRoot = chroot
73
74 path = scriptRoot + "/tmp/ks-script"
75
76 f = open(path, "w")
77 f.write(self.script)
78 f.close()
79 os.chmod(path, 0700)
80
81 if self.logfile is not None:
82 messages = self.logfile
83 elif serial:
84 messages = "/tmp/ks-script.log"
85 else:
86 messages = "/dev/tty3"
87
88 rc = iutil.execWithRedirect(self.interp,
89 [self.interp,"/tmp/ks-script"],
90 stdout = messages, stderr = messages,
91 root = scriptRoot)
92
93 if rc != 0:
94 log("WARNING - Error code %s encountered running a kickstart %%pre/%%post script", rc)
95
96 os.unlink(path)
97
98 class KickstartBase(BaseInstallClass):
99 name = "kickstart"
100
101 def postAction(self, rootPath, serial, intf):
102 win = intf.waitWindow(_("Post Install Script"),
103 _("The post installation script is running..."))
104
105 script = ( "/sbin/syslogd &\n"
106 "sleep 2\n"
107 "/sbin/e-smith/signal-event post-install\n" )
108 s = Script(script, interp="/bin/sh", inChroot=1)
109 log("%s", s)
110 s.run(rootPath, serial)
111 win.pop()
112
113 log("Running kickstart %%post script(s)")
114 for script in self.postScripts:
115 script.run(rootPath, serial)
116 log("All kickstart %%post script(s) have been run")
117
118 def doRootPw(self, id, args):
119 (args, extra) = isys.getopt(args, '', [ 'iscrypted' ])
120
121 isCrypted = 0
122 for n in args:
123 (str, arg) = n
124 if (str == '--iscrypted'):
125 isCrypted = 1
126
127 if len(extra) != 1:
128 raise KickstartValueError, "a single argument is expected to rootPw"
129
130 self.setRootPassword(id, extra[0], isCrypted = isCrypted)
131 self.skipSteps.append("accounts")
132
133 def doFirewall(self, id, args):
134 (args, extra) = isys.getopt(args, '',
135 [ 'dhcp', 'ssh', 'telnet', 'smtp', 'http', 'ftp', 'enabled',
136 'enable', 'port=', 'high', 'medium', 'disabled', 'disable',
137 'trust=' ])
138
139 enable = -1
140 trusts = []
141 ports = []
142
143 for n in args:
144 (str, arg) = n
145 if str == '--ssh':
146 ports.append("22:tcp")
147 elif str == '--telnet':
148 ports.append("23:tcp")
149 elif str == '--smtp':
150 ports.append("25:tcp")
151 elif str == '--http':
152 ports.extend(["80:tcp", "443:tcp"])
153 elif str == '--ftp':
154 ports.append("21:tcp")
155 elif str == '--high' or str == '--medium':
156 log("used deprecated firewall option: %s" %(str[2:],))
157 enable = 1
158 elif str == '--enabled' or str == "--enable":
159 enable = 1
160 elif str == '--disabled' or str == "--disable":
161 enable = 0
162 elif str == '--trust':
163 trusts.append(arg)
164 elif str == '--port':
165 theports = arg.split(",")
166 for p in theports:
167 p = p.strip()
168 if p.find(":") == -1:
169 p = "%s:tcp" %(p,)
170 ports.append(p)
171
172 self.setFirewall(id, enable, trusts, ports)
173
174 def doSELinux(self, id, args):
175 (args, extra) = isys.getopt(args, '',
176 [ 'disabled', 'enforcing',
177 'permissive' ] )
178
179 sel = 2
180
181 for n in args:
182 (str, arg) = n
183 if str == "--disabled":
184 sel = 0
185 elif str == "--permissive":
186 sel = 1
187 elif str == "--enforcing":
188 sel = 2
189
190 self.setSELinux(id, sel)
191
192 def doZFCP(self, id, args):
193 (args, extra) = isys.getopt(args, '',
194 ["devnum", "scsiid", "wwpn", "scsilun",
195 "fcplun"])
196
197 devnum = None
198 scsiid = None
199 wwpn = None
200 scsilun = None
201 fcplun = None
202
203 for n in args:
204 (str, arg) = n
205 if str == "--devnum":
206 devnum = id.zfcp.sanitizeDeviceInput(arg)
207 elif str == "--scsid":
208 scsiid = id.zfcp.sanitizeHexInput(arg)
209 elif str == "--wwpn":
210 wwpn = id.zfcp.sanitizeHexInput(arg)
211 elif str == "--scsilun":
212 scsilun = id.zfcp.sanitizeHexInput(arg)
213 elif str == "--fcplun":
214 fcplun = id.zfcp.sanitizeFCPLInput(arg)
215
216 if id.zfcp.checkValidDevice(devnum) == -1:
217 raise KickstartValueError, "Invalid devnum specified"
218 if id.zfcp.checkValidID(scsiid) == -1:
219 raise KickstartValueError, "Invalid scsiid specified"
220 if id.zfcp.checkValid64BitHex(wwpn) == -1:
221 raise KickstartValueError, "Invalid wwpn specified"
222 if id.zfcp.checkValidID(scsilun) == -1:
223 raise KickstartValueError, "Invalid scsilun specified"
224 if id.zfcp.checkValid64BitHex(fcplun) == -1:
225 raise KickstartValueError, "Invalid fcplun specified"
226
227 if ((devnum is None) or (scsiid is None) or (wwpn is None)
228 or (scsilun is None) or (fcplun is None)):
229 raise KickstartError, "ZFCP config must specify all of devnum, scsiid, wwpn, scsilun, and fcplun"
230
231 self.setZFCP(id, devnum, scsiid, wwpn, scsilun, fcplun)
232 self.skipSteps.append("zfcpconfig")
233
234 def doAuthconfig(self, id, args):
235 (args, extra) = isys.getopt(args, '',
236 [ 'useshadow', 'enableshadow',
237 'enablemd5',
238 'enablenis', 'nisdomain=', 'nisserver=',
239 'enableldap', 'enableldapauth', 'ldapserver=', 'ldapbasedn=',
240 'enableldaptls',
241 'enablekrb5', 'krb5realm=', 'krb5kdc=', 'krb5adminserver=',
242 'enablehesiod', 'hesiodlhs=', 'hesiodrhs=',
243 'enablesmbauth', 'smbservers=', 'smbworkgroup=',
244 'enablecache'])
245
246 useShadow = 0
247
248 useMd5 = 0
249
250 useNis = 0
251 nisServer = ""
252 nisDomain = ""
253 nisBroadcast = 0
254
255 useLdap = 0
256 useLdapauth = 0
257 useLdaptls = 0
258 ldapServer = ""
259 ldapBasedn = ""
260
261 useKrb5 = 0
262 krb5Realm = ""
263 krb5Kdc = ""
264 krb5Admin = ""
265
266 useHesiod = 0
267 hesiodLhs = ""
268 hesiodRhs = ""
269
270 useSamba = 0
271 smbServers = ""
272 smbWorkgroup = ""
273
274 enableCache = 0
275
276 for n in args:
277 (str, arg) = n
278 if (str == '--enablenis'):
279 useNis = 1
280 elif (str == '--useshadow') or (str == '--enableshadow'):
281 useShadow = 1
282 elif (str == '--enablemd5'):
283 useMd5 = 1
284 elif (str == '--nisserver'):
285 nisServer = arg
286 elif (str == '--nisdomain'):
287 nisDomain = arg
288 elif (str == '--enableldap'):
289 useLdap = 1
290 elif (str == '--enableldapauth'):
291 useLdapauth = 1
292 elif (str == '--ldapserver'):
293 ldapServer = arg
294 elif (str == '--ldapbasedn'):
295 ldapBasedn = arg
296 elif (str == '--enableldaptls'):
297 useLdaptls = 1
298 elif (str == '--enablekrb5'):
299 useKrb5 = 1
300 elif (str == '--krb5realm'):
301 krb5Realm = arg
302 elif (str == '--krb5kdc'):
303 krb5Kdc = arg
304 elif (str == '--krb5adminserver'):
305 krb5Admin = arg
306 elif (str == '--enablehesiod'):
307 useHesiod = 1
308 elif (str == '--hesiodlhs'):
309 hesiodLhs = arg
310 elif (str == '--hesiodrhs'):
311 hesiodRhs = arg
312 elif (str == '--enablesmbauth'):
313 useSamba = 1
314 elif (str == '--smbservers'):
315 smbServers = arg
316 elif (str == '--smbworkgroup'):
317 smbWorkgroup = arg
318 elif (str == '--enablecache'):
319 enableCache = 1
320
321
322 if useNis and not nisServer: nisBroadcast = 1
323
324 self.setAuthentication(id, useShadow, useMd5,
325 useNis, nisDomain, nisBroadcast, nisServer,
326 useLdap, useLdapauth, ldapServer,
327 ldapBasedn, useLdaptls,
328 useKrb5, krb5Realm, krb5Kdc, krb5Admin,
329 useHesiod, hesiodLhs, hesiodRhs,
330 useSamba, smbServers, smbWorkgroup,
331 enableCache)
332
333 self.skipSteps.append("authentication")
334
335 def doBootloader (self, id, args, useLilo = 0):
336 (args, extra) = isys.getopt(args, '',
337 [ 'append=', 'location=', 'useLilo', 'lba32',
338 'password=', 'md5pass=', 'linear', 'nolinear',
339 'upgrade', 'driveorder='])
340
341 validLocations = [ "mbr", "partition", "none", "boot" ]
342 appendLine = ""
343 location = "mbr"
344 password = None
345 md5pass = None
346 forceLBA = 0
347 linear = 1
348 upgrade = 0
349 driveorder = []
350
351 for n in args:
352 (str, arg) = n
353 if str == '--append':
354 appendLine = arg
355 elif str == '--location':
356 location = arg
357 elif str == '--useLilo':
358 # log("used deprecated option --useLilo, ignoring")
359 useLilo = 1
360 elif str == '--linear':
361 linear = 1
362 elif str == '--nolinear':
363 linear = 0
364 elif str == '--lba32':
365 forceLBA = 1
366 elif str == '--password':
367 password = arg
368 elif str == '--md5pass':
369 md5pass = arg
370 elif str == '--upgrade':
371 upgrade = 1
372 elif str == '--driveorder':
373 driveorder = string.split(arg, ',')
374
375 if location not in validLocations:
376 raise KickstartValueError, "mbr, partition, or none expected for bootloader command"
377 if location == "none":
378 location = None
379 elif location == "partition":
380 location = "boot"
381
382 if upgrade and not id.upgrade.get():
383 raise KickstartError, "Selected upgrade mode for bootloader but not doing an upgrade"
384
385 if upgrade:
386 id.bootloader.kickstart = 1
387 id.bootloader.doUpgradeOnly = 1
388
389 if location is None:
390 self.skipSteps.append("bootloadersetup")
391 self.skipSteps.append("instbootloader")
392 else:
393 self.showSteps.append("bootloadersetup")
394 self.setBootloader(id, useLilo, location, linear, forceLBA,
395 password, md5pass, appendLine, driveorder)
396
397 self.skipSteps.append("upgbootloader")
398 self.skipSteps.append("bootloader")
399 self.skipSteps.append("bootloaderadvanced")
400
401 def doLilo (self, id, args):
402 self.doBootloader(id, args, useLilo = 1)
403
404 def doFirstboot(self, id, args):
405 (args, extra) = isys.getopt(args, '',
406 ['reconfig', 'enable', 'enabled',
407 'disable', 'disabled'])
408
409 fb = FIRSTBOOT_SKIP
410
411 for n in args:
412 (str, arg) = n
413 if str == '--reconfig':
414 fb = FIRSTBOOT_RECONFIG
415 elif str == '--enable' or str == "--enabled":
416 fb = FIRSTBOOT_DEFAULT
417 elif str == '--disable' or str == "--disabled":
418 fb = FIRSTBOOT_SKIP
419
420 id.firstboot = fb
421
422
423 def doLiloCheck (self, id, args):
424 drives = isys.hardDriveDict ().keys()
425 drives.sort(isys.compareDrives)
426 device = drives[0]
427 isys.makeDevInode(device, '/tmp/' + device)
428 fd = os.open('/tmp/' + device, os.O_RDONLY)
429 os.unlink('/tmp/' + device)
430 block = os.read(fd, 512)
431 os.close(fd)
432 if block[6:10] == "LILO":
433 sys.exit(0)
434
435 def doTimezone(self, id, args):
436 (args, extra) = isys.getopt(args, '',
437 [ 'utc' ])
438
439 isUtc = 0
440
441 for n in args:
442 (str, arg) = n
443 if str == '--utc':
444 isUtc = 1
445
446 self.setTimezoneInfo(id, extra[0], asUtc = isUtc)
447
448 self.skipSteps.append("timezone")
449
450
451 def doXconfig(self, id, args):
452 (args, extra) = isys.getopt(args, '',
453 [ 'server=', 'card=', 'videoram=',
454 'monitor=', 'hsync=', 'vsync=',
455 'resolution=', 'depth=',
456 'startxonboot', 'noprobe', 'defaultdesktop=' ])
457
458 if extra:
459 raise KickstartValueError, "unexpected arguments to xconfig command"
460
461 server = None
462 card = None
463 videoRam = None
464 monitor = None
465 hsync = None
466 vsync = None
467 resolution = None
468 depth = None
469 noProbe = 0
470 startX = 0
471 defaultdesktop = ""
472
473 for n in args:
474 (str, arg) = n
475 if (str == "--noprobe"):
476 noProbe = 1
477 elif (str == "--server"):
478 server = arg
479 elif (str == "--card"):
480 card = arg
481 elif (str == "--videoram"):
482 videoRam = arg
483 elif (str == "--monitor"):
484 monitor = arg
485 elif (str == "--hsync"):
486 hsync = arg
487 elif (str == "--vsync"):
488 vsync = arg
489 elif (str == "--resolution"):
490 resolution = arg
491 elif (str == "--depth"):
492 depth = string.atoi(arg)
493 elif (str == "--startxonboot"):
494 startX = 1
495 elif (str == "--defaultdesktop"):
496 defaultdesktop = arg
497
498 self.configureX(id, server, card, videoRam, monitor, hsync, vsync,
499 resolution, depth, noProbe, startX)
500 self.setDesktop(id, defaultdesktop)
501
502 self.skipSteps.append("videocard")
503 self.skipSteps.append("monitor")
504 self.skipSteps.append("xcustom")
505 self.skipSteps.append("handleX11pkgs")
506 self.skipSteps.append("checkmonitorok")
507 self.skipSteps.append("setsanex")
508
509 def doMonitor(self, id, args):
510 (args, extra) = isys.getopt(args, '',
511 [ 'monitor=', 'hsync=', 'vsync=' ])
512
513 if extra:
514 raise KickstartValueError, "unexpected arguments to monitor command"
515
516 monitor = None
517 hsync = None
518 vsync = None
519
520 for n in args:
521 (str, arg) = n
522 if (str == "--monitor"):
523 monitor = arg
524 elif (str == "--hsync"):
525 hsync = arg
526 elif (str == "--vsync"):
527 vsync = arg
528
529 self.skipSteps.append("monitor")
530 self.skipSteps.append("checkmonitorok")
531
532 self.setMonitor(id, hsync = hsync, vsync = vsync,
533 monitorName = monitor)
534
535 def doUpgrade(self, id, args):
536 self.installType = "upgrade"
537 id.upgrade.set(1)
538
539 def doNetwork(self, id, args):
540 # nodns is only used by the loader
541 (args, extra) = isys.getopt(args, '',
542 [ 'bootproto=', 'ip=', 'netmask=', 'gateway=', 'nameserver=',
543 'nodns', 'device=', 'hostname=', 'ethtool=', 'onboot=',
544 'dhcpclass=', 'essid=', 'wepkey=', 'notksdevice'])
545 bootProto = "dhcp"
546 ip = None
547 netmask = ""
548 gateway = ""
549 nameserver = ""
550 hostname = ""
551 ethtool = ""
552 essid = ""
553 wepkey = ""
554 onboot = 1
555 device = None
556 dhcpclass = None
557 for n in args:
558 (str, arg) = n
559 if str == "--bootproto":
560 bootProto = arg
561 elif str == "--ip":
562 ip = arg
563 elif str == "--netmask":
564 netmask = arg
565 elif str == "--gateway":
566 gateway = arg
567 elif str == "--nameserver":
568 nameserver = arg
569 elif str == "--device":
570 device = arg
571 elif str == "--hostname":
572 hostname = arg
573 elif str== "--ethtool":
574 ethtool = arg
575 elif str == "--essid":
576 essid = arg
577 elif str == "--wepkey":
578 wepkey = arg
579 elif str== "--onboot":
580 if arg == 'no':
581 onboot = 0
582 else:
583 onboot = 1
584 elif str == "--class":
585 dhcpclass = arg
586
587 self.setNetwork(id, bootProto, ip, netmask, ethtool, device=device, onboot=onboot, dhcpclass=dhcpclass, essid=essid, wepkey=wepkey)
588 if hostname != "":
589 self.setHostname(id, hostname, override = 1)
590 if nameserver != "":
591 self.setNameserver(id, nameserver)
592 if gateway != "":
593 self.setGateway(id, gateway)
594
595 def doLang(self, id, args):
596 self.setLanguage(id, args[0])
597 self.skipSteps.append("language")
598
599 def doLangSupport (self, id, args):
600 (args, extra) = isys.getopt(args, '', [ 'default=' ])
601 deflang = "en_US.UTF-8"
602 if args:
603 deflang = args[0][1]
604 else:
605 # if they specified no default we default to en_US if
606 # they installed support for more than one lang, otherwise
607 # we default to the one language they specified support for
608 if extra is None:
609 deflang = "en_US.UTF-8"
610 elif len(extra) >= 1:
611 deflang = extra[0]
612 else:
613 deflang = "en_US.UTF-8"
614
615 self.setLanguageDefault (id, deflang)
616 self.setLanguageSupport(id, extra)
617
618 self.skipSteps.append("languagesupport")
619
620 def doKeyboard(self, id, args):
621 self.setKeyboard(id, args[0])
622 id.keyboard.beenset = 1
623 self.skipSteps.append("keyboard")
624
625 def doZeroMbr(self, id, args):
626 self.setZeroMbr(id, 1)
627
628 def doMouse(self, id, args):
629 #Don't do anything with mice anymore
630 return
631
632 ## (args, extra) = isys.getopt(args, '', [ 'device=', 'emulthree' ])
633 ## mouseType = "none"
634 ## device = None
635 ## emulThree = 0
636
637 ## for n in args:
638 ## (str, arg) = n
639 ## if str == "--device":
640 ## device = arg
641 ## elif str == "--emulthree":
642 ## emulThree = 1
643
644 ## if extra:
645 ## mouseType = extra[0]
646
647 ## if mouseType != "none":
648 ## self.setMouse(id, mouseType, device, emulThree)
649
650 ## self.skipSteps.append("mouse")
651
652 def doReboot(self, id, args):
653 self.skipSteps.append("complete")
654
655 def doSkipX(self, id, args):
656 self.skipSteps.append("checkmonitorok")
657 self.skipSteps.append("setsanex")
658 self.skipSteps.append("videocard")
659 self.skipSteps.append("monitor")
660 self.skipSteps.append("xcustom")
661 self.skipSteps.append("handleX11pkgs")
662 self.skipSteps.append("writexconfig")
663 if id.xsetup is not None:
664 id.xsetup.skipx = 1
665
666 def doInteractive(self, id, args):
667 self.interactive = 1
668
669 def doAutoStep(self, id, args):
670 flags.autostep = 1
671 flags.autoscreenshot = 0
672
673 (xargs, xtra) = isys.getopt(args, '', ['autoscreenshot'])
674 for n in xargs:
675 (str, arg) = n
676 if str == "--autoscreenshot":
677 flags.autoscreenshot = 1
678
679
680 # read the kickstart config... if parsePre is set, only parse
681 # the %pre, otherwise ignore the %pre. assume we're starting in where
682 def readKickstart(self, id, file, parsePre = 0, where = "commands"):
683 handlers = {
684 "auth" : self.doAuthconfig ,
685 "authconfig" : self.doAuthconfig ,
686 "autopart" : self.doAutoPart ,
687 "cdrom" : None ,
688 "clearpart" : self.doClearPart ,
689 "ignoredisk" : self.doIgnoreDisk ,
690 "device" : None ,
691 "deviceprobe" : None ,
692 "driverdisk" : None ,
693 "firewall" : self.doFirewall ,
694 "selinux" : self.doSELinux ,
695 "harddrive" : None ,
696 "install" : None ,
697 "keyboard" : self.doKeyboard ,
698 "lang" : self.doLang ,
699 "langsupport" : self.doLangSupport ,
700 "lilo" : self.doLilo ,
701 "bootloader" : self.doBootloader ,
702 "lilocheck" : self.doLiloCheck ,
703 "mouse" : self.doMouse ,
704 "network" : self.doNetwork ,
705 "nfs" : None ,
706 "part" : self.definePartition ,
707 "partition" : self.definePartition ,
708 "raid" : self.defineRaid ,
709 "volgroup" : self.defineVolumeGroup,
710 "logvol" : self.defineLogicalVolume,
711 "reboot" : self.doReboot ,
712 "poweroff" : self.doReboot ,
713 "halt" : self.doReboot ,
714 "shutdown" : self.doReboot ,
715 "rootpw" : self.doRootPw ,
716 "skipx" : self.doSkipX ,
717 "text" : None ,
718 "graphical" : None ,
719 "cmdline" : None ,
720 "timezone" : self.doTimezone ,
721 "url" : None ,
722 "upgrade" : self.doUpgrade ,
723 "xconfig" : self.doXconfig ,
724 "monitor" : self.doMonitor ,
725 "xdisplay" : None ,
726 "zerombr" : self.doZeroMbr ,
727 "interactive" : self.doInteractive ,
728 "autostep" : self.doAutoStep ,
729 "firstboot" : self.doFirstboot ,
730 "vnc" : None ,
731 }
732
733 packages = []
734 groups = []
735 excludedPackages = []
736
737 script = ""
738 scriptInterp = "/bin/sh"
739 scriptLog = None
740 if where == "pre" or where == "traceback":
741 scriptChroot = 0
742 else:
743 scriptChroot = 1
744
745 for n in open(file).readlines():
746 args = isys.parseArgv(n)
747
748 # don't eliminate white space or comments from scripts
749 if where not in ["pre", "post", "traceback"]:
750 if not args or args[0][0] == '#': continue
751
752 if args and (args[0] in ["%pre", "%post", "%traceback"]):
753 if ((where =="pre" and parsePre) or
754 (where in ["post", "traceback"] and not parsePre)):
755 s = Script(script, scriptInterp, scriptChroot, scriptLog)
756 if where == "pre":
757 self.preScripts.append(s)
758 elif where == "post":
759 self.postScripts.append(s)
760 else:
761 self.tracebackScripts.append(s)
762
763 where = args[0][1:]
764 args = isys.parseArgv(n)
765
766 script = ""
767 scriptInterp = "/bin/sh"
768 scriptLog = None
769 if where == "pre" or where == "traceback":
770 scriptChroot = 0
771 else:
772 scriptChroot = 1
773
774 argList = [ 'interpreter=', "log=", "logfile=" ]
775 if where == "post":
776 argList.append('nochroot')
777
778 (args, extra) = isys.getopt(args, '', argList)
779 for n in args:
780 (str, arg) = n
781
782 if str == "--nochroot":
783 scriptChroot = 0
784 elif str == "--interpreter":
785 scriptInterp = arg
786 elif str == "--log" or str == "--logfile":
787 scriptLog = arg
788
789 elif args and args[0] == "%include" and not parsePre:
790 if len(args) < 2:
791 raise KickstartError, "Invalid %include line"
792 else:
793 # read in the included file and set our where appropriately
794 where = self.readKickstart(id, args[1], where = where)
795 elif args and args[0] == "%packages":
796 if ((where =="pre" and parsePre) or
797 (where in ["post", "traceback"] and not parsePre)):
798 s = Script(script, scriptInterp, scriptChroot, scriptLog)
799 if where == "pre":
800 self.preScripts.append(s)
801 elif where == "post":
802 self.postScripts.append(s)
803 else:
804 self.tracebackScripts.append(s)
805
806 # if we're parsing the %pre, we don't need to continue
807 if parsePre:
808 continue
809
810 if len(args) > 1:
811 for arg in args[1:]:
812 if arg == "--resolvedeps":
813 id.handleDeps = RESOLVE_DEPS
814 elif arg == "--ignoredeps":
815 id.handleDeps = IGNORE_DEPS
816 elif arg == "--excludedocs":
817 id.excludeDocs = 1
818 elif arg == "--ignoremissing":
819 self.handleMissing = KS_MISSING_IGNORE
820 elif arg == "--nobase":
821 self.addBase = 0
822
823 where = "packages"
824 self.skipSteps.append("package-selection")
825 else:
826 # if we're parsing the %pre and not in the pre, continue
827 if parsePre and where != "pre":
828 continue
829 elif where == "packages":
830 #Scan for comments in package list...drop off
831 #everything after "#" mark
832 try:
833 ind = string.index(n, "#")
834 n = n[:ind]
835 except:
836 #No "#" found in line
837 pass
838
839 if n[0] == '@':
840 n = n[1:]
841 n = string.strip (n)
842 groups.append(n)
843 elif n[0] == '-':
844 n = n[1:]
845 n = string.strip(n)
846 excludedPackages.append(n)
847 else:
848 n = string.strip (n)
849 packages.append(n)
850 elif where == "commands":
851 if handlers.has_key(args[0]):
852 if handlers[args[0]] is not None:
853 handlers[args[0]](id, args[1:])
854 else:
855 # unrecognized command
856 raise KickstartError, "Unrecognized ks command: %s\nOn the line: %s" % (args[0], n)
857 elif where in ["pre", "post", "traceback"]:
858 script = script + n
859 else:
860 raise KickstartError, "I'm lost in kickstart"
861
862 self.groupList.extend(groups)
863 self.packageList.extend(packages)
864 self.excludedList.extend(excludedPackages)
865
866 # test to see if they specified to clear partitions and also
867 # tried to --onpart on a logical partition
868 #
869 # XXX
870 #
871 #if iutil.getArch() == 'i386' and self.fstab:
872 #clear = self.getClearParts()
873 #if clear == FSEDIT_CLEAR_LINUX or clear == FSEDIT_CLEAR_ALL:
874 #for (mntpoint, (dev, fstype, reformat)) in self.fstab:
875 #if int(dev[-1:]) > 4:
876 #raise RuntimeError, "Clearpart and --onpart on non-primary partition %s not allowed" % dev
877
878 if ((where =="pre" and parsePre) or
879 (where in ["post", "traceback"] and not parsePre)):
880 s = Script(script, scriptInterp, scriptChroot, scriptLog)
881 if where == "pre":
882 self.preScripts.append(s)
883 elif where == "post":
884 self.postScripts.append(s)
885 else:
886 self.tracebackScripts.append(s)
887
888 return where
889
890 def doClearPart(self, id, args):
891 type = CLEARPART_TYPE_NONE
892 drives = None
893 initAll = 0
894
895 (args, extra) = isys.getopt(args, '', [ 'linux', 'all', 'drives=',
896 'initlabel', 'none'])
897
898 for n in args:
899 (str, arg) = n
900 if str == '--linux':
901 type = CLEARPART_TYPE_LINUX
902 elif str == '--all':
903 type = CLEARPART_TYPE_ALL
904 elif str == '--drives':
905 drives = string.split(arg, ',')
906 elif str == '--initlabel':
907 initAll = 1
908 elif str == '--none':
909 type = CLEARPART_TYPE_NONE
910
911 self.setClearParts(id, type, drives, initAll = initAll)
912
913 # this adds a partition to the autopartition list replacing anything
914 # else with this mountpoint so that you can use autopart and override /
915 def addPartRequest(self, partitions, request):
916 if not request.mountpoint:
917 partitions.autoPartitionRequests.append(request)
918 return
919
920 for req in partitions.autoPartitionRequests:
921 if req.mountpoint and req.mountpoint == request.mountpoint:
922 partitions.autoPartitionRequests.remove(req)
923 break
924 partitions.autoPartitionRequests.append(request)
925
926 def doAutoPart(self, id, args):
927 # sets up default autopartitioning. use clearpart separately
928 # if you want it
929 self.setDefaultPartitioning(id, doClear = 0)
930
931 id.partitions.isKickstart = 1
932
933 self.skipSteps.append("partition")
934 self.skipSteps.append("partitionmethod")
935 self.skipSteps.append("partitionmethodsetup")
936 self.skipSteps.append("fdisk")
937 self.skipSteps.append("autopartition")
938 self.skipSteps.append("zfcpconfig")
939
940 def defineLogicalVolume(self, id, args):
941 (args, extra) = isys.getopt(args, '', [ 'vgname=',
942 'size=',
943 'name=',
944 'fstype=',
945 'percent=',
946 'maxsize=',
947 'grow',
948 'recommended',
949 'noformat',
950 'useexisting'])
951
952 mountpoint = None
953 vgname = None
954 size = None
955 name = None
956 fstype = None
957 percent = None
958 grow = 0
959 maxSizeMB = 0
960 format = 1
961 recommended = None
962 preexist = 0
963
964 for n in args:
965 (str, arg) = n
966 if str == '--vgname':
967 vgname = arg
968 elif str == '--size':
969 size = int(arg)
970 elif str == '--name':
971 name = arg
972 elif str == '--fstype':
973 fstype = arg
974 elif str == '--percent':
975 percent = int(arg)
976 elif str == '--maxsize':
977 maxSizeMB = int(arg)
978 elif str == '--grow':
979 grow = 1
980 elif str == '--recommended':
981 recommended = 1
982 elif str == "--noformat":
983 format = 0
984 preexist = 1
985 elif str == "--useexisting":
986 preexist = 1
987
988 if extra[0] == 'swap':
989 filesystem = fileSystemTypeGet('swap')
990 mountpoint = None
991 if recommended:
992 (size, maxSizeMB) = iutil.swapSuggestion()
993 grow = 1
994 else:
995 if fstype:
996 filesystem = fileSystemTypeGet(fstype)
997 else:
998 filesystem = fileSystemTypeGetDefault()
999
1000 mountpoint = extra[0]
1001
1002 # sanity check mountpoint
1003 if mountpoint is not None and mountpoint[0] != '/':
1004 raise KickstartError, "The mount point \"%s\" is not valid." % (mountpoint,)
1005
1006 if not vgname:
1007 raise KickstartError, "Must specify the volume group for the logical volume to be in"
1008 if not size and not percent and not preexist:
1009 raise KickstartError, "Must specify the size of a logical volume"
1010 if percent and percent <= 0 or percent > 100:
1011 raise KickstartValueError, "Logical Volume percentage must be between 0 and 100 percent"
1012
1013 if not name:
1014 raise KickstartError, "Must specify a logical volume name"
1015
1016 vgid = self.ksVGMapping[vgname]
1017 for areq in id.partitions.autoPartitionRequests:
1018 if areq.type == REQUEST_LV:
1019 if areq.volumeGroup == vgid and areq.logicalVolumeName == name:
1020 raise KickstartValueError, "Logical volume name %s already used in volume group %s" % (name,vgname)
1021
1022 if not self.ksVGMapping.has_key(vgname):
1023 raise KickstartValueError, "Logical volume specifies a non-existent volume group"
1024
1025 request = partRequests.LogicalVolumeRequestSpec(filesystem,
1026 format = format,
1027 mountpoint = mountpoint,
1028 size = size,
1029 percent = percent,
1030 volgroup = vgid,
1031 lvname = name,
1032 grow = grow,
1033 maxSizeMB=maxSizeMB,
1034 preexist = preexist)
1035 self.addPartRequest(id.partitions, request)
1036
1037
1038 def defineVolumeGroup(self, id, args):
1039 (args, extra) = isys.getopt(args, '', ['noformat','useexisting',
1040 'pesize='])
1041
1042 preexist = 0
1043 format = 1
1044 pesize = 32768
1045
1046 vgname = extra[0]
1047
1048 for n in args:
1049 (str, arg) = n
1050 if str == '--noformat' or str == '--useexisting':
1051 preexist = 1
1052 format = 0
1053 elif str == "--pesize":
1054 pesize = int(arg)
1055
1056 pvs = []
1057 # get the unique ids of each of the physical volumes
1058 for pv in extra[1:]:
1059 if pv not in self.ksPVMapping.keys():
1060 raise KickstartError, "Tried to use an undefined partition in Volume Group specification"
1061 pvs.append(self.ksPVMapping[pv])
1062
1063 if len(pvs) == 0 and not preexist:
1064 raise KickstartError, "Volume group defined without any physical volumes"
1065
1066 if pesize not in lvm.getPossiblePhysicalExtents(floor=1024):
1067 raise KickstartError, "Volume group specified invalid pesize: %d" %(pesize,)
1068
1069 # get a sort of hackish id
1070 uniqueID = self.ksID
1071 self.ksVGMapping[extra[0]] = uniqueID
1072 self.ksID = self.ksID + 1
1073
1074 request = partRequests.VolumeGroupRequestSpec(vgname = vgname,
1075 physvols = pvs,
1076 preexist = preexist,
1077 format = format,
1078 pesize = pesize)
1079 request.uniqueID = uniqueID
1080 self.addPartRequest(id.partitions, request)
1081
1082 def defineRaid(self, id, args):
1083 (args, extra) = isys.getopt(args, '', [ 'level=', 'device=',
1084 'spares=', 'fstype=',
1085 'noformat', 'useexisting'] )
1086
1087 level = None
1088 raidDev = None
1089 spares = 0
1090 fstype = None
1091 format = 1
1092 uniqueID = None
1093 preexist = 0
1094
1095 for n in args:
1096 (str, arg) = n
1097 if str == '--level':
1098 level = arg
1099 elif str == "--device":
1100 raidDev = arg
1101 if raidDev[0:2] == "md":
1102 raidDev = raidDev[2:]
1103 raidDev = int(raidDev)
1104 elif str == "--spares":
1105 spares = int(arg)
1106 elif str == "--noformat":
1107 format = 0
1108 preexist = 1
1109 elif str == "--useexisting":
1110 preexist = 1
1111 elif str == "--fstype":
1112 fstype = arg
1113
1114 if extra[0] == 'swap':
1115 filesystem = fileSystemTypeGet('swap')
1116 mountpoint = None
1117 elif extra[0].startswith("pv."):
1118 filesystem = fileSystemTypeGet("physical volume (LVM)")
1119 mountpoint = None
1120
1121 if self.ksPVMapping.has_key(extra[0]):
1122 raise KickstartError, "Defined PV partition %s multiple times" % (extra[0],)
1123
1124 # get a sort of hackish id
1125 uniqueID = self.ksID
1126 self.ksPVMapping[extra[0]] = uniqueID
1127 self.ksID = self.ksID + 1
1128 else:
1129 if fstype:
1130 filesystem = fileSystemTypeGet(fstype)
1131 else:
1132 filesystem = fileSystemTypeGetDefault()
1133
1134 mountpoint = extra[0]
1135
1136 # sanity check mountpoint
1137 if mountpoint is not None and mountpoint[0] != '/':
1138 raise KickstartError, "The mount point \"%s\" is not valid." % (mountpoint,)
1139
1140 raidmems = []
1141 # get the unique ids of each of the raid members
1142 for member in extra[1:]:
1143 if member not in self.ksRaidMapping.keys():
1144 raise KickstartError, "Tried to use an undefined partition in RAID specification"
1145 if member in self.ksUsedMembers:
1146 raise KickstartError, "Tried to use the RAID member %s in two or more RAID specifications" % (member,)
1147
1148 raidmems.append(self.ksRaidMapping[member])
1149 self.ksUsedMembers.append(member)
1150
1151 # XXX this shouldn't have to happen =\
1152 if raid.isRaid0(level):
1153 level = "RAID0"
1154 elif raid.isRaid1(level):
1155 level = "RAID1"
1156 elif raid.isRaid5(level):
1157 level = "RAID5"
1158 elif raid.isRaid6(level):
1159 level = "RAID6"
1160
1161 if not level and preexist == 0:
1162 raise KickstartValueError, "RAID Partition defined without RAID level"
1163 if len(raidmems) == 0 and preexist == 0:
1164 raise KickstartValueError, "RAID Partition defined without any RAID members"
1165
1166 request = partRequests.RaidRequestSpec(filesystem,
1167 mountpoint = mountpoint,
1168 raidmembers = raidmems,
1169 raidlevel = level,
1170 raidspares = spares,
1171 format = format,
1172 raidminor = raidDev,
1173 preexist = preexist)
1174
1175 if uniqueID:
1176 request.uniqueID = uniqueID
1177 if preexist and raidDev is not None:
1178 request.device = "md%s" %(raidDev,)
1179
1180 self.addPartRequest(id.partitions, request)
1181
1182
1183 def definePartition(self, id, args):
1184 # we set up partition requests (whee!)
1185 size = None
1186 grow = None
1187 maxSize = None
1188 disk = None
1189 onPart = None
1190 fsopts = None
1191 type = None
1192 primOnly = None
1193 format = 1
1194 fstype = None
1195 mountpoint = None
1196 uniqueID = None
1197 start = None
1198 end = None
1199 badblocks = None
1200 recommended = None
1201
1202 (args, extra) = isys.getopt(args, '', [ 'size=', 'maxsize=',
1203 'grow', 'onpart=', 'ondisk=',
1204 'bytes-per-inode=', 'usepart=',
1205 'type=', 'fstype=', 'asprimary',
1206 'noformat', 'start=', 'end=',
1207 'badblocks', 'recommended',
1208 'ondrive=', 'onbiosdisk=' ])
1209
1210 for n in args:
1211 (str, arg) = n
1212 if str == '--size':
1213 size = int(arg)
1214 elif str == '--maxsize':
1215 maxSize = int(arg)
1216 elif str == '--grow':
1217 grow = 1
1218 elif str == '--onpart' or str == '--usepart':
1219 onPart = arg
1220 elif str == '--ondisk' or str == '--ondrive':
1221 disk = arg
1222 elif str == '--onbiosdisk':
1223 disk = isys.doGetBiosDisk(arg)
1224 if disk is None:
1225 raise KickstartValueError, "Specified BIOS disk %s cannot be determined" %(arg,)
1226 elif str == '--bytes-per-inode':
1227 fsopts = ['-i', arg]
1228 # XXX this doesn't do anything right now
1229 elif str == '--type':
1230 type = int(arg)
1231 elif str == "--active":
1232 active = 1
1233 elif str == "--asprimary":
1234 primOnly = 1
1235 elif str == "--noformat":
1236 format = 0
1237 elif str == "--fstype":
1238 fstype = arg
1239 elif str == "--start":
1240 start = int(arg)
1241 elif str == "--end":
1242 end = int(arg)
1243 elif str == "--badblocks":
1244 # no longer support badblocks checking
1245 log("WARNING: --badblocks specified but is no longer supported")
1246 elif str == "--recommended":
1247 recommended = 1
1248
1249 if len(extra) != 1:
1250 raise KickstartValueError, "partition command requires one anonymous argument"
1251
1252 if extra[0] == 'swap':
1253 filesystem = fileSystemTypeGet('swap')
1254 mountpoint = None
1255 if recommended:
1256 (size, maxSize) = iutil.swapSuggestion()
1257 grow = 1
1258 # if people want to specify no mountpoint for some reason, let them
1259 # this is really needed for pSeries boot partitions :(
1260 elif extra[0] == 'None':
1261 mountpoint = None
1262 if fstype:
1263 filesystem = fileSystemTypeGet(fstype)
1264 else:
1265 filesystem = fileSystemTypeGetDefault()
1266 elif extra[0] == 'prepboot':
1267 filesystem = fileSystemTypeGet("PPC PReP Boot")
1268 mountpoint = None
1269 elif extra[0].startswith("raid."):
1270 filesystem = fileSystemTypeGet("software RAID")
1271
1272 if self.ksRaidMapping.has_key(extra[0]):
1273 raise KickstartError, "Defined RAID partition %s multiple times" % (extra[0],)
1274
1275 # get a sort of hackish id
1276 uniqueID = self.ksID
1277 self.ksRaidMapping[extra[0]] = uniqueID
1278 self.ksID = self.ksID + 1
1279 elif extra[0].startswith("pv."):
1280 filesystem = fileSystemTypeGet("physical volume (LVM)")
1281
1282 if self.ksPVMapping.has_key(extra[0]):
1283 raise KickstartError, "Defined PV partition %s multiple times" % (extra[0],)
1284
1285 # get a sort of hackish id
1286 uniqueID = self.ksID
1287 self.ksPVMapping[extra[0]] = uniqueID
1288 self.ksID = self.ksID + 1
1289 # XXX should we let people not do this for some reason?
1290 elif extra[0] == "/boot/efi":
1291 filesystem = fileSystemTypeGet("vfat")
1292 mountpoint = extra[0]
1293 else:
1294 if fstype:
1295 filesystem = fileSystemTypeGet(fstype)
1296 mountpoint = extra[0]
1297 else:
1298 filesystem = fileSystemTypeGetDefault()
1299 mountpoint = extra[0]
1300
1301 if (size is None) and (not start and not end) and (not onPart):
1302 raise KickstartValueError, "partition command requires a size specification"
1303 if start and not disk:
1304 raise KickstartValueError, "partition command with start cylinder requires a drive specification"
1305 if disk and disk not in isys.hardDriveDict().keys():
1306 raise KickstartValueError, "specified disk %s in partition command which does not exist" %(disk,)
1307
1308 # XXX bytes per inode is the only per fs option at the moment
1309 # and we can assume that it works like this since it only works
1310 # with ext[23]
1311 if fsopts:
1312 filesystem.extraFormatArgs.extend(fsopts)
1313
1314 request = partRequests.PartitionSpec(filesystem,
1315 mountpoint = mountpoint,
1316 format = 1)
1317
1318 if size is not None:
1319 request.size = size
1320 if start:
1321 request.start = start
1322 if end:
1323 request.end = end
1324 if grow:
1325 request.grow = 1
1326 if maxSize:
1327 request.maxSizeMB = maxSize
1328 if disk:
1329 request.drive = [ disk ]
1330 if primOnly:
1331 request.primary = 1
1332 if not format:
1333 request.format = 0
1334 if uniqueID:
1335 request.uniqueID = uniqueID
1336 if badblocks:
1337 request.badblocks = badblocks
1338 if onPart:
1339 # strip spurious /dev
1340 if onPart.startswith("/dev/"):
1341 onPart = onPart[5:]
1342 request.device = onPart
1343 for areq in id.partitions.autoPartitionRequests:
1344 if areq.device is not None and areq.device == onPart:
1345 raise KickstartValueError, "Partition %s already used" %(onPart,)
1346
1347 self.addPartRequest(id.partitions, request)
1348 id.partitions.isKickstart = 1
1349
1350 self.skipSteps.append("partition")
1351 self.skipSteps.append("partitionmethod")
1352 self.skipSteps.append("partitionmethodsetup")
1353 self.skipSteps.append("fdisk")
1354 self.skipSteps.append("autopartition")
1355 self.skipSteps.append("zfcpconfig")
1356
1357 def doIgnoreDisk(self, id, args):
1358 # add disks to ignore list
1359 drives = []
1360 (args, extra) = isys.getopt(args, '', [ 'drives=' ])
1361
1362 for n in args:
1363 (str, arg) = n
1364 if str == '--drives':
1365 drives = string.split(arg, ',')
1366
1367 self.setIgnoredDisks(id, drives)
1368
1369 def setSteps(self, dispatch):
1370 if self.installType == "upgrade":
1371 from upgradeclass import InstallClass
1372 theUpgradeclass = InstallClass(0)
1373 theUpgradeclass.setSteps(dispatch)
1374
1375 # we have no way to specify migrating yet
1376 dispatch.skipStep("upgrademigfind")
1377 dispatch.skipStep("upgrademigratefs")
1378 dispatch.skipStep("upgradecontinue")
1379 dispatch.skipStep("findinstall", permanent = 1)
1380 dispatch.skipStep("language")
1381 dispatch.skipStep("keyboard")
1382 # dispatch.skipStep("mouse")
1383 dispatch.skipStep("welcome")
1384 dispatch.skipStep("betanag")
1385 dispatch.skipStep("installtype")
1386 else:
1387 BaseInstallClass.setSteps(self, dispatch)
1388 dispatch.skipStep("findrootparts")
1389
1390 if self.interactive or flags.autostep:
1391 dispatch.skipStep("installtype")
1392 dispatch.skipStep("partitionmethod")
1393 dispatch.skipStep("partitionmethodsetup")
1394 dispatch.skipStep("fdisk")
1395 dispatch.skipStep("autopartition")
1396 dispatch.skipStep("bootdisk")
1397
1398 # because these steps depend on the monitor being probed
1399 # properly, and will stop you if you have an unprobed monitor,
1400 # we should skip them for autostep
1401 if flags.autostep:
1402 dispatch.skipStep("checkmonitorok")
1403 dispatch.skipStep("monitor")
1404 return
1405
1406 dispatch.skipStep("bootdisk")
1407 dispatch.skipStep("welcome")
1408 dispatch.skipStep("betanag")
1409 dispatch.skipStep("confirminstall")
1410 dispatch.skipStep("confirmupgrade")
1411 dispatch.skipStep("network")
1412 dispatch.skipStep("installtype")
1413
1414 # skipping firewall by default, disabled by default
1415 dispatch.skipStep("firewall")
1416
1417 for n in self.skipSteps:
1418 dispatch.skipStep(n)
1419 for n in self.showSteps:
1420 dispatch.skipStep(n, skip = 0)
1421
1422 def setInstallData(self, id, intf = None):
1423 BaseInstallClass.setInstallData(self, id)
1424
1425 self.setEarlySwapOn(1)
1426 self.postScripts = []
1427 self.preScripts = []
1428 self.tracebackScripts = []
1429
1430 self.installType = "install"
1431 self.id = id
1432 self.id.firstboot = FIRSTBOOT_SKIP
1433
1434 # parse the %pre
1435 try:
1436 self.readKickstart(id, self.file, parsePre = 1)
1437 except KickstartError, e:
1438 raise KickstartError, e
1439
1440 log("Running kickstart %%pre script(s)")
1441 for script in self.preScripts:
1442 script.run("/", self.serial)
1443 log("All kickstart %%pre script(s) have been run")
1444
1445 # now read the kickstart file for real
1446 try:
1447 self.readKickstart(id, self.file)
1448 except KickstartError, e:
1449 log("Exception parsing ks.cfg: %s" %(e,))
1450 if intf is None:
1451 raise KickstartError, e
1452 else:
1453 intf.kickstartErrorWindow(e.__str__())
1454
1455 def runTracebackScripts(self):
1456 log("Running kickstart %%traceback script(s)")
1457 for script in self.tracebackScripts:
1458 script.run("/", self.serial)
1459
1460 # Note that this assumes setGroupSelection() is called before
1461 # setPackageSelection()
1462 def setPackageSelection(self, hdlist, intf):
1463 for n in self.packageList:
1464
1465 # allow arch:name syntax
1466 if n.find(".") != -1:
1467 fields = n.split(".")
1468 name = string.join(fields[:-1], ".")
1469 arch = fields[-1]
1470 found = 0
1471 if hdlist.pkgnames.has_key(name):
1472 pkgs = hdlist.pkgnames[name]
1473 for (nevra, parch) in pkgs:
1474 if parch == arch:
1475 hdlist.pkgs[nevra].select()
1476 found = 1
1477 continue
1478 if found:
1479 continue
1480
1481 if hdlist.has_key(n):
1482 hdlist[n].select()
1483 continue
1484
1485 if self.handleMissing == KS_MISSING_IGNORE:
1486 log("package %s doesn't exist, ignoring" %(n,))
1487 continue
1488
1489
1490 rc = intf.messageWindow(_("Missing Package"),
1491 _("You have specified that the "
1492 "package '%s' should be installed. "
1493 "This package does not exist. "
1494 "Would you like to continue or "
1495 "abort your installation?") %(n,),
1496 type="custom",
1497 custom_buttons=[_("_Abort"),
1498 _("_Continue")])
1499 if rc == 0:
1500 sys.exit(1)
1501 else:
1502 pass
1503
1504
1505 def setGroupSelection(self, grpset, intf):
1506 grpset.unselectAll()
1507
1508 if self.addBase:
1509 grpset.selectGroup("base")
1510 for n in self.groupList:
1511 try:
1512 grpset.selectGroup(n)
1513 except KeyError:
1514 if self.handleMissing == KS_MISSING_IGNORE:
1515 log("group %s doesn't exist, ignoring" %(n,))
1516 else:
1517 rc = intf.messageWindow(_("Missing Group"),
1518 _("You have specified that the "
1519 "group '%s' should be installed. "
1520 "This group does not exist. "
1521 "Would you like to continue or "
1522 "abort your installation?")
1523 %(n,),
1524 type="custom",
1525 custom_buttons=[_("_Abort"),
1526 _("_Continue")])
1527 if rc == 0:
1528 sys.exit(1)
1529 else:
1530 pass
1531
1532 for n in self.excludedList:
1533 # allow arch:name syntax
1534 if n.find(".") != -1:
1535 fields = n.split(".")
1536 name = string.join(fields[:-1], ".")
1537 arch = fields[-1]
1538 if grpset.hdrlist.pkgnames.has_key(name):
1539 pkgs = grpset.hdrlist.pkgnames[name]
1540 for (nevra, parch) in pkgs:
1541 if parch == arch:
1542 grpset.hdrlist.pkgs[nevra].unselect(isManual = 1)
1543 continue
1544
1545 if grpset.hdrlist.has_key(n):
1546 grpset.hdrlist[n].unselect(isManual = 1)
1547 else:
1548 log("%s does not exist, can't exclude" %(n,))
1549
1550
1551 def __init__(self, file, serial):
1552 self.serial = serial
1553 self.file = file
1554 self.skipSteps = []
1555 self.showSteps = []
1556 self.interactive = 0
1557 self.addBase = 1
1558 self.packageList = []
1559 self.groupList = []
1560 self.excludedList = []
1561 self.ksRaidMapping = {}
1562 self.ksUsedMembers = []
1563 self.ksPVMapping = {}
1564 self.ksVGMapping = {}
1565 # XXX hack to give us a starting point for RAID, LVM, etc unique IDs.
1566 self.ksID = 100000
1567
1568 # how to handle missing packages
1569 self.handleMissing = KS_MISSING_PROMPT
1570
1571 BaseInstallClass.__init__(self, 0)
1572
1573 def Kickstart(file, serial):
1574
1575 f = open(file, "r")
1576 lines = f.readlines()
1577 f.close()
1578
1579 passedLines = []
1580 while lines:
1581 l = lines[0]
1582 lines = lines[1:]
1583 if l == "%installclass\n":
1584 break
1585 passedLines.append(l)
1586
1587 if lines:
1588 newKsFile = file + ".new"
1589 f = open(newKsFile, "w")
1590 f.writelines(passedLines)
1591 f.close()
1592
1593 f = open('/tmp/ksclass.py', "w")
1594 f.writelines(lines)
1595 f.close()
1596
1597 oldPath = sys.path
1598 sys.path.append('/tmp')
1599
1600 from ksclass import CustomKickstart
1601 os.unlink("/tmp/ksclass.py")
1602
1603 ksClass = CustomKickstart(newKsFile, serial)
1604 os.unlink(newKsFile)
1605 else:
1606 ksClass = KickstartBase(file, serial)
1607
1608 return ksClass
1609
1610
1611 # see if any vnc parameters are specified in the kickstart file
1612 def parseKickstartVNC(ksfile):
1613 try:
1614 f = open(ksfile, "r")
1615 except:
1616 raise KSAppendException("Unable to open ks file %s" % (ksfile,))
1617
1618 lines = f.readlines()
1619 f.close()
1620
1621 usevnc = 0
1622 vnchost = None
1623 vncport = None
1624 vncpasswd = None
1625 for l in lines:
1626 args = isys.parseArgv(l)
1627
1628 if args:
1629 if args[0] in ("%pre", "%post", "%traceback", "%packages"):
1630 break
1631
1632 if args[0] != 'vnc':
1633 continue
1634 else:
1635 continue
1636
1637 idx = 1
1638 while idx < len(args):
1639 if args[idx] == "--password":
1640 try:
1641 vncpasswd = args[idx+1]
1642 except:
1643 raise KickstartError, "Missing argument to vnc --password option"
1644 idx += 2
1645 elif args[idx] == "--connect":
1646 try:
1647 connectspec = args[idx+1]
1648 except:
1649 raise KickstartError, "Missing argument to vnc --connect option"
1650 cargs = string.split(connectspec, ":")
1651 vnchost = cargs[0]
1652 if len(cargs) > 1:
1653 if len(cargs[1]) > 0:
1654 vncport = cargs[1]
1655
1656 idx += 2
1657 else:
1658 raise KickstartError, "Unknown vnc option %s" % (args[idx],)
1659
1660 usevnc = 1
1661 break
1662
1663 return (usevnc, vncpasswd, vnchost, vncport)
1664
1665 #
1666 # look through ksfile and if it contains a line:
1667 #
1668 # %ksappend <url>
1669 #
1670 # pull <url> down and append to /tmp/ks.cfg. This is run before we actually
1671 # parse the complete kickstart file.
1672 #
1673 # Main use is to have the ks.cfg you send to the loader by minimal, and then
1674 # use %ksappend to pull via https anything private (like passwords, etc) in
1675 # the second stage.
1676 #
1677 def pullRemainingKickstartConfig(ksfile):
1678 try:
1679 f = open(ksfile, "r")
1680 except:
1681 raise KSAppendException("Unable to open ks file %s" % (ksfile,))
1682
1683 lines = f.readlines()
1684 f.close()
1685
1686 url = None
1687 for l in lines:
1688 ll = l.strip()
1689 if string.find(ll, "%ksappend") == -1:
1690 continue
1691
1692 try:
1693 (xxx, ksurl) = string.split(ll, ' ')
1694 except:
1695 raise KSAppendException("Illegal url for %%ksappend - %s" % (ll,))
1696
1697 log("Attempting to pull second part of ks.cfg from url %s" % (ksurl,))
1698
1699 try:
1700 url = urllib2.urlopen(ksurl)
1701 except urllib2.HTTPError, e:
1702 raise KSAppendException("IOError: %s:%s" % (e.code, e.msg))
1703 except urllib2.URLError, e:
1704 raise KSAppendException("IOError: -1:%s" % (e.reason,))
1705 else:
1706 # sanity check result - sometimes FTP doesnt
1707 # catch a file is missing
1708 try:
1709 clen = url.info()['content-length']
1710 except Exception, e:
1711 clen = 0
1712
1713 if clen < 1:
1714 raise KSAppendException("IOError: -1:File not found")
1715
1716 break
1717
1718 # if we got something then rewrite /tmp/ks.cfg with new information
1719 if url is not None:
1720 os.rename("/tmp/ks.cfg", "/tmp/ks.cfg-part1")
1721
1722 # insert contents of original /tmp/ks.cfg w/o %ksappend line
1723 f = open("/tmp/ks.cfg", 'w+')
1724 for l in lines:
1725 ll = l.strip()
1726 if string.find(ll, "%ksappend") != -1:
1727 continue
1728 f.write(l)
1729
1730 # now write part we just grabbed
1731 f.write(url.read())
1732 f.close()
1733
1734 # close up url and we're done
1735 url.close()
1736
1737 return None
1738

admin@koozali.org
ViewVC Help
Powered by ViewVC 1.2.1 RSS 2.0 feed