diff options
author | Chris Lumens <clumens@redhat.com> | 2009-02-18 14:16:04 -0500 |
---|---|---|
committer | Chris Lumens <clumens@redhat.com> | 2009-03-04 15:37:03 -0500 |
commit | 9276f6795674a776f29ccbaa4ebb0ed2b5b2e25f (patch) | |
tree | 1ab506a889a7c1c565d7bec43ff6ccba97460ecf /booty/checkbootloader.py | |
parent | f6ccb426af374f745efe53cfbb1df1175e550de7 (diff) | |
download | anaconda-9276f6795674a776f29ccbaa4ebb0ed2b5b2e25f.tar.gz anaconda-9276f6795674a776f29ccbaa4ebb0ed2b5b2e25f.tar.xz anaconda-9276f6795674a776f29ccbaa4ebb0ed2b5b2e25f.zip |
Add the existing booty back into anaconda.
Welcome back, booty. We missed you.
Diffstat (limited to 'booty/checkbootloader.py')
-rw-r--r-- | booty/checkbootloader.py | 270 |
1 files changed, 270 insertions, 0 deletions
diff --git a/booty/checkbootloader.py b/booty/checkbootloader.py new file mode 100644 index 000000000..38cb8255d --- /dev/null +++ b/booty/checkbootloader.py @@ -0,0 +1,270 @@ +#!/usr/bin/python +# +# Check to see whether it looks like GRUB or LILO is the boot loader +# being used on the system. +# +# Jeremy Katz <katzj@redhat.com> +# Peter Jones <pjones@redhat.com> +# +# Copyright 2001,2005 Red Hat, Inc. +# +# This software may be freely redistributed under the terms of the GNU +# library public license. +# +# You should have received a copy of the GNU Library Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + +import os +import string +import rhpl + +grubConfigFile = "/etc/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 +# should eventually just go from there +def getDiskPart(dev): + """Return (disk, partition number) tuple for dev""" + cut = len(dev) + if (dev[:3] == "rd/" or dev[:4] == "ida/" or + dev[:6] == "cciss/"): + if dev[-2] == 'p': + cut = -1 + elif dev[-3] == 'p': + cut = -2 + else: + if dev[-2] in string.digits: + cut = -2 + elif dev[-1] in string.digits: + cut = -1 + + name = dev[:cut] + + # 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 + + if cut < 0: + partNum = int(dev[cut:]) - 1 + else: + partNum = None + + return (name, partNum) + + +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") + lines = f.readlines() + f.close() + except: + return rc + + 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 + if stripPart: + disk = getDiskPart(dev)[0] + rc.append(disk) + else: + rc.append(dev) + + return rc + + +def getBootBlock(bootDev, instRoot, seekBlocks=0): + """Get the boot block from bootDev. Return a 512 byte string.""" + block = " " * 512 + if bootDev is None: + return block + + # get the devices in the raid device + if bootDev[5:7] == "md": + bootDevs = getRaidDisks(bootDev[5:]) + bootDevs.sort() + else: + bootDevs = [ bootDev[5:] ] + + # FIXME: this is kind of a hack + # look at all of the devs in the raid device until we can read the + # boot block for one of them. should do this better at some point + # by looking at all of the drives properly + 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 + except: + pass + return block + +# takes a line like #boot=/dev/hda and returns /dev/hda +# also handles cases like quoted versions and other nonsense +def getBootDevString(line): + dev = string.split(line, '=')[1] + dev = string.strip(dev) + dev = string.replace(dev, '"', '') + 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) + +efi = None +## Determine if the hardware supports EFI. +# @return True if so, False otherwise. +def isEfi(): + global efi + if efi is not None: + return efi + + efi = False + if rhpl.getArch() in ("ia64", "i386", "x86_64"): + # XXX need to make sure efivars is loaded... + if os.path.exists("/sys/firmware/efi"): + efi = True + + return efi + +def getBootloaderTypeAndBoot(instRoot = "/"): + haveGrubConf = 1 + haveLiloConf = 1 + haveYabootConf = 1 + haveSiloConf = 1 + + bootDev = None + + # make sure they have the config file, otherwise we definitely can't + # use that bootloader + if not os.access(instRoot + grubConfigFile, os.R_OK): + haveGrubConf = 0 + if not os.access(instRoot + liloConfigFile, os.R_OK): + 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 + for (fn, stanza) in [ ("/etc/sysconfig/grub", "boot="), + (grubConfigFile, "#boot=") ]: + try: + f = open(instRoot + fn, "r") + except: + continue + + # the following bits of code are straight from checkbootloader.py + lines = f.readlines() + f.close() + for line in lines: + if line.startswith(stanza): + bootDev = getBootDevString(line) + break + if bootDev is not None: + break + + if isEfi(): + return ("GRUB", bootDev) + + if bootDev is not None: + block = getBootBlock(bootDev, instRoot) + # XXX I don't like this, but it's what the maintainer suggested :( + 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) + break + + block = getBootBlock(bootDev, instRoot) + # this at least is well-defined + if block[6:10] == "LILO": + return ("LILO", bootDev) + + if haveYabootConf: + f = open(instRoot + yabootConfigFile, "r") + lines = f.readlines() + for line in lines: + if line[0:5] == "boot=": + bootDev = getBootDevList(line) + + 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) + +def whichBootLoader(instRoot = "/"): + ret = getBootloaderTypeAndBoot(instRoot) + if not ret: + return None + else: + return ret[0] + +if __name__ == "__main__": + bootloader = whichBootLoader() + if bootloader: + print "Found %s." % (bootloader) + else: + print "Unable to determine boot loader." |