/[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.4 - (hide annotations) (download) (as text)
Wed Nov 23 22:49:43 2005 UTC (19 years, 1 month ago) by slords
Branch: MAIN
Changes since 1.3: +5 -5 lines
Content type: text/x-python
Checkpoint

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

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