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

Annotation of /cdrom.image/updates/bootloaderInfo.py

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


Revision 1.8 - (hide annotations) (download) (as text)
Wed Apr 5 21:11:51 2006 UTC (18 years, 8 months ago) by slords
Branch: MAIN
Changes since 1.7: +4 -9 lines
Content type: text/x-python
Cleanup

1 slords 1.1 #
2     # bootloaderInfo.py - bootloader config object used in creation of new
3     # bootloader configs. Originally from anaconda
4     #
5     # Jeremy Katz <katzj@redhat.com>
6     # Erik Troan <ewt@redhat.com>
7 slords 1.5 # Peter Jones <pjones@redhat.com>
8 slords 1.1 #
9 slords 1.5 # Copyright 2005 Red Hat, Inc.
10 slords 1.1 #
11     # This software may be freely redistributed under the terms of the GNU
12     # library public license.
13     #
14     # You should have received a copy of the GNU Library Public License
15     # along with this program; if not, write to the Free Software
16     # Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
17     #
18    
19 slords 1.8 import os, sys
20 slords 1.2 import isys
21 slords 1.1 import crypt
22 slords 1.5 import random
23 slords 1.1 import butil
24     import string
25    
26     from lilo import LiloConfigFile
27     from rhpl.log import log
28     from rhpl.translate import _, N_
29     import rhpl.executil
30    
31     import booty
32     import checkbootloader
33    
34     dosFilesystems = ('FAT', 'fat16', 'fat32', 'ntfs', 'hpfs')
35    
36     if os.path.exists('edd'):
37     sys.path.append('edd/')
38     else:
39     sys.path.append('/usr/lib/bootloader')
40    
41     if butil.getArch() == "i386":
42     import edd
43    
44     def doesDualBoot():
45     if butil.getArch() == "i386" or butil.getArch() == "x86_64":
46     return 1
47     return 0
48    
49     # hack and a half
50     # there's no guarantee that data is written to the disk and grub
51     # reads both the filesystem and the disk. suck.
52     def syncDataToDisk(dev, mntpt, instRoot = "/"):
53     import isys, fsset
54     isys.sync()
55     isys.sync()
56     isys.sync()
57    
58     # and xfs is even more "special" (#117968)
59     if fsset.isValidXFS(dev):
60     rhpl.executil.execWithRedirect( "/usr/sbin/xfs_freeze",
61     ["/usr/sbin/xfs_freeze", "-f", mntpt],
62     stdout = "/dev/tty5",
63     stderr = "/dev/tty5",
64     root = instRoot)
65     rhpl.executil.execWithRedirect( "/usr/sbin/xfs_freeze",
66     ["/usr/sbin/xfs_freeze", "-u", mntpt],
67     stdout = "/dev/tty5",
68     stderr = "/dev/tty5",
69     root = instRoot)
70    
71     class BootyNoKernelWarning:
72     def __init__ (self, value=""):
73     self.value = value
74    
75     def __str__ (self):
76     return self.value
77    
78     class KernelArguments:
79    
80     def get(self):
81     return self.args
82    
83     def set(self, args):
84     self.args = args
85    
86     def chandevget(self):
87     return self.cargs
88    
89     def chandevset(self, args):
90     self.cargs = args
91    
92     def append(self, args):
93     if self.args:
94     # don't duplicate the addition of an argument (#128492)
95     if self.args.find(args) != -1:
96     return
97     self.args = self.args + " "
98     self.args = self.args + "%s" % (args,)
99    
100    
101     def __init__(self):
102     str = ""
103    
104     if butil.getArch() == "s390":
105     self.cargs = []
106     f = open("/tmp/install.cfg")
107     lines = f.readlines()
108     for line in lines:
109     try:
110     (vname,vparm) = line.split('=', 1)
111     vname = vname.strip()
112     vparm = vparm.replace('"','')
113     vparm = vparm.strip()
114     if vname == "DASD":
115     str = str + "dasd=" + vparm
116     if vname == "CHANDEV":
117     self.cargs.append(vparm)
118     if vname == "QETHPARM":
119     self.cargs.append(vparm)
120     except Exception, e:
121     pass
122    
123     # look for kernel arguments we know should be preserved and add them
124     ourargs = ["speakup_synth=", "apic", "noapic", "apm=", "ide=nodma", "noht", "acpi=", "video="]
125     f = open("/proc/cmdline")
126     cmdline = f.read()[:-1]
127     f.close()
128     cmdlineargs = cmdline.split(" ")
129     for arg in cmdlineargs:
130     for check in ourargs:
131     if arg.startswith(check):
132     if str: str = str + " "
133     str = str + arg
134    
135     self.args = str
136    
137     class BootImages:
138     # returns dictionary of (label, longlabel, devtype) pairs indexed by device
139     def getImages(self):
140     # return a copy so users can modify it w/o affecting us
141    
142     dict = {}
143     for key in self.images.keys():
144     dict[key] = self.images[key]
145    
146     return dict
147    
148     def setImageLabel(self, dev, label, setLong = 0):
149     if setLong:
150     self.images[dev] = (self.images[dev][0], label,
151     self.images[dev][2])
152     else:
153     self.images[dev] = (label, self.images[dev][1],
154     self.images[dev][2])
155    
156    
157     # default is a device
158     def setDefault(self, default):
159     self.default = default
160    
161     def getDefault(self):
162     return self.default
163    
164     # XXX this has internal anaconda-ish knowledge. ick
165     def setup(self, diskSet, fsset):
166     devices = {}
167     devs = self.availableBootDevices(diskSet, fsset)
168     for (dev, type) in devs:
169     devices[dev] = 1
170    
171     # These partitions have disappeared
172     for dev in self.images.keys():
173     if not devices.has_key(dev): del self.images[dev]
174    
175     # These have appeared
176     for (dev, type) in devs:
177     if not self.images.has_key(dev):
178 slords 1.5 if type in dosFilesystems and doesDualBoot():
179     self.images[dev] = ("Other", "Other", type)
180     elif type in ("hfs", "hfs+") and butil.getPPCMachine() == "PMac":
181 slords 1.1 self.images[dev] = ("Other", "Other", type)
182     else:
183     self.images[dev] = (None, None, type)
184    
185    
186     if not self.images.has_key(self.default):
187     entry = fsset.getEntryByMountPoint('/')
188     self.default = entry.device.getDevice()
189     (label, longlabel, type) = self.images[self.default]
190     if not label:
191     self.images[self.default] = ("linux",
192     butil.getProductName(), type)
193    
194     # XXX more internal anaconda knowledge
195     def availableBootDevices(self, diskSet, fsset):
196     devs = []
197     foundDos = 0
198     for (dev, type) in diskSet.partitionTypes():
199     if type in dosFilesystems and not foundDos and doesDualBoot():
200     import isys
201     import partedUtils
202    
203     isys.makeDevInode(dev, '/tmp/' + dev)
204     part = partedUtils.get_partition_by_name(diskSet.disks, dev)
205     if part.native_type not in partedUtils.dosPartitionTypes:
206     continue
207    
208     try:
209     bootable = isys.checkBoot('/tmp/' + dev)
210     devs.append((dev, type))
211     foundDos = 1
212     except Exception, e:
213     log("exception checking %s: %s" %(dev, e))
214     pass
215     elif ((type == 'ntfs' or type =='hpfs') and not foundDos
216     and doesDualBoot()):
217     devs.append((dev, type))
218     # maybe questionable, but the first ntfs or fat is likely to
219     # be the correct one to boot with XP using ntfs
220     foundDos = 1
221 slords 1.5 elif type in ('hfs', 'hfs+') and butil.getPPCMachine() == "PMac":
222 slords 1.1 import isys
223     import partedUtils
224    
225     part = partedUtils.get_partition_by_name(diskSet.disks, dev)
226     if partedUtils.get_flags(part) != "boot":
227     devs.append((dev, type))
228    
229     slash = fsset.getEntryByMountPoint('/')
230     if not slash or not slash.device or not slash.fsystem:
231     raise ValueError, ("Trying to pick boot devices but do not have a "
232     "sane root partition. Aborting install.")
233     devs.append((slash.device.getDevice(), slash.fsystem.getName()))
234    
235     devs.sort()
236    
237     return devs
238    
239    
240    
241     def __init__(self):
242     self.default = None
243     self.images = {}
244    
245    
246     class bootloaderInfo:
247     def setUseGrub(self, val):
248     pass
249    
250     def useGrub(self):
251     return self.useGrubVal
252    
253     def setForceLBA(self, val):
254     pass
255    
256     def setPassword(self, val, isCrypted = 1):
257     pass
258    
259     def getPassword(self):
260     pass
261    
262     def getDevice(self):
263     return self.device
264    
265     def setDevice(self, device):
266     self.device = device
267    
268     (dev, part) = getDiskPart(device)
269     if part is None:
270     self.defaultDevice = "mbr"
271     else:
272     self.defaultDevice = "partition"
273    
274     # XXX need to abstract out the requirement for a fsset to be able
275     # to get it "on the fly" on a running system as well as being able
276     # to get it how we do now from anaconda. probably by having the
277     # first thing in the chain create a "fsset" object that has the
278     # dictionary of mounted filesystems since that's what we care about
279     def getBootloaderConfig(self, instRoot, fsset, bl, langs, kernelList,
280     chainList, defaultDev):
281     images = bl.images.getImages()
282    
283     # on upgrade read in the lilo config file
284     lilo = LiloConfigFile ()
285     self.perms = 0600
286     if os.access (instRoot + self.configfile, os.R_OK):
287     self.perms = os.stat(instRoot + self.configfile)[0] & 0777
288     lilo.read (instRoot + self.configfile)
289     os.rename(instRoot + self.configfile,
290     instRoot + self.configfile + '.rpmsave')
291     # if it's an absolute symlink, just get it out of our way
292     elif (os.path.islink(instRoot + self.configfile) and
293     os.readlink(instRoot + self.configfile)[0] == '/'):
294     os.rename(instRoot + self.configfile,
295     instRoot + self.configfile + '.rpmsave')
296    
297     # Remove any invalid entries that are in the file; we probably
298     # just removed those kernels.
299     for label in lilo.listImages():
300     (fsType, sl, path, other) = lilo.getImage(label)
301     if fsType == "other": continue
302    
303     if not os.access(instRoot + sl.getPath(), os.R_OK):
304     lilo.delImage(label)
305    
306     lilo.addEntry("prompt", replace = 0)
307     lilo.addEntry("timeout", "20", replace = 0)
308    
309     rootDev = fsset.getEntryByMountPoint("/").device.getDevice()
310     if not rootDev:
311     raise RuntimeError, "Installing lilo, but there is no root device"
312    
313     if rootDev == defaultDev:
314     lilo.addEntry("default", kernelList[0][0])
315     else:
316     lilo.addEntry("default", chainList[0][0])
317    
318     for (label, longlabel, version) in kernelList:
319     kernelTag = "-" + version
320     kernelFile = self.kernelLocation + "vmlinuz" + kernelTag
321    
322     try:
323     lilo.delImage(label)
324     except IndexError, msg:
325     pass
326    
327     sl = LiloConfigFile(imageType = "image", path = kernelFile)
328    
329     initrd = booty.makeInitrd (kernelTag, instRoot)
330    
331     sl.addEntry("label", label)
332     if os.access (instRoot + initrd, os.R_OK):
333     sl.addEntry("initrd", "%sinitrd%s.img" %(self.kernelLocation,
334     kernelTag))
335    
336     sl.addEntry("read-only")
337    
338     append = "%s" %(self.args.get(),)
339     realroot = getRootDevName(initrd, fsset, rootDev, instRoot)
340     if not realroot.startswith("LABEL="):
341     sl.addEntry("root", '/dev/' + rootDev)
342     else:
343     if len(append) > 0:
344     append = "%s root=%s" %(append,realroot)
345     else:
346     append = "root=%s" %(realroot,)
347    
348     if len(append) > 0:
349     sl.addEntry('append', '"%s"' % (append,))
350    
351     lilo.addImage (sl)
352    
353     for (label, longlabel, device) in chainList:
354     if ((not label) or (label == "")):
355     continue
356     try:
357     (fsType, sl, path, other) = lilo.getImage(label)
358     lilo.delImage(label)
359     except IndexError:
360     sl = LiloConfigFile(imageType = "other",
361     path = "/dev/%s" %(device))
362     sl.addEntry("optional")
363    
364     sl.addEntry("label", label)
365     lilo.addImage (sl)
366    
367     # Sanity check #1. There could be aliases in sections which conflict
368     # with the new images we just created. If so, erase those aliases
369     imageNames = {}
370     for label in lilo.listImages():
371     imageNames[label] = 1
372    
373     for label in lilo.listImages():
374     (fsType, sl, path, other) = lilo.getImage(label)
375     if sl.testEntry('alias'):
376     alias = sl.getEntry('alias')
377     if imageNames.has_key(alias):
378     sl.delEntry('alias')
379     imageNames[alias] = 1
380    
381     # Sanity check #2. If single-key is turned on, go through all of
382     # the image names (including aliases) (we just built the list) and
383     # see if single-key will still work.
384     if lilo.testEntry('single-key'):
385     singleKeys = {}
386     turnOff = 0
387     for label in imageNames.keys():
388     l = label[0]
389     if singleKeys.has_key(l):
390     turnOff = 1
391     singleKeys[l] = 1
392     if turnOff:
393     lilo.delEntry('single-key')
394    
395     return lilo
396    
397     def write(self, instRoot, fsset, bl, langs, kernelList, chainList,
398     defaultDev, justConfig, intf = None):
399     if len(kernelList) >= 1:
400     config = self.getBootloaderConfig(instRoot, fsset, bl, langs,
401     kernelList, chainList,
402     defaultDev)
403     config.write(instRoot + self.configfile, perms = self.perms)
404     else:
405     self.noKernelsWarn(intf)
406    
407     return ""
408    
409     # XXX in the future we also should do some validation on the config
410     # file that's already there
411     # XXX concept of the intf isn't very well defined outside of anaconda...
412     # probably should just pass back up an error
413     def noKernelsWarn(self, intf):
414     raise BootyNoKernelWarning
415    
416     def getArgList(self):
417     args = []
418    
419     if self.defaultDevice is None:
420     args.append("--location=none")
421     return args
422    
423     args.append("--location=%s" % (self.defaultDevice,))
424 slords 1.5 args.append("--driveorder=%s" % (",".join(self.drivelist)))
425 slords 1.1
426     if self.args.get():
427     args.append("--append=\"%s\"" %(self.args.get()))
428    
429     return args
430    
431     def writeKS(self, f):
432     f.write("bootloader")
433     for arg in self.getArgList():
434     f.write(" " + arg)
435     f.write("\n")
436    
437     def createDriveList(self):
438     # create a drive list that we can use for drive mappings
439     # XXX has anaconda internals knowledge
440     import isys
441     import flags
442     drives = isys.hardDriveDict().keys()
443     drives.sort (isys.compareDrives)
444    
445     # now filter out all of the removable media unless expert mode
446     rc = []
447     for drive in drives:
448     if not isys.driveIsRemovable(drive) or flags.flags.expert:
449     rc.append(drive)
450     return rc
451    
452     def __init__(self):
453     self.args = KernelArguments()
454     self.images = BootImages()
455     self.device = None
456     self.defaultDevice = None # XXX hack, used by kickstart
457     self.useGrubVal = 0 # only used on x86
458     self.configfile = None
459     self.kernelLocation = "/boot/"
460     self.forceLBA32 = 0
461     self.password = None
462     self.pure = None
463     self.above1024 = 0
464    
465     # this has somewhat strange semantics. if 0, act like a normal
466     # "install" case. if 1, update lilo.conf (since grubby won't do that)
467     # and then run lilo or grub only.
468     # XXX THIS IS A HACK. implementation details are only there for x86
469     self.doUpgradeOnly = 0
470     self.kickstart = 0
471    
472     self.drivelist = self.createDriveList()
473    
474     from flags import flags
475     if flags.serial != 0:
476     # now look at /proc/cmdline to pull any serial console
477     # args
478     f = open("/proc/cmdline", "r")
479     cmdline = f.read()[:-1]
480     f.close()
481    
482     options = ""
483     device = None
484     cmdlineargs = cmdline.split(" ")
485     for arg in cmdlineargs:
486     # found a console argument
487     if arg.startswith("console="):
488     (foo, console) = arg.split("=")
489     # the options are everything after the comma
490     comma = console.find(",")
491     if comma != -1:
492     options = console[comma:]
493     device = console[:comma]
494     else:
495     options = ""
496     device = console
497    
498     if device is None:
499     self.serialDevice = "ttyS0"
500     self.serialOptions = ""
501     else:
502     self.serialDevice = device
503     # don't keep the comma in the options
504     self.serialOptions = options[1:]
505    
506     self.args.append("console=%s%s" %(self.serialDevice, options))
507    
508     self.serial = 1
509     else:
510     self.serial = 0
511     self.serialDevice = None
512     self.serialOptions = None
513    
514     if flags.virtpconsole is not None:
515     if flags.virtpconsole.startswith("/dev/"):
516     con = flags.virtpconsole[5:]
517     else:
518     con = flags.virtpconsole
519     self.args.append("console=%s" %(con,))
520    
521    
522     class ia64BootloaderInfo(bootloaderInfo):
523     # XXX wouldn't it be nice to have a real interface to use efibootmgr from?
524     def removeOldEfiEntries(self, instRoot):
525     p = os.pipe()
526     rhpl.executil.execWithRedirect('/usr/sbin/efibootmgr', ["efibootmgr"],
527     root = instRoot, stdout = p[1])
528     os.close(p[1])
529    
530     c = os.read(p[0], 1)
531     buf = c
532     while (c):
533     c = os.read(p[0], 1)
534     buf = buf + c
535     os.close(p[0])
536     lines = string.split(buf, '\n')
537     for line in lines:
538     fields = string.split(line)
539     if len(fields) < 2:
540     continue
541     if string.join(fields[1:], " ") == butil.getProductName():
542     entry = fields[0][4:8]
543     rhpl.executil.execWithRedirect('/usr/sbin/efibootmgr',
544     ["efibootmgr", "-b", entry, "-B"],
545     root = instRoot,
546     stdout="/dev/tty5", stderr="/dev/tty5")
547    
548     def getBootloaderConfig(self, instRoot, fsset, bl, langs, kernelList,
549     chainList, defaultDev):
550     config = bootloaderInfo.getBootloaderConfig(self, instRoot, fsset,
551     bl, langs,
552     kernelList, chainList,
553     defaultDev)
554     # altix boxes need relocatable (#120851)
555     config.addEntry("relocatable")
556    
557     return config
558    
559     def writeLilo(self, instRoot, fsset, bl, langs, kernelList,
560     chainList, defaultDev, justConfig):
561     config = self.getBootloaderConfig(instRoot, fsset, bl, langs,
562     kernelList, chainList, defaultDev)
563     config.write(instRoot + self.configfile, perms = self.perms)
564    
565     return ""
566    
567     def write(self, instRoot, fsset, bl, langs, kernelList, chainList,
568     defaultDev, justConfig, intf):
569     if len(kernelList) >= 1:
570     str = self.writeLilo(instRoot, fsset, bl, langs, kernelList,
571     chainList, defaultDev, justConfig)
572     else:
573     self.noKernelsWarn(intf)
574    
575     bootdev = fsset.getEntryByMountPoint("/boot/efi").device.getDevice()
576     if not bootdev:
577     bootdev = fsset.getEntryByDeviceName("sda1").device.getDevice()
578    
579     if not os.access(instRoot + "/etc/elilo.conf", os.R_OK):
580     os.symlink("../" + self.configfile, instRoot + "/etc/elilo.conf")
581    
582     ind = len(bootdev)
583     try:
584     while (bootdev[ind-1] in string.digits):
585     ind = ind - 1
586     except IndexError:
587     ind = len(bootdev) - 1
588    
589     bootdisk = bootdev[:ind]
590     bootpart = bootdev[ind:]
591     if (bootdisk.startswith('ida/') or bootdisk.startswith('cciss/') or
592 slords 1.5 bootdisk.startswith('rd/') or bootdisk.startswith('sx8/')):
593 slords 1.1 bootdisk = bootdisk[:-1]
594    
595     self.removeOldEfiEntries(instRoot)
596    
597     argv = [ "/usr/sbin/efibootmgr", "-c" , "-w", "-L",
598     butil.getProductName(), "-d", "/dev/%s" % bootdisk,
599     "-p", bootpart, "-l", "EFI\\redhat\\elilo.efi" ]
600     rhpl.executil.execWithRedirect(argv[0], argv, root = instRoot,
601     stdout = "/dev/tty5",
602     stderr = "/dev/tty5")
603    
604    
605     def __init__(self):
606     bootloaderInfo.__init__(self)
607     self.useGrubVal = 1
608     self.kernelLocation = ""
609     self.configfile = "/boot/efi/EFI/redhat/elilo.conf"
610    
611    
612     class x86BootloaderInfo(bootloaderInfo):
613     def setPassword(self, val, isCrypted = 1):
614     if not val:
615     self.password = val
616     self.pure = val
617     return
618    
619     if isCrypted and self.useGrubVal == 0:
620     log("requested crypted password with lilo; ignoring")
621     self.pure = None
622     return
623     elif isCrypted:
624     self.password = val
625     self.pure = None
626     else:
627     salt = "$1$"
628     saltLen = 8
629    
630     for i in range(saltLen):
631 slords 1.5 salt = salt + random.choice (string.letters +
632     string.digits + './')
633 slords 1.1
634     self.password = crypt.crypt (val, salt)
635     self.pure = val
636    
637     def getPassword (self):
638     return self.pure
639    
640     def setForceLBA(self, val):
641     self.forceLBA32 = val
642    
643     def setUseGrub(self, val):
644     self.useGrubVal = val
645    
646     def getPhysicalDevices(self, device):
647     # This finds a list of devices on which the given device name resides.
648     # Accepted values for "device" are raid1 md devices (i.e. "md0"),
649     # physical disks ("hda"), and real partitions on physical disks
650     # ("hda1"). Volume groups/logical volumes are not accepted.
651     #
652     # XXX this has internal anaconda-ish knowledge. ick.
653     import isys
654     import lvm
655    
656     if string.split(device, '/', 1)[0] in map (lambda vg: vg[0],
657     lvm.vglist()):
658     return []
659    
660     if device.startswith('md'):
661     bootable = 0
662     parts = checkbootloader.getRaidDisks(device, 1, stripPart=0)
663     parts.sort()
664     return parts
665    
666     return [device]
667    
668     def writeGrub(self, instRoot, fsset, bl, langs, kernelList, chainList,
669     defaultDev, justConfigFile):
670     if len(kernelList) < 1:
671     return ""
672    
673     images = bl.images.getImages()
674     rootDev = fsset.getEntryByMountPoint("/").device.getDevice()
675    
676     if not os.path.isdir(instRoot + '/boot/grub/'):
677     os.mkdir(instRoot + '/boot/grub', 0755)
678    
679     # XXX old config file should be read here for upgrade
680    
681     cf = '/boot/grub/grub.conf'
682     self.perms = 0600
683     if os.access (instRoot + cf, os.R_OK):
684     self.perms = os.stat(instRoot + cf)[0] & 0777
685     os.rename(instRoot + cf,
686     instRoot + cf + '.rpmsave')
687    
688     grubTarget = bl.getDevice()
689     target = "mbr"
690     if grubTarget[-1].isdigit() and not grubTarget.startswith('md'):
691     target = "partition"
692 slords 1.5
693 slords 1.1 f = open(instRoot + cf, "w+")
694    
695     f.write("# grub.conf generated by anaconda\n")
696     f.write("#\n")
697     f.write("# Note that you do not have to rerun grub "
698     "after making changes to this file\n")
699    
700     bootDev = fsset.getEntryByMountPoint("/boot")
701     grubPath = "/grub"
702     cfPath = "/"
703     if not bootDev:
704     bootDev = fsset.getEntryByMountPoint("/")
705     grubPath = "/boot/grub"
706     cfPath = "/boot/"
707     f.write("# NOTICE: You do not have a /boot partition. "
708     "This means that\n")
709     f.write("# all kernel and initrd paths are relative "
710     "to /, eg.\n")
711     else:
712     f.write("# NOTICE: You have a /boot partition. This means "
713     "that\n")
714     f.write("# all kernel and initrd paths are relative "
715     "to /boot/, eg.\n")
716    
717     bootDevs = self.getPhysicalDevices(bootDev.device.getDevice())
718     bootDev = bootDev.device.getDevice()
719 slords 1.5
720 slords 1.1 f.write('# root %s\n' % self.grubbyPartitionName(bootDevs[0]))
721     f.write("# kernel %svmlinuz-version ro "
722     "root=/dev/%s\n" % (cfPath, rootDev))
723     f.write("# initrd %sinitrd-version.img\n" % (cfPath))
724     f.write("#boot=/dev/%s\n" % (grubTarget))
725    
726 slords 1.5 # Check to see if smp kernel should be default or not
727 slords 1.3 if isys.smpAvailable() or isys.htavailable():
728     smpCapable=1
729 slords 1.5 else:
730 slords 1.3 smpCapable=0
731    
732 slords 1.1 # get the default image to boot... we have to walk and find it
733     # since grub indexes by where it is in the config file
734     if defaultDev == rootDev:
735 slords 1.2 for kernel in range(0, len(kernelList)):
736     default=kernel
737 slords 1.3 version=kernelList[kernel][2]
738     if version.find('smp')<0 and not smpCapable:
739     break
740     if version.find('smp')>=0 and smpCapable:
741     break
742 slords 1.1 else:
743     # if the default isn't linux, it's the first thing in the
744     # chain list
745     default = len(kernelList)
746    
747     # keep track of which devices are used for the device.map
748     usedDevs = {}
749    
750     f.write('default=%s\n' % (default))
751     if len(chainList) > 0:
752     timeout = 5
753     else:
754     timeout = 5
755     f.write('timeout=%d\n' %(timeout,))
756    
757     if self.serial == 1:
758     # grub the 0-based number of the serial console device
759     unit = self.serialDevice[-1]
760    
761     # and we want to set the speed too
762     speedend = 0
763     for char in self.serialOptions:
764     if char not in string.digits:
765     break
766     speedend = speedend + 1
767     if speedend != 0:
768     speed = self.serialOptions[:speedend]
769     else:
770     # reasonable default
771     speed = "9600"
772    
773     f.write("serial --unit=%s --speed=%s\n" %(unit, speed))
774     f.write("terminal --timeout=5 serial console\n")
775     else:
776     # we only want splashimage if they're not using a serial console
777     if os.access("%s/boot/grub/splash.xpm.gz" %(instRoot,), os.R_OK):
778     f.write('splashimage=%s%sgrub/splash.xpm.gz\n'
779     % (self.grubbyPartitionName(bootDevs[0]), cfPath))
780     f.write("hiddenmenu\n")
781    
782     for dev in self.getPhysicalDevices(grubTarget):
783     usedDevs[dev] = 1
784 slords 1.5
785 slords 1.1 if self.password:
786     f.write('password --md5 %s\n' %(self.password))
787    
788     for (label, longlabel, version) in kernelList:
789     kernelTag = "-" + version
790     kernelFile = "%svmlinuz%s" % (cfPath, kernelTag)
791    
792     initrd = booty.makeInitrd (kernelTag, instRoot)
793    
794     f.write('title %s (%s)\n' % (longlabel, version))
795     f.write('\troot %s\n' % self.grubbyPartitionName(bootDevs[0]))
796    
797     realroot = getRootDevName(initrd, fsset, rootDev, instRoot)
798     realroot = " root=%s" %(realroot,)
799    
800     f.write('\tkernel %s ro%s' % (kernelFile, realroot))
801     if self.args.get():
802     f.write(' %s' % self.args.get())
803     f.write('\n')
804    
805     if os.access (instRoot + initrd, os.R_OK):
806     f.write('\tinitrd %sinitrd%s.img\n' % (cfPath, kernelTag))
807    
808     for (label, longlabel, device) in chainList:
809     if ((not longlabel) or (longlabel == "")):
810     continue
811     f.write('title %s\n' % (longlabel))
812     f.write('\trootnoverify %s\n' % self.grubbyPartitionName(device))
813     # f.write('\tmakeactive\n')
814     f.write('\tchainloader +1')
815     f.write('\n')
816     usedDevs[device] = 1
817    
818     f.close()
819     os.chmod(instRoot + "/boot/grub/grub.conf", self.perms)
820    
821     try:
822     # make symlink for menu.lst (default config file name)
823     if os.access (instRoot + "/boot/grub/menu.lst", os.R_OK):
824     os.rename(instRoot + "/boot/grub/menu.lst",
825     instRoot + "/boot/grub/menu.lst.rpmsave")
826     os.symlink("./grub.conf", instRoot + "/boot/grub/menu.lst")
827     except:
828     pass
829    
830     try:
831     # make symlink for /etc/grub.conf (config files belong in /etc)
832     if os.access (instRoot + "/etc/grub.conf", os.R_OK):
833     os.rename(instRoot + "/etc/grub.conf",
834     instRoot + "/etc/grub.conf.rpmsave")
835     os.symlink("../boot/grub/grub.conf", instRoot + "/etc/grub.conf")
836     except:
837     pass
838    
839     for dev in self.getPhysicalDevices(rootDev):
840     usedDevs[dev] = 1
841 slords 1.8
842 slords 1.7 for dev in bootDevs:
843     usedDevs[dev] = 1
844 slords 1.1
845     if not os.access(instRoot + "/boot/grub/device.map", os.R_OK):
846     f = open(instRoot + "/boot/grub/device.map", "w+")
847     f.write("# this device map was generated by anaconda\n")
848     f.write("(fd0) /dev/fd0\n")
849     devs = usedDevs.keys()
850     usedDevs = {}
851     for dev in devs:
852     drive = getDiskPart(dev)[0]
853     if usedDevs.has_key(drive):
854     continue
855     usedDevs[drive] = 1
856     devs = usedDevs.keys()
857     devs.sort()
858     for drive in devs:
859     # XXX hack city. If they're not the sort of thing that'll
860     # be in the device map, they shouldn't still be in the list.
861     if not drive.startswith('md'):
862     f.write("(%s) /dev/%s\n" % (self.grubbyDiskName(drive),
863 slords 1.5 drive))
864 slords 1.1 f.close()
865    
866     if self.forceLBA32:
867     forcelba = "--force-lba "
868     else:
869     forcelba = ""
870    
871     sysconf = '/etc/sysconfig/grub'
872     if os.access (instRoot + sysconf, os.R_OK):
873     self.perms = os.stat(instRoot + sysconf)[0] & 0777
874     os.rename(instRoot + sysconf,
875     instRoot + sysconf + '.rpmsave')
876     # if it's an absolute symlink, just get it out of our way
877     elif (os.path.islink(instRoot + sysconf) and
878     os.readlink(instRoot + sysconf)[0] == '/'):
879     os.rename(instRoot + sysconf,
880     instRoot + sysconf + '.rpmsave')
881     f = open(instRoot + sysconf, 'w+')
882     f.write("boot=/dev/%s\n" %(grubTarget,))
883 slords 1.5 # XXX forcelba never gets read back...
884 slords 1.1 if self.forceLBA32:
885     f.write("forcelba=1\n")
886     else:
887     f.write("forcelba=0\n")
888     f.close()
889    
890     cmds = []
891     for bootDev in bootDevs:
892 slords 1.6 gtDisk = self.grubbyPartitionName(getDiskPart(bootDev)[0])
893 slords 1.5 bPart = self.grubbyPartitionName(bootDev)
894 slords 1.1
895     stage1Target = gtDisk
896     if target == "partition":
897 slords 1.6 stage1Target = self.grubbyPartitionName(bootDev)
898 slords 1.1
899 slords 1.8 cmd = "root %s\nsetup %s" % (bPart, stage1Target)
900 slords 1.1 cmds.append(cmd)
901 slords 1.5
902 slords 1.1 if not justConfigFile:
903     log("GRUB commands:")
904     for cmd in cmds:
905     log("\t%s\n", cmd)
906    
907     # copy the stage files over into /boot
908     rhpl.executil.execWithRedirect( "/sbin/grub-install",
909     ["/sbin/grub-install", "--just-copy"],
910     stdout = "/dev/tty5", stderr = "/dev/tty5",
911     root = instRoot)
912    
913    
914    
915     # FIXME: hack to try to make sure everything is written to the disk
916     if cfPath == "/":
917     syncDataToDisk(bootDev, "/boot", instRoot)
918     else:
919     syncDataToDisk(bootDev, "/", instRoot)
920    
921     # really install the bootloader
922     p = os.pipe()
923     for cmd in cmds:
924 slords 1.5 os.write(p[1], cmd + '\n')
925 slords 1.1 os.close(p[1])
926     rhpl.executil.execWithRedirect('/sbin/grub' ,
927     [ "grub", "--batch", "--no-floppy",
928     "--device-map=/boot/grub/device.map" ],
929     stdin = p[0],
930     stdout = "/dev/tty5", stderr = "/dev/tty5",
931     root = instRoot)
932     os.close(p[0])
933    
934     return ""
935    
936     def getMatchingPart(self, bootDev, target):
937     bootName, bootPartNum = getDiskPart(bootDev)
938     devices = self.getPhysicalDevices(target)
939     for device in devices:
940     name, partNum = getDiskPart(device)
941     if name == bootName:
942     return device
943     return devices[0]
944    
945     def grubbyDiskName(self, name):
946     return "hd%d" % self.drivelist.index(name)
947    
948     def grubbyPartitionName(self, dev):
949     (name, partNum) = getDiskPart(dev)
950     if partNum != None:
951     return "(%s,%d)" % (self.grubbyDiskName(name), partNum)
952     else:
953     return "(%s)" %(self.grubbyDiskName(name))
954    
955    
956     def getBootloaderConfig(self, instRoot, fsset, bl, langs, kernelList,
957     chainList, defaultDev):
958     config = bootloaderInfo.getBootloaderConfig(self, instRoot, fsset,
959     bl, langs,
960     kernelList, chainList,
961     defaultDev)
962    
963     liloTarget = bl.getDevice()
964    
965     config.addEntry("boot", '/dev/' + liloTarget, replace = 0)
966     config.addEntry("map", "/boot/map", replace = 0)
967     config.addEntry("install", "/boot/boot.b", replace = 0)
968     message = "/boot/message"
969    
970     if self.pure is not None and not self.useGrubVal:
971     config.addEntry("restricted", replace = 0)
972     config.addEntry("password", self.pure, replace = 0)
973    
974    
975     import language
976     for lang in language.expandLangs(langs.getDefault()):
977     fn = "/boot/message." + lang
978     if os.access(instRoot + fn, os.R_OK):
979     message = fn
980     break
981    
982     if self.serial == 1:
983     # grab the 0-based number of the serial console device
984     unit = self.serialDevice[-1]
985     # FIXME: we should probably put some options, but lilo
986     # only supports up to 9600 baud so just use the defaults
987     # it's better than nothing :(
988     config.addEntry("serial=%s" %(unit,))
989     else:
990     # message screws up serial console
991     if os.access(instRoot + message, os.R_OK):
992     config.addEntry("message", message, replace = 0)
993    
994 slords 1.5 if not config.testEntry('lba32'):
995 slords 1.1 if self.forceLBA32 or (bl.above1024 and
996     butil.getArch() != "x86_64" and
997     edd.detect()):
998     config.addEntry("lba32", replace = 0)
999    
1000     return config
1001    
1002     # this is a hackish function that depends on the way anaconda writes
1003     # out the grub.conf with a #boot= comment
1004     # XXX this falls into the category of self.doUpgradeOnly
1005     def upgradeGrub(self, instRoot, fsset, bl, langs, kernelList, chainList,
1006     defaultDev, justConfigFile):
1007     if justConfigFile:
1008     return ""
1009    
1010     theDev = None
1011     for (fn, stanza) in [ ("/etc/sysconfig/grub", "boot="),
1012     ("/boot/grub/grub.conf", "#boot=") ]:
1013     try:
1014     f = open(instRoot + fn, "r")
1015     except:
1016     continue
1017    
1018     # the following bits of code are straight from checkbootloader.py
1019     lines = f.readlines()
1020     f.close()
1021     for line in lines:
1022     if line.startswith(stanza):
1023     theDev = checkbootloader.getBootDevString(line)
1024     break
1025     if theDev is not None:
1026     break
1027    
1028     if theDev is None:
1029     # we could find the dev before, but can't now... cry about it
1030     return ""
1031    
1032     # migrate info to /etc/sysconfig/grub
1033     sysconf = '/etc/sysconfig/grub'
1034     if not os.access(instRoot + sysconf, os.R_OK):
1035     f = open(instRoot + sysconf, "w+")
1036     f.write("boot=%s\n" %(theDev,))
1037 slords 1.5 # XXX forcelba never gets read back at all...
1038 slords 1.1 if self.forceLBA32:
1039     f.write("forcelba=1\n")
1040     else:
1041     f.write("forcelba=0\n")
1042     f.close()
1043    
1044     # more suckage. grub-install can't work without a valid /etc/mtab
1045     # so we have to do shenanigans to get updated grub installed...
1046     # steal some more code above
1047     bootDev = fsset.getEntryByMountPoint("/boot")
1048     grubPath = "/grub"
1049     cfPath = "/"
1050     if not bootDev:
1051     bootDev = fsset.getEntryByMountPoint("/")
1052     grubPath = "/boot/grub"
1053     cfPath = "/boot/"
1054    
1055     masterBootDev = bootDev.device.getDevice(asBoot = 0)
1056     if masterBootDev[0:2] == 'md':
1057     rootDevs = checkbootloader.getRaidDisks(masterBootDev, raidLevel=1,
1058     stripPart = 0)
1059     else:
1060     rootDevs = [masterBootDev]
1061    
1062     if theDev[5:7] == 'md':
1063     stage1Devs = checkbootloader.getRaidDisks(theDev[5:], raidLevel=1)
1064     else:
1065     stage1Devs = [theDev[5:]]
1066    
1067     for stage1Dev in stage1Devs:
1068     # cross fingers; if we can't find a root device on the same
1069     # hardware as this boot device, we just blindly hope the first
1070     # thing in the list works.
1071    
1072     grubbyStage1Dev = self.grubbyPartitionName(stage1Dev)
1073    
1074     grubbyRootPart = self.grubbyPartitionName(rootDevs[0])
1075    
1076     for rootDev in rootDevs:
1077     testGrubbyRootDev = getDiskPart(rootDev)[0]
1078     testGrubbyRootDev = self.grubbyPartitionName(testGrubbyRootDev)
1079    
1080     if grubbyStage1Dev == testGrubbyRootDev:
1081     grubbyRootPart = self.grubbyPartitionName(rootDev)
1082     break
1083    
1084 slords 1.8 cmd = "root %s\nsetup %s" % (grubbyRootPart, grubbyStage1Dev)
1085 slords 1.1
1086 slords 1.5 if not justConfigFile:
1087     log("GRUB command %s", cmd)
1088 slords 1.1
1089 slords 1.5 # copy the stage files over into /boot
1090     rhpl.executil.execWithRedirect( "/sbin/grub-install",
1091 slords 1.1 ["/sbin/grub-install", "--just-copy"],
1092     stdout = "/dev/tty5", stderr = "/dev/tty5",
1093     root = instRoot)
1094    
1095 slords 1.5 # get the stage files synced to disk
1096     import isys
1097     isys.sync()
1098     isys.sync()
1099     isys.sync()
1100 slords 1.1
1101 slords 1.5 # really install the bootloader
1102     p = os.pipe()
1103     os.write(p[1], cmd + '\n')
1104     os.close(p[1])
1105     rhpl.executil.execWithRedirect('/sbin/grub' ,
1106 slords 1.1 [ "grub", "--batch", "--no-floppy",
1107     "--device-map=/boot/grub/device.map" ],
1108     stdin = p[0],
1109     stdout = "/dev/tty5", stderr = "/dev/tty5",
1110     root = instRoot)
1111 slords 1.5 os.close(p[0])
1112 slords 1.1
1113     return ""
1114    
1115    
1116     def write(self, instRoot, fsset, bl, langs, kernelList, chainList,
1117     defaultDev, justConfig, intf):
1118     # XXX HACK ALERT - see declaration above
1119     if self.doUpgradeOnly:
1120 slords 1.5 if self.useGrubVal:
1121 slords 1.1 self.upgradeGrub(instRoot, fsset, bl, langs, kernelList,
1122     chainList, defaultDev, justConfig)
1123    
1124     # and the hacks continue. with 2.6, ide-scsi isn't used
1125     # anymore (#116622)
1126     import isys
1127     cdrw = isys.ideCdRwList()
1128     torem = []
1129     for device in cdrw:
1130     torem.append("%s=ide-scsi" %(device,))
1131    
1132     for fn in ("/etc/lilo.conf", "/boot/grub/grub.conf",
1133     "/etc/lilo.conf.anaconda"):
1134     if not os.path.exists(instRoot + fn):
1135     continue
1136     f = open(instRoot + fn, "r")
1137     buf = f.read()
1138     f.close()
1139     for dev in torem:
1140     buf = buf.replace(dev, "")
1141     f = open(instRoot + fn, "w")
1142     f.write(buf)
1143     f.close()
1144     return
1145     if len(kernelList) < 1:
1146     self.noKernelsWarn(intf)
1147    
1148     str = self.writeGrub(instRoot, fsset, bl, langs, kernelList,
1149     chainList, defaultDev,
1150     justConfig | (not self.useGrubVal))
1151     # XXX move the lilo.conf out of the way if they're using GRUB
1152     # so that /sbin/installkernel does a more correct thing
1153     if self.useGrubVal and os.access(instRoot + '/etc/lilo.conf', os.R_OK):
1154     os.rename(instRoot + "/etc/lilo.conf",
1155     instRoot + "/etc/lilo.conf.anaconda")
1156    
1157    
1158    
1159     def getArgList(self):
1160     args = bootloaderInfo.getArgList(self)
1161    
1162     if self.forceLBA32:
1163     args.append("--lba32")
1164     if self.password:
1165     args.append("--md5pass=%s" %(self.password))
1166    
1167    
1168     # XXX add location of bootloader here too
1169    
1170     return args
1171    
1172     def __init__(self):
1173     bootloaderInfo.__init__(self)
1174     # XXX use checkbootloader to determine what to default to
1175     self.useGrubVal = 1
1176     self.kernelLocation = "/boot/"
1177     self.configfile = "/etc/lilo.conf"
1178     self.password = None
1179     self.pure = None
1180    
1181     class s390BootloaderInfo(bootloaderInfo):
1182     def getBootloaderConfig(self, instRoot, fsset, bl, langs, kernelList,
1183     chainList, defaultDev):
1184     images = bl.images.getImages()
1185    
1186     # on upgrade read in the lilo config file
1187     lilo = LiloConfigFile ()
1188     self.perms = 0600
1189     if os.access (instRoot + self.configfile, os.R_OK):
1190     self.perms = os.stat(instRoot + self.configfile)[0] & 0777
1191     lilo.read (instRoot + self.configfile)
1192     os.rename(instRoot + self.configfile,
1193     instRoot + self.configfile + '.rpmsave')
1194    
1195     # Remove any invalid entries that are in the file; we probably
1196     # just removed those kernels.
1197     for label in lilo.listImages():
1198     (fsType, sl, path, other) = lilo.getImage(label)
1199     if fsType == "other": continue
1200    
1201     if not os.access(instRoot + sl.getPath(), os.R_OK):
1202     lilo.delImage(label)
1203    
1204     rootDev = fsset.getEntryByMountPoint("/").device.getDevice()
1205     if not rootDev:
1206     raise RuntimeError, "Installing zipl, but there is no root device"
1207    
1208     if rootDev == defaultDev:
1209     lilo.addEntry("default", kernelList[0][0])
1210     else:
1211     lilo.addEntry("default", chainList[0][0])
1212    
1213     for (label, longlabel, version) in kernelList:
1214     kernelTag = "-" + version
1215     kernelFile = self.kernelLocation + "vmlinuz" + kernelTag
1216    
1217     try:
1218     lilo.delImage(label)
1219     except IndexError, msg:
1220     pass
1221    
1222     sl = LiloConfigFile(imageType = "image", path = kernelFile)
1223    
1224     initrd = booty.makeInitrd (kernelTag, instRoot)
1225    
1226     sl.addEntry("label", label)
1227     if os.access (instRoot + initrd, os.R_OK):
1228     sl.addEntry("initrd",
1229     "%sinitrd%s.img" %(self.kernelLocation, kernelTag))
1230    
1231     sl.addEntry("read-only")
1232     sl.addEntry("root", '/dev/' + rootDev)
1233     sl.addEntry("ipldevice", '/dev/' + rootDev[:-1])
1234    
1235     if self.args.get():
1236     sl.addEntry('append', '"%s"' % self.args.get())
1237    
1238     lilo.addImage (sl)
1239    
1240     for (label, longlabel, device) in chainList:
1241     if ((not label) or (label == "")):
1242     continue
1243     try:
1244     (fsType, sl, path, other) = lilo.getImage(label)
1245     lilo.delImage(label)
1246     except IndexError:
1247     sl = LiloConfigFile(imageType = "other",
1248     path = "/dev/%s" %(device))
1249     sl.addEntry("optional")
1250    
1251     sl.addEntry("label", label)
1252     lilo.addImage (sl)
1253    
1254     # Sanity check #1. There could be aliases in sections which conflict
1255     # with the new images we just created. If so, erase those aliases
1256     imageNames = {}
1257     for label in lilo.listImages():
1258     imageNames[label] = 1
1259    
1260     for label in lilo.listImages():
1261     (fsType, sl, path, other) = lilo.getImage(label)
1262     if sl.testEntry('alias'):
1263     alias = sl.getEntry('alias')
1264     if imageNames.has_key(alias):
1265     sl.delEntry('alias')
1266     imageNames[alias] = 1
1267    
1268     # Sanity check #2. If single-key is turned on, go through all of
1269     # the image names (including aliases) (we just built the list) and
1270     # see if single-key will still work.
1271     if lilo.testEntry('single-key'):
1272     singleKeys = {}
1273     turnOff = 0
1274     for label in imageNames.keys():
1275     l = label[0]
1276     if singleKeys.has_key(l):
1277     turnOff = 1
1278     singleKeys[l] = 1
1279     if turnOff:
1280     lilo.delEntry('single-key')
1281    
1282     return lilo
1283    
1284     def writeChandevConf(self, bl, instroot): # S/390 only
1285     cf = "/etc/chandev.conf"
1286     self.perms = 0644
1287     if bl.args.chandevget():
1288     fd = os.open(instroot + "/etc/chandev.conf",
1289     os.O_WRONLY | os.O_CREAT)
1290     os.write(fd, "noauto\n")
1291     for cdev in bl.args.chandevget():
1292     os.write(fd,'%s\n' % cdev)
1293     os.close(fd)
1294     return ""
1295    
1296    
1297     def writeZipl(self, instRoot, fsset, bl, langs, kernelList, chainList,
1298     defaultDev, justConfigFile):
1299     images = bl.images.getImages()
1300     rootDev = fsset.getEntryByMountPoint("/").device.getDevice()
1301    
1302     cf = '/etc/zipl.conf'
1303     self.perms = 0600
1304     if os.access (instRoot + cf, os.R_OK):
1305     self.perms = os.stat(instRoot + cf)[0] & 0777
1306     os.rename(instRoot + cf,
1307     instRoot + cf + '.rpmsave')
1308    
1309     f = open(instRoot + cf, "w+")
1310    
1311     f.write('[defaultboot]\n')
1312     f.write('default=' + kernelList[0][0] + '\n')
1313     f.write('target=%s\n' % (self.kernelLocation))
1314    
1315     cfPath = "/boot/"
1316     for (label, longlabel, version) in kernelList:
1317     kernelTag = "-" + version
1318     kernelFile = "%svmlinuz%s" % (cfPath, kernelTag)
1319    
1320     initrd = booty.makeInitrd (kernelTag, instRoot)
1321     f.write('[%s]\n' % (label))
1322     f.write('\timage=%s\n' % (kernelFile))
1323     if os.access (instRoot + initrd, os.R_OK):
1324     f.write('\tramdisk=%sinitrd%s.img\n' %(self.kernelLocation,
1325     kernelTag))
1326     realroot = getRootDevName(initrd, fsset, rootDev, instRoot)
1327     f.write('\tparameters="root=%s' %(realroot,))
1328     if bl.args.get():
1329     f.write(' %s' % (bl.args.get()))
1330     f.write('"\n')
1331    
1332     f.close()
1333    
1334     if not justConfigFile:
1335     argv = [ "/sbin/zipl" ]
1336     rhpl.executil.execWithRedirect(argv[0], argv, root = instRoot,
1337     stdout = "/dev/stdout",
1338     stderr = "/dev/stderr")
1339    
1340     return ""
1341    
1342     def write(self, instRoot, fsset, bl, langs, kernelList, chainList,
1343     defaultDev, justConfig, intf):
1344     str = self.writeZipl(instRoot, fsset, bl, langs, kernelList,
1345     chainList, defaultDev,
1346     justConfig | (not self.useZiplVal))
1347     str = self.writeChandevConf(bl, instRoot)
1348    
1349     def __init__(self):
1350     bootloaderInfo.__init__(self)
1351     self.useZiplVal = 1 # only used on s390
1352     self.kernelLocation = "/boot/"
1353     self.configfile = "/etc/zipl.conf"
1354    
1355    
1356     class alphaBootloaderInfo(bootloaderInfo):
1357     def wholeDevice (self, path):
1358     (device, foo) = getDiskPart(path)
1359     return device
1360    
1361     def partitionNum (self, path):
1362     # getDiskPart returns part numbers 0-based; we need it one based
1363     # *sigh*
1364     (foo, partitionNumber) = getDiskPart(path)
1365     return partitionNumber + 1
1366    
1367     # See if we would have to use MILO. MILO isn't supported by Red Hat.
1368     def useMilo (self):
1369     try:
1370     f = open ('/proc/cpuinfo', 'ro')
1371     except:
1372     return
1373     lines = f.readlines ()
1374     f.close()
1375     serial = ""
1376     for line in lines:
1377     if line.find("system serial number") != -1:
1378     serial = string.strip (string.split (line, ':')[1])
1379     break
1380    
1381     if serial and len (serial) >= 4 and serial.startswith("MILO"):
1382     return 1
1383     else:
1384     return 0
1385    
1386     def writeAboot(self, instRoot, fsset, bl, langs, kernelList,
1387     chainList, defaultDev, justConfig):
1388     # Get bootDevice and rootDevice
1389     rootDevice = fsset.getEntryByMountPoint("/").device.getDevice()
1390     if fsset.getEntryByMountPoint("/boot"):
1391     bootDevice = fsset.getEntryByMountPoint("/boot").device.getDevice()
1392     else:
1393     bootDevice = rootDevice
1394     bootnotroot = bootDevice != rootDevice
1395    
1396     # If /etc/aboot.conf already exists we rename it
1397     # /etc/aboot.conf.rpmsave.
1398     if os.path.isfile(instRoot + self.configfile):
1399     os.rename (instRoot + self.configfile,
1400     instRoot + self.configfile + ".rpmsave")
1401    
1402     # Then we create the necessary files. If the root device isn't
1403     # the boot device, we create /boot/etc/ where the aboot.conf
1404     # will live, and we create /etc/aboot.conf as a symlink to it.
1405     if bootnotroot:
1406     # Do we have /boot/etc ? If not, create one
1407     if not os.path.isdir (instRoot + '/boot/etc'):
1408     os.mkdir(instRoot + '/boot/etc', 0755)
1409    
1410     # We install the symlink (/etc/aboot.conf has already been
1411     # renamed in necessary.)
1412     os.symlink("../boot" + self.configfile, instRoot + self.configfile)
1413    
1414     cfPath = instRoot + "/boot" + self.configfile
1415     # Kernel path is set to / because a boot partition will
1416     # be a root on its own.
1417     kernelPath = '/'
1418     # Otherwise, we just need to create /etc/aboot.conf.
1419     else:
1420     cfPath = instRoot + self.configfile
1421     kernelPath = self.kernelLocation
1422    
1423     # If we already have an aboot.conf, rename it
1424     if os.access (cfPath, os.R_OK):
1425     self.perms = os.stat(cfPath)[0] & 0777
1426     os.rename(cfPath, cfPath + '.rpmsave')
1427    
1428     # Now we're going to create and populate cfPath.
1429     f = open (cfPath, 'w+')
1430     f.write ("# aboot default configurations\n")
1431    
1432     if bootnotroot:
1433     f.write ("# NOTICE: You have a /boot partition. This means that\n")
1434     f.write ("# all kernel paths are relative to /boot/\n")
1435    
1436     # bpn is the boot partition number.
1437     bpn = self.partitionNum(bootDevice)
1438     lines = 0
1439    
1440     # We write entries line using the following format:
1441     # <line><bpn><kernel-name> root=<rootdev> [options]
1442     # We get all the kernels we need to know about in kernelList.
1443    
1444     for (kernel, tag, kernelTag) in kernelList:
1445     kernelFile = "%svmlinuz-%s" %(kernelPath, kernelTag)
1446    
1447     f.write("%d:%d%s" %(lines, bpn, kernelFile))
1448    
1449     # See if we can come up with an initrd argument that exists
1450     initrd = booty.makeInitrd (kernelTag, instRoot)
1451     if os.access(instRoot + initrd, os.R_OK):
1452     f.write(" initrd=%sinitrd-%s.img" %(kernelPath, kernelTag))
1453    
1454     realroot = getRootDevName(initrd, fsset, rootDevice, instRoot)
1455     f.write(" root=%s" %(realroot,))
1456    
1457     args = self.args.get()
1458     if args:
1459     f.write(" %s" %(args,))
1460    
1461     f.write("\n")
1462     lines = lines + 1
1463    
1464     # We're done writing the file
1465     f.close ()
1466     del f
1467    
1468     if not justConfig:
1469     # Now we're ready to write the relevant boot information. wbd
1470     # is the whole boot device, bdpn is the boot device partition
1471     # number.
1472     wbd = self.wholeDevice (bootDevice)
1473     bdpn = self.partitionNum (bootDevice)
1474    
1475     # Calling swriteboot. The first argument is the disk to write
1476     # to and the second argument is a path to the bootstrap loader
1477     # file.
1478     args = ("swriteboot", ("/dev/%s" % wbd), "/boot/bootlx")
1479     log("swriteboot command: %s" %(args,))
1480     rhpl.executil.execWithRedirect ('/sbin/swriteboot', args,
1481     root = instRoot,
1482     stdout = "/dev/tty5",
1483     stderr = "/dev/tty5")
1484    
1485     # Calling abootconf to configure the installed aboot. The
1486     # first argument is the disk to use, the second argument is
1487     # the number of the partition on which aboot.conf resides.
1488     # It's always the boot partition whether it's / or /boot (with
1489     # the mount point being omitted.)
1490     args = ("abootconf", ("/dev/%s" % wbd), str (bdpn))
1491     log("abootconf command: %s" %(args,))
1492     rhpl.executil.execWithRedirect ('/sbin/abootconf', args,
1493     root = instRoot,
1494     stdout = "/dev/tty5",
1495     stderr = "/dev/tty5")
1496    
1497    
1498     def write(self, instRoot, fsset, bl, langs, kernelList, chainList,
1499     defaultDev, justConfig, intf):
1500     if len(kernelList) < 1:
1501     self.noKernelsWarn(intf)
1502    
1503     if self.useMilo():
1504     intf.messageWindow(_("MILO Not Supported"),
1505     "This system requires the support of MILO to " +
1506     "boot linux (MILO is not included in this " +
1507     "distribution.) The installation of the " +
1508     "bootloader can't be completed on this system.")
1509     # elif not justConfig FIXME.
1510     else:
1511     self.writeAboot(instRoot, fsset, bl, langs, kernelList,
1512     chainList, defaultDev, justConfig)
1513    
1514     def __init__(self):
1515     bootloaderInfo.__init__(self)
1516     self.useGrubVal = 0
1517     self.configfile = "/etc/aboot.conf"
1518     # self.kernelLocation is already set to what we need.
1519     self.password = None
1520     self.pure = None
1521    
1522    
1523     class ppcBootloaderInfo(bootloaderInfo):
1524     def writeYaboot(self, instRoot, fsset, bl, langs, kernelList,
1525     chainList, defaultDev, justConfigFile):
1526    
1527     from flags import flags
1528    
1529     yabootTarget = '/dev/%s' %(bl.getDevice())
1530    
1531     bootDev = fsset.getEntryByMountPoint("/boot")
1532     if bootDev:
1533     cf = "/boot/etc/yaboot.conf"
1534     cfPath = ""
1535     if not os.path.isdir(instRoot + "/boot/etc"):
1536     os.mkdir(instRoot + "/boot/etc")
1537     else:
1538     bootDev = fsset.getEntryByMountPoint("/")
1539     cfPath = "/boot"
1540     cf = "/etc/yaboot.conf"
1541     bootDev = bootDev.device.getDevice(asBoot = 1)
1542    
1543     f = open(instRoot + cf, "w+")
1544 slords 1.5
1545 slords 1.1 f.write("# yaboot.conf generated by anaconda\n\n")
1546    
1547     f.write("boot=%s\n" %(yabootTarget,))
1548     f.write("init-message=Welcome to %s\\!\nHit <TAB> for boot options\n\n"
1549     %(butil.getProductName(),))
1550    
1551     (name, partNum) = getDiskPart(bootDev)
1552     partno = partNum + 1 # 1 based
1553     f.write("partition=%s\n" %(partno,))
1554    
1555 slords 1.5 f.write("timeout=80\n")
1556 slords 1.1 f.write("install=/usr/lib/yaboot/yaboot\n")
1557     f.write("delay=5\n")
1558 slords 1.5 f.write("enablecdboot\n")
1559     f.write("enableofboot\n")
1560     f.write("enablenetboot\n")
1561 slords 1.1
1562     if butil.getPPCMachine() == "PMac":
1563 slords 1.5 # write out the first hfs/hfs+ partition as being macosx
1564     for (label, longlabel, device) in chainList:
1565     if ((not label) or (label == "")):
1566     continue
1567     f.write("macosx=/dev/%s\n" %(device,))
1568     break
1569    
1570 slords 1.1 f.write("magicboot=/usr/lib/yaboot/ofboot\n")
1571    
1572     if butil.getPPCMachine() == "pSeries":
1573     f.write("nonvram\n")
1574    
1575     if self.password:
1576     f.write("password=%s\n" %(self.password,))
1577     f.write("restricted\n")
1578    
1579     f.write("\n")
1580    
1581     rootDev = fsset.getEntryByMountPoint("/").device.getDevice()
1582    
1583     for (label, longlabel, version) in kernelList:
1584     kernelTag = "-" + version
1585     kernelFile = "%s/vmlinuz%s" %(cfPath, kernelTag)
1586    
1587     f.write("image=%s\n" %(kernelFile,))
1588     f.write("\tlabel=%s\n" %(label,))
1589     f.write("\tread-only\n")
1590    
1591     initrd = booty.makeInitrd(kernelTag, instRoot)
1592     if os.access(instRoot + initrd, os.R_OK):
1593     f.write("\tinitrd=%s/initrd%s.img\n" %(cfPath,kernelTag))
1594    
1595     append = "%s" %(self.args.get(),)
1596    
1597     realroot = getRootDevName(initrd, fsset, rootDev, instRoot)
1598     if not realroot.startswith("LABEL="):
1599     f.write("\troot=%s\n" %(realroot,))
1600     else:
1601     if len(append) > 0:
1602     append = "%s root=%s" %(append,realroot)
1603     else:
1604     append = "root=%s" %(realroot,)
1605    
1606     if len(append) > 0:
1607     f.write("\tappend=\"%s\"\n" %(append,))
1608     f.write("\n")
1609    
1610     f.close()
1611     os.chmod(instRoot + cf, 0600)
1612    
1613     # FIXME: hack to make sure things are written to disk
1614     import isys
1615     isys.sync()
1616     isys.sync()
1617     isys.sync()
1618    
1619     ybinargs = [ "/sbin/mkofboot", "-f", "-C", cf ]
1620     if butil.getPPCMachine() == "pSeries":
1621     ybinargs.extend(["--filesystem", "raw"])
1622    
1623    
1624     log("running: %s" %(ybinargs,))
1625 slords 1.5 if not flags.test:
1626 slords 1.1 rhpl.executil.execWithRedirect(ybinargs[0],
1627     ybinargs,
1628     stdout = "/dev/tty5",
1629     stderr = "/dev/tty5",
1630     root = instRoot)
1631    
1632     if (not os.access(instRoot + "/etc/yaboot.conf", os.R_OK) and
1633     os.access(instRoot + "/boot/etc/yaboot.conf", os.R_OK)):
1634     os.symlink("../boot/etc/yaboot.conf",
1635     instRoot + "/etc/yaboot.conf")
1636    
1637     return ""
1638    
1639     def setPassword(self, val, isCrypted = 1):
1640     # yaboot just handles the password and doesn't care if its crypted
1641     # or not
1642     self.password = val
1643    
1644     def write(self, instRoot, fsset, bl, langs, kernelList, chainList,
1645     defaultDev, justConfig, intf):
1646     if len(kernelList) >= 1:
1647     str = self.writeYaboot(instRoot, fsset, bl, langs, kernelList,
1648     chainList, defaultDev, justConfig)
1649     else:
1650     self.noKernelsWarn(intf)
1651    
1652     def __init__(self):
1653     bootloaderInfo.__init__(self)
1654     self.useYabootVal = 1
1655     self.kernelLocation = "/boot"
1656     self.configfile = "/etc/yaboot.conf"
1657    
1658    
1659     class iseriesBootloaderInfo(bootloaderInfo):
1660     def ddFile(self, inf, of, bs = 4096):
1661     src = os.open(inf, os.O_RDONLY)
1662     dest = os.open(of, os.O_WRONLY | os.O_CREAT)
1663     size = 0
1664    
1665     buf = os.read(src, bs)
1666     while len(buf) > 0:
1667     size = size + len(buf)
1668     os.write(dest, buf)
1669     buf = os.read(src, bs)
1670    
1671     os.close(src)
1672     os.close(dest)
1673    
1674     return size
1675    
1676     def write(self, instRoot, fsset, bl, langs, kernelList, chainList,
1677     defaultDev, justConfig, intf):
1678     if len(kernelList) < 1:
1679     self.noKernelsWarn(intf)
1680     return
1681     if len(kernelList) > 1:
1682     # FIXME: how can this happen?
1683     log("more than one kernel on iSeries. bailing and just using "
1684     "the first")
1685    
1686     # iseries is Weird (tm) -- here's the basic theory
1687     # a) have /boot/vmlinitrd-$(version)
1688     # b) copy default kernel to PReP partition
1689     # c) dd default kernel to /proc/iSeries/mf/C/vmlinux
1690     # d) set cmdline in /boot/cmdline-$(version)
1691     # e) copy cmdline to /proc/iSeries/mf/C/cmdline
1692     # f) set default side to 'C' i /proc/iSeries/mf/side
1693     # g) put default kernel and cmdline on side B too (#91038)
1694    
1695     rootDevice = fsset.getEntryByMountPoint("/").device.getDevice()
1696    
1697     # write our command line files
1698     for (kernel, tag, kernelTag) in kernelList:
1699     cmdFile = "%scmdline-%s" %(self.kernelLocation, kernelTag)
1700     initrd = "%sinitrd-%s.img" %(self.kernelLocation, kernelTag)
1701     realroot = getRootDevName(initrd, fsset, rootDevice, instRoot)
1702     f = open(instRoot + cmdFile, "w")
1703     f.write("ro root=%s" %(realroot,))
1704     if bl.args.get():
1705     f.write(" %s" %(bl.args.get(),))
1706     f.write("\n")
1707     f.close()
1708     os.chmod(instRoot + cmdFile, 0644)
1709    
1710     kernel, tag, kernelTag = kernelList[0]
1711     kernelFile = "%svmlinitrd-%s" %(self.kernelLocation, kernelTag)
1712    
1713     # write the kernel to the PReP partition since that's what
1714     # OS/400 will load as NWSSTG
1715     bootDev = bl.getDevice()
1716     if bootDev:
1717     log("Writing kernel %s to PReP partition %s" %(kernelFile,
1718     bootDev))
1719     try:
1720     self.ddFile(instRoot + kernelFile, "%s/dev/%s" %(instRoot,
1721     bootDev))
1722     except Exception, e:
1723     # FIXME: should this be more fatal
1724     log("Failed to write kernel: %s" %(e,))
1725     else:
1726     log("No PReP boot partition, not writing kernel for NWSSTG")
1727    
1728    
1729     # now, it's a lot faster to boot if we don't make people go back
1730     # into OS/400, so set up side C (used by default for NWSSTG) with
1731     # our current bits
1732     for side in ("C", "B"):
1733     log("Writing kernel and cmdline to side %s" %(side,))
1734     wrotekernel = 0
1735     try:
1736     self.ddFile(instRoot + kernelFile,
1737     "%s/proc/iSeries/mf/%s/vmlinux" %(instRoot, side))
1738     wrotekernel = 1
1739     except Exception, e:
1740     # FIXME: should this be more fatal?
1741     log("Failed to write kernel to side %s: %s" %(side, e))
1742    
1743     if wrotekernel == 1:
1744     try:
1745     # blank it. ugh.
1746     f = open("%s/proc/iSeries/mf/%s/cmdline" %(instRoot, side),
1747     "w+")
1748     f.write(" " * 255)
1749     f.close()
1750    
1751     self.ddFile("%s/%scmdline-%s" %(instRoot,
1752     self.kernelLocation,
1753     kernelTag),
1754     "%s/proc/iSeries/mf/%s/cmdline" %(instRoot,
1755     side))
1756     except Exception, e:
1757     log("Failed to write kernel command line to side %s: %s"
1758     %(side, e))
1759    
1760     log("Setting default side to C")
1761     f = open(instRoot + "/proc/iSeries/mf/side", "w")
1762     f.write("C")
1763     f.close()
1764    
1765     def __init__(self):
1766     bootloaderInfo.__init__(self)
1767     self.kernelLocation = "/boot/"
1768    
1769 slords 1.5 class sparcBootloaderInfo(bootloaderInfo):
1770     def writeSilo(self, instRoot, fsset, bl, langs, kernelList,
1771     chainList, defaultDev, justConfigFile):
1772    
1773     from flags import flags
1774    
1775     bootDev = fsset.getEntryByMountPoint("/boot")
1776     if bootDev:
1777     cf = "/boot/silo.conf"
1778     mf = "/boot/silo.message"
1779     cfPath = ""
1780     if not os.path.isdir(instRoot + "/boot"):
1781     os.mkdir(instRoot + "/boot")
1782     else:
1783     bootDev = fsset.getEntryByMountPoint("/")
1784     cf = "/etc/silo.conf"
1785     mf = "/etc/silo.message"
1786     cfPath = "/boot"
1787     bootDev = bootDev.device.getDevice(asBoot = 1)
1788 slords 1.1
1789 slords 1.5 f = open(instRoot + mf, "w+")
1790     f.write("Welcome to %s!\nHit <TAB> for boot options\n\n" % \
1791     (butil.getProductName(),))
1792     f.close()
1793     os.chmod(instRoot + mf, 0600)
1794    
1795     f = open(instRoot + cf, "w+")
1796     f.write("# silo.conf generated by anaconda\n\n")
1797    
1798     f.write("#boot=%s\n" % (bootDev,))
1799     f.write("message=%s\n" % (mf,))
1800     f.write("timeout=50\n")
1801    
1802     (name, partNum) = getDiskPart(bootDev)
1803     partno = partNum + 1
1804     f.write("partition=%s\n" % (partno,))
1805    
1806     if self.password:
1807     f.write("password=%s\n" % (self.password,))
1808     f.write("restricted\n")
1809    
1810     f.write("default=%s\n" % (kernelList[0][0],))
1811     f.write("\n")
1812    
1813     rootDev = fsset.getEntryByMountPoint("/").device.getDevice()
1814    
1815     for (label, longlabel, version) in kernelList:
1816     kernelTag = "-" + version
1817     kernelFile = "%s/vmlinuz%s" % (cfPath, kernelTag)
1818    
1819     f.write("image=%s\n" % (kernelFile,))
1820     f.write("\tlabel=%s\n" % (label,))
1821     f.write("\tread-only\n")
1822    
1823     initrd = booty.makeInitrd(kernelTag, instRoot)
1824     if os.access(instRoot + initrd, os.R_OK):
1825     f.write("\tinitrd=%s/initrd%s.img\n" % (cfPath, kernelTag))
1826    
1827     append = "%s" % (self.args.get(),)
1828    
1829     realroot = getRootDevName(initrd, fsset, rootDev, instRoot)
1830     if not realroot.startswith("LABEL="):
1831     f.write("\troot=%s\n" % (realroot,))
1832     else:
1833     if len(append) > 0:
1834     append = "%s root=%s" % (append, realroot)
1835     else:
1836     append = "root=%s" % (realroot,)
1837    
1838     if len(append) > 0:
1839     f.write("\tappend=\"%s\"\n" % (append,))
1840     f.write("\n")
1841    
1842     f.close()
1843     os.chmod(instRoot + cf, 0600)
1844    
1845     # FIXME: hack to make sure things are written to disk
1846     import isys
1847     isys.sync()
1848     isys.sync()
1849     isys.sync()
1850    
1851     backup = "%s/backup.b" % (cfPath,)
1852     sbinargs = ["/sbin/silo", "-f", "-C", cf, "-S", backup]
1853     if butil.getSparcMachine() == "sun4u":
1854     sbinargs += ["-u"]
1855     else:
1856     sbinargs += ["-U"]
1857    
1858     log("running: %s" % (sbinargs,))
1859     if not flags.test:
1860     rhpl.executil.execWithRedirect(sbinargs[0],
1861     sbinargs,
1862     stdout = "/dev/tty5",
1863     stderr = "/dev/tty5",
1864     root = instRoot)
1865    
1866     if (not os.access(instRoot + "/etc/silo.conf", os.R_OK) and
1867     os.access(instRoot + "/boot/etc/silo.conf", os.R_OK)):
1868     os.symlink("../boot/etc/silo.conf",
1869     instRoot + "/etc/silo.conf")
1870    
1871     return ""
1872    
1873     def setPassword(self, val, isCrypted = 1):
1874     # silo just handles the password unencrypted
1875     self.password = val
1876    
1877     def write(self, instRoot, fsset, bl, langs, kernelList, chainList,
1878     defaultDev, justConfig, intf):
1879     if len(kernelList) >= 1:
1880     self.writeSilo(instRoot, fsset, bl, langs, kernelList, chainList,
1881     defaultDev, justConfig)
1882     else:
1883     self.noKernelsWarn(intf)
1884    
1885     def __init__(self):
1886     bootloaderInfo.__init__(self)
1887     self.useSiloVal = 1
1888     self.kernelLocation = "/boot"
1889     self.configfile = "/etc/silo.conf"
1890 slords 1.1
1891     ###############
1892     # end of boot loader objects... these are just some utility functions used
1893    
1894     # return (disk, partition number) eg ('hda', 1)
1895     def getDiskPart(dev):
1896     cut = len(dev)
1897     if (dev.startswith('rd/') or dev.startswith('ida/') or
1898     dev.startswith('cciss/')):
1899     if dev[-2] == 'p':
1900     cut = -1
1901     elif dev[-3] == 'p':
1902     cut = -2
1903     else:
1904     if dev[-2] in string.digits:
1905     cut = -2
1906     elif dev[-1] in string.digits:
1907     cut = -1
1908    
1909     name = dev[:cut]
1910    
1911     # hack off the trailing 'p' from /dev/cciss/*, for example
1912     if name[-1] == 'p':
1913     for letter in name:
1914     if letter not in string.letters and letter != "/":
1915     name = name[:-1]
1916     break
1917    
1918     if cut < 0:
1919     partNum = int(dev[cut:]) - 1
1920     else:
1921     partNum = None
1922    
1923     return (name, partNum)
1924    
1925     # hackery to determine if we should do root=LABEL=/ or whatnot
1926     # as usual, knows too much about anaconda
1927     def getRootDevName(initrd, fsset, rootDev, instRoot):
1928     if not os.access(instRoot + initrd, os.R_OK):
1929     return "/dev/%s" % (rootDev,)
1930    
1931     try:
1932     rootEntry = fsset.getEntryByMountPoint("/")
1933     if rootEntry.getLabel() is not None:
1934     return "LABEL=%s" %(rootEntry.getLabel(),)
1935     return "/dev/%s" %(rootDev,)
1936     except:
1937     return "/dev/%s" %(rootDev,)
1938    

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