/[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.1 - (hide annotations) (download) (as text)
Sun Jul 3 23:48:44 2005 UTC (19 years, 5 months ago) by slords
Branch: MAIN
Content type: text/x-python
Updates for a24

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

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