#!/usr/bin/python # # Check to see whether it looks like GRUB or LILO is the boot loader # being used on the system. # # Jeremy Katz # Peter Jones # # 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 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 # 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 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 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 = getBootDevString(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."