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