1 |
slords |
1.1 |
diff -up booty-0.44.9/bootloaderInfo.py.smepatches booty-0.44.9/bootloaderInfo.py |
2 |
|
|
--- booty-0.44.9/bootloaderInfo.py.smepatches 2009-01-15 09:28:15.000000000 -0700 |
3 |
|
|
+++ booty-0.44.9/bootloaderInfo.py 2009-08-24 11:10:37.000000000 -0600 |
4 |
|
|
@@ -16,6 +16,7 @@ |
5 |
|
|
# |
6 |
|
|
|
7 |
|
|
import os, sys |
8 |
|
|
+import isys |
9 |
|
|
import crypt |
10 |
|
|
import whrandom |
11 |
|
|
import butil |
12 |
|
|
@@ -419,6 +420,7 @@ class bootloaderInfo: |
13 |
|
|
return args |
14 |
|
|
|
15 |
|
|
args.append("--location=%s" % (self.defaultDevice,)) |
16 |
|
|
+ args.append("--driveorder=%s" % (",".join(self.drivelist))) |
17 |
|
|
|
18 |
|
|
if self.args.get(): |
19 |
|
|
args.append("--append=\"%s\"" %(self.args.get())) |
20 |
|
|
@@ -642,6 +644,28 @@ class x86BootloaderInfo(bootloaderInfo): |
21 |
|
|
def setUseGrub(self, val): |
22 |
|
|
self.useGrubVal = val |
23 |
|
|
|
24 |
|
|
+ def getPhysicalDevices(self, device): |
25 |
|
|
+ # This finds a list of devices on which the given device name resides. |
26 |
|
|
+ # Accepted values for "device" are raid1 md devices (i.e. "md0"), |
27 |
|
|
+ # physical disks ("hda"), and real partitions on physical disks |
28 |
|
|
+ # ("hda1"). Volume groups/logical volumes are not accepted. |
29 |
|
|
+ # |
30 |
|
|
+ # XXX this has internal anaconda-ish knowledge. ick. |
31 |
|
|
+ import isys |
32 |
|
|
+ import lvm |
33 |
|
|
+ |
34 |
|
|
+ if string.split(device, '/', 1)[0] in map (lambda vg: vg[0], |
35 |
|
|
+ lvm.vglist()): |
36 |
|
|
+ return [] |
37 |
|
|
+ |
38 |
|
|
+ if device.startswith('md'): |
39 |
|
|
+ bootable = 0 |
40 |
|
|
+ parts = checkbootloader.getRaidDisks(device, 1, stripPart=0) |
41 |
|
|
+ parts.sort() |
42 |
|
|
+ return parts |
43 |
|
|
+ |
44 |
|
|
+ return [device] |
45 |
|
|
+ |
46 |
|
|
def writeGrub(self, instRoot, fsset, bl, langs, kernelList, chainList, |
47 |
|
|
defaultDev, justConfigFile): |
48 |
|
|
if len(kernelList) < 1: |
49 |
|
|
@@ -663,10 +687,12 @@ class x86BootloaderInfo(bootloaderInfo): |
50 |
|
|
instRoot + cf + '.rpmsave') |
51 |
|
|
|
52 |
|
|
grubTarget = bl.getDevice() |
53 |
|
|
- # XXX wouldn't it be nice if grub really understood raid? :) |
54 |
|
|
- if grubTarget.startswith('md'): |
55 |
|
|
- ent = fsset.getEntryByDeviceName(grubTarget) |
56 |
|
|
- grubTarget = ent.device.members[0] |
57 |
|
|
+ target = "mbr" |
58 |
|
|
+ if (grubTarget.startswith('rd/') or grubTarget.startswith('ida/') or grubTarget.startswith('cciss/')): |
59 |
|
|
+ if grubTarget[-2] == 'p' or grubTarget[-3] == 'p': |
60 |
|
|
+ target = "partition" |
61 |
|
|
+ elif grubTarget[-1].isdigit() and not grubTarget.startswith('md'): |
62 |
|
|
+ target = "partition" |
63 |
|
|
|
64 |
|
|
f = open(instRoot + cf, "w+") |
65 |
|
|
|
66 |
|
|
@@ -692,18 +718,45 @@ class x86BootloaderInfo(bootloaderInfo): |
67 |
|
|
f.write("# all kernel and initrd paths are relative " |
68 |
|
|
"to /boot/, eg.\n") |
69 |
|
|
|
70 |
|
|
- bootDev = bootDev.device.getDevice(asBoot = 1) |
71 |
|
|
+ bootDevs = self.getPhysicalDevices(bootDev.device.getDevice()) |
72 |
|
|
+ bootDev = bootDev.device.getDevice() |
73 |
|
|
|
74 |
|
|
- f.write('# root %s\n' % self.grubbyPartitionName(bootDev)) |
75 |
|
|
+ f.write('# root %s\n' % self.grubbyPartitionName(bootDevs[0])) |
76 |
|
|
f.write("# kernel %svmlinuz-version ro " |
77 |
|
|
"root=/dev/%s\n" % (cfPath, rootDev)) |
78 |
|
|
f.write("# initrd %sinitrd-version.img\n" % (cfPath)) |
79 |
|
|
f.write("#boot=/dev/%s\n" % (grubTarget)) |
80 |
|
|
|
81 |
|
|
+ nthreads = isys.acpicpus() |
82 |
|
|
+ if nthreads == 0: |
83 |
|
|
+ # this should probably be table driven or something... |
84 |
|
|
+ ncpus = isys.smpAvailable() or 1 |
85 |
|
|
+ nthreads = isys.htavailable() or 1 |
86 |
|
|
+ ncores = isys.coresavailable() |
87 |
|
|
+ |
88 |
|
|
+ if ncpus == 1: # machines that have one socket |
89 |
|
|
+ nthreads = nthreads; |
90 |
|
|
+ else: # machines with more than one socket |
91 |
|
|
+ nthreads = (int(nthreads / ncores) or 1) * ncpus |
92 |
|
|
+ |
93 |
|
|
+ xenkernel = 0 |
94 |
|
|
+ if os.path.exists("/proc/xen/capabilities"): |
95 |
|
|
+ xenkernel = 1 |
96 |
|
|
+ |
97 |
|
|
# get the default image to boot... we have to walk and find it |
98 |
|
|
# since grub indexes by where it is in the config file |
99 |
|
|
if defaultDev == rootDev: |
100 |
|
|
- default = 0 |
101 |
|
|
+ for kernel in range(0, len(kernelList)): |
102 |
|
|
+ default=kernel |
103 |
|
|
+ version=kernelList[kernel][2] |
104 |
|
|
+ if version.find('xen') >= 0: |
105 |
|
|
+ if xenkernel: |
106 |
|
|
+ break |
107 |
|
|
+ elif version.find('smp') >= 0: |
108 |
|
|
+ if not xenkernel and nthreads > 1: |
109 |
|
|
+ break |
110 |
|
|
+ else: |
111 |
|
|
+ break |
112 |
|
|
else: |
113 |
|
|
# if the default isn't linux, it's the first thing in the |
114 |
|
|
# chain list |
115 |
|
|
@@ -741,11 +794,11 @@ class x86BootloaderInfo(bootloaderInfo): |
116 |
|
|
# we only want splashimage if they're not using a serial console |
117 |
|
|
if os.access("%s/boot/grub/splash.xpm.gz" %(instRoot,), os.R_OK): |
118 |
|
|
f.write('splashimage=%s%sgrub/splash.xpm.gz\n' |
119 |
|
|
- % (self.grubbyPartitionName(bootDev), cfPath)) |
120 |
|
|
+ % (self.grubbyPartitionName(bootDevs[0]), cfPath)) |
121 |
|
|
f.write("hiddenmenu\n") |
122 |
|
|
|
123 |
|
|
- usedDevs[bootDev] = 1 |
124 |
|
|
- usedDevs[grubTarget] = 1 |
125 |
|
|
+ for dev in self.getPhysicalDevices(grubTarget): |
126 |
|
|
+ usedDevs[dev] = 1 |
127 |
|
|
|
128 |
|
|
if self.password: |
129 |
|
|
f.write('password --md5 %s\n' %(self.password)) |
130 |
|
|
@@ -757,7 +810,7 @@ class x86BootloaderInfo(bootloaderInfo): |
131 |
|
|
initrd = booty.makeInitrd (kernelTag, instRoot) |
132 |
|
|
|
133 |
|
|
f.write('title %s (%s)\n' % (longlabel, version)) |
134 |
|
|
- f.write('\troot %s\n' % self.grubbyPartitionName(bootDev)) |
135 |
|
|
+ f.write('\troot %s\n' % self.grubbyPartitionName(bootDevs[0])) |
136 |
|
|
|
137 |
|
|
realroot = getRootDevName(initrd, fsset, rootDev, instRoot) |
138 |
|
|
realroot = " root=%s" %(realroot,) |
139 |
|
|
@@ -801,21 +854,31 @@ class x86BootloaderInfo(bootloaderInfo): |
140 |
|
|
except: |
141 |
|
|
pass |
142 |
|
|
|
143 |
|
|
+ for dev in self.getPhysicalDevices(rootDev): |
144 |
|
|
+ usedDevs[dev] = 1 |
145 |
|
|
+ |
146 |
|
|
+ for dev in bootDevs: |
147 |
|
|
+ usedDevs[dev] = 1 |
148 |
|
|
|
149 |
|
|
if not os.access(instRoot + "/boot/grub/device.map", os.R_OK): |
150 |
|
|
f = open(instRoot + "/boot/grub/device.map", "w+") |
151 |
|
|
f.write("# this device map was generated by anaconda\n") |
152 |
|
|
f.write("(fd0) /dev/fd0\n") |
153 |
|
|
devs = usedDevs.keys() |
154 |
|
|
- devs.sort() |
155 |
|
|
usedDevs = {} |
156 |
|
|
for dev in devs: |
157 |
|
|
drive = getDiskPart(dev)[0] |
158 |
|
|
if usedDevs.has_key(drive): |
159 |
|
|
continue |
160 |
|
|
- f.write("(%s) /dev/%s\n" % (self.grubbyDiskName(drive), |
161 |
|
|
- drive)) |
162 |
|
|
usedDevs[drive] = 1 |
163 |
|
|
+ devs = usedDevs.keys() |
164 |
|
|
+ devs.sort() |
165 |
|
|
+ for drive in devs: |
166 |
|
|
+ # XXX hack city. If they're not the sort of thing that'll |
167 |
|
|
+ # be in the device map, they shouldn't still be in the list. |
168 |
|
|
+ if not drive.startswith('md'): |
169 |
|
|
+ f.write("(%s) /dev/%s\n" % (self.grubbyDiskName(drive), |
170 |
|
|
+ drive)) |
171 |
|
|
f.close() |
172 |
|
|
|
173 |
|
|
args = "--stage2=/boot/grub/stage2 " |
174 |
|
|
@@ -840,14 +903,22 @@ class x86BootloaderInfo(bootloaderInfo): |
175 |
|
|
f.write("forcelba=0\n") |
176 |
|
|
f.close() |
177 |
|
|
|
178 |
|
|
- part = self.grubbyPartitionName(bootDev) |
179 |
|
|
- prefix = "%s/%s" % (self.grubbyPartitionName(bootDev), grubPath) |
180 |
|
|
- cmd = "root %s\ninstall %s%s/stage1 d %s %s/stage2 p %s%s/grub.conf" % \ |
181 |
|
|
- (part, args, grubPath, self.grubbyPartitionName(grubTarget), |
182 |
|
|
- grubPath, part, grubPath) |
183 |
|
|
+ cmds = [] |
184 |
|
|
+ for bootDev in bootDevs: |
185 |
|
|
+ gtDisk = self.grubbyPartitionName(getDiskPart(bootDev)[0]) |
186 |
|
|
+ bPart = self.grubbyPartitionName(bootDev) |
187 |
|
|
+ |
188 |
|
|
+ stage1Target = gtDisk |
189 |
|
|
+ if target == "partition": |
190 |
|
|
+ stage1Target = self.grubbyPartitionName(bootDev) |
191 |
|
|
+ |
192 |
|
|
+ cmd = "root %s\nsetup %s" % (bPart, stage1Target) |
193 |
|
|
+ cmds.append(cmd) |
194 |
|
|
|
195 |
|
|
if not justConfigFile: |
196 |
|
|
- log("GRUB command %s", cmd) |
197 |
|
|
+ log("GRUB commands:") |
198 |
|
|
+ for cmd in cmds: |
199 |
|
|
+ log("\t%s\n", cmd) |
200 |
|
|
|
201 |
|
|
# copy the stage files over into /boot |
202 |
|
|
rhpl.executil.execWithRedirect( "/sbin/grub-install", |
203 |
|
|
@@ -865,7 +936,8 @@ class x86BootloaderInfo(bootloaderInfo): |
204 |
|
|
|
205 |
|
|
# really install the bootloader |
206 |
|
|
p = os.pipe() |
207 |
|
|
- os.write(p[1], cmd + '\n') |
208 |
|
|
+ for cmd in cmds: |
209 |
|
|
+ os.write(p[1], cmd + '\n') |
210 |
|
|
os.close(p[1]) |
211 |
|
|
rhpl.executil.execWithRedirect('/sbin/grub' , |
212 |
|
|
[ "grub", "--batch", "--no-floppy", |
213 |
|
|
@@ -1044,41 +1116,64 @@ class x86BootloaderInfo(bootloaderInfo): |
214 |
|
|
bootDev = fsset.getEntryByMountPoint("/") |
215 |
|
|
grubPath = "/boot/grub" |
216 |
|
|
cfPath = "/boot/" |
217 |
|
|
- bootDev = bootDev.device.getDevice(asBoot = 1) |
218 |
|
|
|
219 |
|
|
- part = self.grubbyPartitionName(bootDev) |
220 |
|
|
- prefix = "%s/%s" % (self.grubbyPartitionName(bootDev), grubPath) |
221 |
|
|
- args = "--stage2=/boot/grub/stage2 " |
222 |
|
|
- cmd = "root %s\ninstall %s%s/stage1 d %s %s/stage2 p %s%s/grub.conf" % \ |
223 |
|
|
- (part, args, grubPath, self.grubbyPartitionName(theDev[5:]), |
224 |
|
|
- grubPath, part, grubPath) |
225 |
|
|
- |
226 |
|
|
- if not justConfigFile: |
227 |
|
|
- log("GRUB command %s", cmd) |
228 |
|
|
+ masterBootDev = bootDev.device.getDevice(asBoot = 0) |
229 |
|
|
+ if masterBootDev[0:2] == 'md': |
230 |
|
|
+ rootDevs = checkbootloader.getRaidDisks(masterBootDev, raidLevel=1, |
231 |
|
|
+ stripPart = 0) |
232 |
|
|
+ else: |
233 |
|
|
+ rootDevs = [masterBootDev] |
234 |
|
|
|
235 |
|
|
- # copy the stage files over into /boot |
236 |
|
|
- rhpl.executil.execWithRedirect( "/sbin/grub-install", |
237 |
|
|
+ if theDev[5:7] == 'md': |
238 |
|
|
+ stage1Devs = checkbootloader.getRaidDisks(theDev[5:], raidLevel=1) |
239 |
|
|
+ else: |
240 |
|
|
+ stage1Devs = [theDev[5:]] |
241 |
|
|
+ |
242 |
|
|
+ for stage1Dev in stage1Devs: |
243 |
|
|
+ # cross fingers; if we can't find a root device on the same |
244 |
|
|
+ # hardware as this boot device, we just blindly hope the first |
245 |
|
|
+ # thing in the list works. |
246 |
|
|
+ |
247 |
|
|
+ grubbyStage1Dev = self.grubbyPartitionName(stage1Dev) |
248 |
|
|
+ |
249 |
|
|
+ grubbyRootPart = self.grubbyPartitionName(rootDevs[0]) |
250 |
|
|
+ |
251 |
|
|
+ for rootDev in rootDevs: |
252 |
|
|
+ testGrubbyRootDev = getDiskPart(rootDev)[0] |
253 |
|
|
+ testGrubbyRootDev = self.grubbyPartitionName(testGrubbyRootDev) |
254 |
|
|
+ |
255 |
|
|
+ if grubbyStage1Dev == testGrubbyRootDev: |
256 |
|
|
+ grubbyRootPart = self.grubbyPartitionName(rootDev) |
257 |
|
|
+ break |
258 |
|
|
+ |
259 |
|
|
+ cmd = "root %s\nsetup %s" % (grubbyRootPart, grubbyStage1Dev) |
260 |
|
|
+ |
261 |
|
|
+ if not justConfigFile: |
262 |
|
|
+ log("GRUB command %s", cmd) |
263 |
|
|
+ |
264 |
|
|
+ # copy the stage files over into /boot |
265 |
|
|
+ rhpl.executil.execWithRedirect( "/sbin/grub-install", |
266 |
|
|
["/sbin/grub-install", "--just-copy"], |
267 |
|
|
stdout = "/dev/tty5", stderr = "/dev/tty5", |
268 |
|
|
root = instRoot) |
269 |
|
|
|
270 |
|
|
- # get the stage files synced to disk |
271 |
|
|
- import isys |
272 |
|
|
- isys.sync() |
273 |
|
|
- isys.sync() |
274 |
|
|
- isys.sync() |
275 |
|
|
+ # get the stage files synced to disk |
276 |
|
|
+ import isys |
277 |
|
|
+ isys.sync() |
278 |
|
|
+ isys.sync() |
279 |
|
|
+ isys.sync() |
280 |
|
|
|
281 |
|
|
- # really install the bootloader |
282 |
|
|
- p = os.pipe() |
283 |
|
|
- os.write(p[1], cmd + '\n') |
284 |
|
|
- os.close(p[1]) |
285 |
|
|
- rhpl.executil.execWithRedirect('/sbin/grub' , |
286 |
|
|
+ # really install the bootloader |
287 |
|
|
+ p = os.pipe() |
288 |
|
|
+ os.write(p[1], cmd + '\n') |
289 |
|
|
+ os.close(p[1]) |
290 |
|
|
+ rhpl.executil.execWithRedirect('/sbin/grub' , |
291 |
|
|
[ "grub", "--batch", "--no-floppy", |
292 |
|
|
"--device-map=/boot/grub/device.map" ], |
293 |
|
|
stdin = p[0], |
294 |
|
|
stdout = "/dev/tty5", stderr = "/dev/tty5", |
295 |
|
|
root = instRoot) |
296 |
|
|
- os.close(p[0]) |
297 |
|
|
+ os.close(p[0]) |
298 |
|
|
|
299 |
|
|
return "" |
300 |
|
|
|
301 |
|
|
diff -up booty-0.44.9/butil.py.smepatches booty-0.44.9/butil.py |
302 |
|
|
--- booty-0.44.9/butil.py.smepatches 2009-01-15 09:28:15.000000000 -0700 |
303 |
|
|
+++ booty-0.44.9/butil.py 2009-08-24 11:09:16.000000000 -0600 |
304 |
|
|
@@ -134,9 +134,9 @@ def getPPCMacBook(): |
305 |
|
|
|
306 |
|
|
# returns a product name to use for the boot loader string |
307 |
|
|
def getProductName(): |
308 |
|
|
- # try redhat-release first |
309 |
|
|
- if os.access("/etc/redhat-release", os.R_OK): |
310 |
|
|
- f = open("/etc/redhat-release", "r") |
311 |
|
|
+ # try e-smith-release first |
312 |
|
|
+ if os.access("/etc/e-smith-release", os.R_OK): |
313 |
|
|
+ f = open("/etc/e-smith-release", "r") |
314 |
|
|
lines = f.readlines() |
315 |
|
|
f.close() |
316 |
|
|
for buf in lines: |
317 |
|
|
diff -up booty-0.44.9/checkbootloader.py.smepatches booty-0.44.9/checkbootloader.py |
318 |
|
|
--- booty-0.44.9/checkbootloader.py.smepatches 2009-01-15 09:28:15.000000000 -0700 |
319 |
|
|
+++ booty-0.44.9/checkbootloader.py 2009-08-24 11:10:37.000000000 -0600 |
320 |
|
|
@@ -56,8 +56,13 @@ def getDiskPart(dev): |
321 |
|
|
return (name, partNum) |
322 |
|
|
|
323 |
|
|
|
324 |
|
|
-def getRaidDisks(raidDevice): |
325 |
|
|
+def getRaidDisks(raidDevice, raidLevel=None, stripPart=1): |
326 |
|
|
rc = [] |
327 |
|
|
+ if raidLevel is not None: |
328 |
|
|
+ try: |
329 |
|
|
+ raidLevel = "raid%d" % (int(raidLevel),) |
330 |
|
|
+ except ValueError: |
331 |
|
|
+ pass |
332 |
|
|
|
333 |
|
|
try: |
334 |
|
|
f = open("/proc/mdstat", "r") |
335 |
|
|
@@ -69,14 +74,19 @@ def getRaidDisks(raidDevice): |
336 |
|
|
for line in lines: |
337 |
|
|
fields = string.split(line, ' ') |
338 |
|
|
if fields[0] == raidDevice: |
339 |
|
|
+ if raidLevel is not None and fields[3] != raidLevel: |
340 |
|
|
+ continue |
341 |
|
|
for field in fields[4:]: |
342 |
|
|
if string.find(field, "[") == -1: |
343 |
|
|
continue |
344 |
|
|
dev = string.split(field, '[')[0] |
345 |
|
|
if len(dev) == 0: |
346 |
|
|
continue |
347 |
|
|
- disk = getDiskPart(dev)[0] |
348 |
|
|
- rc.append(disk) |
349 |
|
|
+ if stripPart: |
350 |
|
|
+ disk = getDiskPart(dev)[0] |
351 |
|
|
+ rc.append(disk) |
352 |
|
|
+ else: |
353 |
|
|
+ rc.append(dev) |
354 |
|
|
|
355 |
|
|
return rc |
356 |
|
|
|