1 |
#!/usr/bin/python |
2 |
# |
3 |
# Check to see whether it looks like GRUB or LILO is the boot loader |
4 |
# being used on the system. |
5 |
# |
6 |
# Jeremy Katz <katzj@redhat.com> |
7 |
# |
8 |
# Copyright 2001 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 |
import os,sys |
18 |
import string |
19 |
|
20 |
grubConfigFile = "/boot/grub/grub.conf" |
21 |
liloConfigFile = "/etc/lilo.conf" |
22 |
yabootConfigFile = "/etc/yaboot.conf" |
23 |
|
24 |
|
25 |
# XXX: this is cut and pasted directly from booty/bootloaderInfo.py |
26 |
# should eventually just go from there |
27 |
def getDiskPart(dev): |
28 |
"""Return (disk, partition number) tuple for dev""" |
29 |
cut = len(dev) |
30 |
if (dev[:3] == "rd/" or dev[:4] == "ida/" or |
31 |
dev[:6] == "cciss/"): |
32 |
if dev[-2] == 'p': |
33 |
cut = -1 |
34 |
elif dev[-3] == 'p': |
35 |
cut = -2 |
36 |
else: |
37 |
if dev[-2] in string.digits: |
38 |
cut = -2 |
39 |
elif dev[-1] in string.digits: |
40 |
cut = -1 |
41 |
|
42 |
name = dev[:cut] |
43 |
|
44 |
# hack off the trailing 'p' from /dev/cciss/*, for example |
45 |
if name[-1] == 'p': |
46 |
for letter in name: |
47 |
if letter not in string.letters and letter != "/": |
48 |
name = name[:-1] |
49 |
break |
50 |
|
51 |
if cut < 0: |
52 |
partNum = int(dev[cut:]) - 1 |
53 |
else: |
54 |
partNum = None |
55 |
|
56 |
return (name, partNum) |
57 |
|
58 |
|
59 |
def getRaidDisks(raidDevice, raidLevel=None, stripPart=1): |
60 |
rc = [] |
61 |
if raidLevel is not None: |
62 |
try: |
63 |
raidLevel = "raid%d" % (int(raidLevel),) |
64 |
except ValueError: |
65 |
pass |
66 |
|
67 |
try: |
68 |
f = open("/proc/mdstat", "r") |
69 |
lines = f.readlines() |
70 |
f.close() |
71 |
except: |
72 |
return rc |
73 |
|
74 |
for line in lines: |
75 |
fields = string.split(line, ' ') |
76 |
if fields[0] == raidDevice: |
77 |
if raidLevel is not None and fields[3] != raidLevel: |
78 |
continue |
79 |
for field in fields[4:]: |
80 |
if string.find(field, "[") == -1: |
81 |
continue |
82 |
dev = string.split(field, '[')[0] |
83 |
if len(dev) == 0: |
84 |
continue |
85 |
if stripPart: |
86 |
disk = getDiskPart(dev)[0] |
87 |
rc.append(disk) |
88 |
else: |
89 |
rc.append(dev) |
90 |
|
91 |
return rc |
92 |
|
93 |
|
94 |
def getBootBlock(bootDev, instRoot, seekBlocks=0): |
95 |
"""Get the boot block from bootDev. Return a 512 byte string.""" |
96 |
block = " " * 512 |
97 |
if bootDev is None: |
98 |
return block |
99 |
|
100 |
# get the devices in the raid device |
101 |
if bootDev[5:7] == "md": |
102 |
bootDevs = getRaidDisks(bootDev[5:]) |
103 |
bootDevs.sort() |
104 |
else: |
105 |
bootDevs = [ bootDev[5:] ] |
106 |
|
107 |
# FIXME: this is kind of a hack |
108 |
# look at all of the devs in the raid device until we can read the |
109 |
# boot block for one of them. should do this better at some point |
110 |
# by looking at all of the drives properly |
111 |
for dev in bootDevs: |
112 |
try: |
113 |
fd = os.open("%s/dev/%s" % (instRoot, dev), os.O_RDONLY) |
114 |
if seekBlocks > 0: |
115 |
os.lseek(fd, seekBlocks * 512, 0) |
116 |
block = os.read(fd, 512) |
117 |
os.close(fd) |
118 |
return block |
119 |
except: |
120 |
pass |
121 |
return block |
122 |
|
123 |
# takes a line like #boot=/dev/hda and returns /dev/hda |
124 |
# also handles cases like quoted versions and other nonsense |
125 |
def getBootDevString(line): |
126 |
dev = string.split(line, '=')[1] |
127 |
dev = string.strip(dev) |
128 |
dev = string.replace(dev, '"', '') |
129 |
dev = string.replace(dev, "'", "") |
130 |
return dev |
131 |
|
132 |
def getBootloaderTypeAndBoot(instRoot = "/"): |
133 |
haveGrubConf = 1 |
134 |
haveLiloConf = 1 |
135 |
haveYabootConf = 1 |
136 |
|
137 |
bootDev = None |
138 |
|
139 |
# make sure they have the config file, otherwise we definitely can't |
140 |
# use that bootloader |
141 |
if not os.access(instRoot + grubConfigFile, os.R_OK): |
142 |
haveGrubConf = 0 |
143 |
if not os.access(instRoot + liloConfigFile, os.R_OK): |
144 |
haveLiloConf = 0 |
145 |
if not os.access(instRoot + yabootConfigFile, os.R_OK): |
146 |
haveYabootConf = 0 |
147 |
|
148 |
if haveGrubConf: |
149 |
bootDev = None |
150 |
for (fn, stanza) in [ ("/etc/sysconfig/grub", "boot="), |
151 |
(grubConfigFile, "#boot=") ]: |
152 |
try: |
153 |
f = open(instRoot + fn, "r") |
154 |
except: |
155 |
continue |
156 |
|
157 |
# the following bits of code are straight from checkbootloader.py |
158 |
lines = f.readlines() |
159 |
f.close() |
160 |
for line in lines: |
161 |
if line.startswith(stanza): |
162 |
import checkbootloader |
163 |
bootDev = getBootDevString(line) |
164 |
break |
165 |
if bootDev is not None: |
166 |
break |
167 |
|
168 |
if bootDev is not None: |
169 |
block = getBootBlock(bootDev, instRoot) |
170 |
# XXX I don't like this, but it's what the maintainer suggested :( |
171 |
if string.find(block, "GRUB") >= 0: |
172 |
return ("GRUB", bootDev) |
173 |
|
174 |
if haveLiloConf: |
175 |
f = open(instRoot + liloConfigFile, "r") |
176 |
lines = f.readlines() |
177 |
for line in lines: |
178 |
if line[0:5] == "boot=": |
179 |
bootDev = getBootDevString(line) |
180 |
break |
181 |
|
182 |
block = getBootBlock(bootDev, instRoot) |
183 |
# this at least is well-defined |
184 |
if block[6:10] == "LILO": |
185 |
return ("LILO", bootDev) |
186 |
|
187 |
if haveYabootConf: |
188 |
f = open(instRoot + yabootConfigFile, "r") |
189 |
lines = f.readlines() |
190 |
for line in lines: |
191 |
if line[0:5] == "boot=": |
192 |
bootDev = getBootDevString(line) |
193 |
|
194 |
if bootDev: |
195 |
return ("YABOOT", bootDev) |
196 |
|
197 |
return (None, None) |
198 |
|
199 |
def whichBootLoader(instRoot = "/"): |
200 |
ret = getBootloaderTypeAndBoot(instRoot) |
201 |
if not ret: |
202 |
return None |
203 |
else: |
204 |
return ret[0] |
205 |
|
206 |
if __name__ == "__main__": |
207 |
bootloader = whichBootLoader() |
208 |
if bootloader: |
209 |
print "Found %s." % (bootloader) |
210 |
else: |
211 |
print "Unable to determine boot loader." |