1 |
slords |
1.1 |
# |
2 |
|
|
# bootloaderInfo.py - bootloader config object used in creation of new |
3 |
|
|
# bootloader configs. Originally from anaconda |
4 |
|
|
# |
5 |
|
|
# Jeremy Katz <katzj@redhat.com> |
6 |
|
|
# Erik Troan <ewt@redhat.com> |
7 |
slords |
1.5 |
# Peter Jones <pjones@redhat.com> |
8 |
slords |
1.1 |
# |
9 |
slords |
1.5 |
# Copyright 2005 Red Hat, Inc. |
10 |
slords |
1.1 |
# |
11 |
|
|
# This software may be freely redistributed under the terms of the GNU |
12 |
|
|
# library public license. |
13 |
|
|
# |
14 |
|
|
# You should have received a copy of the GNU Library Public License |
15 |
|
|
# along with this program; if not, write to the Free Software |
16 |
|
|
# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. |
17 |
|
|
# |
18 |
|
|
|
19 |
slords |
1.2 |
import isys |
20 |
slords |
1.1 |
import os, sys |
21 |
|
|
import crypt |
22 |
slords |
1.5 |
import random |
23 |
slords |
1.1 |
import butil |
24 |
|
|
import string |
25 |
|
|
|
26 |
|
|
from lilo import LiloConfigFile |
27 |
|
|
from rhpl.log import log |
28 |
|
|
from rhpl.translate import _, N_ |
29 |
|
|
import rhpl.executil |
30 |
|
|
|
31 |
|
|
import booty |
32 |
|
|
import checkbootloader |
33 |
|
|
|
34 |
|
|
dosFilesystems = ('FAT', 'fat16', 'fat32', 'ntfs', 'hpfs') |
35 |
|
|
|
36 |
|
|
if os.path.exists('edd'): |
37 |
|
|
sys.path.append('edd/') |
38 |
|
|
else: |
39 |
|
|
sys.path.append('/usr/lib/bootloader') |
40 |
|
|
|
41 |
|
|
if butil.getArch() == "i386": |
42 |
|
|
import edd |
43 |
|
|
|
44 |
|
|
def doesDualBoot(): |
45 |
|
|
if butil.getArch() == "i386" or butil.getArch() == "x86_64": |
46 |
|
|
return 1 |
47 |
|
|
return 0 |
48 |
|
|
|
49 |
|
|
# hack and a half |
50 |
|
|
# there's no guarantee that data is written to the disk and grub |
51 |
|
|
# reads both the filesystem and the disk. suck. |
52 |
|
|
def syncDataToDisk(dev, mntpt, instRoot = "/"): |
53 |
|
|
import isys, fsset |
54 |
|
|
isys.sync() |
55 |
|
|
isys.sync() |
56 |
|
|
isys.sync() |
57 |
|
|
|
58 |
|
|
# and xfs is even more "special" (#117968) |
59 |
|
|
if fsset.isValidXFS(dev): |
60 |
|
|
rhpl.executil.execWithRedirect( "/usr/sbin/xfs_freeze", |
61 |
|
|
["/usr/sbin/xfs_freeze", "-f", mntpt], |
62 |
|
|
stdout = "/dev/tty5", |
63 |
|
|
stderr = "/dev/tty5", |
64 |
|
|
root = instRoot) |
65 |
|
|
rhpl.executil.execWithRedirect( "/usr/sbin/xfs_freeze", |
66 |
|
|
["/usr/sbin/xfs_freeze", "-u", mntpt], |
67 |
|
|
stdout = "/dev/tty5", |
68 |
|
|
stderr = "/dev/tty5", |
69 |
|
|
root = instRoot) |
70 |
|
|
|
71 |
|
|
class BootyNoKernelWarning: |
72 |
|
|
def __init__ (self, value=""): |
73 |
|
|
self.value = value |
74 |
|
|
|
75 |
|
|
def __str__ (self): |
76 |
|
|
return self.value |
77 |
|
|
|
78 |
|
|
class KernelArguments: |
79 |
|
|
|
80 |
|
|
def get(self): |
81 |
|
|
return self.args |
82 |
|
|
|
83 |
|
|
def set(self, args): |
84 |
|
|
self.args = args |
85 |
|
|
|
86 |
|
|
def chandevget(self): |
87 |
|
|
return self.cargs |
88 |
|
|
|
89 |
|
|
def chandevset(self, args): |
90 |
|
|
self.cargs = args |
91 |
|
|
|
92 |
|
|
def append(self, args): |
93 |
|
|
if self.args: |
94 |
|
|
# don't duplicate the addition of an argument (#128492) |
95 |
|
|
if self.args.find(args) != -1: |
96 |
|
|
return |
97 |
|
|
self.args = self.args + " " |
98 |
|
|
self.args = self.args + "%s" % (args,) |
99 |
|
|
|
100 |
|
|
|
101 |
|
|
def __init__(self): |
102 |
|
|
str = "" |
103 |
|
|
|
104 |
|
|
if butil.getArch() == "s390": |
105 |
|
|
self.cargs = [] |
106 |
|
|
f = open("/tmp/install.cfg") |
107 |
|
|
lines = f.readlines() |
108 |
|
|
for line in lines: |
109 |
|
|
try: |
110 |
|
|
(vname,vparm) = line.split('=', 1) |
111 |
|
|
vname = vname.strip() |
112 |
|
|
vparm = vparm.replace('"','') |
113 |
|
|
vparm = vparm.strip() |
114 |
|
|
if vname == "DASD": |
115 |
|
|
str = str + "dasd=" + vparm |
116 |
|
|
if vname == "CHANDEV": |
117 |
|
|
self.cargs.append(vparm) |
118 |
|
|
if vname == "QETHPARM": |
119 |
|
|
self.cargs.append(vparm) |
120 |
|
|
except Exception, e: |
121 |
|
|
pass |
122 |
|
|
|
123 |
|
|
# look for kernel arguments we know should be preserved and add them |
124 |
|
|
ourargs = ["speakup_synth=", "apic", "noapic", "apm=", "ide=nodma", "noht", "acpi=", "video="] |
125 |
|
|
f = open("/proc/cmdline") |
126 |
|
|
cmdline = f.read()[:-1] |
127 |
|
|
f.close() |
128 |
|
|
cmdlineargs = cmdline.split(" ") |
129 |
|
|
for arg in cmdlineargs: |
130 |
|
|
for check in ourargs: |
131 |
|
|
if arg.startswith(check): |
132 |
|
|
if str: str = str + " " |
133 |
|
|
str = str + arg |
134 |
|
|
|
135 |
|
|
self.args = str |
136 |
|
|
|
137 |
|
|
class BootImages: |
138 |
|
|
# returns dictionary of (label, longlabel, devtype) pairs indexed by device |
139 |
|
|
def getImages(self): |
140 |
|
|
# return a copy so users can modify it w/o affecting us |
141 |
|
|
|
142 |
|
|
dict = {} |
143 |
|
|
for key in self.images.keys(): |
144 |
|
|
dict[key] = self.images[key] |
145 |
|
|
|
146 |
|
|
return dict |
147 |
|
|
|
148 |
|
|
def setImageLabel(self, dev, label, setLong = 0): |
149 |
|
|
if setLong: |
150 |
|
|
self.images[dev] = (self.images[dev][0], label, |
151 |
|
|
self.images[dev][2]) |
152 |
|
|
else: |
153 |
|
|
self.images[dev] = (label, self.images[dev][1], |
154 |
|
|
self.images[dev][2]) |
155 |
|
|
|
156 |
|
|
|
157 |
|
|
# default is a device |
158 |
|
|
def setDefault(self, default): |
159 |
|
|
self.default = default |
160 |
|
|
|
161 |
|
|
def getDefault(self): |
162 |
|
|
return self.default |
163 |
|
|
|
164 |
|
|
# XXX this has internal anaconda-ish knowledge. ick |
165 |
|
|
def setup(self, diskSet, fsset): |
166 |
|
|
devices = {} |
167 |
|
|
devs = self.availableBootDevices(diskSet, fsset) |
168 |
|
|
for (dev, type) in devs: |
169 |
|
|
devices[dev] = 1 |
170 |
|
|
|
171 |
|
|
# These partitions have disappeared |
172 |
|
|
for dev in self.images.keys(): |
173 |
|
|
if not devices.has_key(dev): del self.images[dev] |
174 |
|
|
|
175 |
|
|
# These have appeared |
176 |
|
|
for (dev, type) in devs: |
177 |
|
|
if not self.images.has_key(dev): |
178 |
slords |
1.5 |
if type in dosFilesystems and doesDualBoot(): |
179 |
|
|
self.images[dev] = ("Other", "Other", type) |
180 |
|
|
elif type in ("hfs", "hfs+") and butil.getPPCMachine() == "PMac": |
181 |
slords |
1.1 |
self.images[dev] = ("Other", "Other", type) |
182 |
|
|
else: |
183 |
|
|
self.images[dev] = (None, None, type) |
184 |
|
|
|
185 |
|
|
|
186 |
|
|
if not self.images.has_key(self.default): |
187 |
|
|
entry = fsset.getEntryByMountPoint('/') |
188 |
|
|
self.default = entry.device.getDevice() |
189 |
|
|
(label, longlabel, type) = self.images[self.default] |
190 |
|
|
if not label: |
191 |
|
|
self.images[self.default] = ("linux", |
192 |
|
|
butil.getProductName(), type) |
193 |
|
|
|
194 |
|
|
# XXX more internal anaconda knowledge |
195 |
|
|
def availableBootDevices(self, diskSet, fsset): |
196 |
|
|
devs = [] |
197 |
|
|
foundDos = 0 |
198 |
|
|
for (dev, type) in diskSet.partitionTypes(): |
199 |
|
|
if type in dosFilesystems and not foundDos and doesDualBoot(): |
200 |
|
|
import isys |
201 |
|
|
import partedUtils |
202 |
|
|
|
203 |
|
|
isys.makeDevInode(dev, '/tmp/' + dev) |
204 |
|
|
part = partedUtils.get_partition_by_name(diskSet.disks, dev) |
205 |
|
|
if part.native_type not in partedUtils.dosPartitionTypes: |
206 |
|
|
continue |
207 |
|
|
|
208 |
|
|
try: |
209 |
|
|
bootable = isys.checkBoot('/tmp/' + dev) |
210 |
|
|
devs.append((dev, type)) |
211 |
|
|
foundDos = 1 |
212 |
|
|
except Exception, e: |
213 |
|
|
log("exception checking %s: %s" %(dev, e)) |
214 |
|
|
pass |
215 |
|
|
elif ((type == 'ntfs' or type =='hpfs') and not foundDos |
216 |
|
|
and doesDualBoot()): |
217 |
|
|
devs.append((dev, type)) |
218 |
|
|
# maybe questionable, but the first ntfs or fat is likely to |
219 |
|
|
# be the correct one to boot with XP using ntfs |
220 |
|
|
foundDos = 1 |
221 |
slords |
1.5 |
elif type in ('hfs', 'hfs+') and butil.getPPCMachine() == "PMac": |
222 |
slords |
1.1 |
import isys |
223 |
|
|
import partedUtils |
224 |
|
|
|
225 |
|
|
part = partedUtils.get_partition_by_name(diskSet.disks, dev) |
226 |
|
|
if partedUtils.get_flags(part) != "boot": |
227 |
|
|
devs.append((dev, type)) |
228 |
|
|
|
229 |
|
|
slash = fsset.getEntryByMountPoint('/') |
230 |
|
|
if not slash or not slash.device or not slash.fsystem: |
231 |
|
|
raise ValueError, ("Trying to pick boot devices but do not have a " |
232 |
|
|
"sane root partition. Aborting install.") |
233 |
|
|
devs.append((slash.device.getDevice(), slash.fsystem.getName())) |
234 |
|
|
|
235 |
|
|
devs.sort() |
236 |
|
|
|
237 |
|
|
return devs |
238 |
|
|
|
239 |
|
|
|
240 |
|
|
|
241 |
|
|
def __init__(self): |
242 |
|
|
self.default = None |
243 |
|
|
self.images = {} |
244 |
|
|
|
245 |
|
|
|
246 |
|
|
class bootloaderInfo: |
247 |
|
|
def setUseGrub(self, val): |
248 |
|
|
pass |
249 |
|
|
|
250 |
|
|
def useGrub(self): |
251 |
|
|
return self.useGrubVal |
252 |
|
|
|
253 |
|
|
def setForceLBA(self, val): |
254 |
|
|
pass |
255 |
|
|
|
256 |
|
|
def setPassword(self, val, isCrypted = 1): |
257 |
|
|
pass |
258 |
|
|
|
259 |
|
|
def getPassword(self): |
260 |
|
|
pass |
261 |
|
|
|
262 |
|
|
def getDevice(self): |
263 |
|
|
return self.device |
264 |
|
|
|
265 |
|
|
def setDevice(self, device): |
266 |
|
|
self.device = device |
267 |
|
|
|
268 |
|
|
(dev, part) = getDiskPart(device) |
269 |
|
|
if part is None: |
270 |
|
|
self.defaultDevice = "mbr" |
271 |
|
|
else: |
272 |
|
|
self.defaultDevice = "partition" |
273 |
|
|
|
274 |
|
|
# XXX need to abstract out the requirement for a fsset to be able |
275 |
|
|
# to get it "on the fly" on a running system as well as being able |
276 |
|
|
# to get it how we do now from anaconda. probably by having the |
277 |
|
|
# first thing in the chain create a "fsset" object that has the |
278 |
|
|
# dictionary of mounted filesystems since that's what we care about |
279 |
|
|
def getBootloaderConfig(self, instRoot, fsset, bl, langs, kernelList, |
280 |
|
|
chainList, defaultDev): |
281 |
|
|
images = bl.images.getImages() |
282 |
|
|
|
283 |
|
|
# on upgrade read in the lilo config file |
284 |
|
|
lilo = LiloConfigFile () |
285 |
|
|
self.perms = 0600 |
286 |
|
|
if os.access (instRoot + self.configfile, os.R_OK): |
287 |
|
|
self.perms = os.stat(instRoot + self.configfile)[0] & 0777 |
288 |
|
|
lilo.read (instRoot + self.configfile) |
289 |
|
|
os.rename(instRoot + self.configfile, |
290 |
|
|
instRoot + self.configfile + '.rpmsave') |
291 |
|
|
# if it's an absolute symlink, just get it out of our way |
292 |
|
|
elif (os.path.islink(instRoot + self.configfile) and |
293 |
|
|
os.readlink(instRoot + self.configfile)[0] == '/'): |
294 |
|
|
os.rename(instRoot + self.configfile, |
295 |
|
|
instRoot + self.configfile + '.rpmsave') |
296 |
|
|
|
297 |
|
|
# Remove any invalid entries that are in the file; we probably |
298 |
|
|
# just removed those kernels. |
299 |
|
|
for label in lilo.listImages(): |
300 |
|
|
(fsType, sl, path, other) = lilo.getImage(label) |
301 |
|
|
if fsType == "other": continue |
302 |
|
|
|
303 |
|
|
if not os.access(instRoot + sl.getPath(), os.R_OK): |
304 |
|
|
lilo.delImage(label) |
305 |
|
|
|
306 |
|
|
lilo.addEntry("prompt", replace = 0) |
307 |
|
|
lilo.addEntry("timeout", "20", replace = 0) |
308 |
|
|
|
309 |
|
|
rootDev = fsset.getEntryByMountPoint("/").device.getDevice() |
310 |
|
|
if not rootDev: |
311 |
|
|
raise RuntimeError, "Installing lilo, but there is no root device" |
312 |
|
|
|
313 |
|
|
if rootDev == defaultDev: |
314 |
|
|
lilo.addEntry("default", kernelList[0][0]) |
315 |
|
|
else: |
316 |
|
|
lilo.addEntry("default", chainList[0][0]) |
317 |
|
|
|
318 |
|
|
for (label, longlabel, version) in kernelList: |
319 |
|
|
kernelTag = "-" + version |
320 |
|
|
kernelFile = self.kernelLocation + "vmlinuz" + kernelTag |
321 |
|
|
|
322 |
|
|
try: |
323 |
|
|
lilo.delImage(label) |
324 |
|
|
except IndexError, msg: |
325 |
|
|
pass |
326 |
|
|
|
327 |
|
|
sl = LiloConfigFile(imageType = "image", path = kernelFile) |
328 |
|
|
|
329 |
|
|
initrd = booty.makeInitrd (kernelTag, instRoot) |
330 |
|
|
|
331 |
|
|
sl.addEntry("label", label) |
332 |
|
|
if os.access (instRoot + initrd, os.R_OK): |
333 |
|
|
sl.addEntry("initrd", "%sinitrd%s.img" %(self.kernelLocation, |
334 |
|
|
kernelTag)) |
335 |
|
|
|
336 |
|
|
sl.addEntry("read-only") |
337 |
|
|
|
338 |
|
|
append = "%s" %(self.args.get(),) |
339 |
|
|
realroot = getRootDevName(initrd, fsset, rootDev, instRoot) |
340 |
|
|
if not realroot.startswith("LABEL="): |
341 |
|
|
sl.addEntry("root", '/dev/' + rootDev) |
342 |
|
|
else: |
343 |
|
|
if len(append) > 0: |
344 |
|
|
append = "%s root=%s" %(append,realroot) |
345 |
|
|
else: |
346 |
|
|
append = "root=%s" %(realroot,) |
347 |
|
|
|
348 |
|
|
if len(append) > 0: |
349 |
|
|
sl.addEntry('append', '"%s"' % (append,)) |
350 |
|
|
|
351 |
|
|
lilo.addImage (sl) |
352 |
|
|
|
353 |
|
|
for (label, longlabel, device) in chainList: |
354 |
|
|
if ((not label) or (label == "")): |
355 |
|
|
continue |
356 |
|
|
try: |
357 |
|
|
(fsType, sl, path, other) = lilo.getImage(label) |
358 |
|
|
lilo.delImage(label) |
359 |
|
|
except IndexError: |
360 |
|
|
sl = LiloConfigFile(imageType = "other", |
361 |
|
|
path = "/dev/%s" %(device)) |
362 |
|
|
sl.addEntry("optional") |
363 |
|
|
|
364 |
|
|
sl.addEntry("label", label) |
365 |
|
|
lilo.addImage (sl) |
366 |
|
|
|
367 |
|
|
# Sanity check #1. There could be aliases in sections which conflict |
368 |
|
|
# with the new images we just created. If so, erase those aliases |
369 |
|
|
imageNames = {} |
370 |
|
|
for label in lilo.listImages(): |
371 |
|
|
imageNames[label] = 1 |
372 |
|
|
|
373 |
|
|
for label in lilo.listImages(): |
374 |
|
|
(fsType, sl, path, other) = lilo.getImage(label) |
375 |
|
|
if sl.testEntry('alias'): |
376 |
|
|
alias = sl.getEntry('alias') |
377 |
|
|
if imageNames.has_key(alias): |
378 |
|
|
sl.delEntry('alias') |
379 |
|
|
imageNames[alias] = 1 |
380 |
|
|
|
381 |
|
|
# Sanity check #2. If single-key is turned on, go through all of |
382 |
|
|
# the image names (including aliases) (we just built the list) and |
383 |
|
|
# see if single-key will still work. |
384 |
|
|
if lilo.testEntry('single-key'): |
385 |
|
|
singleKeys = {} |
386 |
|
|
turnOff = 0 |
387 |
|
|
for label in imageNames.keys(): |
388 |
|
|
l = label[0] |
389 |
|
|
if singleKeys.has_key(l): |
390 |
|
|
turnOff = 1 |
391 |
|
|
singleKeys[l] = 1 |
392 |
|
|
if turnOff: |
393 |
|
|
lilo.delEntry('single-key') |
394 |
|
|
|
395 |
|
|
return lilo |
396 |
|
|
|
397 |
|
|
def write(self, instRoot, fsset, bl, langs, kernelList, chainList, |
398 |
|
|
defaultDev, justConfig, intf = None): |
399 |
|
|
if len(kernelList) >= 1: |
400 |
|
|
config = self.getBootloaderConfig(instRoot, fsset, bl, langs, |
401 |
|
|
kernelList, chainList, |
402 |
|
|
defaultDev) |
403 |
|
|
config.write(instRoot + self.configfile, perms = self.perms) |
404 |
|
|
else: |
405 |
|
|
self.noKernelsWarn(intf) |
406 |
|
|
|
407 |
|
|
return "" |
408 |
|
|
|
409 |
|
|
# XXX in the future we also should do some validation on the config |
410 |
|
|
# file that's already there |
411 |
|
|
# XXX concept of the intf isn't very well defined outside of anaconda... |
412 |
|
|
# probably should just pass back up an error |
413 |
|
|
def noKernelsWarn(self, intf): |
414 |
|
|
raise BootyNoKernelWarning |
415 |
|
|
|
416 |
|
|
def getArgList(self): |
417 |
|
|
args = [] |
418 |
|
|
|
419 |
|
|
if self.defaultDevice is None: |
420 |
|
|
args.append("--location=none") |
421 |
|
|
return args |
422 |
|
|
|
423 |
|
|
args.append("--location=%s" % (self.defaultDevice,)) |
424 |
slords |
1.5 |
args.append("--driveorder=%s" % (",".join(self.drivelist))) |
425 |
slords |
1.1 |
|
426 |
|
|
if self.args.get(): |
427 |
|
|
args.append("--append=\"%s\"" %(self.args.get())) |
428 |
|
|
|
429 |
|
|
return args |
430 |
|
|
|
431 |
|
|
def writeKS(self, f): |
432 |
|
|
f.write("bootloader") |
433 |
|
|
for arg in self.getArgList(): |
434 |
|
|
f.write(" " + arg) |
435 |
|
|
f.write("\n") |
436 |
|
|
|
437 |
|
|
def createDriveList(self): |
438 |
|
|
# create a drive list that we can use for drive mappings |
439 |
|
|
# XXX has anaconda internals knowledge |
440 |
|
|
import isys |
441 |
|
|
import flags |
442 |
|
|
drives = isys.hardDriveDict().keys() |
443 |
|
|
drives.sort (isys.compareDrives) |
444 |
|
|
|
445 |
|
|
# now filter out all of the removable media unless expert mode |
446 |
|
|
rc = [] |
447 |
|
|
for drive in drives: |
448 |
|
|
if not isys.driveIsRemovable(drive) or flags.flags.expert: |
449 |
|
|
rc.append(drive) |
450 |
|
|
return rc |
451 |
|
|
|
452 |
|
|
def __init__(self): |
453 |
|
|
self.args = KernelArguments() |
454 |
|
|
self.images = BootImages() |
455 |
|
|
self.device = None |
456 |
|
|
self.defaultDevice = None # XXX hack, used by kickstart |
457 |
|
|
self.useGrubVal = 0 # only used on x86 |
458 |
|
|
self.configfile = None |
459 |
|
|
self.kernelLocation = "/boot/" |
460 |
|
|
self.forceLBA32 = 0 |
461 |
|
|
self.password = None |
462 |
|
|
self.pure = None |
463 |
|
|
self.above1024 = 0 |
464 |
|
|
|
465 |
|
|
# this has somewhat strange semantics. if 0, act like a normal |
466 |
|
|
# "install" case. if 1, update lilo.conf (since grubby won't do that) |
467 |
|
|
# and then run lilo or grub only. |
468 |
|
|
# XXX THIS IS A HACK. implementation details are only there for x86 |
469 |
|
|
self.doUpgradeOnly = 0 |
470 |
|
|
self.kickstart = 0 |
471 |
|
|
|
472 |
|
|
self.drivelist = self.createDriveList() |
473 |
|
|
|
474 |
|
|
from flags import flags |
475 |
|
|
if flags.serial != 0: |
476 |
|
|
# now look at /proc/cmdline to pull any serial console |
477 |
|
|
# args |
478 |
|
|
f = open("/proc/cmdline", "r") |
479 |
|
|
cmdline = f.read()[:-1] |
480 |
|
|
f.close() |
481 |
|
|
|
482 |
|
|
options = "" |
483 |
|
|
device = None |
484 |
|
|
cmdlineargs = cmdline.split(" ") |
485 |
|
|
for arg in cmdlineargs: |
486 |
|
|
# found a console argument |
487 |
|
|
if arg.startswith("console="): |
488 |
|
|
(foo, console) = arg.split("=") |
489 |
|
|
# the options are everything after the comma |
490 |
|
|
comma = console.find(",") |
491 |
|
|
if comma != -1: |
492 |
|
|
options = console[comma:] |
493 |
|
|
device = console[:comma] |
494 |
|
|
else: |
495 |
|
|
options = "" |
496 |
|
|
device = console |
497 |
|
|
|
498 |
|
|
if device is None: |
499 |
|
|
self.serialDevice = "ttyS0" |
500 |
|
|
self.serialOptions = "" |
501 |
|
|
else: |
502 |
|
|
self.serialDevice = device |
503 |
|
|
# don't keep the comma in the options |
504 |
|
|
self.serialOptions = options[1:] |
505 |
|
|
|
506 |
|
|
self.args.append("console=%s%s" %(self.serialDevice, options)) |
507 |
|
|
|
508 |
|
|
self.serial = 1 |
509 |
|
|
else: |
510 |
|
|
self.serial = 0 |
511 |
|
|
self.serialDevice = None |
512 |
|
|
self.serialOptions = None |
513 |
|
|
|
514 |
|
|
if flags.virtpconsole is not None: |
515 |
|
|
if flags.virtpconsole.startswith("/dev/"): |
516 |
|
|
con = flags.virtpconsole[5:] |
517 |
|
|
else: |
518 |
|
|
con = flags.virtpconsole |
519 |
|
|
self.args.append("console=%s" %(con,)) |
520 |
|
|
|
521 |
|
|
|
522 |
|
|
class ia64BootloaderInfo(bootloaderInfo): |
523 |
|
|
# XXX wouldn't it be nice to have a real interface to use efibootmgr from? |
524 |
|
|
def removeOldEfiEntries(self, instRoot): |
525 |
|
|
p = os.pipe() |
526 |
|
|
rhpl.executil.execWithRedirect('/usr/sbin/efibootmgr', ["efibootmgr"], |
527 |
|
|
root = instRoot, stdout = p[1]) |
528 |
|
|
os.close(p[1]) |
529 |
|
|
|
530 |
|
|
c = os.read(p[0], 1) |
531 |
|
|
buf = c |
532 |
|
|
while (c): |
533 |
|
|
c = os.read(p[0], 1) |
534 |
|
|
buf = buf + c |
535 |
|
|
os.close(p[0]) |
536 |
|
|
lines = string.split(buf, '\n') |
537 |
|
|
for line in lines: |
538 |
|
|
fields = string.split(line) |
539 |
|
|
if len(fields) < 2: |
540 |
|
|
continue |
541 |
|
|
if string.join(fields[1:], " ") == butil.getProductName(): |
542 |
|
|
entry = fields[0][4:8] |
543 |
|
|
rhpl.executil.execWithRedirect('/usr/sbin/efibootmgr', |
544 |
|
|
["efibootmgr", "-b", entry, "-B"], |
545 |
|
|
root = instRoot, |
546 |
|
|
stdout="/dev/tty5", stderr="/dev/tty5") |
547 |
|
|
|
548 |
|
|
def getBootloaderConfig(self, instRoot, fsset, bl, langs, kernelList, |
549 |
|
|
chainList, defaultDev): |
550 |
|
|
config = bootloaderInfo.getBootloaderConfig(self, instRoot, fsset, |
551 |
|
|
bl, langs, |
552 |
|
|
kernelList, chainList, |
553 |
|
|
defaultDev) |
554 |
|
|
# altix boxes need relocatable (#120851) |
555 |
|
|
config.addEntry("relocatable") |
556 |
|
|
|
557 |
|
|
return config |
558 |
|
|
|
559 |
|
|
def writeLilo(self, instRoot, fsset, bl, langs, kernelList, |
560 |
|
|
chainList, defaultDev, justConfig): |
561 |
|
|
config = self.getBootloaderConfig(instRoot, fsset, bl, langs, |
562 |
|
|
kernelList, chainList, defaultDev) |
563 |
|
|
config.write(instRoot + self.configfile, perms = self.perms) |
564 |
|
|
|
565 |
|
|
return "" |
566 |
|
|
|
567 |
|
|
def write(self, instRoot, fsset, bl, langs, kernelList, chainList, |
568 |
|
|
defaultDev, justConfig, intf): |
569 |
|
|
if len(kernelList) >= 1: |
570 |
|
|
str = self.writeLilo(instRoot, fsset, bl, langs, kernelList, |
571 |
|
|
chainList, defaultDev, justConfig) |
572 |
|
|
else: |
573 |
|
|
self.noKernelsWarn(intf) |
574 |
|
|
|
575 |
|
|
bootdev = fsset.getEntryByMountPoint("/boot/efi").device.getDevice() |
576 |
|
|
if not bootdev: |
577 |
|
|
bootdev = fsset.getEntryByDeviceName("sda1").device.getDevice() |
578 |
|
|
|
579 |
|
|
if not os.access(instRoot + "/etc/elilo.conf", os.R_OK): |
580 |
|
|
os.symlink("../" + self.configfile, instRoot + "/etc/elilo.conf") |
581 |
|
|
|
582 |
|
|
ind = len(bootdev) |
583 |
|
|
try: |
584 |
|
|
while (bootdev[ind-1] in string.digits): |
585 |
|
|
ind = ind - 1 |
586 |
|
|
except IndexError: |
587 |
|
|
ind = len(bootdev) - 1 |
588 |
|
|
|
589 |
|
|
bootdisk = bootdev[:ind] |
590 |
|
|
bootpart = bootdev[ind:] |
591 |
|
|
if (bootdisk.startswith('ida/') or bootdisk.startswith('cciss/') or |
592 |
slords |
1.5 |
bootdisk.startswith('rd/') or bootdisk.startswith('sx8/')): |
593 |
slords |
1.1 |
bootdisk = bootdisk[:-1] |
594 |
|
|
|
595 |
|
|
self.removeOldEfiEntries(instRoot) |
596 |
|
|
|
597 |
|
|
argv = [ "/usr/sbin/efibootmgr", "-c" , "-w", "-L", |
598 |
|
|
butil.getProductName(), "-d", "/dev/%s" % bootdisk, |
599 |
|
|
"-p", bootpart, "-l", "EFI\\redhat\\elilo.efi" ] |
600 |
|
|
rhpl.executil.execWithRedirect(argv[0], argv, root = instRoot, |
601 |
|
|
stdout = "/dev/tty5", |
602 |
|
|
stderr = "/dev/tty5") |
603 |
|
|
|
604 |
|
|
|
605 |
|
|
def __init__(self): |
606 |
|
|
bootloaderInfo.__init__(self) |
607 |
|
|
self.useGrubVal = 1 |
608 |
|
|
self.kernelLocation = "" |
609 |
|
|
self.configfile = "/boot/efi/EFI/redhat/elilo.conf" |
610 |
|
|
|
611 |
|
|
|
612 |
|
|
class x86BootloaderInfo(bootloaderInfo): |
613 |
|
|
def setPassword(self, val, isCrypted = 1): |
614 |
|
|
if not val: |
615 |
|
|
self.password = val |
616 |
|
|
self.pure = val |
617 |
|
|
return |
618 |
|
|
|
619 |
|
|
if isCrypted and self.useGrubVal == 0: |
620 |
|
|
log("requested crypted password with lilo; ignoring") |
621 |
|
|
self.pure = None |
622 |
|
|
return |
623 |
|
|
elif isCrypted: |
624 |
|
|
self.password = val |
625 |
|
|
self.pure = None |
626 |
|
|
else: |
627 |
|
|
salt = "$1$" |
628 |
|
|
saltLen = 8 |
629 |
|
|
|
630 |
|
|
for i in range(saltLen): |
631 |
slords |
1.5 |
salt = salt + random.choice (string.letters + |
632 |
|
|
string.digits + './') |
633 |
slords |
1.1 |
|
634 |
|
|
self.password = crypt.crypt (val, salt) |
635 |
|
|
self.pure = val |
636 |
|
|
|
637 |
|
|
def getPassword (self): |
638 |
|
|
return self.pure |
639 |
|
|
|
640 |
|
|
def setForceLBA(self, val): |
641 |
|
|
self.forceLBA32 = val |
642 |
|
|
|
643 |
|
|
def setUseGrub(self, val): |
644 |
|
|
self.useGrubVal = val |
645 |
|
|
|
646 |
|
|
def getPhysicalDevices(self, device): |
647 |
|
|
# This finds a list of devices on which the given device name resides. |
648 |
|
|
# Accepted values for "device" are raid1 md devices (i.e. "md0"), |
649 |
|
|
# physical disks ("hda"), and real partitions on physical disks |
650 |
|
|
# ("hda1"). Volume groups/logical volumes are not accepted. |
651 |
|
|
# |
652 |
|
|
# XXX this has internal anaconda-ish knowledge. ick. |
653 |
|
|
import isys |
654 |
|
|
import lvm |
655 |
|
|
|
656 |
|
|
if string.split(device, '/', 1)[0] in map (lambda vg: vg[0], |
657 |
|
|
lvm.vglist()): |
658 |
|
|
return [] |
659 |
|
|
|
660 |
|
|
if device.startswith('md'): |
661 |
|
|
bootable = 0 |
662 |
|
|
parts = checkbootloader.getRaidDisks(device, 1, stripPart=0) |
663 |
|
|
parts.sort() |
664 |
|
|
return parts |
665 |
|
|
|
666 |
|
|
return [device] |
667 |
|
|
|
668 |
|
|
def writeGrub(self, instRoot, fsset, bl, langs, kernelList, chainList, |
669 |
|
|
defaultDev, justConfigFile): |
670 |
|
|
if len(kernelList) < 1: |
671 |
|
|
return "" |
672 |
|
|
|
673 |
|
|
images = bl.images.getImages() |
674 |
|
|
rootDev = fsset.getEntryByMountPoint("/").device.getDevice() |
675 |
|
|
|
676 |
|
|
if not os.path.isdir(instRoot + '/boot/grub/'): |
677 |
|
|
os.mkdir(instRoot + '/boot/grub', 0755) |
678 |
|
|
|
679 |
|
|
# XXX old config file should be read here for upgrade |
680 |
|
|
|
681 |
|
|
cf = '/boot/grub/grub.conf' |
682 |
|
|
self.perms = 0600 |
683 |
|
|
if os.access (instRoot + cf, os.R_OK): |
684 |
|
|
self.perms = os.stat(instRoot + cf)[0] & 0777 |
685 |
|
|
os.rename(instRoot + cf, |
686 |
|
|
instRoot + cf + '.rpmsave') |
687 |
|
|
|
688 |
|
|
grubTarget = bl.getDevice() |
689 |
|
|
target = "mbr" |
690 |
|
|
if grubTarget[-1].isdigit() and not grubTarget.startswith('md'): |
691 |
|
|
target = "partition" |
692 |
slords |
1.5 |
|
693 |
slords |
1.1 |
f = open(instRoot + cf, "w+") |
694 |
|
|
|
695 |
|
|
f.write("# grub.conf generated by anaconda\n") |
696 |
|
|
f.write("#\n") |
697 |
|
|
f.write("# Note that you do not have to rerun grub " |
698 |
|
|
"after making changes to this file\n") |
699 |
|
|
|
700 |
|
|
bootDev = fsset.getEntryByMountPoint("/boot") |
701 |
|
|
grubPath = "/grub" |
702 |
|
|
cfPath = "/" |
703 |
|
|
if not bootDev: |
704 |
|
|
bootDev = fsset.getEntryByMountPoint("/") |
705 |
|
|
grubPath = "/boot/grub" |
706 |
|
|
cfPath = "/boot/" |
707 |
|
|
f.write("# NOTICE: You do not have a /boot partition. " |
708 |
|
|
"This means that\n") |
709 |
|
|
f.write("# all kernel and initrd paths are relative " |
710 |
|
|
"to /, eg.\n") |
711 |
|
|
else: |
712 |
|
|
f.write("# NOTICE: You have a /boot partition. This means " |
713 |
|
|
"that\n") |
714 |
|
|
f.write("# all kernel and initrd paths are relative " |
715 |
|
|
"to /boot/, eg.\n") |
716 |
|
|
|
717 |
|
|
bootDevs = self.getPhysicalDevices(bootDev.device.getDevice()) |
718 |
|
|
bootDev = bootDev.device.getDevice() |
719 |
slords |
1.5 |
|
720 |
slords |
1.1 |
f.write('# root %s\n' % self.grubbyPartitionName(bootDevs[0])) |
721 |
|
|
f.write("# kernel %svmlinuz-version ro " |
722 |
|
|
"root=/dev/%s\n" % (cfPath, rootDev)) |
723 |
|
|
f.write("# initrd %sinitrd-version.img\n" % (cfPath)) |
724 |
|
|
f.write("#boot=/dev/%s\n" % (grubTarget)) |
725 |
|
|
|
726 |
slords |
1.5 |
# Check to see if smp kernel should be default or not |
727 |
slords |
1.3 |
if isys.smpAvailable() or isys.htavailable(): |
728 |
|
|
smpCapable=1 |
729 |
slords |
1.5 |
else: |
730 |
slords |
1.3 |
smpCapable=0 |
731 |
|
|
|
732 |
slords |
1.1 |
# get the default image to boot... we have to walk and find it |
733 |
|
|
# since grub indexes by where it is in the config file |
734 |
|
|
if defaultDev == rootDev: |
735 |
slords |
1.2 |
for kernel in range(0, len(kernelList)): |
736 |
|
|
default=kernel |
737 |
slords |
1.3 |
version=kernelList[kernel][2] |
738 |
|
|
if version.find('smp')<0 and not smpCapable: |
739 |
|
|
break |
740 |
|
|
if version.find('smp')>=0 and smpCapable: |
741 |
|
|
break |
742 |
slords |
1.1 |
else: |
743 |
|
|
# if the default isn't linux, it's the first thing in the |
744 |
|
|
# chain list |
745 |
|
|
default = len(kernelList) |
746 |
|
|
|
747 |
|
|
# keep track of which devices are used for the device.map |
748 |
|
|
usedDevs = {} |
749 |
|
|
|
750 |
|
|
f.write('default=%s\n' % (default)) |
751 |
|
|
if len(chainList) > 0: |
752 |
|
|
timeout = 5 |
753 |
|
|
else: |
754 |
|
|
timeout = 5 |
755 |
|
|
f.write('timeout=%d\n' %(timeout,)) |
756 |
|
|
|
757 |
|
|
if self.serial == 1: |
758 |
|
|
# grub the 0-based number of the serial console device |
759 |
|
|
unit = self.serialDevice[-1] |
760 |
|
|
|
761 |
|
|
# and we want to set the speed too |
762 |
|
|
speedend = 0 |
763 |
|
|
for char in self.serialOptions: |
764 |
|
|
if char not in string.digits: |
765 |
|
|
break |
766 |
|
|
speedend = speedend + 1 |
767 |
|
|
if speedend != 0: |
768 |
|
|
speed = self.serialOptions[:speedend] |
769 |
|
|
else: |
770 |
|
|
# reasonable default |
771 |
|
|
speed = "9600" |
772 |
|
|
|
773 |
|
|
f.write("serial --unit=%s --speed=%s\n" %(unit, speed)) |
774 |
|
|
f.write("terminal --timeout=5 serial console\n") |
775 |
|
|
else: |
776 |
|
|
# we only want splashimage if they're not using a serial console |
777 |
|
|
if os.access("%s/boot/grub/splash.xpm.gz" %(instRoot,), os.R_OK): |
778 |
|
|
f.write('splashimage=%s%sgrub/splash.xpm.gz\n' |
779 |
|
|
% (self.grubbyPartitionName(bootDevs[0]), cfPath)) |
780 |
|
|
f.write("hiddenmenu\n") |
781 |
|
|
|
782 |
|
|
for dev in self.getPhysicalDevices(grubTarget): |
783 |
|
|
usedDevs[dev] = 1 |
784 |
slords |
1.5 |
|
785 |
slords |
1.1 |
if self.password: |
786 |
|
|
f.write('password --md5 %s\n' %(self.password)) |
787 |
|
|
|
788 |
|
|
for (label, longlabel, version) in kernelList: |
789 |
|
|
kernelTag = "-" + version |
790 |
|
|
kernelFile = "%svmlinuz%s" % (cfPath, kernelTag) |
791 |
|
|
|
792 |
|
|
initrd = booty.makeInitrd (kernelTag, instRoot) |
793 |
|
|
|
794 |
|
|
f.write('title %s (%s)\n' % (longlabel, version)) |
795 |
|
|
f.write('\troot %s\n' % self.grubbyPartitionName(bootDevs[0])) |
796 |
|
|
|
797 |
|
|
realroot = getRootDevName(initrd, fsset, rootDev, instRoot) |
798 |
|
|
realroot = " root=%s" %(realroot,) |
799 |
|
|
|
800 |
|
|
f.write('\tkernel %s ro%s' % (kernelFile, realroot)) |
801 |
|
|
if self.args.get(): |
802 |
|
|
f.write(' %s' % self.args.get()) |
803 |
|
|
f.write('\n') |
804 |
|
|
|
805 |
|
|
if os.access (instRoot + initrd, os.R_OK): |
806 |
|
|
f.write('\tinitrd %sinitrd%s.img\n' % (cfPath, kernelTag)) |
807 |
|
|
|
808 |
|
|
for (label, longlabel, device) in chainList: |
809 |
|
|
if ((not longlabel) or (longlabel == "")): |
810 |
|
|
continue |
811 |
|
|
f.write('title %s\n' % (longlabel)) |
812 |
|
|
f.write('\trootnoverify %s\n' % self.grubbyPartitionName(device)) |
813 |
|
|
# f.write('\tmakeactive\n') |
814 |
|
|
f.write('\tchainloader +1') |
815 |
|
|
f.write('\n') |
816 |
|
|
usedDevs[device] = 1 |
817 |
|
|
|
818 |
|
|
f.close() |
819 |
|
|
os.chmod(instRoot + "/boot/grub/grub.conf", self.perms) |
820 |
|
|
|
821 |
|
|
try: |
822 |
|
|
# make symlink for menu.lst (default config file name) |
823 |
|
|
if os.access (instRoot + "/boot/grub/menu.lst", os.R_OK): |
824 |
|
|
os.rename(instRoot + "/boot/grub/menu.lst", |
825 |
|
|
instRoot + "/boot/grub/menu.lst.rpmsave") |
826 |
|
|
os.symlink("./grub.conf", instRoot + "/boot/grub/menu.lst") |
827 |
|
|
except: |
828 |
|
|
pass |
829 |
|
|
|
830 |
|
|
try: |
831 |
|
|
# make symlink for /etc/grub.conf (config files belong in /etc) |
832 |
|
|
if os.access (instRoot + "/etc/grub.conf", os.R_OK): |
833 |
|
|
os.rename(instRoot + "/etc/grub.conf", |
834 |
|
|
instRoot + "/etc/grub.conf.rpmsave") |
835 |
|
|
os.symlink("../boot/grub/grub.conf", instRoot + "/etc/grub.conf") |
836 |
|
|
except: |
837 |
|
|
pass |
838 |
|
|
|
839 |
|
|
for dev in self.getPhysicalDevices(rootDev): |
840 |
|
|
usedDevs[dev] = 1 |
841 |
|
|
|
842 |
|
|
if not os.access(instRoot + "/boot/grub/device.map", os.R_OK): |
843 |
|
|
f = open(instRoot + "/boot/grub/device.map", "w+") |
844 |
|
|
f.write("# this device map was generated by anaconda\n") |
845 |
|
|
f.write("(fd0) /dev/fd0\n") |
846 |
|
|
devs = usedDevs.keys() |
847 |
|
|
usedDevs = {} |
848 |
|
|
for dev in devs: |
849 |
|
|
drive = getDiskPart(dev)[0] |
850 |
|
|
if usedDevs.has_key(drive): |
851 |
|
|
continue |
852 |
|
|
usedDevs[drive] = 1 |
853 |
|
|
devs = usedDevs.keys() |
854 |
|
|
devs.sort() |
855 |
|
|
for drive in devs: |
856 |
|
|
# XXX hack city. If they're not the sort of thing that'll |
857 |
|
|
# be in the device map, they shouldn't still be in the list. |
858 |
|
|
if not drive.startswith('md'): |
859 |
|
|
f.write("(%s) /dev/%s\n" % (self.grubbyDiskName(drive), |
860 |
slords |
1.5 |
drive)) |
861 |
slords |
1.1 |
f.close() |
862 |
|
|
|
863 |
|
|
if self.forceLBA32: |
864 |
|
|
forcelba = "--force-lba " |
865 |
|
|
else: |
866 |
|
|
forcelba = "" |
867 |
|
|
|
868 |
|
|
sysconf = '/etc/sysconfig/grub' |
869 |
|
|
if os.access (instRoot + sysconf, os.R_OK): |
870 |
|
|
self.perms = os.stat(instRoot + sysconf)[0] & 0777 |
871 |
|
|
os.rename(instRoot + sysconf, |
872 |
|
|
instRoot + sysconf + '.rpmsave') |
873 |
|
|
# if it's an absolute symlink, just get it out of our way |
874 |
|
|
elif (os.path.islink(instRoot + sysconf) and |
875 |
|
|
os.readlink(instRoot + sysconf)[0] == '/'): |
876 |
|
|
os.rename(instRoot + sysconf, |
877 |
|
|
instRoot + sysconf + '.rpmsave') |
878 |
|
|
f = open(instRoot + sysconf, 'w+') |
879 |
|
|
f.write("boot=/dev/%s\n" %(grubTarget,)) |
880 |
slords |
1.5 |
# XXX forcelba never gets read back... |
881 |
slords |
1.1 |
if self.forceLBA32: |
882 |
|
|
f.write("forcelba=1\n") |
883 |
|
|
else: |
884 |
|
|
f.write("forcelba=0\n") |
885 |
|
|
f.close() |
886 |
|
|
|
887 |
|
|
cmds = [] |
888 |
|
|
for bootDev in bootDevs: |
889 |
|
|
gtPart = self.getMatchingPart(bootDev, grubTarget) |
890 |
|
|
gtDisk = self.grubbyPartitionName(getDiskPart(gtPart)[0]) |
891 |
slords |
1.5 |
bPart = self.grubbyPartitionName(bootDev) |
892 |
slords |
1.1 |
cmd = "root %s" % (bPart,) |
893 |
|
|
cmds.append(cmd) |
894 |
|
|
|
895 |
|
|
stage1Target = gtDisk |
896 |
|
|
if target == "partition": |
897 |
|
|
stage1Target = self.grubbyPartitionName(gtPart) |
898 |
|
|
|
899 |
slords |
1.5 |
cmd = "install %s%s/stage1 d %s %s/stage2 p %s%s/grub.conf" % \ |
900 |
|
|
(forcelba, grubPath, stage1Target, grubPath, bPart, grubPath) |
901 |
slords |
1.1 |
cmds.append(cmd) |
902 |
slords |
1.5 |
|
903 |
slords |
1.1 |
if not justConfigFile: |
904 |
|
|
log("GRUB commands:") |
905 |
|
|
for cmd in cmds: |
906 |
|
|
log("\t%s\n", cmd) |
907 |
|
|
|
908 |
|
|
# copy the stage files over into /boot |
909 |
|
|
rhpl.executil.execWithRedirect( "/sbin/grub-install", |
910 |
|
|
["/sbin/grub-install", "--just-copy"], |
911 |
|
|
stdout = "/dev/tty5", stderr = "/dev/tty5", |
912 |
|
|
root = instRoot) |
913 |
|
|
|
914 |
|
|
|
915 |
|
|
|
916 |
|
|
# FIXME: hack to try to make sure everything is written to the disk |
917 |
|
|
if cfPath == "/": |
918 |
|
|
syncDataToDisk(bootDev, "/boot", instRoot) |
919 |
|
|
else: |
920 |
|
|
syncDataToDisk(bootDev, "/", instRoot) |
921 |
|
|
|
922 |
|
|
# really install the bootloader |
923 |
|
|
p = os.pipe() |
924 |
|
|
for cmd in cmds: |
925 |
slords |
1.5 |
os.write(p[1], cmd + '\n') |
926 |
slords |
1.1 |
os.close(p[1]) |
927 |
|
|
rhpl.executil.execWithRedirect('/sbin/grub' , |
928 |
|
|
[ "grub", "--batch", "--no-floppy", |
929 |
|
|
"--device-map=/boot/grub/device.map" ], |
930 |
|
|
stdin = p[0], |
931 |
|
|
stdout = "/dev/tty5", stderr = "/dev/tty5", |
932 |
|
|
root = instRoot) |
933 |
|
|
os.close(p[0]) |
934 |
|
|
|
935 |
|
|
return "" |
936 |
|
|
|
937 |
|
|
def getMatchingPart(self, bootDev, target): |
938 |
|
|
bootName, bootPartNum = getDiskPart(bootDev) |
939 |
|
|
devices = self.getPhysicalDevices(target) |
940 |
|
|
for device in devices: |
941 |
|
|
name, partNum = getDiskPart(device) |
942 |
|
|
if name == bootName: |
943 |
|
|
return device |
944 |
|
|
return devices[0] |
945 |
|
|
|
946 |
|
|
def grubbyDiskName(self, name): |
947 |
|
|
return "hd%d" % self.drivelist.index(name) |
948 |
|
|
|
949 |
|
|
def grubbyPartitionName(self, dev): |
950 |
|
|
(name, partNum) = getDiskPart(dev) |
951 |
|
|
if partNum != None: |
952 |
|
|
return "(%s,%d)" % (self.grubbyDiskName(name), partNum) |
953 |
|
|
else: |
954 |
|
|
return "(%s)" %(self.grubbyDiskName(name)) |
955 |
|
|
|
956 |
|
|
|
957 |
|
|
def getBootloaderConfig(self, instRoot, fsset, bl, langs, kernelList, |
958 |
|
|
chainList, defaultDev): |
959 |
|
|
config = bootloaderInfo.getBootloaderConfig(self, instRoot, fsset, |
960 |
|
|
bl, langs, |
961 |
|
|
kernelList, chainList, |
962 |
|
|
defaultDev) |
963 |
|
|
|
964 |
|
|
liloTarget = bl.getDevice() |
965 |
|
|
|
966 |
|
|
config.addEntry("boot", '/dev/' + liloTarget, replace = 0) |
967 |
|
|
config.addEntry("map", "/boot/map", replace = 0) |
968 |
|
|
config.addEntry("install", "/boot/boot.b", replace = 0) |
969 |
|
|
message = "/boot/message" |
970 |
|
|
|
971 |
|
|
if self.pure is not None and not self.useGrubVal: |
972 |
|
|
config.addEntry("restricted", replace = 0) |
973 |
|
|
config.addEntry("password", self.pure, replace = 0) |
974 |
|
|
|
975 |
|
|
|
976 |
|
|
import language |
977 |
|
|
for lang in language.expandLangs(langs.getDefault()): |
978 |
|
|
fn = "/boot/message." + lang |
979 |
|
|
if os.access(instRoot + fn, os.R_OK): |
980 |
|
|
message = fn |
981 |
|
|
break |
982 |
|
|
|
983 |
|
|
if self.serial == 1: |
984 |
|
|
# grab the 0-based number of the serial console device |
985 |
|
|
unit = self.serialDevice[-1] |
986 |
|
|
# FIXME: we should probably put some options, but lilo |
987 |
|
|
# only supports up to 9600 baud so just use the defaults |
988 |
|
|
# it's better than nothing :( |
989 |
|
|
config.addEntry("serial=%s" %(unit,)) |
990 |
|
|
else: |
991 |
|
|
# message screws up serial console |
992 |
|
|
if os.access(instRoot + message, os.R_OK): |
993 |
|
|
config.addEntry("message", message, replace = 0) |
994 |
|
|
|
995 |
slords |
1.5 |
if not config.testEntry('lba32'): |
996 |
slords |
1.1 |
if self.forceLBA32 or (bl.above1024 and |
997 |
|
|
butil.getArch() != "x86_64" and |
998 |
|
|
edd.detect()): |
999 |
|
|
config.addEntry("lba32", replace = 0) |
1000 |
|
|
|
1001 |
|
|
return config |
1002 |
|
|
|
1003 |
|
|
# this is a hackish function that depends on the way anaconda writes |
1004 |
|
|
# out the grub.conf with a #boot= comment |
1005 |
|
|
# XXX this falls into the category of self.doUpgradeOnly |
1006 |
|
|
def upgradeGrub(self, instRoot, fsset, bl, langs, kernelList, chainList, |
1007 |
|
|
defaultDev, justConfigFile): |
1008 |
|
|
if justConfigFile: |
1009 |
|
|
return "" |
1010 |
|
|
|
1011 |
|
|
theDev = None |
1012 |
|
|
for (fn, stanza) in [ ("/etc/sysconfig/grub", "boot="), |
1013 |
|
|
("/boot/grub/grub.conf", "#boot=") ]: |
1014 |
|
|
try: |
1015 |
|
|
f = open(instRoot + fn, "r") |
1016 |
|
|
except: |
1017 |
|
|
continue |
1018 |
|
|
|
1019 |
|
|
# the following bits of code are straight from checkbootloader.py |
1020 |
|
|
lines = f.readlines() |
1021 |
|
|
f.close() |
1022 |
|
|
for line in lines: |
1023 |
|
|
if line.startswith(stanza): |
1024 |
|
|
theDev = checkbootloader.getBootDevString(line) |
1025 |
|
|
break |
1026 |
|
|
if theDev is not None: |
1027 |
|
|
break |
1028 |
|
|
|
1029 |
|
|
if theDev is None: |
1030 |
|
|
# we could find the dev before, but can't now... cry about it |
1031 |
|
|
return "" |
1032 |
|
|
|
1033 |
|
|
# migrate info to /etc/sysconfig/grub |
1034 |
|
|
sysconf = '/etc/sysconfig/grub' |
1035 |
|
|
if not os.access(instRoot + sysconf, os.R_OK): |
1036 |
|
|
f = open(instRoot + sysconf, "w+") |
1037 |
|
|
f.write("boot=%s\n" %(theDev,)) |
1038 |
slords |
1.5 |
# XXX forcelba never gets read back at all... |
1039 |
slords |
1.1 |
if self.forceLBA32: |
1040 |
|
|
f.write("forcelba=1\n") |
1041 |
|
|
else: |
1042 |
|
|
f.write("forcelba=0\n") |
1043 |
|
|
f.close() |
1044 |
|
|
|
1045 |
|
|
# more suckage. grub-install can't work without a valid /etc/mtab |
1046 |
|
|
# so we have to do shenanigans to get updated grub installed... |
1047 |
|
|
# steal some more code above |
1048 |
|
|
bootDev = fsset.getEntryByMountPoint("/boot") |
1049 |
|
|
grubPath = "/grub" |
1050 |
|
|
cfPath = "/" |
1051 |
|
|
if not bootDev: |
1052 |
|
|
bootDev = fsset.getEntryByMountPoint("/") |
1053 |
|
|
grubPath = "/boot/grub" |
1054 |
|
|
cfPath = "/boot/" |
1055 |
|
|
|
1056 |
|
|
masterBootDev = bootDev.device.getDevice(asBoot = 0) |
1057 |
|
|
if masterBootDev[0:2] == 'md': |
1058 |
|
|
rootDevs = checkbootloader.getRaidDisks(masterBootDev, raidLevel=1, |
1059 |
|
|
stripPart = 0) |
1060 |
|
|
else: |
1061 |
|
|
rootDevs = [masterBootDev] |
1062 |
|
|
|
1063 |
|
|
if theDev[5:7] == 'md': |
1064 |
|
|
stage1Devs = checkbootloader.getRaidDisks(theDev[5:], raidLevel=1) |
1065 |
|
|
else: |
1066 |
|
|
stage1Devs = [theDev[5:]] |
1067 |
|
|
|
1068 |
|
|
for stage1Dev in stage1Devs: |
1069 |
|
|
# cross fingers; if we can't find a root device on the same |
1070 |
|
|
# hardware as this boot device, we just blindly hope the first |
1071 |
|
|
# thing in the list works. |
1072 |
|
|
|
1073 |
|
|
grubbyStage1Dev = self.grubbyPartitionName(stage1Dev) |
1074 |
|
|
|
1075 |
|
|
grubbyRootPart = self.grubbyPartitionName(rootDevs[0]) |
1076 |
|
|
|
1077 |
|
|
for rootDev in rootDevs: |
1078 |
|
|
testGrubbyRootDev = getDiskPart(rootDev)[0] |
1079 |
|
|
testGrubbyRootDev = self.grubbyPartitionName(testGrubbyRootDev) |
1080 |
|
|
|
1081 |
|
|
if grubbyStage1Dev == testGrubbyRootDev: |
1082 |
|
|
grubbyRootPart = self.grubbyPartitionName(rootDev) |
1083 |
|
|
break |
1084 |
|
|
|
1085 |
slords |
1.5 |
cmd = "root %s\ninstall %s/stage1 d %s %s/stage2 p %s%s/grub.conf" \ |
1086 |
|
|
% (grubbyRootPart, grubPath, grubbyStage1Dev, |
1087 |
|
|
grubPath, grubbyRootPart, grubPath) |
1088 |
slords |
1.1 |
|
1089 |
slords |
1.5 |
if not justConfigFile: |
1090 |
|
|
log("GRUB command %s", cmd) |
1091 |
slords |
1.1 |
|
1092 |
slords |
1.5 |
# copy the stage files over into /boot |
1093 |
|
|
rhpl.executil.execWithRedirect( "/sbin/grub-install", |
1094 |
slords |
1.1 |
["/sbin/grub-install", "--just-copy"], |
1095 |
|
|
stdout = "/dev/tty5", stderr = "/dev/tty5", |
1096 |
|
|
root = instRoot) |
1097 |
|
|
|
1098 |
slords |
1.5 |
# get the stage files synced to disk |
1099 |
|
|
import isys |
1100 |
|
|
isys.sync() |
1101 |
|
|
isys.sync() |
1102 |
|
|
isys.sync() |
1103 |
slords |
1.1 |
|
1104 |
slords |
1.5 |
# really install the bootloader |
1105 |
|
|
p = os.pipe() |
1106 |
|
|
os.write(p[1], cmd + '\n') |
1107 |
|
|
os.close(p[1]) |
1108 |
|
|
rhpl.executil.execWithRedirect('/sbin/grub' , |
1109 |
slords |
1.1 |
[ "grub", "--batch", "--no-floppy", |
1110 |
|
|
"--device-map=/boot/grub/device.map" ], |
1111 |
|
|
stdin = p[0], |
1112 |
|
|
stdout = "/dev/tty5", stderr = "/dev/tty5", |
1113 |
|
|
root = instRoot) |
1114 |
slords |
1.5 |
os.close(p[0]) |
1115 |
slords |
1.1 |
|
1116 |
|
|
return "" |
1117 |
|
|
|
1118 |
|
|
|
1119 |
|
|
def write(self, instRoot, fsset, bl, langs, kernelList, chainList, |
1120 |
|
|
defaultDev, justConfig, intf): |
1121 |
|
|
# XXX HACK ALERT - see declaration above |
1122 |
|
|
if self.doUpgradeOnly: |
1123 |
slords |
1.5 |
if self.useGrubVal: |
1124 |
slords |
1.1 |
self.upgradeGrub(instRoot, fsset, bl, langs, kernelList, |
1125 |
|
|
chainList, defaultDev, justConfig) |
1126 |
|
|
|
1127 |
|
|
# and the hacks continue. with 2.6, ide-scsi isn't used |
1128 |
|
|
# anymore (#116622) |
1129 |
|
|
import isys |
1130 |
|
|
cdrw = isys.ideCdRwList() |
1131 |
|
|
torem = [] |
1132 |
|
|
for device in cdrw: |
1133 |
|
|
torem.append("%s=ide-scsi" %(device,)) |
1134 |
|
|
|
1135 |
|
|
for fn in ("/etc/lilo.conf", "/boot/grub/grub.conf", |
1136 |
|
|
"/etc/lilo.conf.anaconda"): |
1137 |
|
|
if not os.path.exists(instRoot + fn): |
1138 |
|
|
continue |
1139 |
|
|
f = open(instRoot + fn, "r") |
1140 |
|
|
buf = f.read() |
1141 |
|
|
f.close() |
1142 |
|
|
for dev in torem: |
1143 |
|
|
buf = buf.replace(dev, "") |
1144 |
|
|
f = open(instRoot + fn, "w") |
1145 |
|
|
f.write(buf) |
1146 |
|
|
f.close() |
1147 |
|
|
return |
1148 |
|
|
if len(kernelList) < 1: |
1149 |
|
|
self.noKernelsWarn(intf) |
1150 |
|
|
|
1151 |
|
|
str = self.writeGrub(instRoot, fsset, bl, langs, kernelList, |
1152 |
|
|
chainList, defaultDev, |
1153 |
|
|
justConfig | (not self.useGrubVal)) |
1154 |
|
|
# XXX move the lilo.conf out of the way if they're using GRUB |
1155 |
|
|
# so that /sbin/installkernel does a more correct thing |
1156 |
|
|
if self.useGrubVal and os.access(instRoot + '/etc/lilo.conf', os.R_OK): |
1157 |
|
|
os.rename(instRoot + "/etc/lilo.conf", |
1158 |
|
|
instRoot + "/etc/lilo.conf.anaconda") |
1159 |
|
|
|
1160 |
|
|
|
1161 |
|
|
|
1162 |
|
|
def getArgList(self): |
1163 |
|
|
args = bootloaderInfo.getArgList(self) |
1164 |
|
|
|
1165 |
|
|
if self.forceLBA32: |
1166 |
|
|
args.append("--lba32") |
1167 |
|
|
if self.password: |
1168 |
|
|
args.append("--md5pass=%s" %(self.password)) |
1169 |
|
|
|
1170 |
|
|
|
1171 |
|
|
# XXX add location of bootloader here too |
1172 |
|
|
|
1173 |
|
|
return args |
1174 |
|
|
|
1175 |
|
|
def __init__(self): |
1176 |
|
|
bootloaderInfo.__init__(self) |
1177 |
|
|
# XXX use checkbootloader to determine what to default to |
1178 |
|
|
self.useGrubVal = 1 |
1179 |
|
|
self.kernelLocation = "/boot/" |
1180 |
|
|
self.configfile = "/etc/lilo.conf" |
1181 |
|
|
self.password = None |
1182 |
|
|
self.pure = None |
1183 |
|
|
|
1184 |
|
|
class s390BootloaderInfo(bootloaderInfo): |
1185 |
|
|
def getBootloaderConfig(self, instRoot, fsset, bl, langs, kernelList, |
1186 |
|
|
chainList, defaultDev): |
1187 |
|
|
images = bl.images.getImages() |
1188 |
|
|
|
1189 |
|
|
# on upgrade read in the lilo config file |
1190 |
|
|
lilo = LiloConfigFile () |
1191 |
|
|
self.perms = 0600 |
1192 |
|
|
if os.access (instRoot + self.configfile, os.R_OK): |
1193 |
|
|
self.perms = os.stat(instRoot + self.configfile)[0] & 0777 |
1194 |
|
|
lilo.read (instRoot + self.configfile) |
1195 |
|
|
os.rename(instRoot + self.configfile, |
1196 |
|
|
instRoot + self.configfile + '.rpmsave') |
1197 |
|
|
|
1198 |
|
|
# Remove any invalid entries that are in the file; we probably |
1199 |
|
|
# just removed those kernels. |
1200 |
|
|
for label in lilo.listImages(): |
1201 |
|
|
(fsType, sl, path, other) = lilo.getImage(label) |
1202 |
|
|
if fsType == "other": continue |
1203 |
|
|
|
1204 |
|
|
if not os.access(instRoot + sl.getPath(), os.R_OK): |
1205 |
|
|
lilo.delImage(label) |
1206 |
|
|
|
1207 |
|
|
rootDev = fsset.getEntryByMountPoint("/").device.getDevice() |
1208 |
|
|
if not rootDev: |
1209 |
|
|
raise RuntimeError, "Installing zipl, but there is no root device" |
1210 |
|
|
|
1211 |
|
|
if rootDev == defaultDev: |
1212 |
|
|
lilo.addEntry("default", kernelList[0][0]) |
1213 |
|
|
else: |
1214 |
|
|
lilo.addEntry("default", chainList[0][0]) |
1215 |
|
|
|
1216 |
|
|
for (label, longlabel, version) in kernelList: |
1217 |
|
|
kernelTag = "-" + version |
1218 |
|
|
kernelFile = self.kernelLocation + "vmlinuz" + kernelTag |
1219 |
|
|
|
1220 |
|
|
try: |
1221 |
|
|
lilo.delImage(label) |
1222 |
|
|
except IndexError, msg: |
1223 |
|
|
pass |
1224 |
|
|
|
1225 |
|
|
sl = LiloConfigFile(imageType = "image", path = kernelFile) |
1226 |
|
|
|
1227 |
|
|
initrd = booty.makeInitrd (kernelTag, instRoot) |
1228 |
|
|
|
1229 |
|
|
sl.addEntry("label", label) |
1230 |
|
|
if os.access (instRoot + initrd, os.R_OK): |
1231 |
|
|
sl.addEntry("initrd", |
1232 |
|
|
"%sinitrd%s.img" %(self.kernelLocation, kernelTag)) |
1233 |
|
|
|
1234 |
|
|
sl.addEntry("read-only") |
1235 |
|
|
sl.addEntry("root", '/dev/' + rootDev) |
1236 |
|
|
sl.addEntry("ipldevice", '/dev/' + rootDev[:-1]) |
1237 |
|
|
|
1238 |
|
|
if self.args.get(): |
1239 |
|
|
sl.addEntry('append', '"%s"' % self.args.get()) |
1240 |
|
|
|
1241 |
|
|
lilo.addImage (sl) |
1242 |
|
|
|
1243 |
|
|
for (label, longlabel, device) in chainList: |
1244 |
|
|
if ((not label) or (label == "")): |
1245 |
|
|
continue |
1246 |
|
|
try: |
1247 |
|
|
(fsType, sl, path, other) = lilo.getImage(label) |
1248 |
|
|
lilo.delImage(label) |
1249 |
|
|
except IndexError: |
1250 |
|
|
sl = LiloConfigFile(imageType = "other", |
1251 |
|
|
path = "/dev/%s" %(device)) |
1252 |
|
|
sl.addEntry("optional") |
1253 |
|
|
|
1254 |
|
|
sl.addEntry("label", label) |
1255 |
|
|
lilo.addImage (sl) |
1256 |
|
|
|
1257 |
|
|
# Sanity check #1. There could be aliases in sections which conflict |
1258 |
|
|
# with the new images we just created. If so, erase those aliases |
1259 |
|
|
imageNames = {} |
1260 |
|
|
for label in lilo.listImages(): |
1261 |
|
|
imageNames[label] = 1 |
1262 |
|
|
|
1263 |
|
|
for label in lilo.listImages(): |
1264 |
|
|
(fsType, sl, path, other) = lilo.getImage(label) |
1265 |
|
|
if sl.testEntry('alias'): |
1266 |
|
|
alias = sl.getEntry('alias') |
1267 |
|
|
if imageNames.has_key(alias): |
1268 |
|
|
sl.delEntry('alias') |
1269 |
|
|
imageNames[alias] = 1 |
1270 |
|
|
|
1271 |
|
|
# Sanity check #2. If single-key is turned on, go through all of |
1272 |
|
|
# the image names (including aliases) (we just built the list) and |
1273 |
|
|
# see if single-key will still work. |
1274 |
|
|
if lilo.testEntry('single-key'): |
1275 |
|
|
singleKeys = {} |
1276 |
|
|
turnOff = 0 |
1277 |
|
|
for label in imageNames.keys(): |
1278 |
|
|
l = label[0] |
1279 |
|
|
if singleKeys.has_key(l): |
1280 |
|
|
turnOff = 1 |
1281 |
|
|
singleKeys[l] = 1 |
1282 |
|
|
if turnOff: |
1283 |
|
|
lilo.delEntry('single-key') |
1284 |
|
|
|
1285 |
|
|
return lilo |
1286 |
|
|
|
1287 |
|
|
def writeChandevConf(self, bl, instroot): # S/390 only |
1288 |
|
|
cf = "/etc/chandev.conf" |
1289 |
|
|
self.perms = 0644 |
1290 |
|
|
if bl.args.chandevget(): |
1291 |
|
|
fd = os.open(instroot + "/etc/chandev.conf", |
1292 |
|
|
os.O_WRONLY | os.O_CREAT) |
1293 |
|
|
os.write(fd, "noauto\n") |
1294 |
|
|
for cdev in bl.args.chandevget(): |
1295 |
|
|
os.write(fd,'%s\n' % cdev) |
1296 |
|
|
os.close(fd) |
1297 |
|
|
return "" |
1298 |
|
|
|
1299 |
|
|
|
1300 |
|
|
def writeZipl(self, instRoot, fsset, bl, langs, kernelList, chainList, |
1301 |
|
|
defaultDev, justConfigFile): |
1302 |
|
|
images = bl.images.getImages() |
1303 |
|
|
rootDev = fsset.getEntryByMountPoint("/").device.getDevice() |
1304 |
|
|
|
1305 |
|
|
cf = '/etc/zipl.conf' |
1306 |
|
|
self.perms = 0600 |
1307 |
|
|
if os.access (instRoot + cf, os.R_OK): |
1308 |
|
|
self.perms = os.stat(instRoot + cf)[0] & 0777 |
1309 |
|
|
os.rename(instRoot + cf, |
1310 |
|
|
instRoot + cf + '.rpmsave') |
1311 |
|
|
|
1312 |
|
|
f = open(instRoot + cf, "w+") |
1313 |
|
|
|
1314 |
|
|
f.write('[defaultboot]\n') |
1315 |
|
|
f.write('default=' + kernelList[0][0] + '\n') |
1316 |
|
|
f.write('target=%s\n' % (self.kernelLocation)) |
1317 |
|
|
|
1318 |
|
|
cfPath = "/boot/" |
1319 |
|
|
for (label, longlabel, version) in kernelList: |
1320 |
|
|
kernelTag = "-" + version |
1321 |
|
|
kernelFile = "%svmlinuz%s" % (cfPath, kernelTag) |
1322 |
|
|
|
1323 |
|
|
initrd = booty.makeInitrd (kernelTag, instRoot) |
1324 |
|
|
f.write('[%s]\n' % (label)) |
1325 |
|
|
f.write('\timage=%s\n' % (kernelFile)) |
1326 |
|
|
if os.access (instRoot + initrd, os.R_OK): |
1327 |
|
|
f.write('\tramdisk=%sinitrd%s.img\n' %(self.kernelLocation, |
1328 |
|
|
kernelTag)) |
1329 |
|
|
realroot = getRootDevName(initrd, fsset, rootDev, instRoot) |
1330 |
|
|
f.write('\tparameters="root=%s' %(realroot,)) |
1331 |
|
|
if bl.args.get(): |
1332 |
|
|
f.write(' %s' % (bl.args.get())) |
1333 |
|
|
f.write('"\n') |
1334 |
|
|
|
1335 |
|
|
f.close() |
1336 |
|
|
|
1337 |
|
|
if not justConfigFile: |
1338 |
|
|
argv = [ "/sbin/zipl" ] |
1339 |
|
|
rhpl.executil.execWithRedirect(argv[0], argv, root = instRoot, |
1340 |
|
|
stdout = "/dev/stdout", |
1341 |
|
|
stderr = "/dev/stderr") |
1342 |
|
|
|
1343 |
|
|
return "" |
1344 |
|
|
|
1345 |
|
|
def write(self, instRoot, fsset, bl, langs, kernelList, chainList, |
1346 |
|
|
defaultDev, justConfig, intf): |
1347 |
|
|
str = self.writeZipl(instRoot, fsset, bl, langs, kernelList, |
1348 |
|
|
chainList, defaultDev, |
1349 |
|
|
justConfig | (not self.useZiplVal)) |
1350 |
|
|
str = self.writeChandevConf(bl, instRoot) |
1351 |
|
|
|
1352 |
|
|
def __init__(self): |
1353 |
|
|
bootloaderInfo.__init__(self) |
1354 |
|
|
self.useZiplVal = 1 # only used on s390 |
1355 |
|
|
self.kernelLocation = "/boot/" |
1356 |
|
|
self.configfile = "/etc/zipl.conf" |
1357 |
|
|
|
1358 |
|
|
|
1359 |
|
|
class alphaBootloaderInfo(bootloaderInfo): |
1360 |
|
|
def wholeDevice (self, path): |
1361 |
|
|
(device, foo) = getDiskPart(path) |
1362 |
|
|
return device |
1363 |
|
|
|
1364 |
|
|
def partitionNum (self, path): |
1365 |
|
|
# getDiskPart returns part numbers 0-based; we need it one based |
1366 |
|
|
# *sigh* |
1367 |
|
|
(foo, partitionNumber) = getDiskPart(path) |
1368 |
|
|
return partitionNumber + 1 |
1369 |
|
|
|
1370 |
|
|
# See if we would have to use MILO. MILO isn't supported by Red Hat. |
1371 |
|
|
def useMilo (self): |
1372 |
|
|
try: |
1373 |
|
|
f = open ('/proc/cpuinfo', 'ro') |
1374 |
|
|
except: |
1375 |
|
|
return |
1376 |
|
|
lines = f.readlines () |
1377 |
|
|
f.close() |
1378 |
|
|
serial = "" |
1379 |
|
|
for line in lines: |
1380 |
|
|
if line.find("system serial number") != -1: |
1381 |
|
|
serial = string.strip (string.split (line, ':')[1]) |
1382 |
|
|
break |
1383 |
|
|
|
1384 |
|
|
if serial and len (serial) >= 4 and serial.startswith("MILO"): |
1385 |
|
|
return 1 |
1386 |
|
|
else: |
1387 |
|
|
return 0 |
1388 |
|
|
|
1389 |
|
|
def writeAboot(self, instRoot, fsset, bl, langs, kernelList, |
1390 |
|
|
chainList, defaultDev, justConfig): |
1391 |
|
|
# Get bootDevice and rootDevice |
1392 |
|
|
rootDevice = fsset.getEntryByMountPoint("/").device.getDevice() |
1393 |
|
|
if fsset.getEntryByMountPoint("/boot"): |
1394 |
|
|
bootDevice = fsset.getEntryByMountPoint("/boot").device.getDevice() |
1395 |
|
|
else: |
1396 |
|
|
bootDevice = rootDevice |
1397 |
|
|
bootnotroot = bootDevice != rootDevice |
1398 |
|
|
|
1399 |
|
|
# If /etc/aboot.conf already exists we rename it |
1400 |
|
|
# /etc/aboot.conf.rpmsave. |
1401 |
|
|
if os.path.isfile(instRoot + self.configfile): |
1402 |
|
|
os.rename (instRoot + self.configfile, |
1403 |
|
|
instRoot + self.configfile + ".rpmsave") |
1404 |
|
|
|
1405 |
|
|
# Then we create the necessary files. If the root device isn't |
1406 |
|
|
# the boot device, we create /boot/etc/ where the aboot.conf |
1407 |
|
|
# will live, and we create /etc/aboot.conf as a symlink to it. |
1408 |
|
|
if bootnotroot: |
1409 |
|
|
# Do we have /boot/etc ? If not, create one |
1410 |
|
|
if not os.path.isdir (instRoot + '/boot/etc'): |
1411 |
|
|
os.mkdir(instRoot + '/boot/etc', 0755) |
1412 |
|
|
|
1413 |
|
|
# We install the symlink (/etc/aboot.conf has already been |
1414 |
|
|
# renamed in necessary.) |
1415 |
|
|
os.symlink("../boot" + self.configfile, instRoot + self.configfile) |
1416 |
|
|
|
1417 |
|
|
cfPath = instRoot + "/boot" + self.configfile |
1418 |
|
|
# Kernel path is set to / because a boot partition will |
1419 |
|
|
# be a root on its own. |
1420 |
|
|
kernelPath = '/' |
1421 |
|
|
# Otherwise, we just need to create /etc/aboot.conf. |
1422 |
|
|
else: |
1423 |
|
|
cfPath = instRoot + self.configfile |
1424 |
|
|
kernelPath = self.kernelLocation |
1425 |
|
|
|
1426 |
|
|
# If we already have an aboot.conf, rename it |
1427 |
|
|
if os.access (cfPath, os.R_OK): |
1428 |
|
|
self.perms = os.stat(cfPath)[0] & 0777 |
1429 |
|
|
os.rename(cfPath, cfPath + '.rpmsave') |
1430 |
|
|
|
1431 |
|
|
# Now we're going to create and populate cfPath. |
1432 |
|
|
f = open (cfPath, 'w+') |
1433 |
|
|
f.write ("# aboot default configurations\n") |
1434 |
|
|
|
1435 |
|
|
if bootnotroot: |
1436 |
|
|
f.write ("# NOTICE: You have a /boot partition. This means that\n") |
1437 |
|
|
f.write ("# all kernel paths are relative to /boot/\n") |
1438 |
|
|
|
1439 |
|
|
# bpn is the boot partition number. |
1440 |
|
|
bpn = self.partitionNum(bootDevice) |
1441 |
|
|
lines = 0 |
1442 |
|
|
|
1443 |
|
|
# We write entries line using the following format: |
1444 |
|
|
# <line><bpn><kernel-name> root=<rootdev> [options] |
1445 |
|
|
# We get all the kernels we need to know about in kernelList. |
1446 |
|
|
|
1447 |
|
|
for (kernel, tag, kernelTag) in kernelList: |
1448 |
|
|
kernelFile = "%svmlinuz-%s" %(kernelPath, kernelTag) |
1449 |
|
|
|
1450 |
|
|
f.write("%d:%d%s" %(lines, bpn, kernelFile)) |
1451 |
|
|
|
1452 |
|
|
# See if we can come up with an initrd argument that exists |
1453 |
|
|
initrd = booty.makeInitrd (kernelTag, instRoot) |
1454 |
|
|
if os.access(instRoot + initrd, os.R_OK): |
1455 |
|
|
f.write(" initrd=%sinitrd-%s.img" %(kernelPath, kernelTag)) |
1456 |
|
|
|
1457 |
|
|
realroot = getRootDevName(initrd, fsset, rootDevice, instRoot) |
1458 |
|
|
f.write(" root=%s" %(realroot,)) |
1459 |
|
|
|
1460 |
|
|
args = self.args.get() |
1461 |
|
|
if args: |
1462 |
|
|
f.write(" %s" %(args,)) |
1463 |
|
|
|
1464 |
|
|
f.write("\n") |
1465 |
|
|
lines = lines + 1 |
1466 |
|
|
|
1467 |
|
|
# We're done writing the file |
1468 |
|
|
f.close () |
1469 |
|
|
del f |
1470 |
|
|
|
1471 |
|
|
if not justConfig: |
1472 |
|
|
# Now we're ready to write the relevant boot information. wbd |
1473 |
|
|
# is the whole boot device, bdpn is the boot device partition |
1474 |
|
|
# number. |
1475 |
|
|
wbd = self.wholeDevice (bootDevice) |
1476 |
|
|
bdpn = self.partitionNum (bootDevice) |
1477 |
|
|
|
1478 |
|
|
# Calling swriteboot. The first argument is the disk to write |
1479 |
|
|
# to and the second argument is a path to the bootstrap loader |
1480 |
|
|
# file. |
1481 |
|
|
args = ("swriteboot", ("/dev/%s" % wbd), "/boot/bootlx") |
1482 |
|
|
log("swriteboot command: %s" %(args,)) |
1483 |
|
|
rhpl.executil.execWithRedirect ('/sbin/swriteboot', args, |
1484 |
|
|
root = instRoot, |
1485 |
|
|
stdout = "/dev/tty5", |
1486 |
|
|
stderr = "/dev/tty5") |
1487 |
|
|
|
1488 |
|
|
# Calling abootconf to configure the installed aboot. The |
1489 |
|
|
# first argument is the disk to use, the second argument is |
1490 |
|
|
# the number of the partition on which aboot.conf resides. |
1491 |
|
|
# It's always the boot partition whether it's / or /boot (with |
1492 |
|
|
# the mount point being omitted.) |
1493 |
|
|
args = ("abootconf", ("/dev/%s" % wbd), str (bdpn)) |
1494 |
|
|
log("abootconf command: %s" %(args,)) |
1495 |
|
|
rhpl.executil.execWithRedirect ('/sbin/abootconf', args, |
1496 |
|
|
root = instRoot, |
1497 |
|
|
stdout = "/dev/tty5", |
1498 |
|
|
stderr = "/dev/tty5") |
1499 |
|
|
|
1500 |
|
|
|
1501 |
|
|
def write(self, instRoot, fsset, bl, langs, kernelList, chainList, |
1502 |
|
|
defaultDev, justConfig, intf): |
1503 |
|
|
if len(kernelList) < 1: |
1504 |
|
|
self.noKernelsWarn(intf) |
1505 |
|
|
|
1506 |
|
|
if self.useMilo(): |
1507 |
|
|
intf.messageWindow(_("MILO Not Supported"), |
1508 |
|
|
"This system requires the support of MILO to " + |
1509 |
|
|
"boot linux (MILO is not included in this " + |
1510 |
|
|
"distribution.) The installation of the " + |
1511 |
|
|
"bootloader can't be completed on this system.") |
1512 |
|
|
# elif not justConfig FIXME. |
1513 |
|
|
else: |
1514 |
|
|
self.writeAboot(instRoot, fsset, bl, langs, kernelList, |
1515 |
|
|
chainList, defaultDev, justConfig) |
1516 |
|
|
|
1517 |
|
|
def __init__(self): |
1518 |
|
|
bootloaderInfo.__init__(self) |
1519 |
|
|
self.useGrubVal = 0 |
1520 |
|
|
self.configfile = "/etc/aboot.conf" |
1521 |
|
|
# self.kernelLocation is already set to what we need. |
1522 |
|
|
self.password = None |
1523 |
|
|
self.pure = None |
1524 |
|
|
|
1525 |
|
|
|
1526 |
|
|
class ppcBootloaderInfo(bootloaderInfo): |
1527 |
|
|
def writeYaboot(self, instRoot, fsset, bl, langs, kernelList, |
1528 |
|
|
chainList, defaultDev, justConfigFile): |
1529 |
|
|
|
1530 |
|
|
from flags import flags |
1531 |
|
|
|
1532 |
|
|
yabootTarget = '/dev/%s' %(bl.getDevice()) |
1533 |
|
|
|
1534 |
|
|
bootDev = fsset.getEntryByMountPoint("/boot") |
1535 |
|
|
if bootDev: |
1536 |
|
|
cf = "/boot/etc/yaboot.conf" |
1537 |
|
|
cfPath = "" |
1538 |
|
|
if not os.path.isdir(instRoot + "/boot/etc"): |
1539 |
|
|
os.mkdir(instRoot + "/boot/etc") |
1540 |
|
|
else: |
1541 |
|
|
bootDev = fsset.getEntryByMountPoint("/") |
1542 |
|
|
cfPath = "/boot" |
1543 |
|
|
cf = "/etc/yaboot.conf" |
1544 |
|
|
bootDev = bootDev.device.getDevice(asBoot = 1) |
1545 |
|
|
|
1546 |
|
|
f = open(instRoot + cf, "w+") |
1547 |
slords |
1.5 |
|
1548 |
slords |
1.1 |
f.write("# yaboot.conf generated by anaconda\n\n") |
1549 |
|
|
|
1550 |
|
|
f.write("boot=%s\n" %(yabootTarget,)) |
1551 |
|
|
f.write("init-message=Welcome to %s\\!\nHit <TAB> for boot options\n\n" |
1552 |
|
|
%(butil.getProductName(),)) |
1553 |
|
|
|
1554 |
|
|
(name, partNum) = getDiskPart(bootDev) |
1555 |
|
|
partno = partNum + 1 # 1 based |
1556 |
|
|
f.write("partition=%s\n" %(partno,)) |
1557 |
|
|
|
1558 |
slords |
1.5 |
f.write("timeout=80\n") |
1559 |
slords |
1.1 |
f.write("install=/usr/lib/yaboot/yaboot\n") |
1560 |
|
|
f.write("delay=5\n") |
1561 |
slords |
1.5 |
f.write("enablecdboot\n") |
1562 |
|
|
f.write("enableofboot\n") |
1563 |
|
|
f.write("enablenetboot\n") |
1564 |
slords |
1.1 |
|
1565 |
|
|
if butil.getPPCMachine() == "PMac": |
1566 |
slords |
1.5 |
# write out the first hfs/hfs+ partition as being macosx |
1567 |
|
|
for (label, longlabel, device) in chainList: |
1568 |
|
|
if ((not label) or (label == "")): |
1569 |
|
|
continue |
1570 |
|
|
f.write("macosx=/dev/%s\n" %(device,)) |
1571 |
|
|
break |
1572 |
|
|
|
1573 |
slords |
1.1 |
f.write("magicboot=/usr/lib/yaboot/ofboot\n") |
1574 |
|
|
|
1575 |
|
|
if butil.getPPCMachine() == "pSeries": |
1576 |
|
|
f.write("nonvram\n") |
1577 |
|
|
|
1578 |
|
|
if self.password: |
1579 |
|
|
f.write("password=%s\n" %(self.password,)) |
1580 |
|
|
f.write("restricted\n") |
1581 |
|
|
|
1582 |
|
|
f.write("\n") |
1583 |
|
|
|
1584 |
|
|
rootDev = fsset.getEntryByMountPoint("/").device.getDevice() |
1585 |
|
|
|
1586 |
|
|
for (label, longlabel, version) in kernelList: |
1587 |
|
|
kernelTag = "-" + version |
1588 |
|
|
kernelFile = "%s/vmlinuz%s" %(cfPath, kernelTag) |
1589 |
|
|
|
1590 |
|
|
f.write("image=%s\n" %(kernelFile,)) |
1591 |
|
|
f.write("\tlabel=%s\n" %(label,)) |
1592 |
|
|
f.write("\tread-only\n") |
1593 |
|
|
|
1594 |
|
|
initrd = booty.makeInitrd(kernelTag, instRoot) |
1595 |
|
|
if os.access(instRoot + initrd, os.R_OK): |
1596 |
|
|
f.write("\tinitrd=%s/initrd%s.img\n" %(cfPath,kernelTag)) |
1597 |
|
|
|
1598 |
|
|
append = "%s" %(self.args.get(),) |
1599 |
|
|
|
1600 |
|
|
realroot = getRootDevName(initrd, fsset, rootDev, instRoot) |
1601 |
|
|
if not realroot.startswith("LABEL="): |
1602 |
|
|
f.write("\troot=%s\n" %(realroot,)) |
1603 |
|
|
else: |
1604 |
|
|
if len(append) > 0: |
1605 |
|
|
append = "%s root=%s" %(append,realroot) |
1606 |
|
|
else: |
1607 |
|
|
append = "root=%s" %(realroot,) |
1608 |
|
|
|
1609 |
|
|
if len(append) > 0: |
1610 |
|
|
f.write("\tappend=\"%s\"\n" %(append,)) |
1611 |
|
|
f.write("\n") |
1612 |
|
|
|
1613 |
|
|
f.close() |
1614 |
|
|
os.chmod(instRoot + cf, 0600) |
1615 |
|
|
|
1616 |
|
|
# FIXME: hack to make sure things are written to disk |
1617 |
|
|
import isys |
1618 |
|
|
isys.sync() |
1619 |
|
|
isys.sync() |
1620 |
|
|
isys.sync() |
1621 |
|
|
|
1622 |
|
|
ybinargs = [ "/sbin/mkofboot", "-f", "-C", cf ] |
1623 |
|
|
if butil.getPPCMachine() == "pSeries": |
1624 |
|
|
ybinargs.extend(["--filesystem", "raw"]) |
1625 |
|
|
|
1626 |
|
|
|
1627 |
|
|
log("running: %s" %(ybinargs,)) |
1628 |
slords |
1.5 |
if not flags.test: |
1629 |
slords |
1.1 |
rhpl.executil.execWithRedirect(ybinargs[0], |
1630 |
|
|
ybinargs, |
1631 |
|
|
stdout = "/dev/tty5", |
1632 |
|
|
stderr = "/dev/tty5", |
1633 |
|
|
root = instRoot) |
1634 |
|
|
|
1635 |
|
|
if (not os.access(instRoot + "/etc/yaboot.conf", os.R_OK) and |
1636 |
|
|
os.access(instRoot + "/boot/etc/yaboot.conf", os.R_OK)): |
1637 |
|
|
os.symlink("../boot/etc/yaboot.conf", |
1638 |
|
|
instRoot + "/etc/yaboot.conf") |
1639 |
|
|
|
1640 |
|
|
return "" |
1641 |
|
|
|
1642 |
|
|
def setPassword(self, val, isCrypted = 1): |
1643 |
|
|
# yaboot just handles the password and doesn't care if its crypted |
1644 |
|
|
# or not |
1645 |
|
|
self.password = val |
1646 |
|
|
|
1647 |
|
|
def write(self, instRoot, fsset, bl, langs, kernelList, chainList, |
1648 |
|
|
defaultDev, justConfig, intf): |
1649 |
|
|
if len(kernelList) >= 1: |
1650 |
|
|
str = self.writeYaboot(instRoot, fsset, bl, langs, kernelList, |
1651 |
|
|
chainList, defaultDev, justConfig) |
1652 |
|
|
else: |
1653 |
|
|
self.noKernelsWarn(intf) |
1654 |
|
|
|
1655 |
|
|
def __init__(self): |
1656 |
|
|
bootloaderInfo.__init__(self) |
1657 |
|
|
self.useYabootVal = 1 |
1658 |
|
|
self.kernelLocation = "/boot" |
1659 |
|
|
self.configfile = "/etc/yaboot.conf" |
1660 |
|
|
|
1661 |
|
|
|
1662 |
|
|
class iseriesBootloaderInfo(bootloaderInfo): |
1663 |
|
|
def ddFile(self, inf, of, bs = 4096): |
1664 |
|
|
src = os.open(inf, os.O_RDONLY) |
1665 |
|
|
dest = os.open(of, os.O_WRONLY | os.O_CREAT) |
1666 |
|
|
size = 0 |
1667 |
|
|
|
1668 |
|
|
buf = os.read(src, bs) |
1669 |
|
|
while len(buf) > 0: |
1670 |
|
|
size = size + len(buf) |
1671 |
|
|
os.write(dest, buf) |
1672 |
|
|
buf = os.read(src, bs) |
1673 |
|
|
|
1674 |
|
|
os.close(src) |
1675 |
|
|
os.close(dest) |
1676 |
|
|
|
1677 |
|
|
return size |
1678 |
|
|
|
1679 |
|
|
def write(self, instRoot, fsset, bl, langs, kernelList, chainList, |
1680 |
|
|
defaultDev, justConfig, intf): |
1681 |
|
|
if len(kernelList) < 1: |
1682 |
|
|
self.noKernelsWarn(intf) |
1683 |
|
|
return |
1684 |
|
|
if len(kernelList) > 1: |
1685 |
|
|
# FIXME: how can this happen? |
1686 |
|
|
log("more than one kernel on iSeries. bailing and just using " |
1687 |
|
|
"the first") |
1688 |
|
|
|
1689 |
|
|
# iseries is Weird (tm) -- here's the basic theory |
1690 |
|
|
# a) have /boot/vmlinitrd-$(version) |
1691 |
|
|
# b) copy default kernel to PReP partition |
1692 |
|
|
# c) dd default kernel to /proc/iSeries/mf/C/vmlinux |
1693 |
|
|
# d) set cmdline in /boot/cmdline-$(version) |
1694 |
|
|
# e) copy cmdline to /proc/iSeries/mf/C/cmdline |
1695 |
|
|
# f) set default side to 'C' i /proc/iSeries/mf/side |
1696 |
|
|
# g) put default kernel and cmdline on side B too (#91038) |
1697 |
|
|
|
1698 |
|
|
rootDevice = fsset.getEntryByMountPoint("/").device.getDevice() |
1699 |
|
|
|
1700 |
|
|
# write our command line files |
1701 |
|
|
for (kernel, tag, kernelTag) in kernelList: |
1702 |
|
|
cmdFile = "%scmdline-%s" %(self.kernelLocation, kernelTag) |
1703 |
|
|
initrd = "%sinitrd-%s.img" %(self.kernelLocation, kernelTag) |
1704 |
|
|
realroot = getRootDevName(initrd, fsset, rootDevice, instRoot) |
1705 |
|
|
f = open(instRoot + cmdFile, "w") |
1706 |
|
|
f.write("ro root=%s" %(realroot,)) |
1707 |
|
|
if bl.args.get(): |
1708 |
|
|
f.write(" %s" %(bl.args.get(),)) |
1709 |
|
|
f.write("\n") |
1710 |
|
|
f.close() |
1711 |
|
|
os.chmod(instRoot + cmdFile, 0644) |
1712 |
|
|
|
1713 |
|
|
kernel, tag, kernelTag = kernelList[0] |
1714 |
|
|
kernelFile = "%svmlinitrd-%s" %(self.kernelLocation, kernelTag) |
1715 |
|
|
|
1716 |
|
|
# write the kernel to the PReP partition since that's what |
1717 |
|
|
# OS/400 will load as NWSSTG |
1718 |
|
|
bootDev = bl.getDevice() |
1719 |
|
|
if bootDev: |
1720 |
|
|
log("Writing kernel %s to PReP partition %s" %(kernelFile, |
1721 |
|
|
bootDev)) |
1722 |
|
|
try: |
1723 |
|
|
self.ddFile(instRoot + kernelFile, "%s/dev/%s" %(instRoot, |
1724 |
|
|
bootDev)) |
1725 |
|
|
except Exception, e: |
1726 |
|
|
# FIXME: should this be more fatal |
1727 |
|
|
log("Failed to write kernel: %s" %(e,)) |
1728 |
|
|
else: |
1729 |
|
|
log("No PReP boot partition, not writing kernel for NWSSTG") |
1730 |
|
|
|
1731 |
|
|
|
1732 |
|
|
# now, it's a lot faster to boot if we don't make people go back |
1733 |
|
|
# into OS/400, so set up side C (used by default for NWSSTG) with |
1734 |
|
|
# our current bits |
1735 |
|
|
for side in ("C", "B"): |
1736 |
|
|
log("Writing kernel and cmdline to side %s" %(side,)) |
1737 |
|
|
wrotekernel = 0 |
1738 |
|
|
try: |
1739 |
|
|
self.ddFile(instRoot + kernelFile, |
1740 |
|
|
"%s/proc/iSeries/mf/%s/vmlinux" %(instRoot, side)) |
1741 |
|
|
wrotekernel = 1 |
1742 |
|
|
except Exception, e: |
1743 |
|
|
# FIXME: should this be more fatal? |
1744 |
|
|
log("Failed to write kernel to side %s: %s" %(side, e)) |
1745 |
|
|
|
1746 |
|
|
if wrotekernel == 1: |
1747 |
|
|
try: |
1748 |
|
|
# blank it. ugh. |
1749 |
|
|
f = open("%s/proc/iSeries/mf/%s/cmdline" %(instRoot, side), |
1750 |
|
|
"w+") |
1751 |
|
|
f.write(" " * 255) |
1752 |
|
|
f.close() |
1753 |
|
|
|
1754 |
|
|
self.ddFile("%s/%scmdline-%s" %(instRoot, |
1755 |
|
|
self.kernelLocation, |
1756 |
|
|
kernelTag), |
1757 |
|
|
"%s/proc/iSeries/mf/%s/cmdline" %(instRoot, |
1758 |
|
|
side)) |
1759 |
|
|
except Exception, e: |
1760 |
|
|
log("Failed to write kernel command line to side %s: %s" |
1761 |
|
|
%(side, e)) |
1762 |
|
|
|
1763 |
|
|
log("Setting default side to C") |
1764 |
|
|
f = open(instRoot + "/proc/iSeries/mf/side", "w") |
1765 |
|
|
f.write("C") |
1766 |
|
|
f.close() |
1767 |
|
|
|
1768 |
|
|
def __init__(self): |
1769 |
|
|
bootloaderInfo.__init__(self) |
1770 |
|
|
self.kernelLocation = "/boot/" |
1771 |
|
|
|
1772 |
slords |
1.5 |
class sparcBootloaderInfo(bootloaderInfo): |
1773 |
|
|
def writeSilo(self, instRoot, fsset, bl, langs, kernelList, |
1774 |
|
|
chainList, defaultDev, justConfigFile): |
1775 |
|
|
|
1776 |
|
|
from flags import flags |
1777 |
|
|
|
1778 |
|
|
bootDev = fsset.getEntryByMountPoint("/boot") |
1779 |
|
|
if bootDev: |
1780 |
|
|
cf = "/boot/silo.conf" |
1781 |
|
|
mf = "/boot/silo.message" |
1782 |
|
|
cfPath = "" |
1783 |
|
|
if not os.path.isdir(instRoot + "/boot"): |
1784 |
|
|
os.mkdir(instRoot + "/boot") |
1785 |
|
|
else: |
1786 |
|
|
bootDev = fsset.getEntryByMountPoint("/") |
1787 |
|
|
cf = "/etc/silo.conf" |
1788 |
|
|
mf = "/etc/silo.message" |
1789 |
|
|
cfPath = "/boot" |
1790 |
|
|
bootDev = bootDev.device.getDevice(asBoot = 1) |
1791 |
slords |
1.1 |
|
1792 |
slords |
1.5 |
f = open(instRoot + mf, "w+") |
1793 |
|
|
f.write("Welcome to %s!\nHit <TAB> for boot options\n\n" % \ |
1794 |
|
|
(butil.getProductName(),)) |
1795 |
|
|
f.close() |
1796 |
|
|
os.chmod(instRoot + mf, 0600) |
1797 |
|
|
|
1798 |
|
|
f = open(instRoot + cf, "w+") |
1799 |
|
|
f.write("# silo.conf generated by anaconda\n\n") |
1800 |
|
|
|
1801 |
|
|
f.write("#boot=%s\n" % (bootDev,)) |
1802 |
|
|
f.write("message=%s\n" % (mf,)) |
1803 |
|
|
f.write("timeout=50\n") |
1804 |
|
|
|
1805 |
|
|
(name, partNum) = getDiskPart(bootDev) |
1806 |
|
|
partno = partNum + 1 |
1807 |
|
|
f.write("partition=%s\n" % (partno,)) |
1808 |
|
|
|
1809 |
|
|
if self.password: |
1810 |
|
|
f.write("password=%s\n" % (self.password,)) |
1811 |
|
|
f.write("restricted\n") |
1812 |
|
|
|
1813 |
|
|
f.write("default=%s\n" % (kernelList[0][0],)) |
1814 |
|
|
f.write("\n") |
1815 |
|
|
|
1816 |
|
|
rootDev = fsset.getEntryByMountPoint("/").device.getDevice() |
1817 |
|
|
|
1818 |
|
|
for (label, longlabel, version) in kernelList: |
1819 |
|
|
kernelTag = "-" + version |
1820 |
|
|
kernelFile = "%s/vmlinuz%s" % (cfPath, kernelTag) |
1821 |
|
|
|
1822 |
|
|
f.write("image=%s\n" % (kernelFile,)) |
1823 |
|
|
f.write("\tlabel=%s\n" % (label,)) |
1824 |
|
|
f.write("\tread-only\n") |
1825 |
|
|
|
1826 |
|
|
initrd = booty.makeInitrd(kernelTag, instRoot) |
1827 |
|
|
if os.access(instRoot + initrd, os.R_OK): |
1828 |
|
|
f.write("\tinitrd=%s/initrd%s.img\n" % (cfPath, kernelTag)) |
1829 |
|
|
|
1830 |
|
|
append = "%s" % (self.args.get(),) |
1831 |
|
|
|
1832 |
|
|
realroot = getRootDevName(initrd, fsset, rootDev, instRoot) |
1833 |
|
|
if not realroot.startswith("LABEL="): |
1834 |
|
|
f.write("\troot=%s\n" % (realroot,)) |
1835 |
|
|
else: |
1836 |
|
|
if len(append) > 0: |
1837 |
|
|
append = "%s root=%s" % (append, realroot) |
1838 |
|
|
else: |
1839 |
|
|
append = "root=%s" % (realroot,) |
1840 |
|
|
|
1841 |
|
|
if len(append) > 0: |
1842 |
|
|
f.write("\tappend=\"%s\"\n" % (append,)) |
1843 |
|
|
f.write("\n") |
1844 |
|
|
|
1845 |
|
|
f.close() |
1846 |
|
|
os.chmod(instRoot + cf, 0600) |
1847 |
|
|
|
1848 |
|
|
# FIXME: hack to make sure things are written to disk |
1849 |
|
|
import isys |
1850 |
|
|
isys.sync() |
1851 |
|
|
isys.sync() |
1852 |
|
|
isys.sync() |
1853 |
|
|
|
1854 |
|
|
backup = "%s/backup.b" % (cfPath,) |
1855 |
|
|
sbinargs = ["/sbin/silo", "-f", "-C", cf, "-S", backup] |
1856 |
|
|
if butil.getSparcMachine() == "sun4u": |
1857 |
|
|
sbinargs += ["-u"] |
1858 |
|
|
else: |
1859 |
|
|
sbinargs += ["-U"] |
1860 |
|
|
|
1861 |
|
|
log("running: %s" % (sbinargs,)) |
1862 |
|
|
if not flags.test: |
1863 |
|
|
rhpl.executil.execWithRedirect(sbinargs[0], |
1864 |
|
|
sbinargs, |
1865 |
|
|
stdout = "/dev/tty5", |
1866 |
|
|
stderr = "/dev/tty5", |
1867 |
|
|
root = instRoot) |
1868 |
|
|
|
1869 |
|
|
if (not os.access(instRoot + "/etc/silo.conf", os.R_OK) and |
1870 |
|
|
os.access(instRoot + "/boot/etc/silo.conf", os.R_OK)): |
1871 |
|
|
os.symlink("../boot/etc/silo.conf", |
1872 |
|
|
instRoot + "/etc/silo.conf") |
1873 |
|
|
|
1874 |
|
|
return "" |
1875 |
|
|
|
1876 |
|
|
def setPassword(self, val, isCrypted = 1): |
1877 |
|
|
# silo just handles the password unencrypted |
1878 |
|
|
self.password = val |
1879 |
|
|
|
1880 |
|
|
def write(self, instRoot, fsset, bl, langs, kernelList, chainList, |
1881 |
|
|
defaultDev, justConfig, intf): |
1882 |
|
|
if len(kernelList) >= 1: |
1883 |
|
|
self.writeSilo(instRoot, fsset, bl, langs, kernelList, chainList, |
1884 |
|
|
defaultDev, justConfig) |
1885 |
|
|
else: |
1886 |
|
|
self.noKernelsWarn(intf) |
1887 |
|
|
|
1888 |
|
|
def __init__(self): |
1889 |
|
|
bootloaderInfo.__init__(self) |
1890 |
|
|
self.useSiloVal = 1 |
1891 |
|
|
self.kernelLocation = "/boot" |
1892 |
|
|
self.configfile = "/etc/silo.conf" |
1893 |
slords |
1.1 |
|
1894 |
|
|
############### |
1895 |
|
|
# end of boot loader objects... these are just some utility functions used |
1896 |
|
|
|
1897 |
|
|
# return (disk, partition number) eg ('hda', 1) |
1898 |
|
|
def getDiskPart(dev): |
1899 |
|
|
cut = len(dev) |
1900 |
|
|
if (dev.startswith('rd/') or dev.startswith('ida/') or |
1901 |
|
|
dev.startswith('cciss/')): |
1902 |
|
|
if dev[-2] == 'p': |
1903 |
|
|
cut = -1 |
1904 |
|
|
elif dev[-3] == 'p': |
1905 |
|
|
cut = -2 |
1906 |
|
|
else: |
1907 |
|
|
if dev[-2] in string.digits: |
1908 |
|
|
cut = -2 |
1909 |
|
|
elif dev[-1] in string.digits: |
1910 |
|
|
cut = -1 |
1911 |
|
|
|
1912 |
|
|
name = dev[:cut] |
1913 |
|
|
|
1914 |
|
|
# hack off the trailing 'p' from /dev/cciss/*, for example |
1915 |
|
|
if name[-1] == 'p': |
1916 |
|
|
for letter in name: |
1917 |
|
|
if letter not in string.letters and letter != "/": |
1918 |
|
|
name = name[:-1] |
1919 |
|
|
break |
1920 |
|
|
|
1921 |
|
|
if cut < 0: |
1922 |
|
|
partNum = int(dev[cut:]) - 1 |
1923 |
|
|
else: |
1924 |
|
|
partNum = None |
1925 |
|
|
|
1926 |
|
|
return (name, partNum) |
1927 |
|
|
|
1928 |
|
|
# hackery to determine if we should do root=LABEL=/ or whatnot |
1929 |
|
|
# as usual, knows too much about anaconda |
1930 |
|
|
def getRootDevName(initrd, fsset, rootDev, instRoot): |
1931 |
|
|
if not os.access(instRoot + initrd, os.R_OK): |
1932 |
|
|
return "/dev/%s" % (rootDev,) |
1933 |
|
|
|
1934 |
|
|
try: |
1935 |
|
|
rootEntry = fsset.getEntryByMountPoint("/") |
1936 |
|
|
if rootEntry.getLabel() is not None: |
1937 |
|
|
return "LABEL=%s" %(rootEntry.getLabel(),) |
1938 |
|
|
return "/dev/%s" %(rootDev,) |
1939 |
|
|
except: |
1940 |
|
|
return "/dev/%s" %(rootDev,) |
1941 |
|
|
|