/[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.6 - (hide annotations) (download) (as text)
Wed Apr 5 04:20:56 2006 UTC (18 years, 8 months ago) by slords
Branch: MAIN
Changes since 1.5: +7 -8 lines
Content type: text/x-python
Create /boot partition first to get it in sync faster.
Install grub so hard drives can fail nicely.

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.2 import isys
20 slords 1.1 import os, sys
21     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    
842     if not os.access(instRoot + "/boot/grub/device.map", os.R_OK):
843     f = open(instRoot + "/boot/grub/device.map", "w+")
844     f.write("# this device map was generated by anaconda\n")
845     f.write("(fd0) /dev/fd0\n")
846     devs = usedDevs.keys()
847     usedDevs = {}
848     for dev in devs:
849     drive = getDiskPart(dev)[0]
850     if usedDevs.has_key(drive):
851     continue
852     usedDevs[drive] = 1
853     devs = usedDevs.keys()
854     devs.sort()
855     for drive in devs:
856     # XXX hack city. If they're not the sort of thing that'll
857     # be in the device map, they shouldn't still be in the list.
858     if not drive.startswith('md'):
859     f.write("(%s) /dev/%s\n" % (self.grubbyDiskName(drive),
860 slords 1.5 drive))
861 slords 1.1 f.close()
862    
863     if self.forceLBA32:
864     forcelba = "--force-lba "
865     else:
866     forcelba = ""
867    
868     sysconf = '/etc/sysconfig/grub'
869     if os.access (instRoot + sysconf, os.R_OK):
870     self.perms = os.stat(instRoot + sysconf)[0] & 0777
871     os.rename(instRoot + sysconf,
872     instRoot + sysconf + '.rpmsave')
873     # if it's an absolute symlink, just get it out of our way
874     elif (os.path.islink(instRoot + sysconf) and
875     os.readlink(instRoot + sysconf)[0] == '/'):
876     os.rename(instRoot + sysconf,
877     instRoot + sysconf + '.rpmsave')
878     f = open(instRoot + sysconf, 'w+')
879     f.write("boot=/dev/%s\n" %(grubTarget,))
880 slords 1.5 # XXX forcelba never gets read back...
881 slords 1.1 if self.forceLBA32:
882     f.write("forcelba=1\n")
883     else:
884     f.write("forcelba=0\n")
885     f.close()
886    
887     cmds = []
888     for bootDev in bootDevs:
889 slords 1.6 gtDisk = self.grubbyPartitionName(getDiskPart(bootDev)[0])
890 slords 1.5 bPart = self.grubbyPartitionName(bootDev)
891 slords 1.1 cmd = "root %s" % (bPart,)
892     cmds.append(cmd)
893    
894     stage1Target = gtDisk
895     if target == "partition":
896 slords 1.6 stage1Target = self.grubbyPartitionName(bootDev)
897 slords 1.1
898 slords 1.6 cmd = "install %s/stage1 %s %s1+16 p %s%s/stage2 %s/grub.conf" % \
899     (grubPath, stage1Target, stage1Target, bPart, grubPath, grubPath)
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.6 cmd = "root %s\ninstall %s/stage1 %s %s1+16 p %s%s/stage2 %s/grub.conf" \
1085     % (grubbyRootPart, grubPath, stage1Dev, stage1Dev,
1086     grubbyRootPart, grubPath, grubPath)
1087 slords 1.1
1088 slords 1.5 if not justConfigFile:
1089     log("GRUB command %s", cmd)
1090 slords 1.1
1091 slords 1.5 # copy the stage files over into /boot
1092     rhpl.executil.execWithRedirect( "/sbin/grub-install",
1093 slords 1.1 ["/sbin/grub-install", "--just-copy"],
1094     stdout = "/dev/tty5", stderr = "/dev/tty5",
1095     root = instRoot)
1096    
1097 slords 1.5 # get the stage files synced to disk
1098     import isys
1099     isys.sync()
1100     isys.sync()
1101     isys.sync()
1102 slords 1.1
1103 slords 1.5 # really install the bootloader
1104     p = os.pipe()
1105     os.write(p[1], cmd + '\n')
1106     os.close(p[1])
1107     rhpl.executil.execWithRedirect('/sbin/grub' ,
1108 slords 1.1 [ "grub", "--batch", "--no-floppy",
1109     "--device-map=/boot/grub/device.map" ],
1110     stdin = p[0],
1111     stdout = "/dev/tty5", stderr = "/dev/tty5",
1112     root = instRoot)
1113 slords 1.5 os.close(p[0])
1114 slords 1.1
1115     return ""
1116    
1117    
1118     def write(self, instRoot, fsset, bl, langs, kernelList, chainList,
1119     defaultDev, justConfig, intf):
1120     # XXX HACK ALERT - see declaration above
1121     if self.doUpgradeOnly:
1122 slords 1.5 if self.useGrubVal:
1123 slords 1.1 self.upgradeGrub(instRoot, fsset, bl, langs, kernelList,
1124     chainList, defaultDev, justConfig)
1125    
1126     # and the hacks continue. with 2.6, ide-scsi isn't used
1127     # anymore (#116622)
1128     import isys
1129     cdrw = isys.ideCdRwList()
1130     torem = []
1131     for device in cdrw:
1132     torem.append("%s=ide-scsi" %(device,))
1133    
1134     for fn in ("/etc/lilo.conf", "/boot/grub/grub.conf",
1135     "/etc/lilo.conf.anaconda"):
1136     if not os.path.exists(instRoot + fn):
1137     continue
1138     f = open(instRoot + fn, "r")
1139     buf = f.read()
1140     f.close()
1141     for dev in torem:
1142     buf = buf.replace(dev, "")
1143     f = open(instRoot + fn, "w")
1144     f.write(buf)
1145     f.close()
1146     return
1147     if len(kernelList) < 1:
1148     self.noKernelsWarn(intf)
1149    
1150     str = self.writeGrub(instRoot, fsset, bl, langs, kernelList,
1151     chainList, defaultDev,
1152     justConfig | (not self.useGrubVal))
1153     # XXX move the lilo.conf out of the way if they're using GRUB
1154     # so that /sbin/installkernel does a more correct thing
1155     if self.useGrubVal and os.access(instRoot + '/etc/lilo.conf', os.R_OK):
1156     os.rename(instRoot + "/etc/lilo.conf",
1157     instRoot + "/etc/lilo.conf.anaconda")
1158    
1159    
1160    
1161     def getArgList(self):
1162     args = bootloaderInfo.getArgList(self)
1163    
1164     if self.forceLBA32:
1165     args.append("--lba32")
1166     if self.password:
1167     args.append("--md5pass=%s" %(self.password))
1168    
1169    
1170     # XXX add location of bootloader here too
1171    
1172     return args
1173    
1174     def __init__(self):
1175     bootloaderInfo.__init__(self)
1176     # XXX use checkbootloader to determine what to default to
1177     self.useGrubVal = 1
1178     self.kernelLocation = "/boot/"
1179     self.configfile = "/etc/lilo.conf"
1180     self.password = None
1181     self.pure = None
1182    
1183     class s390BootloaderInfo(bootloaderInfo):
1184     def getBootloaderConfig(self, instRoot, fsset, bl, langs, kernelList,
1185     chainList, defaultDev):
1186     images = bl.images.getImages()
1187    
1188     # on upgrade read in the lilo config file
1189     lilo = LiloConfigFile ()
1190     self.perms = 0600
1191     if os.access (instRoot + self.configfile, os.R_OK):
1192     self.perms = os.stat(instRoot + self.configfile)[0] & 0777
1193     lilo.read (instRoot + self.configfile)
1194     os.rename(instRoot + self.configfile,
1195     instRoot + self.configfile + '.rpmsave')
1196    
1197     # Remove any invalid entries that are in the file; we probably
1198     # just removed those kernels.
1199     for label in lilo.listImages():
1200     (fsType, sl, path, other) = lilo.getImage(label)
1201     if fsType == "other": continue
1202    
1203     if not os.access(instRoot + sl.getPath(), os.R_OK):
1204     lilo.delImage(label)
1205    
1206     rootDev = fsset.getEntryByMountPoint("/").device.getDevice()
1207     if not rootDev:
1208     raise RuntimeError, "Installing zipl, but there is no root device"
1209    
1210     if rootDev == defaultDev:
1211     lilo.addEntry("default", kernelList[0][0])
1212     else:
1213     lilo.addEntry("default", chainList[0][0])
1214    
1215     for (label, longlabel, version) in kernelList:
1216     kernelTag = "-" + version
1217     kernelFile = self.kernelLocation + "vmlinuz" + kernelTag
1218    
1219     try:
1220     lilo.delImage(label)
1221     except IndexError, msg:
1222     pass
1223    
1224     sl = LiloConfigFile(imageType = "image", path = kernelFile)
1225    
1226     initrd = booty.makeInitrd (kernelTag, instRoot)
1227    
1228     sl.addEntry("label", label)
1229     if os.access (instRoot + initrd, os.R_OK):
1230     sl.addEntry("initrd",
1231     "%sinitrd%s.img" %(self.kernelLocation, kernelTag))
1232    
1233     sl.addEntry("read-only")
1234     sl.addEntry("root", '/dev/' + rootDev)
1235     sl.addEntry("ipldevice", '/dev/' + rootDev[:-1])
1236    
1237     if self.args.get():
1238     sl.addEntry('append', '"%s"' % self.args.get())
1239    
1240     lilo.addImage (sl)
1241    
1242     for (label, longlabel, device) in chainList:
1243     if ((not label) or (label == "")):
1244     continue
1245     try:
1246     (fsType, sl, path, other) = lilo.getImage(label)
1247     lilo.delImage(label)
1248     except IndexError:
1249     sl = LiloConfigFile(imageType = "other",
1250     path = "/dev/%s" %(device))
1251     sl.addEntry("optional")
1252    
1253     sl.addEntry("label", label)
1254     lilo.addImage (sl)
1255    
1256     # Sanity check #1. There could be aliases in sections which conflict
1257     # with the new images we just created. If so, erase those aliases
1258     imageNames = {}
1259     for label in lilo.listImages():
1260     imageNames[label] = 1
1261    
1262     for label in lilo.listImages():
1263     (fsType, sl, path, other) = lilo.getImage(label)
1264     if sl.testEntry('alias'):
1265     alias = sl.getEntry('alias')
1266     if imageNames.has_key(alias):
1267     sl.delEntry('alias')
1268     imageNames[alias] = 1
1269    
1270     # Sanity check #2. If single-key is turned on, go through all of
1271     # the image names (including aliases) (we just built the list) and
1272     # see if single-key will still work.
1273     if lilo.testEntry('single-key'):
1274     singleKeys = {}
1275     turnOff = 0
1276     for label in imageNames.keys():
1277     l = label[0]
1278     if singleKeys.has_key(l):
1279     turnOff = 1
1280     singleKeys[l] = 1
1281     if turnOff:
1282     lilo.delEntry('single-key')
1283    
1284     return lilo
1285    
1286     def writeChandevConf(self, bl, instroot): # S/390 only
1287     cf = "/etc/chandev.conf"
1288     self.perms = 0644
1289     if bl.args.chandevget():
1290     fd = os.open(instroot + "/etc/chandev.conf",
1291     os.O_WRONLY | os.O_CREAT)
1292     os.write(fd, "noauto\n")
1293     for cdev in bl.args.chandevget():
1294     os.write(fd,'%s\n' % cdev)
1295     os.close(fd)
1296     return ""
1297    
1298    
1299     def writeZipl(self, instRoot, fsset, bl, langs, kernelList, chainList,
1300     defaultDev, justConfigFile):
1301     images = bl.images.getImages()
1302     rootDev = fsset.getEntryByMountPoint("/").device.getDevice()
1303    
1304     cf = '/etc/zipl.conf'
1305     self.perms = 0600
1306     if os.access (instRoot + cf, os.R_OK):
1307     self.perms = os.stat(instRoot + cf)[0] & 0777
1308     os.rename(instRoot + cf,
1309     instRoot + cf + '.rpmsave')
1310    
1311     f = open(instRoot + cf, "w+")
1312    
1313     f.write('[defaultboot]\n')
1314     f.write('default=' + kernelList[0][0] + '\n')
1315     f.write('target=%s\n' % (self.kernelLocation))
1316    
1317     cfPath = "/boot/"
1318     for (label, longlabel, version) in kernelList:
1319     kernelTag = "-" + version
1320     kernelFile = "%svmlinuz%s" % (cfPath, kernelTag)
1321    
1322     initrd = booty.makeInitrd (kernelTag, instRoot)
1323     f.write('[%s]\n' % (label))
1324     f.write('\timage=%s\n' % (kernelFile))
1325     if os.access (instRoot + initrd, os.R_OK):
1326     f.write('\tramdisk=%sinitrd%s.img\n' %(self.kernelLocation,
1327     kernelTag))
1328     realroot = getRootDevName(initrd, fsset, rootDev, instRoot)
1329     f.write('\tparameters="root=%s' %(realroot,))
1330     if bl.args.get():
1331     f.write(' %s' % (bl.args.get()))
1332     f.write('"\n')
1333    
1334     f.close()
1335    
1336     if not justConfigFile:
1337     argv = [ "/sbin/zipl" ]
1338     rhpl.executil.execWithRedirect(argv[0], argv, root = instRoot,
1339     stdout = "/dev/stdout",
1340     stderr = "/dev/stderr")
1341    
1342     return ""
1343    
1344     def write(self, instRoot, fsset, bl, langs, kernelList, chainList,
1345     defaultDev, justConfig, intf):
1346     str = self.writeZipl(instRoot, fsset, bl, langs, kernelList,
1347     chainList, defaultDev,
1348     justConfig | (not self.useZiplVal))
1349     str = self.writeChandevConf(bl, instRoot)
1350    
1351     def __init__(self):
1352     bootloaderInfo.__init__(self)
1353     self.useZiplVal = 1 # only used on s390
1354     self.kernelLocation = "/boot/"
1355     self.configfile = "/etc/zipl.conf"
1356    
1357    
1358     class alphaBootloaderInfo(bootloaderInfo):
1359     def wholeDevice (self, path):
1360     (device, foo) = getDiskPart(path)
1361     return device
1362    
1363     def partitionNum (self, path):
1364     # getDiskPart returns part numbers 0-based; we need it one based
1365     # *sigh*
1366     (foo, partitionNumber) = getDiskPart(path)
1367     return partitionNumber + 1
1368    
1369     # See if we would have to use MILO. MILO isn't supported by Red Hat.
1370     def useMilo (self):
1371     try:
1372     f = open ('/proc/cpuinfo', 'ro')
1373     except:
1374     return
1375     lines = f.readlines ()
1376     f.close()
1377     serial = ""
1378     for line in lines:
1379     if line.find("system serial number") != -1:
1380     serial = string.strip (string.split (line, ':')[1])
1381     break
1382    
1383     if serial and len (serial) >= 4 and serial.startswith("MILO"):
1384     return 1
1385     else:
1386     return 0
1387    
1388     def writeAboot(self, instRoot, fsset, bl, langs, kernelList,
1389     chainList, defaultDev, justConfig):
1390     # Get bootDevice and rootDevice
1391     rootDevice = fsset.getEntryByMountPoint("/").device.getDevice()
1392     if fsset.getEntryByMountPoint("/boot"):
1393     bootDevice = fsset.getEntryByMountPoint("/boot").device.getDevice()
1394     else:
1395     bootDevice = rootDevice
1396     bootnotroot = bootDevice != rootDevice
1397    
1398     # If /etc/aboot.conf already exists we rename it
1399     # /etc/aboot.conf.rpmsave.
1400     if os.path.isfile(instRoot + self.configfile):
1401     os.rename (instRoot + self.configfile,
1402     instRoot + self.configfile + ".rpmsave")
1403    
1404     # Then we create the necessary files. If the root device isn't
1405     # the boot device, we create /boot/etc/ where the aboot.conf
1406     # will live, and we create /etc/aboot.conf as a symlink to it.
1407     if bootnotroot:
1408     # Do we have /boot/etc ? If not, create one
1409     if not os.path.isdir (instRoot + '/boot/etc'):
1410     os.mkdir(instRoot + '/boot/etc', 0755)
1411    
1412     # We install the symlink (/etc/aboot.conf has already been
1413     # renamed in necessary.)
1414     os.symlink("../boot" + self.configfile, instRoot + self.configfile)
1415    
1416     cfPath = instRoot + "/boot" + self.configfile
1417     # Kernel path is set to / because a boot partition will
1418     # be a root on its own.
1419     kernelPath = '/'
1420     # Otherwise, we just need to create /etc/aboot.conf.
1421     else:
1422     cfPath = instRoot + self.configfile
1423     kernelPath = self.kernelLocation
1424    
1425     # If we already have an aboot.conf, rename it
1426     if os.access (cfPath, os.R_OK):
1427     self.perms = os.stat(cfPath)[0] & 0777
1428     os.rename(cfPath, cfPath + '.rpmsave')
1429    
1430     # Now we're going to create and populate cfPath.
1431     f = open (cfPath, 'w+')
1432     f.write ("# aboot default configurations\n")
1433    
1434     if bootnotroot:
1435     f.write ("# NOTICE: You have a /boot partition. This means that\n")
1436     f.write ("# all kernel paths are relative to /boot/\n")
1437    
1438     # bpn is the boot partition number.
1439     bpn = self.partitionNum(bootDevice)
1440     lines = 0
1441    
1442     # We write entries line using the following format:
1443     # <line><bpn><kernel-name> root=<rootdev> [options]
1444     # We get all the kernels we need to know about in kernelList.
1445    
1446     for (kernel, tag, kernelTag) in kernelList:
1447     kernelFile = "%svmlinuz-%s" %(kernelPath, kernelTag)
1448    
1449     f.write("%d:%d%s" %(lines, bpn, kernelFile))
1450    
1451     # See if we can come up with an initrd argument that exists
1452     initrd = booty.makeInitrd (kernelTag, instRoot)
1453     if os.access(instRoot + initrd, os.R_OK):
1454     f.write(" initrd=%sinitrd-%s.img" %(kernelPath, kernelTag))
1455    
1456     realroot = getRootDevName(initrd, fsset, rootDevice, instRoot)
1457     f.write(" root=%s" %(realroot,))
1458    
1459     args = self.args.get()
1460     if args:
1461     f.write(" %s" %(args,))
1462    
1463     f.write("\n")
1464     lines = lines + 1
1465    
1466     # We're done writing the file
1467     f.close ()
1468     del f
1469    
1470     if not justConfig:
1471     # Now we're ready to write the relevant boot information. wbd
1472     # is the whole boot device, bdpn is the boot device partition
1473     # number.
1474     wbd = self.wholeDevice (bootDevice)
1475     bdpn = self.partitionNum (bootDevice)
1476    
1477     # Calling swriteboot. The first argument is the disk to write
1478     # to and the second argument is a path to the bootstrap loader
1479     # file.
1480     args = ("swriteboot", ("/dev/%s" % wbd), "/boot/bootlx")
1481     log("swriteboot command: %s" %(args,))
1482     rhpl.executil.execWithRedirect ('/sbin/swriteboot', args,
1483     root = instRoot,
1484     stdout = "/dev/tty5",
1485     stderr = "/dev/tty5")
1486    
1487     # Calling abootconf to configure the installed aboot. The
1488     # first argument is the disk to use, the second argument is
1489     # the number of the partition on which aboot.conf resides.
1490     # It's always the boot partition whether it's / or /boot (with
1491     # the mount point being omitted.)
1492     args = ("abootconf", ("/dev/%s" % wbd), str (bdpn))
1493     log("abootconf command: %s" %(args,))
1494     rhpl.executil.execWithRedirect ('/sbin/abootconf', args,
1495     root = instRoot,
1496     stdout = "/dev/tty5",
1497     stderr = "/dev/tty5")
1498    
1499    
1500     def write(self, instRoot, fsset, bl, langs, kernelList, chainList,
1501     defaultDev, justConfig, intf):
1502     if len(kernelList) < 1:
1503     self.noKernelsWarn(intf)
1504    
1505     if self.useMilo():
1506     intf.messageWindow(_("MILO Not Supported"),
1507     "This system requires the support of MILO to " +
1508     "boot linux (MILO is not included in this " +
1509     "distribution.) The installation of the " +
1510     "bootloader can't be completed on this system.")
1511     # elif not justConfig FIXME.
1512     else:
1513     self.writeAboot(instRoot, fsset, bl, langs, kernelList,
1514     chainList, defaultDev, justConfig)
1515    
1516     def __init__(self):
1517     bootloaderInfo.__init__(self)
1518     self.useGrubVal = 0
1519     self.configfile = "/etc/aboot.conf"
1520     # self.kernelLocation is already set to what we need.
1521     self.password = None
1522     self.pure = None
1523    
1524    
1525     class ppcBootloaderInfo(bootloaderInfo):
1526     def writeYaboot(self, instRoot, fsset, bl, langs, kernelList,
1527     chainList, defaultDev, justConfigFile):
1528    
1529     from flags import flags
1530    
1531     yabootTarget = '/dev/%s' %(bl.getDevice())
1532    
1533     bootDev = fsset.getEntryByMountPoint("/boot")
1534     if bootDev:
1535     cf = "/boot/etc/yaboot.conf"
1536     cfPath = ""
1537     if not os.path.isdir(instRoot + "/boot/etc"):
1538     os.mkdir(instRoot + "/boot/etc")
1539     else:
1540     bootDev = fsset.getEntryByMountPoint("/")
1541     cfPath = "/boot"
1542     cf = "/etc/yaboot.conf"
1543     bootDev = bootDev.device.getDevice(asBoot = 1)
1544    
1545     f = open(instRoot + cf, "w+")
1546 slords 1.5
1547 slords 1.1 f.write("# yaboot.conf generated by anaconda\n\n")
1548    
1549     f.write("boot=%s\n" %(yabootTarget,))
1550     f.write("init-message=Welcome to %s\\!\nHit <TAB> for boot options\n\n"
1551     %(butil.getProductName(),))
1552    
1553     (name, partNum) = getDiskPart(bootDev)
1554     partno = partNum + 1 # 1 based
1555     f.write("partition=%s\n" %(partno,))
1556    
1557 slords 1.5 f.write("timeout=80\n")
1558 slords 1.1 f.write("install=/usr/lib/yaboot/yaboot\n")
1559     f.write("delay=5\n")
1560 slords 1.5 f.write("enablecdboot\n")
1561     f.write("enableofboot\n")
1562     f.write("enablenetboot\n")
1563 slords 1.1
1564     if butil.getPPCMachine() == "PMac":
1565 slords 1.5 # write out the first hfs/hfs+ partition as being macosx
1566     for (label, longlabel, device) in chainList:
1567     if ((not label) or (label == "")):
1568     continue
1569     f.write("macosx=/dev/%s\n" %(device,))
1570     break
1571    
1572 slords 1.1 f.write("magicboot=/usr/lib/yaboot/ofboot\n")
1573    
1574     if butil.getPPCMachine() == "pSeries":
1575     f.write("nonvram\n")
1576    
1577     if self.password:
1578     f.write("password=%s\n" %(self.password,))
1579     f.write("restricted\n")
1580    
1581     f.write("\n")
1582    
1583     rootDev = fsset.getEntryByMountPoint("/").device.getDevice()
1584    
1585     for (label, longlabel, version) in kernelList:
1586     kernelTag = "-" + version
1587     kernelFile = "%s/vmlinuz%s" %(cfPath, kernelTag)
1588    
1589     f.write("image=%s\n" %(kernelFile,))
1590     f.write("\tlabel=%s\n" %(label,))
1591     f.write("\tread-only\n")
1592    
1593     initrd = booty.makeInitrd(kernelTag, instRoot)
1594     if os.access(instRoot + initrd, os.R_OK):
1595     f.write("\tinitrd=%s/initrd%s.img\n" %(cfPath,kernelTag))
1596    
1597     append = "%s" %(self.args.get(),)
1598    
1599     realroot = getRootDevName(initrd, fsset, rootDev, instRoot)
1600     if not realroot.startswith("LABEL="):
1601     f.write("\troot=%s\n" %(realroot,))
1602     else:
1603     if len(append) > 0:
1604     append = "%s root=%s" %(append,realroot)
1605     else:
1606     append = "root=%s" %(realroot,)
1607    
1608     if len(append) > 0:
1609     f.write("\tappend=\"%s\"\n" %(append,))
1610     f.write("\n")
1611    
1612     f.close()
1613     os.chmod(instRoot + cf, 0600)
1614    
1615     # FIXME: hack to make sure things are written to disk
1616     import isys
1617     isys.sync()
1618     isys.sync()
1619     isys.sync()
1620    
1621     ybinargs = [ "/sbin/mkofboot", "-f", "-C", cf ]
1622     if butil.getPPCMachine() == "pSeries":
1623     ybinargs.extend(["--filesystem", "raw"])
1624    
1625    
1626     log("running: %s" %(ybinargs,))
1627 slords 1.5 if not flags.test:
1628 slords 1.1 rhpl.executil.execWithRedirect(ybinargs[0],
1629     ybinargs,
1630     stdout = "/dev/tty5",
1631     stderr = "/dev/tty5",
1632     root = instRoot)
1633    
1634     if (not os.access(instRoot + "/etc/yaboot.conf", os.R_OK) and
1635     os.access(instRoot + "/boot/etc/yaboot.conf", os.R_OK)):
1636     os.symlink("../boot/etc/yaboot.conf",
1637     instRoot + "/etc/yaboot.conf")
1638    
1639     return ""
1640    
1641     def setPassword(self, val, isCrypted = 1):
1642     # yaboot just handles the password and doesn't care if its crypted
1643     # or not
1644     self.password = val
1645    
1646     def write(self, instRoot, fsset, bl, langs, kernelList, chainList,
1647     defaultDev, justConfig, intf):
1648     if len(kernelList) >= 1:
1649     str = self.writeYaboot(instRoot, fsset, bl, langs, kernelList,
1650     chainList, defaultDev, justConfig)
1651     else:
1652     self.noKernelsWarn(intf)
1653    
1654     def __init__(self):
1655     bootloaderInfo.__init__(self)
1656     self.useYabootVal = 1
1657     self.kernelLocation = "/boot"
1658     self.configfile = "/etc/yaboot.conf"
1659    
1660    
1661     class iseriesBootloaderInfo(bootloaderInfo):
1662     def ddFile(self, inf, of, bs = 4096):
1663     src = os.open(inf, os.O_RDONLY)
1664     dest = os.open(of, os.O_WRONLY | os.O_CREAT)
1665     size = 0
1666    
1667     buf = os.read(src, bs)
1668     while len(buf) > 0:
1669     size = size + len(buf)
1670     os.write(dest, buf)
1671     buf = os.read(src, bs)
1672    
1673     os.close(src)
1674     os.close(dest)
1675    
1676     return size
1677    
1678     def write(self, instRoot, fsset, bl, langs, kernelList, chainList,
1679     defaultDev, justConfig, intf):
1680     if len(kernelList) < 1:
1681     self.noKernelsWarn(intf)
1682     return
1683     if len(kernelList) > 1:
1684     # FIXME: how can this happen?
1685     log("more than one kernel on iSeries. bailing and just using "
1686     "the first")
1687    
1688     # iseries is Weird (tm) -- here's the basic theory
1689     # a) have /boot/vmlinitrd-$(version)
1690     # b) copy default kernel to PReP partition
1691     # c) dd default kernel to /proc/iSeries/mf/C/vmlinux
1692     # d) set cmdline in /boot/cmdline-$(version)
1693     # e) copy cmdline to /proc/iSeries/mf/C/cmdline
1694     # f) set default side to 'C' i /proc/iSeries/mf/side
1695     # g) put default kernel and cmdline on side B too (#91038)
1696    
1697     rootDevice = fsset.getEntryByMountPoint("/").device.getDevice()
1698    
1699     # write our command line files
1700     for (kernel, tag, kernelTag) in kernelList:
1701     cmdFile = "%scmdline-%s" %(self.kernelLocation, kernelTag)
1702     initrd = "%sinitrd-%s.img" %(self.kernelLocation, kernelTag)
1703     realroot = getRootDevName(initrd, fsset, rootDevice, instRoot)
1704     f = open(instRoot + cmdFile, "w")
1705     f.write("ro root=%s" %(realroot,))
1706     if bl.args.get():
1707     f.write(" %s" %(bl.args.get(),))
1708     f.write("\n")
1709     f.close()
1710     os.chmod(instRoot + cmdFile, 0644)
1711    
1712     kernel, tag, kernelTag = kernelList[0]
1713     kernelFile = "%svmlinitrd-%s" %(self.kernelLocation, kernelTag)
1714    
1715     # write the kernel to the PReP partition since that's what
1716     # OS/400 will load as NWSSTG
1717     bootDev = bl.getDevice()
1718     if bootDev:
1719     log("Writing kernel %s to PReP partition %s" %(kernelFile,
1720     bootDev))
1721     try:
1722     self.ddFile(instRoot + kernelFile, "%s/dev/%s" %(instRoot,
1723     bootDev))
1724     except Exception, e:
1725     # FIXME: should this be more fatal
1726     log("Failed to write kernel: %s" %(e,))
1727     else:
1728     log("No PReP boot partition, not writing kernel for NWSSTG")
1729    
1730    
1731     # now, it's a lot faster to boot if we don't make people go back
1732     # into OS/400, so set up side C (used by default for NWSSTG) with
1733     # our current bits
1734     for side in ("C", "B"):
1735     log("Writing kernel and cmdline to side %s" %(side,))
1736     wrotekernel = 0
1737     try:
1738     self.ddFile(instRoot + kernelFile,
1739     "%s/proc/iSeries/mf/%s/vmlinux" %(instRoot, side))
1740     wrotekernel = 1
1741     except Exception, e:
1742     # FIXME: should this be more fatal?
1743     log("Failed to write kernel to side %s: %s" %(side, e))
1744    
1745     if wrotekernel == 1:
1746     try:
1747     # blank it. ugh.
1748     f = open("%s/proc/iSeries/mf/%s/cmdline" %(instRoot, side),
1749     "w+")
1750     f.write(" " * 255)
1751     f.close()
1752    
1753     self.ddFile("%s/%scmdline-%s" %(instRoot,
1754     self.kernelLocation,
1755     kernelTag),
1756     "%s/proc/iSeries/mf/%s/cmdline" %(instRoot,
1757     side))
1758     except Exception, e:
1759     log("Failed to write kernel command line to side %s: %s"
1760     %(side, e))
1761    
1762     log("Setting default side to C")
1763     f = open(instRoot + "/proc/iSeries/mf/side", "w")
1764     f.write("C")
1765     f.close()
1766    
1767     def __init__(self):
1768     bootloaderInfo.__init__(self)
1769     self.kernelLocation = "/boot/"
1770    
1771 slords 1.5 class sparcBootloaderInfo(bootloaderInfo):
1772     def writeSilo(self, instRoot, fsset, bl, langs, kernelList,
1773     chainList, defaultDev, justConfigFile):
1774    
1775     from flags import flags
1776    
1777     bootDev = fsset.getEntryByMountPoint("/boot")
1778     if bootDev:
1779     cf = "/boot/silo.conf"
1780     mf = "/boot/silo.message"
1781     cfPath = ""
1782     if not os.path.isdir(instRoot + "/boot"):
1783     os.mkdir(instRoot + "/boot")
1784     else:
1785     bootDev = fsset.getEntryByMountPoint("/")
1786     cf = "/etc/silo.conf"
1787     mf = "/etc/silo.message"
1788     cfPath = "/boot"
1789     bootDev = bootDev.device.getDevice(asBoot = 1)
1790 slords 1.1
1791 slords 1.5 f = open(instRoot + mf, "w+")
1792     f.write("Welcome to %s!\nHit <TAB> for boot options\n\n" % \
1793     (butil.getProductName(),))
1794     f.close()
1795     os.chmod(instRoot + mf, 0600)
1796    
1797     f = open(instRoot + cf, "w+")
1798     f.write("# silo.conf generated by anaconda\n\n")
1799    
1800     f.write("#boot=%s\n" % (bootDev,))
1801     f.write("message=%s\n" % (mf,))
1802     f.write("timeout=50\n")
1803    
1804     (name, partNum) = getDiskPart(bootDev)
1805     partno = partNum + 1
1806     f.write("partition=%s\n" % (partno,))
1807    
1808     if self.password:
1809     f.write("password=%s\n" % (self.password,))
1810     f.write("restricted\n")
1811    
1812     f.write("default=%s\n" % (kernelList[0][0],))
1813     f.write("\n")
1814    
1815     rootDev = fsset.getEntryByMountPoint("/").device.getDevice()
1816    
1817     for (label, longlabel, version) in kernelList:
1818     kernelTag = "-" + version
1819     kernelFile = "%s/vmlinuz%s" % (cfPath, kernelTag)
1820    
1821     f.write("image=%s\n" % (kernelFile,))
1822     f.write("\tlabel=%s\n" % (label,))
1823     f.write("\tread-only\n")
1824    
1825     initrd = booty.makeInitrd(kernelTag, instRoot)
1826     if os.access(instRoot + initrd, os.R_OK):
1827     f.write("\tinitrd=%s/initrd%s.img\n" % (cfPath, kernelTag))
1828    
1829     append = "%s" % (self.args.get(),)
1830    
1831     realroot = getRootDevName(initrd, fsset, rootDev, instRoot)
1832     if not realroot.startswith("LABEL="):
1833     f.write("\troot=%s\n" % (realroot,))
1834     else:
1835     if len(append) > 0:
1836     append = "%s root=%s" % (append, realroot)
1837     else:
1838     append = "root=%s" % (realroot,)
1839    
1840     if len(append) > 0:
1841     f.write("\tappend=\"%s\"\n" % (append,))
1842     f.write("\n")
1843    
1844     f.close()
1845     os.chmod(instRoot + cf, 0600)
1846    
1847     # FIXME: hack to make sure things are written to disk
1848     import isys
1849     isys.sync()
1850     isys.sync()
1851     isys.sync()
1852    
1853     backup = "%s/backup.b" % (cfPath,)
1854     sbinargs = ["/sbin/silo", "-f", "-C", cf, "-S", backup]
1855     if butil.getSparcMachine() == "sun4u":
1856     sbinargs += ["-u"]
1857     else:
1858     sbinargs += ["-U"]
1859    
1860     log("running: %s" % (sbinargs,))
1861     if not flags.test:
1862     rhpl.executil.execWithRedirect(sbinargs[0],
1863     sbinargs,
1864     stdout = "/dev/tty5",
1865     stderr = "/dev/tty5",
1866     root = instRoot)
1867    
1868     if (not os.access(instRoot + "/etc/silo.conf", os.R_OK) and
1869     os.access(instRoot + "/boot/etc/silo.conf", os.R_OK)):
1870     os.symlink("../boot/etc/silo.conf",
1871     instRoot + "/etc/silo.conf")
1872    
1873     return ""
1874    
1875     def setPassword(self, val, isCrypted = 1):
1876     # silo just handles the password unencrypted
1877     self.password = val
1878    
1879     def write(self, instRoot, fsset, bl, langs, kernelList, chainList,
1880     defaultDev, justConfig, intf):
1881     if len(kernelList) >= 1:
1882     self.writeSilo(instRoot, fsset, bl, langs, kernelList, chainList,
1883     defaultDev, justConfig)
1884     else:
1885     self.noKernelsWarn(intf)
1886    
1887     def __init__(self):
1888     bootloaderInfo.__init__(self)
1889     self.useSiloVal = 1
1890     self.kernelLocation = "/boot"
1891     self.configfile = "/etc/silo.conf"
1892 slords 1.1
1893     ###############
1894     # end of boot loader objects... these are just some utility functions used
1895    
1896     # return (disk, partition number) eg ('hda', 1)
1897     def getDiskPart(dev):
1898     cut = len(dev)
1899     if (dev.startswith('rd/') or dev.startswith('ida/') or
1900     dev.startswith('cciss/')):
1901     if dev[-2] == 'p':
1902     cut = -1
1903     elif dev[-3] == 'p':
1904     cut = -2
1905     else:
1906     if dev[-2] in string.digits:
1907     cut = -2
1908     elif dev[-1] in string.digits:
1909     cut = -1
1910    
1911     name = dev[:cut]
1912    
1913     # hack off the trailing 'p' from /dev/cciss/*, for example
1914     if name[-1] == 'p':
1915     for letter in name:
1916     if letter not in string.letters and letter != "/":
1917     name = name[:-1]
1918     break
1919    
1920     if cut < 0:
1921     partNum = int(dev[cut:]) - 1
1922     else:
1923     partNum = None
1924    
1925     return (name, partNum)
1926    
1927     # hackery to determine if we should do root=LABEL=/ or whatnot
1928     # as usual, knows too much about anaconda
1929     def getRootDevName(initrd, fsset, rootDev, instRoot):
1930     if not os.access(instRoot + initrd, os.R_OK):
1931     return "/dev/%s" % (rootDev,)
1932    
1933     try:
1934     rootEntry = fsset.getEntryByMountPoint("/")
1935     if rootEntry.getLabel() is not None:
1936     return "LABEL=%s" %(rootEntry.getLabel(),)
1937     return "/dev/%s" %(rootDev,)
1938     except:
1939     return "/dev/%s" %(rootDev,)
1940    

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