/[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.1 - (show annotations) (download) (as text)
Sat Jul 30 07:28:39 2005 UTC (18 years, 10 months ago) by slords
Branch: MAIN
Content type: text/x-python
First major pass as anaconda installer
- Install/Upgrade detection working
- Only screens we want are being displayed
- Raid/LVM partitioning all done for installer
- Except for post-install (run, status) install is done
- TODO: post-install script isn't running
- TODO: post-upgrade script isn't working
- TODO: raid migration for upgrades
- TODO: status message for post-{install,upgrade}

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

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