From 93fcd3224a342b905b31d40da2058d3ea910eb0c Mon Sep 17 00:00:00 2001 From: Shad L. Lords Date: Mon, 26 Oct 2009 22:16:17 -0600 Subject: [PATCH] Backport RHEL5 boot installer --- bootloaderInfo.py | 884 +++++++++++++++++++++++++++++----------------------- checkbootloader.py | 85 ++++-- 2 files changed, 559 insertions(+), 410 deletions(-) diff --git a/bootloaderInfo.py b/bootloaderInfo.py index 57caaf9..3668ee8 100644 --- a/bootloaderInfo.py +++ b/bootloaderInfo.py @@ -4,8 +4,9 @@ # # Jeremy Katz # Erik Troan +# Peter Jones # -# Copyright 2002 Red Hat, Inc. +# Copyright 2005 Red Hat, Inc. # # This software may be freely redistributed under the terms of the GNU # library public license. @@ -76,10 +77,10 @@ class BootyNoKernelWarning: class KernelArguments: def get(self): - return self.args + return self.args def set(self, args): - self.args = args + self.args = args def chandevget(self): return self.cargs @@ -135,13 +136,13 @@ class KernelArguments: class BootImages: # returns dictionary of (label, longlabel, devtype) pairs indexed by device def getImages(self): - # return a copy so users can modify it w/o affecting us + # return a copy so users can modify it w/o affecting us - dict = {} - for key in self.images.keys(): - dict[key] = self.images[key] + dict = {} + for key in self.images.keys(): + dict[key] = self.images[key] - return dict + return dict def setImageLabel(self, dev, label, setLong = 0): if setLong: @@ -154,25 +155,25 @@ class BootImages: # default is a device def setDefault(self, default): - self.default = default + self.default = default def getDefault(self): - return self.default + return self.default # XXX this has internal anaconda-ish knowledge. ick def setup(self, diskSet, fsset): - devices = {} - devs = self.availableBootDevices(diskSet, fsset) - for (dev, type) in devs: - devices[dev] = 1 - - # These partitions have disappeared - for dev in self.images.keys(): - if not devices.has_key(dev): del self.images[dev] - - # These have appeared - for (dev, type) in devs: - if not self.images.has_key(dev): + devices = {} + devs = self.availableBootDevices(diskSet, fsset) + for (dev, type) in devs: + devices[dev] = 1 + + # These partitions have disappeared + for dev in self.images.keys(): + if not devices.has_key(dev): del self.images[dev] + + # These have appeared + for (dev, type) in devs: + if not self.images.has_key(dev): if type in dosFilesystems: self.images[dev] = ("Other", "Other", type) elif type in ("hfs", "hfs+") and butil.getPPCMachine() == "PMac": @@ -181,12 +182,12 @@ class BootImages: self.images[dev] = (None, None, type) - if not self.images.has_key(self.default): - entry = fsset.getEntryByMountPoint('/') - self.default = entry.device.getDevice() - (label, longlabel, type) = self.images[self.default] - if not label: - self.images[self.default] = ("linux", + if not self.images.has_key(self.default): + entry = fsset.getEntryByMountPoint('/') + self.default = entry.device.getDevice() + (label, longlabel, type) = self.images[self.default] + if not label: + self.images[self.default] = ("linux", butil.getProductName(), type) # XXX more internal anaconda knowledge @@ -208,7 +209,7 @@ class BootImages: devs.append((dev, type)) foundDos = 1 except Exception, e: - log("exception checking %s: %s" %(dev, e)) + #log("exception checking %s: %s" %(dev, e)) pass elif ((type == 'ntfs' or type =='hpfs') and not foundDos and doesDualBoot()): @@ -222,7 +223,7 @@ class BootImages: part = partedUtils.get_partition_by_name(diskSet.disks, dev) if partedUtils.get_flags(part) != "boot": - devs.append((dev, type)) + devs.append((dev, type)) slash = fsset.getEntryByMountPoint('/') if not slash or not slash.device or not slash.fsystem: @@ -237,16 +238,16 @@ class BootImages: def __init__(self): - self.default = None - self.images = {} + self.default = None + self.images = {} class bootloaderInfo: def setUseGrub(self, val): - pass + pass def useGrub(self): - return self.useGrubVal + return self.useGrubVal def setForceLBA(self, val): pass @@ -276,62 +277,62 @@ class bootloaderInfo: # dictionary of mounted filesystems since that's what we care about def getBootloaderConfig(self, instRoot, fsset, bl, langs, kernelList, chainList, defaultDev): - images = bl.images.getImages() + images = bl.images.getImages() # on upgrade read in the lilo config file - lilo = LiloConfigFile () - self.perms = 0600 + lilo = LiloConfigFile () + self.perms = 0600 if os.access (instRoot + self.configfile, os.R_OK): - self.perms = os.stat(instRoot + self.configfile)[0] & 0777 - lilo.read (instRoot + self.configfile) - os.rename(instRoot + self.configfile, - instRoot + self.configfile + '.rpmsave') + self.perms = os.stat(instRoot + self.configfile)[0] & 0777 + lilo.read (instRoot + self.configfile) + os.rename(instRoot + self.configfile, + instRoot + self.configfile + '.rpmsave') # if it's an absolute symlink, just get it out of our way elif (os.path.islink(instRoot + self.configfile) and os.readlink(instRoot + self.configfile)[0] == '/'): os.rename(instRoot + self.configfile, instRoot + self.configfile + '.rpmsave') - # Remove any invalid entries that are in the file; we probably - # just removed those kernels. - for label in lilo.listImages(): - (fsType, sl, path, other) = lilo.getImage(label) - if fsType == "other": continue + # Remove any invalid entries that are in the file; we probably + # just removed those kernels. + for label in lilo.listImages(): + (fsType, sl, path, other) = lilo.getImage(label) + if fsType == "other": continue - if not os.access(instRoot + sl.getPath(), os.R_OK): - lilo.delImage(label) + if not os.access(instRoot + sl.getPath(), os.R_OK): + lilo.delImage(label) - lilo.addEntry("prompt", replace = 0) - lilo.addEntry("timeout", "20", replace = 0) + lilo.addEntry("prompt", replace = 0) + lilo.addEntry("timeout", "20", replace = 0) rootDev = fsset.getEntryByMountPoint("/").device.getDevice() - if not rootDev: + if not rootDev: raise RuntimeError, "Installing lilo, but there is no root device" - if rootDev == defaultDev: - lilo.addEntry("default", kernelList[0][0]) - else: - lilo.addEntry("default", chainList[0][0]) + if rootDev == defaultDev: + lilo.addEntry("default", kernelList[0][0]) + else: + lilo.addEntry("default", chainList[0][0]) - for (label, longlabel, version) in kernelList: - kernelTag = "-" + version - kernelFile = self.kernelLocation + "vmlinuz" + kernelTag + for (label, longlabel, version) in kernelList: + kernelTag = "-" + version + kernelFile = self.kernelLocation + "vmlinuz" + kernelTag - try: - lilo.delImage(label) - except IndexError, msg: - pass + try: + lilo.delImage(label) + except IndexError, msg: + pass - sl = LiloConfigFile(imageType = "image", path = kernelFile) + sl = LiloConfigFile(imageType = "image", path = kernelFile) - initrd = booty.makeInitrd (kernelTag, instRoot) + initrd = booty.makeInitrd (kernelTag, instRoot) - sl.addEntry("label", label) - if os.access (instRoot + initrd, os.R_OK): - sl.addEntry("initrd", "%sinitrd%s.img" %(self.kernelLocation, + sl.addEntry("label", label) + if os.access (instRoot + initrd, os.R_OK): + sl.addEntry("initrd", "%sinitrd%s.img" %(self.kernelLocation, kernelTag)) - sl.addEntry("read-only") + sl.addEntry("read-only") append = "%s" %(self.args.get(),) realroot = getRootDevName(initrd, fsset, rootDev, instRoot) @@ -343,57 +344,57 @@ class bootloaderInfo: else: append = "root=%s" %(realroot,) - if len(append) > 0: - sl.addEntry('append', '"%s"' % (append,)) - - lilo.addImage (sl) + if len(append) > 0: + sl.addEntry('append', '"%s"' % (append,)) - for (label, longlabel, device) in chainList: + lilo.addImage (sl) + + for (label, longlabel, device) in chainList: if ((not label) or (label == "")): continue - try: - (fsType, sl, path, other) = lilo.getImage(label) - lilo.delImage(label) - except IndexError: - sl = LiloConfigFile(imageType = "other", + try: + (fsType, sl, path, other) = lilo.getImage(label) + lilo.delImage(label) + except IndexError: + sl = LiloConfigFile(imageType = "other", path = "/dev/%s" %(device)) - sl.addEntry("optional") - - sl.addEntry("label", label) - lilo.addImage (sl) - - # Sanity check #1. There could be aliases in sections which conflict - # with the new images we just created. If so, erase those aliases - imageNames = {} - for label in lilo.listImages(): - imageNames[label] = 1 - - for label in lilo.listImages(): - (fsType, sl, path, other) = lilo.getImage(label) - if sl.testEntry('alias'): - alias = sl.getEntry('alias') - if imageNames.has_key(alias): - sl.delEntry('alias') - imageNames[alias] = 1 - - # Sanity check #2. If single-key is turned on, go through all of - # the image names (including aliases) (we just built the list) and - # see if single-key will still work. - if lilo.testEntry('single-key'): - singleKeys = {} - turnOff = 0 - for label in imageNames.keys(): - l = label[0] - if singleKeys.has_key(l): - turnOff = 1 - singleKeys[l] = 1 - if turnOff: - lilo.delEntry('single-key') + sl.addEntry("optional") + + sl.addEntry("label", label) + lilo.addImage (sl) + + # Sanity check #1. There could be aliases in sections which conflict + # with the new images we just created. If so, erase those aliases + imageNames = {} + for label in lilo.listImages(): + imageNames[label] = 1 + + for label in lilo.listImages(): + (fsType, sl, path, other) = lilo.getImage(label) + if sl.testEntry('alias'): + alias = sl.getEntry('alias') + if imageNames.has_key(alias): + sl.delEntry('alias') + imageNames[alias] = 1 + + # Sanity check #2. If single-key is turned on, go through all of + # the image names (including aliases) (we just built the list) and + # see if single-key will still work. + if lilo.testEntry('single-key'): + singleKeys = {} + turnOff = 0 + for label in imageNames.keys(): + l = label[0] + if singleKeys.has_key(l): + turnOff = 1 + singleKeys[l] = 1 + if turnOff: + lilo.delEntry('single-key') return lilo def write(self, instRoot, fsset, bl, langs, kernelList, chainList, - defaultDev, justConfig, intf = None): + defaultDev, justConfig, intf = None): if len(kernelList) >= 1: config = self.getBootloaderConfig(instRoot, fsset, bl, langs, kernelList, chainList, @@ -419,6 +420,7 @@ class bootloaderInfo: return args args.append("--location=%s" % (self.defaultDevice,)) + args.append("--driveorder=%s" % (",".join(self.drivelist))) if self.args.get(): args.append("--append=\"%s\"" %(self.args.get())) @@ -437,7 +439,7 @@ class bootloaderInfo: import isys import flags drives = isys.hardDriveDict().keys() - drives.sort (isys.compareDrives) + drives.sort(isys.compareDrives) # now filter out all of the removable media unless expert mode rc = [] @@ -447,16 +449,16 @@ class bootloaderInfo: return rc def __init__(self): - self.args = KernelArguments() - self.images = BootImages() - self.device = None + self.args = KernelArguments() + self.images = BootImages() + self.device = None self.useLinear = 1 # only used for kickstart compatibility self.defaultDevice = None # XXX hack, used by kickstart self.useGrubVal = 0 # only used on x86 self.configfile = None self.kernelLocation = "/boot/" self.forceLBA32 = 0 - self.password = None + self.password = None self.pure = None self.above1024 = 0 @@ -559,12 +561,12 @@ class ia64BootloaderInfo(bootloaderInfo): chainList, defaultDev, justConfig): config = self.getBootloaderConfig(instRoot, fsset, bl, langs, kernelList, chainList, defaultDev) - config.write(instRoot + self.configfile, perms = self.perms) + config.write(instRoot + self.configfile, perms = self.perms) - return "" + return "" def write(self, instRoot, fsset, bl, langs, kernelList, chainList, - defaultDev, justConfig, intf): + defaultDev, justConfig, intf): if len(kernelList) >= 1: str = self.writeLilo(instRoot, fsset, bl, langs, kernelList, chainList, defaultDev, justConfig) @@ -603,11 +605,11 @@ class ia64BootloaderInfo(bootloaderInfo): def __init__(self): bootloaderInfo.__init__(self) - self.useGrubVal = 1 + self.useGrubVal = 1 self.kernelLocation = "" self.configfile = "/boot/efi/EFI/redhat/elilo.conf" - + class x86BootloaderInfo(bootloaderInfo): def setPassword(self, val, isCrypted = 1): if not val: @@ -616,7 +618,7 @@ class x86BootloaderInfo(bootloaderInfo): return if isCrypted and self.useGrubVal == 0: - log("requested crypted password with lilo; ignoring") + #log("requested crypted password with lilo; ignoring") self.pure = None return elif isCrypted: @@ -626,9 +628,9 @@ class x86BootloaderInfo(bootloaderInfo): salt = "$1$" saltLen = 8 - for i in range(saltLen): + for i in range(saltLen): salt = salt + whrandom.choice (string.letters + - string.digits + './') + string.digits + './') self.password = crypt.crypt (val, salt) self.pure = val @@ -640,14 +642,36 @@ class x86BootloaderInfo(bootloaderInfo): self.forceLBA32 = val def setUseGrub(self, val): - self.useGrubVal = val + self.useGrubVal = val + + def getPhysicalDevices(self, device): + # This finds a list of devices on which the given device name resides. + # Accepted values for "device" are raid1 md devices (i.e. "md0"), + # physical disks ("hda"), and real partitions on physical disks + # ("hda1"). Volume groups/logical volumes are not accepted. + # + # XXX this has internal anaconda-ish knowledge. ick. + import isys + import lvm + + if string.split(device, '/', 1)[0] in map (lambda vg: vg[0], + lvm.vglist()): + return [] + + if device.startswith('md'): + bootable = 0 + parts = checkbootloader.getRaidDisks(device, 1, stripPart=0) + parts.sort() + return parts + + return [device] def writeGrub(self, instRoot, fsset, bl, langs, kernelList, chainList, - defaultDev, justConfigFile): + defaultDev, justConfigFile): if len(kernelList) < 1: return "" - images = bl.images.getImages() + images = bl.images.getImages() rootDev = fsset.getEntryByMountPoint("/").device.getDevice() if not os.path.isdir(instRoot + '/boot/grub/'): @@ -655,46 +679,54 @@ class x86BootloaderInfo(bootloaderInfo): # XXX old config file should be read here for upgrade - cf = '/boot/grub/grub.conf' - self.perms = 0600 + cf = '/boot/grub/grub.conf' + self.perms = 0600 if os.access (instRoot + cf, os.R_OK): - self.perms = os.stat(instRoot + cf)[0] & 0777 - os.rename(instRoot + cf, - instRoot + cf + '.rpmsave') + self.perms = os.stat(instRoot + cf)[0] & 0777 + os.rename(instRoot + cf, + instRoot + cf + '.rpmsave') grubTarget = bl.getDevice() - # XXX wouldn't it be nice if grub really understood raid? :) - if grubTarget.startswith('md'): - ent = fsset.getEntryByDeviceName(grubTarget) - grubTarget = ent.device.members[0] - - f = open(instRoot + cf, "w+") + target = "mbr" + if (grubTarget.startswith('rd/') or grubTarget.startswith('ida/') or + grubTarget.startswith('cciss/') or + grubTarget.startswith('sx8/') or + grubTarget.startswith('mapper/')): + if grubTarget[-1].isdigit(): + if grubTarget[-2] == 'p' or \ + (grubTarget[-2].isdigit() and grubTarget[-3] == 'p'): + target = "partition" + elif grubTarget[-1].isdigit() and not grubTarget.startswith('md'): + target = "partition" + + f = open(instRoot + cf, "w+") f.write("# grub.conf generated by anaconda\n") f.write("#\n") f.write("# Note that you do not have to rerun grub " "after making changes to this file\n") - bootDev = fsset.getEntryByMountPoint("/boot") - grubPath = "/grub" - cfPath = "/" - if not bootDev: - bootDev = fsset.getEntryByMountPoint("/") - grubPath = "/boot/grub" - cfPath = "/boot/" + bootDev = fsset.getEntryByMountPoint("/boot") + grubPath = "/grub" + cfPath = "/" + if not bootDev: + bootDev = fsset.getEntryByMountPoint("/") + grubPath = "/boot/grub" + cfPath = "/boot/" f.write("# NOTICE: You do not have a /boot partition. " "This means that\n") f.write("# all kernel and initrd paths are relative " "to /, eg.\n") - else: + else: f.write("# NOTICE: You have a /boot partition. This means " "that\n") f.write("# all kernel and initrd paths are relative " "to /boot/, eg.\n") - bootDev = bootDev.device.getDevice(asBoot = 1) + bootDevs = self.getPhysicalDevices(bootDev.device.getDevice()) + bootDev = bootDev.device.getDevice() - f.write('# root %s\n' % self.grubbyPartitionName(bootDev)) + f.write('# root %s\n' % self.grubbyPartitionName(bootDevs[0])) f.write("# kernel %svmlinuz-version ro " "root=/dev/%s\n" % (cfPath, rootDev)) f.write("# initrd %sinitrd-version.img\n" % (cfPath)) @@ -741,46 +773,46 @@ class x86BootloaderInfo(bootloaderInfo): # we only want splashimage if they're not using a serial console if os.access("%s/boot/grub/splash.xpm.gz" %(instRoot,), os.R_OK): f.write('splashimage=%s%sgrub/splash.xpm.gz\n' - % (self.grubbyPartitionName(bootDev), cfPath)) + % (self.grubbyPartitionName(bootDevs[0]), cfPath)) f.write("hiddenmenu\n") - usedDevs[bootDev] = 1 - usedDevs[grubTarget] = 1 - + for dev in self.getPhysicalDevices(grubTarget): + usedDevs[dev] = 1 + if self.password: f.write('password --md5 %s\n' %(self.password)) - for (label, longlabel, version) in kernelList: - kernelTag = "-" + version - kernelFile = "%svmlinuz%s" % (cfPath, kernelTag) + for (label, longlabel, version) in kernelList: + kernelTag = "-" + version + kernelFile = "%svmlinuz%s" % (cfPath, kernelTag) - initrd = booty.makeInitrd (kernelTag, instRoot) + initrd = booty.makeInitrd (kernelTag, instRoot) - f.write('title %s (%s)\n' % (longlabel, version)) - f.write('\troot %s\n' % self.grubbyPartitionName(bootDev)) + f.write('title %s (%s)\n' % (longlabel, version)) + f.write('\troot %s\n' % self.grubbyPartitionName(bootDevs[0])) realroot = getRootDevName(initrd, fsset, rootDev, instRoot) realroot = " root=%s" %(realroot,) f.write('\tkernel %s ro%s' % (kernelFile, realroot)) - if self.args.get(): - f.write(' %s' % self.args.get()) - f.write('\n') + if self.args.get(): + f.write(' %s' % self.args.get()) + f.write('\n') - if os.access (instRoot + initrd, os.R_OK): - f.write('\tinitrd %sinitrd%s.img\n' % (cfPath, kernelTag)) + if os.access (instRoot + initrd, os.R_OK): + f.write('\tinitrd %sinitrd%s.img\n' % (cfPath, kernelTag)) - for (label, longlabel, device) in chainList: + for (label, longlabel, device) in chainList: if ((not longlabel) or (longlabel == "")): continue - f.write('title %s\n' % (longlabel)) - f.write('\trootnoverify %s\n' % self.grubbyPartitionName(device)) + f.write('title %s\n' % (longlabel)) + f.write('\trootnoverify %s\n' % self.grubbyPartitionName(device)) # f.write('\tmakeactive\n') f.write('\tchainloader +1') - f.write('\n') + f.write('\n') usedDevs[device] = 1 - f.close() + f.close() os.chmod(instRoot + "/boot/grub/grub.conf", self.perms) try: @@ -801,32 +833,39 @@ class x86BootloaderInfo(bootloaderInfo): except: pass + for dev in self.getPhysicalDevices(rootDev) + bootDevs: + usedDevs[dev] = 1 if not os.access(instRoot + "/boot/grub/device.map", os.R_OK): f = open(instRoot + "/boot/grub/device.map", "w+") f.write("# this device map was generated by anaconda\n") - f.write("(fd0) /dev/fd0\n") devs = usedDevs.keys() - devs.sort() usedDevs = {} for dev in devs: drive = getDiskPart(dev)[0] if usedDevs.has_key(drive): continue - f.write("(%s) /dev/%s\n" % (self.grubbyDiskName(drive), - drive)) usedDevs[drive] = 1 + devs = usedDevs.keys() + devs.sort() + for drive in devs: + # XXX hack city. If they're not the sort of thing that'll + # be in the device map, they shouldn't still be in the list. + if not drive.startswith('md'): + f.write("(%s) /dev/%s\n" % (self.grubbyDiskName(drive), + drive)) f.close() - args = "--stage2=/boot/grub/stage2 " if self.forceLBA32: - args = "%s--force-lba " % (args,) + forcelba = "--force-lba " + else: + forcelba = "" sysconf = '/etc/sysconfig/grub' if os.access (instRoot + sysconf, os.R_OK): - self.perms = os.stat(instRoot + sysconf)[0] & 0777 - os.rename(instRoot + sysconf, - instRoot + sysconf + '.rpmsave') + self.perms = os.stat(instRoot + sysconf)[0] & 0777 + os.rename(instRoot + sysconf, + instRoot + sysconf + '.rpmsave') # if it's an absolute symlink, just get it out of our way elif (os.path.islink(instRoot + sysconf) and os.readlink(instRoot + sysconf)[0] == '/'): @@ -834,20 +873,33 @@ class x86BootloaderInfo(bootloaderInfo): instRoot + sysconf + '.rpmsave') f = open(instRoot + sysconf, 'w+') f.write("boot=/dev/%s\n" %(grubTarget,)) + # XXX forcelba never gets read back... if self.forceLBA32: f.write("forcelba=1\n") else: f.write("forcelba=0\n") f.close() - part = self.grubbyPartitionName(bootDev) - prefix = "%s/%s" % (self.grubbyPartitionName(bootDev), grubPath) - cmd = "root %s\ninstall %s%s/stage1 d %s %s/stage2 p %s%s/grub.conf" % \ - (part, args, grubPath, self.grubbyPartitionName(grubTarget), - grubPath, part, grubPath) + cmds = [] + for bootDev in bootDevs: + gtDisk = self.grubbyPartitionName(getDiskPart(bootDev)[0]) + bPart = self.grubbyPartitionName(bootDev) + stage1Target = gtDisk + if target == "partition": + stage1Target = self.grubbyPartitionName(bootDev) + + cmd = "root %s\nsetup %s" % (bPart, stage1Target) + cmds.append(cmd) + if not justConfigFile: - log("GRUB command %s", cmd) + #log("GRUB commands:") + #for cmd in cmds: + # log("\t%s\n", cmd) + if cfPath == "/": + syncDataToDisk(bootDev, "/boot", instRoot) + else: + syncDataToDisk(bootDev, "/", instRoot) # copy the stage files over into /boot rhpl.executil.execWithRedirect( "/sbin/grub-install", @@ -855,27 +907,29 @@ class x86BootloaderInfo(bootloaderInfo): stdout = "/dev/tty5", stderr = "/dev/tty5", root = instRoot) - - - # FIXME: hack to try to make sure everything is written to the disk - if cfPath == "/": - syncDataToDisk(bootDev, "/boot", instRoot) - else: - syncDataToDisk(bootDev, "/", instRoot) - # really install the bootloader - p = os.pipe() - os.write(p[1], cmd + '\n') - os.close(p[1]) - rhpl.executil.execWithRedirect('/sbin/grub' , - [ "grub", "--batch", "--no-floppy", + for cmd in cmds: + p = os.pipe() + os.write(p[1], cmd + '\n') + os.close(p[1]) + import time + + # FIXME: hack to try to make sure everything is written + # to the disk + if cfPath == "/": + syncDataToDisk(bootDev, "/boot", instRoot) + else: + syncDataToDisk(bootDev, "/", instRoot) + + rhpl.executil.execWithRedirect('/sbin/grub' , + [ "grub", "--batch", "--no-floppy", "--device-map=/boot/grub/device.map" ], stdin = p[0], - stdout = "/dev/tty5", stderr = "/dev/tty5", - root = instRoot) - os.close(p[0]) + stdout = "/dev/tty5", stderr = "/dev/tty5", + root = instRoot) + os.close(p[0]) - return "" + return "" def grubbyDiskName(self, name): return "hd%d" % self.drivelist.index(name) @@ -895,11 +949,11 @@ class x86BootloaderInfo(bootloaderInfo): kernelList, chainList, defaultDev) - liloTarget = bl.getDevice() + liloTarget = bl.getDevice() - config.addEntry("boot", '/dev/' + liloTarget, replace = 0) - config.addEntry("map", "/boot/map", replace = 0) - config.addEntry("install", "/boot/boot.b", replace = 0) + config.addEntry("boot", '/dev/' + liloTarget, replace = 0) + config.addEntry("map", "/boot/map", replace = 0) + config.addEntry("install", "/boot/boot.b", replace = 0) message = "/boot/message" if self.pure is not None and not self.useGrubVal: @@ -1013,7 +1067,6 @@ class x86BootloaderInfo(bootloaderInfo): f.close() for line in lines: if line.startswith(stanza): - import checkbootloader theDev = checkbootloader.getBootDevString(line) break if theDev is not None: @@ -1028,6 +1081,7 @@ class x86BootloaderInfo(bootloaderInfo): if not os.access(instRoot + sysconf, os.R_OK): f = open(instRoot + sysconf, "w+") f.write("boot=%s\n" %(theDev,)) + # XXX forcelba never gets read back at all... if self.forceLBA32: f.write("forcelba=1\n") else: @@ -1037,54 +1091,77 @@ class x86BootloaderInfo(bootloaderInfo): # more suckage. grub-install can't work without a valid /etc/mtab # so we have to do shenanigans to get updated grub installed... # steal some more code above - bootDev = fsset.getEntryByMountPoint("/boot") - grubPath = "/grub" - cfPath = "/" - if not bootDev: - bootDev = fsset.getEntryByMountPoint("/") - grubPath = "/boot/grub" - cfPath = "/boot/" - bootDev = bootDev.device.getDevice(asBoot = 1) + bootDev = fsset.getEntryByMountPoint("/boot") + grubPath = "/grub" + cfPath = "/" + if not bootDev: + bootDev = fsset.getEntryByMountPoint("/") + grubPath = "/boot/grub" + cfPath = "/boot/" + + masterBootDev = bootDev.device.getDevice(asBoot = 0) + if masterBootDev[0:2] == 'md': + rootDevs = checkbootloader.getRaidDisks(masterBootDev, raidLevel=1, + stripPart = 0) + else: + rootDevs = [masterBootDev] + + if theDev[5:7] == 'md': + stage1Devs = checkbootloader.getRaidDisks(theDev[5:], raidLevel=1) + else: + stage1Devs = [theDev[5:]] - part = self.grubbyPartitionName(bootDev) - prefix = "%s/%s" % (self.grubbyPartitionName(bootDev), grubPath) - args = "--stage2=/boot/grub/stage2 " - cmd = "root %s\ninstall %s%s/stage1 d %s %s/stage2 p %s%s/grub.conf" % \ - (part, args, grubPath, self.grubbyPartitionName(theDev[5:]), - grubPath, part, grubPath) + for stage1Dev in stage1Devs: + # cross fingers; if we can't find a root device on the same + # hardware as this boot device, we just blindly hope the first + # thing in the list works. + + grubbyStage1Dev = self.grubbyPartitionName(stage1Dev) + + grubbyRootPart = self.grubbyPartitionName(rootDevs[0]) + + for rootDev in rootDevs: + testGrubbyRootDev = getDiskPart(rootDev)[0] + testGrubbyRootDev = self.grubbyPartitionName(testGrubbyRootDev) + + if grubbyStage1Dev == testGrubbyRootDev: + grubbyRootPart = self.grubbyPartitionName(rootDev) + break + + cmd = "root %s\nsetup %s" % (grubbyRootPart, grubbyStage1Dev) - if not justConfigFile: - log("GRUB command %s", cmd) + if not justConfigFile: + #log("GRUB command %s", cmd) - # copy the stage files over into /boot - rhpl.executil.execWithRedirect( "/sbin/grub-install", + # copy the stage files over into /boot + rhpl.executil.execWithRedirect( "/sbin/grub-install", ["/sbin/grub-install", "--just-copy"], stdout = "/dev/tty5", stderr = "/dev/tty5", root = instRoot) - # get the stage files synced to disk - import isys - isys.sync() - isys.sync() - isys.sync() + # get the stage files synced to disk + import isys + isys.sync() + isys.sync() + isys.sync() - # really install the bootloader - p = os.pipe() - os.write(p[1], cmd + '\n') - os.close(p[1]) - rhpl.executil.execWithRedirect('/sbin/grub' , + # really install the bootloader + p = os.pipe() + os.write(p[1], cmd + '\n') + os.close(p[1]) + rhpl.executil.execWithRedirect('/sbin/grub' , [ "grub", "--batch", "--no-floppy", "--device-map=/boot/grub/device.map" ], stdin = p[0], stdout = "/dev/tty5", stderr = "/dev/tty5", root = instRoot) - os.close(p[0]) - - return "" + os.close(p[0]) + + return "" def write(self, instRoot, fsset, bl, langs, kernelList, chainList, - defaultDev, justConfig, intf): + defaultDev, justConfig, intf): # XXX HACK ALERT - see declaration above if self.doUpgradeOnly: if not self.useGrubVal: @@ -1098,7 +1175,7 @@ class x86BootloaderInfo(bootloaderInfo): # and the hacks continue. with 2.6, ide-scsi isn't used # anymore (#116622) - import isys + import isys cdrw = isys.ideCdRwList() torem = [] for device in cdrw: @@ -1154,7 +1231,7 @@ class x86BootloaderInfo(bootloaderInfo): def __init__(self): bootloaderInfo.__init__(self) # XXX use checkbootloader to determine what to default to - self.useGrubVal = 1 + self.useGrubVal = 1 self.kernelLocation = "/boot/" self.configfile = "/etc/lilo.conf" self.password = None @@ -1163,170 +1240,170 @@ class x86BootloaderInfo(bootloaderInfo): class s390BootloaderInfo(bootloaderInfo): def getBootloaderConfig(self, instRoot, fsset, bl, langs, kernelList, chainList, defaultDev): - images = bl.images.getImages() + images = bl.images.getImages() # on upgrade read in the lilo config file - lilo = LiloConfigFile () - self.perms = 0600 + lilo = LiloConfigFile () + self.perms = 0600 if os.access (instRoot + self.configfile, os.R_OK): - self.perms = os.stat(instRoot + self.configfile)[0] & 0777 - lilo.read (instRoot + self.configfile) - os.rename(instRoot + self.configfile, - instRoot + self.configfile + '.rpmsave') + self.perms = os.stat(instRoot + self.configfile)[0] & 0777 + lilo.read (instRoot + self.configfile) + os.rename(instRoot + self.configfile, + instRoot + self.configfile + '.rpmsave') - # Remove any invalid entries that are in the file; we probably - # just removed those kernels. - for label in lilo.listImages(): - (fsType, sl, path, other) = lilo.getImage(label) - if fsType == "other": continue + # Remove any invalid entries that are in the file; we probably + # just removed those kernels. + for label in lilo.listImages(): + (fsType, sl, path, other) = lilo.getImage(label) + if fsType == "other": continue - if not os.access(instRoot + sl.getPath(), os.R_OK): - lilo.delImage(label) + if not os.access(instRoot + sl.getPath(), os.R_OK): + lilo.delImage(label) rootDev = fsset.getEntryByMountPoint("/").device.getDevice() - if not rootDev: + if not rootDev: raise RuntimeError, "Installing zipl, but there is no root device" - if rootDev == defaultDev: - lilo.addEntry("default", kernelList[0][0]) - else: - lilo.addEntry("default", chainList[0][0]) + if rootDev == defaultDev: + lilo.addEntry("default", kernelList[0][0]) + else: + lilo.addEntry("default", chainList[0][0]) - for (label, longlabel, version) in kernelList: - kernelTag = "-" + version - kernelFile = self.kernelLocation + "vmlinuz" + kernelTag + for (label, longlabel, version) in kernelList: + kernelTag = "-" + version + kernelFile = self.kernelLocation + "vmlinuz" + kernelTag - try: - lilo.delImage(label) - except IndexError, msg: - pass + try: + lilo.delImage(label) + except IndexError, msg: + pass - sl = LiloConfigFile(imageType = "image", path = kernelFile) + sl = LiloConfigFile(imageType = "image", path = kernelFile) - initrd = booty.makeInitrd (kernelTag, instRoot) + initrd = booty.makeInitrd (kernelTag, instRoot) - sl.addEntry("label", label) - if os.access (instRoot + initrd, os.R_OK): - sl.addEntry("initrd", + sl.addEntry("label", label) + if os.access (instRoot + initrd, os.R_OK): + sl.addEntry("initrd", "%sinitrd%s.img" %(self.kernelLocation, kernelTag)) - sl.addEntry("read-only") - sl.addEntry("root", '/dev/' + rootDev) + sl.addEntry("read-only") + sl.addEntry("root", '/dev/' + rootDev) sl.addEntry("ipldevice", '/dev/' + rootDev[:-1]) - if self.args.get(): - sl.addEntry('append', '"%s"' % self.args.get()) - - lilo.addImage (sl) + if self.args.get(): + sl.addEntry('append', '"%s"' % self.args.get()) + + lilo.addImage (sl) - for (label, longlabel, device) in chainList: + for (label, longlabel, device) in chainList: if ((not label) or (label == "")): continue - try: - (fsType, sl, path, other) = lilo.getImage(label) - lilo.delImage(label) - except IndexError: - sl = LiloConfigFile(imageType = "other", + try: + (fsType, sl, path, other) = lilo.getImage(label) + lilo.delImage(label) + except IndexError: + sl = LiloConfigFile(imageType = "other", path = "/dev/%s" %(device)) - sl.addEntry("optional") - - sl.addEntry("label", label) - lilo.addImage (sl) - - # Sanity check #1. There could be aliases in sections which conflict - # with the new images we just created. If so, erase those aliases - imageNames = {} - for label in lilo.listImages(): - imageNames[label] = 1 - - for label in lilo.listImages(): - (fsType, sl, path, other) = lilo.getImage(label) - if sl.testEntry('alias'): - alias = sl.getEntry('alias') - if imageNames.has_key(alias): - sl.delEntry('alias') - imageNames[alias] = 1 - - # Sanity check #2. If single-key is turned on, go through all of - # the image names (including aliases) (we just built the list) and - # see if single-key will still work. - if lilo.testEntry('single-key'): - singleKeys = {} - turnOff = 0 - for label in imageNames.keys(): - l = label[0] - if singleKeys.has_key(l): - turnOff = 1 - singleKeys[l] = 1 - if turnOff: - lilo.delEntry('single-key') + sl.addEntry("optional") + + sl.addEntry("label", label) + lilo.addImage (sl) + + # Sanity check #1. There could be aliases in sections which conflict + # with the new images we just created. If so, erase those aliases + imageNames = {} + for label in lilo.listImages(): + imageNames[label] = 1 + + for label in lilo.listImages(): + (fsType, sl, path, other) = lilo.getImage(label) + if sl.testEntry('alias'): + alias = sl.getEntry('alias') + if imageNames.has_key(alias): + sl.delEntry('alias') + imageNames[alias] = 1 + + # Sanity check #2. If single-key is turned on, go through all of + # the image names (including aliases) (we just built the list) and + # see if single-key will still work. + if lilo.testEntry('single-key'): + singleKeys = {} + turnOff = 0 + for label in imageNames.keys(): + l = label[0] + if singleKeys.has_key(l): + turnOff = 1 + singleKeys[l] = 1 + if turnOff: + lilo.delEntry('single-key') return lilo def writeChandevConf(self, bl, instroot): # S/390 only - cf = "/etc/chandev.conf" - self.perms = 0644 + cf = "/etc/chandev.conf" + self.perms = 0644 if bl.args.chandevget(): - fd = os.open(instroot + "/etc/chandev.conf", + fd = os.open(instroot + "/etc/chandev.conf", os.O_WRONLY | os.O_CREAT) os.write(fd, "noauto\n") - for cdev in bl.args.chandevget(): - os.write(fd,'%s\n' % cdev) - os.close(fd) - return "" - + for cdev in bl.args.chandevget(): + os.write(fd,'%s\n' % cdev) + os.close(fd) + return "" + def writeZipl(self, instRoot, fsset, bl, langs, kernelList, chainList, - defaultDev, justConfigFile): - images = bl.images.getImages() + defaultDev, justConfigFile): + images = bl.images.getImages() rootDev = fsset.getEntryByMountPoint("/").device.getDevice() - cf = '/etc/zipl.conf' - self.perms = 0600 + cf = '/etc/zipl.conf' + self.perms = 0600 if os.access (instRoot + cf, os.R_OK): - self.perms = os.stat(instRoot + cf)[0] & 0777 - os.rename(instRoot + cf, - instRoot + cf + '.rpmsave') + self.perms = os.stat(instRoot + cf)[0] & 0777 + os.rename(instRoot + cf, + instRoot + cf + '.rpmsave') - f = open(instRoot + cf, "w+") + f = open(instRoot + cf, "w+") - f.write('[defaultboot]\n') - f.write('default=' + kernelList[0][0] + '\n') - f.write('target=%s\n' % (self.kernelLocation)) + f.write('[defaultboot]\n') + f.write('default=' + kernelList[0][0] + '\n') + f.write('target=%s\n' % (self.kernelLocation)) cfPath = "/boot/" - for (label, longlabel, version) in kernelList: - kernelTag = "-" + version - kernelFile = "%svmlinuz%s" % (cfPath, kernelTag) - - initrd = booty.makeInitrd (kernelTag, instRoot) - f.write('[%s]\n' % (label)) - f.write('\timage=%s\n' % (kernelFile)) - if os.access (instRoot + initrd, os.R_OK): - f.write('\tramdisk=%sinitrd%s.img\n' %(self.kernelLocation, + for (label, longlabel, version) in kernelList: + kernelTag = "-" + version + kernelFile = "%svmlinuz%s" % (cfPath, kernelTag) + + initrd = booty.makeInitrd (kernelTag, instRoot) + f.write('[%s]\n' % (label)) + f.write('\timage=%s\n' % (kernelFile)) + if os.access (instRoot + initrd, os.R_OK): + f.write('\tramdisk=%sinitrd%s.img\n' %(self.kernelLocation, kernelTag)) realroot = getRootDevName(initrd, fsset, rootDev, instRoot) - f.write('\tparameters="root=%s' %(realroot,)) - if bl.args.get(): - f.write(' %s' % (bl.args.get())) - f.write('"\n') + f.write('\tparameters="root=%s' %(realroot,)) + if bl.args.get(): + f.write(' %s' % (bl.args.get())) + f.write('"\n') - f.close() + f.close() - if not justConfigFile: + if not justConfigFile: argv = [ "/sbin/zipl" ] rhpl.executil.execWithRedirect(argv[0], argv, root = instRoot, stdout = "/dev/stdout", stderr = "/dev/stderr") - return "" + return "" def write(self, instRoot, fsset, bl, langs, kernelList, chainList, - defaultDev, justConfig, intf): + defaultDev, justConfig, intf): str = self.writeZipl(instRoot, fsset, bl, langs, kernelList, chainList, defaultDev, justConfig | (not self.useZiplVal)) - str = self.writeChandevConf(bl, instRoot) + str = self.writeChandevConf(bl, instRoot) def __init__(self): bootloaderInfo.__init__(self) @@ -1424,7 +1501,7 @@ class alphaBootloaderInfo(bootloaderInfo): # We get all the kernels we need to know about in kernelList. for (kernel, tag, kernelTag) in kernelList: - kernelFile = "%svmlinuz-%s" %(kernelPath, kernelTag) + kernelFile = "%svmlinuz-%s" %(kernelPath, kernelTag) f.write("%d:%d%s" %(lines, bpn, kernelFile)) @@ -1458,7 +1535,7 @@ class alphaBootloaderInfo(bootloaderInfo): # to and the second argument is a path to the bootstrap loader # file. args = ("swriteboot", ("/dev/%s" % wbd), "/boot/bootlx") - log("swriteboot command: %s" %(args,)) + #log("swriteboot command: %s" %(args,)) rhpl.executil.execWithRedirect ('/sbin/swriteboot', args, root = instRoot, stdout = "/dev/tty5", @@ -1470,7 +1547,7 @@ class alphaBootloaderInfo(bootloaderInfo): # It's always the boot partition whether it's / or /boot (with # the mount point being omitted.) args = ("abootconf", ("/dev/%s" % wbd), str (bdpn)) - log("abootconf command: %s" %(args,)) + #log("abootconf command: %s" %(args,)) rhpl.executil.execWithRedirect ('/sbin/abootconf', args, root = instRoot, stdout = "/dev/tty5", @@ -1478,7 +1555,7 @@ class alphaBootloaderInfo(bootloaderInfo): def write(self, instRoot, fsset, bl, langs, kernelList, chainList, - defaultDev, justConfig, intf): + defaultDev, justConfig, intf): if len(kernelList) < 1: self.noKernelsWarn(intf) @@ -1495,7 +1572,7 @@ class alphaBootloaderInfo(bootloaderInfo): def __init__(self): bootloaderInfo.__init__(self) - self.useGrubVal = 0 + self.useGrubVal = 0 self.configfile = "/etc/aboot.conf" # self.kernelLocation is already set to what we need. self.password = None @@ -1526,10 +1603,11 @@ class ppcBootloaderInfo(bootloaderInfo): return devs + def writeYaboot(self, instRoot, fsset, bl, langs, kernelList, chainList, defaultDev, justConfigFile): - from flags import flags + from flags import flags yabootTarget = string.join(self.getBootDevs(fsset, bl)) @@ -1554,26 +1632,49 @@ class ppcBootloaderInfo(bootloaderInfo): %(butil.getProductName(),)) (name, partNum) = getDiskPart(bootDev) - partno = partNum + 1 # 1 based + if rhpl.getPPCMachine() == "Pegasos": + partno = partNum # Pegasos firmware is broken + else: + partno = partNum + 1 # 1 based f.write("partition=%s\n" %(partno,)) - f.write("timeout=20\n") + f.write("timeout=80\n") f.write("install=/usr/lib/yaboot/yaboot\n") f.write("delay=5\n") - - if butil.getPPCMachine() == "PMac": + f.write("enablecdboot\n") + f.write("enableofboot\n") + f.write("enablenetboot\n") + + yabootProg = "/sbin/mkofboot" + if rhpl.getPPCMachine() == "PMac": + # write out the first hfs/hfs+ partition as being macosx + for (label, longlabel, device) in chainList: + if ((not label) or (label == "")): + continue + f.write("macosx=/dev/%s\n" %(device,)) + break + f.write("magicboot=/usr/lib/yaboot/ofboot\n") - if butil.getPPCMachine() == "pSeries": + if rhpl.getPPCMachine() == "pSeries": f.write("nonvram\n") + f.write("fstype=raw\n") + + if rhpl.getPPCMachine() == "Pegasos": + f.write("nonvram\n") + f.write("mntpoint=/boot/yaboot\n") + f.write("usemount\n") + if not os.access(instRoot + "/boot/yaboot", os.R_OK): + os.mkdir(instRoot + "/boot/yaboot") + yabootProg = "/sbin/ybin" if self.password: f.write("password=%s\n" %(self.password,)) f.write("restricted\n") - + f.write("\n") - rootDev = fsset.getEntryByMountPoint("/").device.getDevice() + rootDev = fsset.getEntryByMountPoint("/").device.getDevice() for (label, longlabel, version) in kernelList: kernelTag = "-" + version @@ -1611,14 +1712,11 @@ class ppcBootloaderInfo(bootloaderInfo): isys.sync() isys.sync() - ybinargs = [ "/sbin/mkofboot", "-f", "-C", cf ] - if butil.getPPCMachine() == "pSeries": - ybinargs.extend(["--filesystem", "raw"]) + ybinargs = [ yabootProg, "-f", "-C", cf ] - - log("running: %s" %(ybinargs,)) - if not flags.test: - rhpl.executil.execWithRedirect(ybinargs[0], + #log("running: %s" %(ybinargs,)) + if not flags.test: + rhpl.executil.execWithRedirect(ybinargs[0], ybinargs, stdout = "/dev/tty5", stderr = "/dev/tty5", @@ -1629,7 +1727,7 @@ class ppcBootloaderInfo(bootloaderInfo): os.symlink("../boot/etc/yaboot.conf", instRoot + "/etc/yaboot.conf") - return "" + return "" def setPassword(self, val, isCrypted = 1): # yaboot just handles the password and doesn't care if its crypted @@ -1637,7 +1735,7 @@ class ppcBootloaderInfo(bootloaderInfo): self.password = val def write(self, instRoot, fsset, bl, langs, kernelList, chainList, - defaultDev, justConfig, intf): + defaultDev, justConfig, intf): if len(kernelList) >= 1: str = self.writeYaboot(instRoot, fsset, bl, langs, kernelList, chainList, defaultDev, justConfig) @@ -1673,10 +1771,10 @@ class iseriesBootloaderInfo(bootloaderInfo): if len(kernelList) < 1: self.noKernelsWarn(intf) return - if len(kernelList) > 1: - # FIXME: how can this happen? - log("more than one kernel on iSeries. bailing and just using " - "the first") + #if len(kernelList) > 1: + # # FIXME: how can this happen? + # log("more than one kernel on iSeries. bailing and just using " + # "the first") # iseries is Weird (tm) -- here's the basic theory # a) have /boot/vmlinitrd-$(version) @@ -1709,23 +1807,24 @@ class iseriesBootloaderInfo(bootloaderInfo): # OS/400 will load as NWSSTG bootDev = bl.getDevice() if bootDev: - log("Writing kernel %s to PReP partition %s" %(kernelFile, - bootDev)) + #log("Writing kernel %s to PReP partition %s" %(kernelFile, bootDev)) try: self.ddFile(instRoot + kernelFile, "%s/dev/%s" %(instRoot, bootDev)) except Exception, e: # FIXME: should this be more fatal - log("Failed to write kernel: %s" %(e,)) + #log("Failed to write kernel: %s" %(e,)) + pass else: - log("No PReP boot partition, not writing kernel for NWSSTG") + #log("No PReP boot partition, not writing kernel for NWSSTG") + pass # now, it's a lot faster to boot if we don't make people go back # into OS/400, so set up side C (used by default for NWSSTG) with # our current bits for side in ("C", "B"): - log("Writing kernel and cmdline to side %s" %(side,)) + #log("Writing kernel and cmdline to side %s" %(side,)) wrotekernel = 0 try: self.ddFile(instRoot + kernelFile, @@ -1733,7 +1832,8 @@ class iseriesBootloaderInfo(bootloaderInfo): wrotekernel = 1 except Exception, e: # FIXME: should this be more fatal? - log("Failed to write kernel to side %s: %s" %(side, e)) + #log("Failed to write kernel to side %s: %s" %(side, e)) + pass if wrotekernel == 1: try: @@ -1749,10 +1849,11 @@ class iseriesBootloaderInfo(bootloaderInfo): "%s/proc/iSeries/mf/%s/cmdline" %(instRoot, side)) except Exception, e: - log("Failed to write kernel command line to side %s: %s" - %(side, e)) + #log("Failed to write kernel command line to side %s: %s" + # %(side, e)) + pass - log("Setting default side to C") + #log("Setting default side to C") f = open(instRoot + "/proc/iSeries/mf/side", "w") f.write("C") f.close() @@ -1770,7 +1871,8 @@ class iseriesBootloaderInfo(bootloaderInfo): def getDiskPart(dev): cut = len(dev) if (dev.startswith('rd/') or dev.startswith('ida/') or - dev.startswith('cciss/') or dev.startswith('sx8/')): + dev.startswith('cciss/') or dev.startswith('sx8/') or + dev.startswith('mapper/')): if dev[-2] == 'p': cut = -1 elif dev[-3] == 'p': @@ -1785,10 +1887,10 @@ def getDiskPart(dev): # hack off the trailing 'p' from /dev/cciss/*, for example if name[-1] == 'p': - for letter in name: - if letter not in string.letters and letter != "/": - name = name[:-1] - break + for letter in name: + if letter not in string.letters and letter != "/": + name = name[:-1] + break if cut < 0: partNum = int(dev[cut:]) - 1 diff --git a/checkbootloader.py b/checkbootloader.py index 604d3fd..4b51056 100644 --- a/checkbootloader.py +++ b/checkbootloader.py @@ -4,8 +4,9 @@ # being used on the system. # # Jeremy Katz +# Peter Jones # -# Copyright 2001 Red Hat, Inc. +# Copyright 2001,2005 Red Hat, Inc. # # This software may be freely redistributed under the terms of the GNU # library public license. @@ -14,12 +15,13 @@ # along with this program; if not, write to the Free Software # Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -import os,sys +import os import string grubConfigFile = "/boot/grub/grub.conf" liloConfigFile = "/etc/lilo.conf" yabootConfigFile = "/etc/yaboot.conf" +siloConfigFile = "/etc/silo.conf" # XXX: this is cut and pasted directly from booty/bootloaderInfo.py @@ -43,10 +45,10 @@ def getDiskPart(dev): # hack off the trailing 'p' from /dev/cciss/*, for example if name[-1] == 'p': - for letter in name: - if letter not in string.letters and letter != "/": - name = name[:-1] - break + for letter in name: + if letter not in string.letters and letter != "/": + name = name[:-1] + break if cut < 0: partNum = int(dev[cut:]) - 1 @@ -56,8 +58,13 @@ def getDiskPart(dev): return (name, partNum) -def getRaidDisks(raidDevice): +def getRaidDisks(raidDevice, raidLevel=None, stripPart=1): rc = [] + if raidLevel is not None: + try: + raidLevel = "raid%d" % (int(raidLevel),) + except ValueError: + pass try: f = open("/proc/mdstat", "r") @@ -69,19 +76,24 @@ def getRaidDisks(raidDevice): for line in lines: fields = string.split(line, ' ') if fields[0] == raidDevice: + if raidLevel is not None and fields[3] != raidLevel: + continue for field in fields[4:]: if string.find(field, "[") == -1: continue dev = string.split(field, '[')[0] if len(dev) == 0: continue - disk = getDiskPart(dev)[0] - rc.append(disk) + if stripPart: + disk = getDiskPart(dev)[0] + rc.append(disk) + else: + rc.append(dev) return rc -def getBootBlock(bootDev, instRoot): +def getBootBlock(bootDev, instRoot, seekBlocks=0): """Get the boot block from bootDev. Return a 512 byte string.""" block = " " * 512 if bootDev is None: @@ -101,6 +113,8 @@ def getBootBlock(bootDev, instRoot): for dev in bootDevs: try: fd = os.open("%s/dev/%s" % (instRoot, dev), os.O_RDONLY) + if seekBlocks > 0: + os.lseek(fd, seekBlocks * 512, 0) block = os.read(fd, 512) os.close(fd) return block @@ -117,10 +131,19 @@ def getBootDevString(line): dev = string.replace(dev, "'", "") return dev +def getBootDevList(line): + devs = string.split(line, '=')[1] + rets = [] + for dev in devs: + dev = getBootDevString("=%s" % (dev,)) + rets.append(dev) + return string.join(rets) + def getBootloaderTypeAndBoot(instRoot = "/"): haveGrubConf = 1 haveLiloConf = 1 haveYabootConf = 1 + haveSiloConf = 1 bootDev = None @@ -132,6 +155,8 @@ def getBootloaderTypeAndBoot(instRoot = "/"): haveLiloConf = 0 if not os.access(instRoot + yabootConfigFile, os.R_OK): haveYabootConf = 0 + if not os.access(instRoot + siloConfigFile, os.R_OK): + haveSiloConf = 0 if haveGrubConf: bootDev = None @@ -147,7 +172,6 @@ def getBootloaderTypeAndBoot(instRoot = "/"): f.close() for line in lines: if line.startswith(stanza): - import checkbootloader bootDev = getBootDevString(line) break if bootDev is not None: @@ -158,17 +182,13 @@ def getBootloaderTypeAndBoot(instRoot = "/"): # XXX I don't like this, but it's what the maintainer suggested :( if string.find(block, "GRUB") >= 0: return ("GRUB", bootDev) - elif instRoot != "/": - block = getBootBlock(bootDev, "/") - if string.find(block, "GRUB") >= 0: - return("GRUB", bootDev) if haveLiloConf: f = open(instRoot + liloConfigFile, "r") lines = f.readlines() for line in lines: if line[0:5] == "boot=": - bootDev = getBootDevString(line) + bootDev = getBootDevString(line) break block = getBootBlock(bootDev, instRoot) @@ -181,10 +201,37 @@ def getBootloaderTypeAndBoot(instRoot = "/"): lines = f.readlines() for line in lines: if line[0:5] == "boot=": - bootDev = getBootDevString(line) + bootDev = getBootDevList(line) + + if bootDev: + return ("YABOOT", bootDev) - if bootDev: - return ("YABOOT", bootDev) + if haveSiloConf: + bootDev = None + # We've never done the /etc/sysconfig/silo thing, but maybe + # we should start... + for (fn, stanza) in [ ("/etc/sysconfig/silo", "boot="), + (grubConfigFile, "#boot=") ]: + try: + f = open(instRoot + fn, "r") + except: + continue + + lines = f.readlines() + f.close() + for line in lines: + if line.startswith(stanza): + bootDev = getBootDevString(line) + break + if bootDev is not None: + break + + if bootDev is not None: + # XXX SILO sucks just like grub. + if getDiskPart(bootDev)[1] != 3: + block = getBootBlock(bootDev, instRoot, 1) + if block[24:28] == "SILO": + return ("SILO", bootDev) return (None, None) -- 1.5.5.6