/[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.5 - (hide annotations) (download) (as text)
Wed Apr 5 01:20:27 2006 UTC (18 years, 8 months ago) by slords
Branch: MAIN
Changes since 1.4: +177 -115 lines
Content type: text/x-python
Update anaconda to be in sync with 4.3 and FC4

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

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