/[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.9 - (hide annotations) (download) (as text)
Tue Jun 6 18:23:19 2006 UTC (18 years, 6 months ago) by segfault-
Branch: MAIN
Changes since 1.8: +11 -5 lines
Content type: text/x-python
Revert grub install behaviour to fix BZ 1510

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

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