/[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.7 - (hide annotations) (download) (as text)
Wed Apr 5 05:13:40 2006 UTC (18 years, 8 months ago) by slords
Branch: MAIN
Changes since 1.6: +3 -0 lines
Content type: text/x-python
Make sure all boot devices are included in the map

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

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