1 |
# |
2 |
# packages.py: package management - mainly package installation |
3 |
# |
4 |
# Erik Troan <ewt@redhat.com> |
5 |
# Matt Wilson <msw@redhat.com> |
6 |
# Michael Fulbright <msf@redhat.com> |
7 |
# Jeremy Katz <katzj@redhat.com> |
8 |
# |
9 |
# Copyright 2001-2003 Red Hat, Inc. |
10 |
# |
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 |
import iutil |
20 |
import isys |
21 |
import rpm |
22 |
import hdrlist |
23 |
import os |
24 |
import timer |
25 |
import time |
26 |
import sys |
27 |
import string |
28 |
import pcmcia |
29 |
import language |
30 |
import fsset |
31 |
import kudzu |
32 |
from flags import flags |
33 |
from product import * |
34 |
from constants import * |
35 |
from syslogd import syslog |
36 |
from hdrlist import PKGTYPE_MANDATORY, PKGTYPE_DEFAULT, DependencyChecker |
37 |
from installmethod import FileCopyException |
38 |
|
39 |
from rhpl.log import log |
40 |
from rhpl.translate import _ |
41 |
import rhpl.arch |
42 |
|
43 |
def queryUpgradeContinue(intf, dir): |
44 |
if dir == DISPATCH_FORWARD: |
45 |
return |
46 |
|
47 |
rc = intf.messageWindow(_("Proceed with upgrade?"), |
48 |
_("The file systems of the Linux installation " |
49 |
"you have chosen to upgrade have already been " |
50 |
"mounted. You cannot go back past this point. " |
51 |
"\n\n") + |
52 |
_( "Would you like to continue with the upgrade?"), |
53 |
type = "yesno") |
54 |
if rc == 0: |
55 |
sys.exit(0) |
56 |
return DISPATCH_FORWARD |
57 |
|
58 |
def doPostAction(id, instPath, intf): |
59 |
id.instClass.postAction(instPath, flags.serial, intf) |
60 |
|
61 |
def firstbootConfiguration(id, instPath): |
62 |
if id.firstboot == FIRSTBOOT_RECONFIG: |
63 |
f = open(instPath + '/etc/reconfigSys', 'w+') |
64 |
f.close() |
65 |
elif id.firstboot == FIRSTBOOT_SKIP: |
66 |
f = open(instPath + '/etc/sysconfig/firstboot', 'w+') |
67 |
f.write('RUN_FIRSTBOOT=NO') |
68 |
f.close() |
69 |
|
70 |
return |
71 |
|
72 |
|
73 |
def writeConfiguration(id, instPath): |
74 |
log("Writing main configuration") |
75 |
if not flags.test: |
76 |
id.write(instPath) |
77 |
|
78 |
def writeKSConfiguration(id, instPath): |
79 |
log("Writing autokickstart file") |
80 |
if not flags.test: |
81 |
fn = instPath + "/root/anaconda-ks.cfg" |
82 |
else: |
83 |
fn = "/tmp/anaconda-ks.cfg" |
84 |
|
85 |
id.writeKS(fn) |
86 |
|
87 |
def copyAnacondaLogs(instPath): |
88 |
log("Copying anaconda logs") |
89 |
for (fn, dest) in (("/tmp/anaconda.log", "anaconda.log"), |
90 |
("/tmp/syslog", "anaconda.syslog"), |
91 |
("/tmp/ramfs/X.log", "anaconda.xlog")): |
92 |
if os.access(fn, os.R_OK): |
93 |
try: |
94 |
iutil.copyFile(fn, "%s/var/log/%s" %(instPath, dest)) |
95 |
os.chmod("%s/var/log/%s" %(instPath, dest), 0600) |
96 |
except: |
97 |
pass |
98 |
|
99 |
def writeXConfiguration(id, instPath): |
100 |
testmode = flags.test |
101 |
|
102 |
# comment out to test |
103 |
if testmode: |
104 |
return |
105 |
# end code to comment to test |
106 |
# uncomment to test writing X config in test mode |
107 |
# try: |
108 |
# os.mkdir("/tmp/etc") |
109 |
# except: |
110 |
# pass |
111 |
# try: |
112 |
# os.mkdir("/tmp/etc/X11") |
113 |
# except: |
114 |
# pass |
115 |
# instPath = '/' |
116 |
# end code for test writing |
117 |
|
118 |
if id.xsetup.skipx: |
119 |
return |
120 |
|
121 |
xserver = id.videocard.primaryCard().getXServer() |
122 |
if not xserver: |
123 |
return |
124 |
|
125 |
log("Writing X configuration") |
126 |
if not testmode: |
127 |
fn = instPath |
128 |
|
129 |
if os.access (instPath + "/etc/X11/X", os.R_OK): |
130 |
os.rename (instPath + "/etc/X11/X", |
131 |
instPath + "/etc/X11/X.rpmsave") |
132 |
|
133 |
try: |
134 |
os.unlink (instPath + "/etc/X11/X") |
135 |
except OSError: |
136 |
pass |
137 |
|
138 |
os.symlink ("../../usr/X11R6/bin/" + xserver, |
139 |
instPath + "/etc/X11/X") |
140 |
else: |
141 |
fn = "/tmp/" |
142 |
|
143 |
id.xsetup.write(fn+"/etc/X11", id.mouse, id.keyboard) |
144 |
id.desktop.write(instPath) |
145 |
|
146 |
def readPackages(intf, method, id): |
147 |
if id.grpset: |
148 |
grpset = id.grpset |
149 |
hdrlist = id.grpset.hdrlist |
150 |
doselect = 0 |
151 |
else: |
152 |
grpset = None |
153 |
hdrlist = None |
154 |
doselect = 1 |
155 |
|
156 |
while hdrlist is None: |
157 |
w = intf.waitWindow(_("Reading"), _("Reading package information...")) |
158 |
try: |
159 |
hdrlist = method.readHeaders() |
160 |
except FileCopyException: |
161 |
w.pop() |
162 |
method.unmountCD() |
163 |
intf.messageWindow(_("Error"), |
164 |
_("Unable to read header list. This may be " |
165 |
"due to a missing file or bad media. " |
166 |
"Press <return> to try again.")) |
167 |
continue |
168 |
|
169 |
w.pop() |
170 |
|
171 |
while grpset is None: |
172 |
try: |
173 |
grpset = method.readComps(hdrlist) |
174 |
except FileCopyException: |
175 |
method.unmountCD() |
176 |
intf.messageWindow(_("Error"), |
177 |
_("Unable to read comps file. This may be " |
178 |
"due to a missing file or bad media. " |
179 |
"Press <return> to try again.")) |
180 |
continue |
181 |
|
182 |
# people make bad tree copies all the time. let's just mandate that |
183 |
# the Core group has to exist in the comps file else we complain |
184 |
if not grpset.groups.has_key("core"): |
185 |
intf.messageWindow(_("Error"), |
186 |
_("The comps file in your installation tree is " |
187 |
"missing critical groups. Please ensure that " |
188 |
"your install tree has been correctly " |
189 |
"generated."), |
190 |
type="custom", custom_icon="error", |
191 |
custom_buttons=[_("_Exit")]) |
192 |
sys.exit(0) |
193 |
|
194 |
while iutil.getArch() == "ia64": |
195 |
try: |
196 |
method.mergeFullHeaders(hdrlist) |
197 |
break |
198 |
except FileCopyException: |
199 |
method.unmountCD() |
200 |
intf.messageWindow(_("Error"), |
201 |
_("Unable to merge header list. This may be " |
202 |
"due to a missing file or bad media. " |
203 |
"Press <return> to try again.")) |
204 |
|
205 |
# this is a crappy hack, but I don't want bug reports from these people |
206 |
if (iutil.getArch() == "i386") and (not grpset.hdrlist.has_key("kernel")): |
207 |
intf.messageWindow(_("Error"), |
208 |
_("You are trying to install on a machine " |
209 |
"which isn't supported by this release of " |
210 |
"%s.") %(productName,), |
211 |
type="custom", custom_icon="error", |
212 |
custom_buttons=[_("_Exit")]) |
213 |
sys.exit(0) |
214 |
|
215 |
id.grpset = grpset |
216 |
|
217 |
if doselect: |
218 |
id.instClass.setGroupSelection(grpset, intf) |
219 |
id.instClass.setPackageSelection(hdrlist, intf) |
220 |
|
221 |
def handleX11Packages(dir, intf, disp, id, instPath): |
222 |
|
223 |
if dir == DISPATCH_BACK: |
224 |
return |
225 |
|
226 |
# skip X setup if it is not being installed |
227 |
# |
228 |
# uncomment this block if you want X configuration to be presented |
229 |
# |
230 |
# START BLOCK |
231 |
# if (not id.grpset.hdrlist.has_key('XFree86') or |
232 |
# not id.grpset.hdrlist['XFree86'].isSelected()): |
233 |
# disp.skipStep("videocard") |
234 |
# disp.skipStep("monitor") |
235 |
# disp.skipStep("xcustom") |
236 |
# disp.skipStep("writexconfig") |
237 |
# id.xsetup.skipx = 1 |
238 |
# elif disp.stepInSkipList("videocard"): |
239 |
# # if X is being installed, but videocard step skipped |
240 |
# # need to turn it back on |
241 |
# disp.skipStep("videocard", skip=0) |
242 |
# disp.skipStep("monitor", skip=0) |
243 |
# disp.skipStep("xcustom", skip=0) |
244 |
# disp.skipStep("writexconfig", skip=0) |
245 |
# id.xsetup.skipx = 0 |
246 |
# END BLOCK |
247 |
|
248 |
# set default runlevel based on packages |
249 |
gnomeSelected = (id.grpset.hdrlist.has_key('gnome-session') |
250 |
and id.grpset.hdrlist['gnome-session'].isSelected()) |
251 |
gdmSelected = (id.grpset.hdrlist.has_key('gdm') |
252 |
and id.grpset.hdrlist['gdm'].isSelected()) |
253 |
kdeSelected = (id.grpset.hdrlist.has_key('kdebase') |
254 |
and id.grpset.hdrlist['kdebase'].isSelected()) |
255 |
xinstalled = ((id.grpset.hdrlist.has_key('xorg-x11') |
256 |
and id.grpset.hdrlist['xorg-x11'].isSelected()) or |
257 |
(id.grpset.hdrlist.has_key('XFree86') |
258 |
and id.grpset.hdrlist['XFree86'].isSelected())) |
259 |
|
260 |
if gnomeSelected: |
261 |
id.desktop.setDefaultDesktop("GNOME") |
262 |
elif kdeSelected: |
263 |
id.desktop.setDefaultDesktop("KDE") |
264 |
|
265 |
if (gdmSelected or kdeSelected) and (xinstalled) and (not flags.serial) and (not flags.virtpconsole): |
266 |
id.desktop.setDefaultRunLevel(5) |
267 |
else: |
268 |
id.desktop.setDefaultRunLevel(3) |
269 |
|
270 |
# verifies that monitor is not Unprobed, and if so we can skip monitor question |
271 |
def checkMonitorOK(monitor, dispatch): |
272 |
rc = 0 |
273 |
if monitor is not None: |
274 |
if monitor.getMonitorID() != "Unprobed Monitor": |
275 |
rc = 1 |
276 |
|
277 |
dispatch.skipStep("monitor", skip=rc) |
278 |
|
279 |
# sets a reasonable default for X settings. |
280 |
def setSaneXSettings(xsetup): |
281 |
if xsetup is not None and xsetup.xhwstate is not None: |
282 |
if not xsetup.imposed_sane_default: |
283 |
# XXX HACK see if we have a user specified LCD display |
284 |
import re |
285 |
|
286 |
regx = re.compile("LCD Panel .*x.*") |
287 |
monid = xsetup.xhwstate.monitor.getMonitorID() |
288 |
lcdres = None |
289 |
if regx.match(monid): |
290 |
for testres in ["640x480", "800x600", "1024x480", "1024x768", |
291 |
"1280x960", "1280x1024", "1400x1050", |
292 |
"1600x1200"]: |
293 |
if string.find(monid, testres) != -1: |
294 |
lcdres = testres |
295 |
break |
296 |
|
297 |
if lcdres is not None: |
298 |
xsetup.xhwstate.set_resolution(lcdres) |
299 |
else: |
300 |
xsetup.xhwstate.choose_sane_default() |
301 |
xsetup.imposed_sane_default = 1 |
302 |
|
303 |
def getAnacondaTS(instPath = None): |
304 |
if instPath: |
305 |
ts = rpm.TransactionSet(instPath) |
306 |
else: |
307 |
ts = rpm.TransactionSet() |
308 |
ts.setVSFlags(~(rpm.RPMVSF_NORSA|rpm.RPMVSF_NODSA)) |
309 |
ts.setFlags(rpm.RPMTRANS_FLAG_ANACONDA) |
310 |
|
311 |
# set color if needed. FIXME: why isn't this the default :/ |
312 |
if (rhpl.arch.canonArch.startswith("ppc64") or |
313 |
rhpl.arch.canonArch in ("s390x", "sparc64", "x86_64", "ia64")): |
314 |
ts.setColor(3) |
315 |
|
316 |
return ts |
317 |
|
318 |
def checkDependencies(dir, intf, disp, id, instPath): |
319 |
if dir == DISPATCH_BACK: |
320 |
return |
321 |
|
322 |
win = intf.waitWindow(_("Dependency Check"), |
323 |
_("Checking dependencies in packages selected for installation...")) |
324 |
|
325 |
# FIXME: we really don't need to build up a ts more than once |
326 |
# granted, this is better than before still |
327 |
if id.upgrade.get(): |
328 |
ts = getAnacondaTS(instPath) |
329 |
how = "u" |
330 |
else: |
331 |
ts = getAnacondaTS() |
332 |
how = "i" |
333 |
|
334 |
# set the rpm log file to /dev/null so that we don't segfault |
335 |
f = open("/dev/null", "w+") |
336 |
rpm.setLogFile(f) |
337 |
ts.scriptFd = f.fileno() |
338 |
|
339 |
for p in id.grpset.hdrlist.pkgs.values(): |
340 |
if p.isSelected(): |
341 |
ts.addInstall(p.hdr, p.hdr, how) |
342 |
depcheck = DependencyChecker(id.grpset, how) |
343 |
id.dependencies = ts.check(depcheck.callback) |
344 |
|
345 |
win.pop() |
346 |
|
347 |
if depcheck.added and id.handleDeps == CHECK_DEPS: |
348 |
disp.skipStep("dependencies", skip = 0) |
349 |
log("had unresolved dependencies, resolved.") |
350 |
disp.skipStep("dependencies") |
351 |
else: |
352 |
disp.skipStep("dependencies") |
353 |
|
354 |
return |
355 |
# FIXME: I BROKE IT |
356 |
# this is kind of hackish, but makes kickstart happy |
357 |
if id.handleDeps == CHECK_DEPS: |
358 |
pass |
359 |
elif id.handleDeps == IGNORE_DEPS: |
360 |
id.comps.selectDepCause(id.dependencies) |
361 |
id.comps.unselectDeps(id.dependencies) |
362 |
elif id.handleDeps == RESOLVE_DEPS: |
363 |
id.comps.selectDepCause(id.dependencies) |
364 |
id.comps.selectDeps(id.dependencies) |
365 |
|
366 |
class InstallCallback: |
367 |
def packageDownloadCB(self, state, amount): |
368 |
self.progress.setPackageStatus(state, amount) |
369 |
|
370 |
def cb(self, what, amount, total, h, (param)): |
371 |
# first time here means we should pop the window telling |
372 |
# user to wait until we get here |
373 |
if not self.beenCalled: |
374 |
self.beenCalled = 1 |
375 |
self.initWindow.pop() |
376 |
|
377 |
if (what == rpm.RPMCALLBACK_TRANS_START): |
378 |
# step 6 is the bulk of the transaction set |
379 |
# processing time |
380 |
if amount == 6: |
381 |
self.progressWindow = \ |
382 |
self.progressWindowClass (_("Processing"), |
383 |
_("Preparing to install..."), |
384 |
total) |
385 |
try: |
386 |
self.incr = total / 10 |
387 |
except: |
388 |
pass |
389 |
if (what == rpm.RPMCALLBACK_TRANS_PROGRESS): |
390 |
if self.progressWindow and amount > self.lastprogress + self.incr: |
391 |
self.progressWindow.set (amount) |
392 |
self.lastprogress = amount |
393 |
|
394 |
if (what == rpm.RPMCALLBACK_TRANS_STOP and self.progressWindow): |
395 |
self.progressWindow.pop () |
396 |
|
397 |
if (what == rpm.RPMCALLBACK_INST_OPEN_FILE): |
398 |
# We don't want to start the timer until we get to the first |
399 |
# file. |
400 |
self.pkgTimer.start() |
401 |
|
402 |
self.progress.setPackage(h) |
403 |
self.progress.setPackageScale(0, 1) |
404 |
self.instLog.write (self.modeText % (hdrlist.nevra(h))) |
405 |
self.instLog.flush () |
406 |
|
407 |
self.rpmFD = -1 |
408 |
self.size = h[rpm.RPMTAG_SIZE] |
409 |
|
410 |
while self.rpmFD < 0: |
411 |
try: |
412 |
fn = self.method.getRPMFilename(h, self.pkgTimer, |
413 |
callback=self.packageDownloadCB) |
414 |
self.rpmFD = os.open(fn, os.O_RDONLY) |
415 |
|
416 |
# Make sure this package seems valid |
417 |
try: |
418 |
hdr = self.ts.hdrFromFdno(self.rpmFD) |
419 |
os.lseek(self.rpmFD, 0, 0) |
420 |
|
421 |
# if we don't have a valid package, throw an error |
422 |
if not hdr: |
423 |
raise SystemError |
424 |
|
425 |
except: |
426 |
try: |
427 |
os.close(self.rpmFD) |
428 |
except: |
429 |
pass |
430 |
self.rpmFD = -1 |
431 |
raise FileCopyException |
432 |
except Exception, e: |
433 |
log("exception was %s for %s-%s-%s" %(e, h['name'], |
434 |
h['version'], |
435 |
h['release'])) |
436 |
|
437 |
self.method.unmountCD() |
438 |
self.messageWindow(_("Error"), |
439 |
_("The package %s-%s-%s cannot be opened. This is due " |
440 |
"to a missing file or perhaps a corrupt package. " |
441 |
"If you are installing from CD media this usually " |
442 |
"means the CD media is corrupt, or the CD drive is " |
443 |
"unable to read the media.\n\n" |
444 |
"Press <return> to try again.") % (h['name'], |
445 |
h['version'], |
446 |
h['release'])) |
447 |
self.progress.setPackageStatus(_("Installing..."), None) |
448 |
fn = self.method.unlinkFilename(fn) |
449 |
return self.rpmFD |
450 |
elif (what == rpm.RPMCALLBACK_INST_PROGRESS): |
451 |
# RPM returns strange values sometimes |
452 |
if amount > total: |
453 |
amount = total |
454 |
if not total or total == 0 or total == "0": |
455 |
total = amount |
456 |
self.progress.setPackageScale(amount, total) |
457 |
elif (what == rpm.RPMCALLBACK_INST_CLOSE_FILE): |
458 |
os.close (self.rpmFD) |
459 |
self.progress.completePackage(h, self.pkgTimer) |
460 |
self.progress.processEvents() |
461 |
elif ((what == rpm.RPMCALLBACK_UNPACK_ERROR) or |
462 |
(what == rpm.RPMCALLBACK_CPIO_ERROR)): |
463 |
# we may want to make this error more fine-grained at some |
464 |
# point |
465 |
pkg = "%s-%s-%s" % (h[rpm.RPMTAG_NAME], |
466 |
h[rpm.RPMTAG_VERSION], |
467 |
h[rpm.RPMTAG_RELEASE]) |
468 |
self.messageWindow(_("Error Installing Package"), |
469 |
_("There was an error installing %s. This " |
470 |
"can indicate media failure, lack of disk " |
471 |
"space, and/or hardware problems. This is " |
472 |
"a fatal error and your install will be " |
473 |
"aborted. Please verify your media and try " |
474 |
"your install again.\n\n" |
475 |
"Press the OK button to reboot " |
476 |
"your system.") % (pkg,)) |
477 |
sys.exit(0) |
478 |
else: |
479 |
pass |
480 |
|
481 |
self.progress.processEvents() |
482 |
|
483 |
def __init__(self, messageWindow, progress, pkgTimer, method, |
484 |
progressWindowClass, instLog, modeText, ts): |
485 |
self.messageWindow = messageWindow |
486 |
self.progress = progress |
487 |
self.pkgTimer = pkgTimer |
488 |
self.method = method |
489 |
self.progressWindowClass = progressWindowClass |
490 |
self.progressWindow = None |
491 |
self.lastprogress = 0 |
492 |
self.incr = 20 |
493 |
self.instLog = instLog |
494 |
self.modeText = modeText |
495 |
self.beenCalled = 0 |
496 |
self.initWindow = None |
497 |
self.ts = ts |
498 |
|
499 |
def sortPackages(first, second): |
500 |
# install packages in cd order (cd tag is 1000002) |
501 |
one = None |
502 |
two = None |
503 |
|
504 |
if first[1000003] != None: |
505 |
one = first[1000003] |
506 |
|
507 |
if second[1000003] != None: |
508 |
two = second[1000003] |
509 |
|
510 |
if one == None or two == None: |
511 |
one = 0 |
512 |
two = 0 |
513 |
if first[1000002] != None: |
514 |
one = first[1000002] |
515 |
|
516 |
if second[1000002] != None: |
517 |
two = second[1000002] |
518 |
|
519 |
if one < two: |
520 |
return -1 |
521 |
elif one > two: |
522 |
return 1 |
523 |
elif (string.lower(first[rpm.RPMTAG_NAME]) |
524 |
< string.lower(second[rpm.RPMTAG_NAME])): |
525 |
return -1 |
526 |
elif (string.lower(first[rpm.RPMTAG_NAME]) |
527 |
> string.lower(second[rpm.RPMTAG_NAME])): |
528 |
return 1 |
529 |
|
530 |
return 0 |
531 |
|
532 |
class rpmErrorClass: |
533 |
|
534 |
def cb(self): |
535 |
self.f.write (rpm.errorString () + "\n") |
536 |
|
537 |
def __init__(self, f): |
538 |
self.f = f |
539 |
|
540 |
def doMigrateFilesystems(dir, thefsset, diskset, upgrade, instPath): |
541 |
if dir == DISPATCH_BACK: |
542 |
return DISPATCH_NOOP |
543 |
|
544 |
if thefsset.haveMigratedFilesystems(): |
545 |
return DISPATCH_NOOP |
546 |
|
547 |
thefsset.migrateFilesystems (instPath) |
548 |
|
549 |
# if we're upgrading, we may need to do lvm device node hackery |
550 |
if upgrade.get(): |
551 |
thefsset.makeLVMNodes(instPath, trylvm1 = 1) |
552 |
|
553 |
|
554 |
def turnOnFilesystems(dir, thefsset, diskset, partitions, upgrade, instPath): |
555 |
if dir == DISPATCH_BACK: |
556 |
log("unmounting filesystems") |
557 |
thefsset.umountFilesystems(instPath) |
558 |
return |
559 |
|
560 |
if flags.setupFilesystems: |
561 |
if not upgrade.get(): |
562 |
partitions.doMetaDeletes(diskset) |
563 |
thefsset.setActive(diskset) |
564 |
if not thefsset.isActive(): |
565 |
diskset.savePartitions () |
566 |
thefsset.checkBadblocks(instPath) |
567 |
if not thefsset.volumesCreated: |
568 |
thefsset.createLogicalVolumes(instPath) |
569 |
thefsset.formatSwap(instPath) |
570 |
thefsset.turnOnSwap(instPath) |
571 |
thefsset.makeFilesystems (instPath) |
572 |
thefsset.mountFilesystems (instPath) |
573 |
|
574 |
def setupTimezone(timezone, upgrade, instPath, dir): |
575 |
# we don't need this on an upgrade or going backwards |
576 |
if upgrade.get() or (dir == DISPATCH_BACK): |
577 |
return |
578 |
|
579 |
# dont do this in test mode! |
580 |
if flags.test: |
581 |
return |
582 |
|
583 |
os.environ["TZ"] = timezone.tz |
584 |
tzfile = "/usr/share/zoneinfo/" + timezone.tz |
585 |
if not os.access(tzfile, os.R_OK): |
586 |
log("unable to set timezone") |
587 |
else: |
588 |
try: |
589 |
iutil.copyFile(tzfile, "/etc/localtime") |
590 |
except OSError, (errno, msg): |
591 |
log("Error copying timezone (from %s): %s" %(tzfile, msg)) |
592 |
|
593 |
if iutil.getArch() == "s390": |
594 |
return |
595 |
args = [ "/usr/sbin/hwclock", "--hctosys" ] |
596 |
if timezone.utc: |
597 |
args.append("-u") |
598 |
elif timezone.arc: |
599 |
args.append("-a") |
600 |
|
601 |
try: |
602 |
iutil.execWithRedirect(args[0], args, stdin = None, |
603 |
stdout = "/dev/tty5", stderr = "/dev/tty5") |
604 |
except RuntimeError: |
605 |
log("Failed to set clock") |
606 |
|
607 |
|
608 |
|
609 |
def doPreInstall(method, id, intf, instPath, dir): |
610 |
if dir == DISPATCH_BACK: |
611 |
for d in ("/selinux", "/dev"): |
612 |
try: |
613 |
isys.umount(instPath + d, removeDir = 0) |
614 |
except Exception, e: |
615 |
log("unable to unmount %s: %s" %(d, e)) |
616 |
return |
617 |
|
618 |
arch = iutil.getArch () |
619 |
|
620 |
# this is a crappy hack, but I don't want bug reports from these people |
621 |
if (arch == "i386") and (not id.grpset.hdrlist.has_key("kernel")): |
622 |
intf.messageWindow(_("Error"), |
623 |
_("You are trying to install on a machine " |
624 |
"which isn't supported by this release of " |
625 |
"%s.") %(productName,), |
626 |
type="custom", custom_icon="error", |
627 |
custom_buttons=[_("_Exit")]) |
628 |
sys.exit(0) |
629 |
|
630 |
# shorthand |
631 |
upgrade = id.upgrade.get() |
632 |
|
633 |
def select(hdrlist, name): |
634 |
if hdrlist.has_key(name): |
635 |
hdrlist[name].select(isManual = 1) |
636 |
return 1 |
637 |
return 0 |
638 |
|
639 |
def selected(hdrlist, name): |
640 |
if hdrlist.has_key(name) and hdrlist[name].isSelected(): |
641 |
return 1 |
642 |
return 0 |
643 |
|
644 |
if not upgrade: |
645 |
foundkernel = 0 |
646 |
nthreads = isys.acpicpus() |
647 |
|
648 |
if nthreads == 0: |
649 |
# this should probably be table driven or something... |
650 |
ncpus = isys.smpAvailable() or 1 |
651 |
nthreads = isys.htavailable() or 1 |
652 |
ncores = isys.coresavailable() |
653 |
|
654 |
if ncpus == 1: # machines that have one socket |
655 |
nthreads = nthreads; |
656 |
else: # machines with more than one socket |
657 |
nthreads = (nthreads / ncores) * ncpus |
658 |
|
659 |
largesmp_min = -1 |
660 |
if iutil.getArch() == "x86_64": |
661 |
largesmp_min = 8 |
662 |
elif iutil.getArch() == "ppc" and iutil.getPPCMachine() != "iSeries": |
663 |
largesmp_min = 64 |
664 |
elif iutil.getArch() == "ia64": |
665 |
largesmp_min = 64 |
666 |
|
667 |
if largesmp_min > 0 and nthreads > largesmp_min and \ |
668 |
select(id.grpset.hdrlist, "kernel-largesmp"): |
669 |
foundKernel = 1 |
670 |
if selected(id.grpset.hdrlist, "gcc"): |
671 |
select(id.grpset.hdrlist, "kernel-largesmp-devel") |
672 |
elif nthreads > 1: |
673 |
if select(id.grpset.hdrlist, "kernel-smp"): |
674 |
foundkernel = 1 |
675 |
if selected(id.grpset.hdrlist, "gcc"): |
676 |
select(id.grpset.hdrlist, "kernel-smp-devel") |
677 |
|
678 |
if iutil.needsEnterpriseKernel(): |
679 |
if select(id.grpset.hdrlist, "kernel-bigmem"): |
680 |
foundkernel = 1 |
681 |
|
682 |
if isys.summitavailable(): |
683 |
if select(id.grpset.hdrlist, "kernel-summit"): |
684 |
foundkernel = 1 |
685 |
|
686 |
if foundkernel == 0: |
687 |
# we *always* need to have some sort of kernel installed |
688 |
select(id.grpset.hdrlist, 'kernel') |
689 |
|
690 |
if (selected(id.grpset.hdrlist, "gcc") and |
691 |
selected(id.grpset.hdrlist, "kernel")): |
692 |
select(id.grpset.hdrlist, "kernel-devel") |
693 |
|
694 |
# if NIS is configured, install ypbind and dependencies: |
695 |
if id.auth.useNIS: |
696 |
select(id.grpset.hdrlist, 'ypbind') |
697 |
select(id.grpset.hdrlist, 'yp-tools') |
698 |
select(id.grpset.hdrlist, 'portmap') |
699 |
|
700 |
if id.auth.useLdap: |
701 |
select(id.grpset.hdrlist, 'nss_ldap') |
702 |
select(id.grpset.hdrlist, 'openldap') |
703 |
select(id.grpset.hdrlist, 'perl') |
704 |
|
705 |
if id.auth.useKrb5: |
706 |
select(id.grpset.hdrlist, 'pam_krb5') |
707 |
select(id.grpset.hdrlist, 'krb5-workstation') |
708 |
select(id.grpset.hdrlist, 'krbafs') |
709 |
select(id.grpset.hdrlist, 'krb5-libs') |
710 |
|
711 |
if id.auth.useSamba: |
712 |
select(id.grpset.hdrlist, 'pam_smb') |
713 |
|
714 |
if iutil.getArch() == "i386" and id.bootloader.useGrubVal == 0: |
715 |
select(id.grpset.hdrlist, 'lilo') |
716 |
elif iutil.getArch() == "i386" and id.bootloader.useGrubVal == 1: |
717 |
select(id.grpset.hdrlist, 'grub') |
718 |
elif iutil.getArch() == "s390": |
719 |
select(id.grpset.hdrlist, 's390utils') |
720 |
elif iutil.getArch() == "ppc": |
721 |
select(id.grpset.hdrlist, 'yaboot') |
722 |
elif iutil.getArch() == "ia64": |
723 |
select(id.grpset.hdrlist, 'elilo') |
724 |
|
725 |
if pcmcia.pcicType(): |
726 |
select(id.grpset.hdrlist, 'pcmcia-cs') |
727 |
|
728 |
for entry in id.fsset.entries: |
729 |
for pkg in entry.fsystem.getNeededPackages(): |
730 |
if select(id.grpset.hdrlist, pkg): |
731 |
log("Needed %s for %s" %(pkg, entry.getMountPoint())) |
732 |
|
733 |
if flags.test: |
734 |
return |
735 |
|
736 |
# make sure that all comps that include other comps are |
737 |
# selected (i.e. - recurse down the selected comps and turn |
738 |
# on the children |
739 |
while 1: |
740 |
try: |
741 |
method.mergeFullHeaders(id.grpset.hdrlist) |
742 |
except FileCopyException: |
743 |
method.unmountCD() |
744 |
intf.messageWindow(_("Error"), |
745 |
_("Unable to merge header list. This may be " |
746 |
"due to a missing file or bad media. " |
747 |
"Press <return> to try again.")) |
748 |
else: |
749 |
break |
750 |
|
751 |
if upgrade: |
752 |
# An old mtab can cause confusion (esp if loop devices are |
753 |
# in it) |
754 |
f = open(instPath + "/etc/mtab", "w+") |
755 |
f.close() |
756 |
|
757 |
# we really started writing modprobe.conf out before things were |
758 |
# all completely ready. so now we need to nuke old modprobe.conf's |
759 |
# if you're upgrading from a 2.4 dist so that we can get the |
760 |
# transition right |
761 |
if (os.path.exists(instPath + "/etc/modules.conf") and |
762 |
os.path.exists(instPath + "/etc/modprobe.conf") and |
763 |
not os.path.exists(instPath + "/etc/modprobe.conf.anacbak")): |
764 |
log("renaming old modprobe.conf -> modprobe.conf.anacbak") |
765 |
os.rename(instPath + "/etc/modprobe.conf", |
766 |
instPath + "/etc/modprobe.conf.anacbak") |
767 |
|
768 |
|
769 |
if method.systemMounted (id.fsset, instPath): |
770 |
id.fsset.umountFilesystems(instPath) |
771 |
return DISPATCH_BACK |
772 |
|
773 |
for i in ( '/var', '/var/lib', '/var/lib/rpm', '/tmp', '/dev', '/etc', |
774 |
'/etc/sysconfig', '/etc/sysconfig/network-scripts', |
775 |
'/etc/X11', '/root', '/var/tmp', '/etc/rpm' ): |
776 |
try: |
777 |
os.mkdir(instPath + i) |
778 |
except os.error, (errno, msg): |
779 |
pass |
780 |
# log("Error making directory %s: %s" % (i, msg)) |
781 |
|
782 |
|
783 |
if flags.setupFilesystems: |
784 |
# setup /etc/rpm/platform for the post-install environment |
785 |
iutil.writeRpmPlatform(instPath) |
786 |
|
787 |
try: |
788 |
# FIXME: making the /var/lib/rpm symlink here is a hack to |
789 |
# workaround db->close() errors from rpm |
790 |
iutil.mkdirChain("/var/lib") |
791 |
for path in ("/var/tmp", "/var/lib/rpm"): |
792 |
if os.path.exists(path) and not os.path.islink(path): |
793 |
iutil.rmrf(path) |
794 |
if not os.path.islink(path): |
795 |
os.symlink("/mnt/sysimage/%s" %(path,), "%s" %(path,)) |
796 |
else: |
797 |
log("%s already exists as a symlink to %s" %(path, os.readlink(path),)) |
798 |
except Exception, e: |
799 |
# how this could happen isn't entirely clear; log it in case |
800 |
# it does and causes problems later |
801 |
log("error creating symlink, continuing anyway: %s" %(e,)) |
802 |
|
803 |
# SELinux hackery (#121369) |
804 |
if flags.selinux: |
805 |
try: |
806 |
os.mkdir(instPath + "/selinux") |
807 |
except Exception, e: |
808 |
pass |
809 |
try: |
810 |
isys.mount("/selinux", instPath + "/selinux", "selinuxfs") |
811 |
except Exception, e: |
812 |
log("error mounting selinuxfs: %s" %(e,)) |
813 |
|
814 |
# we need to have a /dev during install and now that udev is |
815 |
# handling /dev, it gets to be more fun. so just bind mount the |
816 |
# installer /dev |
817 |
if not id.grpset.hdrlist.has_key("dev"): |
818 |
log("no dev package, going to bind mount /dev") |
819 |
isys.mount("/dev", "/mnt/sysimage/dev", bindMount = 1) |
820 |
|
821 |
# try to copy the comps package. if it doesn't work, don't worry about it |
822 |
try: |
823 |
id.compspkg = method.copyFileToTemp("%s/base/comps.rpm" % (productPath,)) |
824 |
except: |
825 |
log("Unable to copy comps package") |
826 |
id.compspkg = None |
827 |
|
828 |
# write out the fstab |
829 |
if not upgrade: |
830 |
id.fsset.write(instPath) |
831 |
# rootpath mode doesn't have this file around |
832 |
if os.access("/tmp/modprobe.conf", os.R_OK): |
833 |
iutil.copyFile("/tmp/modprobe.conf", |
834 |
instPath + "/etc/modprobe.conf") |
835 |
if os.access("/tmp/zfcp.conf", os.R_OK): |
836 |
iutil.copyFile("/tmp/zfcp.conf", |
837 |
instPath + "/etc/zfcp.conf") |
838 |
|
839 |
# make a /etc/mtab so mkinitrd can handle certain hw (usb) correctly |
840 |
f = open(instPath + "/etc/mtab", "w+") |
841 |
f.write(id.fsset.mtab()) |
842 |
f.close() |
843 |
|
844 |
# delay writing migrate adjusted fstab till later, in case |
845 |
# rpm transaction set determines they don't have enough space to upgrade |
846 |
# else: |
847 |
# id.fsset.migratewrite(instPath) |
848 |
|
849 |
def doInstall(method, id, intf, instPath): |
850 |
if flags.test: |
851 |
return |
852 |
|
853 |
# set up dependency white outs |
854 |
import whiteout |
855 |
|
856 |
upgrade = id.upgrade.get() |
857 |
ts = getAnacondaTS(instPath) |
858 |
|
859 |
total = 0 |
860 |
totalSize = 0 |
861 |
totalFiles = 0 |
862 |
|
863 |
if upgrade: |
864 |
how = "u" |
865 |
else: |
866 |
how = "i" |
867 |
rpm.addMacro("__dbi_htconfig", "hash nofsync %{__dbi_other} %{__dbi_perms}") |
868 |
|
869 |
if id.excludeDocs: |
870 |
rpm.addMacro("_excludedocs", "1") |
871 |
|
872 |
l = [] |
873 |
|
874 |
for p in id.grpset.hdrlist.values(): |
875 |
if p.isSelected(): |
876 |
l.append(p) |
877 |
l.sort(sortPackages) |
878 |
|
879 |
progress = intf.progressWindow(_("Processing"), |
880 |
_("Preparing RPM transaction..."), |
881 |
len(l)) |
882 |
|
883 |
|
884 |
# this is kind of a hack, but has to be done so we can have a chance |
885 |
# with broken triggers |
886 |
if upgrade and len(id.upgradeRemove) > 0: |
887 |
# simple rpm callback since erasure doesn't need anything |
888 |
def install_callback(what, bytes, total, h, user): |
889 |
pass |
890 |
|
891 |
for pkg in id.upgradeRemove: |
892 |
ts.addErase(pkg) |
893 |
|
894 |
# set the rpm log file to /dev/null so that we don't segfault |
895 |
f = open("/dev/null", "w+") |
896 |
rpm.setLogFile(f) |
897 |
ts.scriptFd = f.fileno() |
898 |
|
899 |
# if we hit problems, it's not like there's anything we can |
900 |
# do about it |
901 |
ts.run(install_callback, 0) |
902 |
|
903 |
# new transaction set |
904 |
ts.closeDB() |
905 |
del ts |
906 |
ts = getAnacondaTS(instPath) |
907 |
|
908 |
# we don't want to try to remove things more than once (#84221) |
909 |
id.upgradeRemove = [] |
910 |
|
911 |
i = 0 |
912 |
updcount = 0 |
913 |
updintv = len(l) / 25 |
914 |
for p in l: |
915 |
ts.addInstall(p.hdr, p.hdr, how) |
916 |
total = total + 1 |
917 |
totalSize = totalSize + (p[rpm.RPMTAG_SIZE] / 1024) |
918 |
totalFiles = totalFiles + len(p[rpm.RPMTAG_BASENAMES]) |
919 |
i = i + 1 |
920 |
|
921 |
# HACK - dont overload progress bar with useless requests |
922 |
updcount = updcount + 1 |
923 |
if updcount > updintv: |
924 |
progress.set(i) |
925 |
updcount = 0 |
926 |
|
927 |
progress.pop() |
928 |
|
929 |
# set the rpm log file to /dev/null to start with so we don't segfault |
930 |
f = open("/dev/null", "w+") |
931 |
rpm.setLogFile(f) |
932 |
ts.scriptFd = f.fileno() |
933 |
|
934 |
depcheck = DependencyChecker(id.grpset) |
935 |
if not id.grpset.hdrlist.preordered(): |
936 |
log ("WARNING: not all packages in hdlist had order tag") |
937 |
# have to call ts.check before ts.order() to set up the alIndex |
938 |
ts.check(depcheck.callback) |
939 |
log ("did ts.check, doing ts.order") |
940 |
ts.order() |
941 |
log ("ts.order is done") |
942 |
else: |
943 |
ts.check(depcheck.callback) |
944 |
|
945 |
if upgrade: |
946 |
logname = '/root/upgrade.log' |
947 |
else: |
948 |
logname = '/root/install.log' |
949 |
|
950 |
instLogName = instPath + logname |
951 |
try: |
952 |
iutil.rmrf (instLogName) |
953 |
except OSError: |
954 |
pass |
955 |
|
956 |
instLog = open(instLogName, "w+") |
957 |
|
958 |
# dont start syslogd if we arent creating filesystems |
959 |
if flags.setupFilesystems: |
960 |
syslogname = "%s%s.syslog" % (instPath, logname) |
961 |
try: |
962 |
iutil.rmrf (syslogname) |
963 |
except OSError: |
964 |
pass |
965 |
syslog.start (instPath, syslogname) |
966 |
else: |
967 |
syslogname = None |
968 |
|
969 |
if id.compspkg is not None: |
970 |
num = i + 1 |
971 |
else: |
972 |
num = i |
973 |
|
974 |
if upgrade: |
975 |
instLog.write(_("Upgrading %s packages\n\n") % (num,)) |
976 |
else: |
977 |
instLog.write(_("Installing %s packages\n\n") % (num,)) |
978 |
|
979 |
ts.scriptFd = instLog.fileno () |
980 |
log ("setting rpm logfile") |
981 |
rpm.setLogFile(instLog) |
982 |
# the transaction set dup()s the file descriptor and will close the |
983 |
# dup'd when we go out of scope |
984 |
|
985 |
if upgrade: |
986 |
modeText = _("Upgrading %s.\n") |
987 |
else: |
988 |
modeText = _("Installing %s.\n") |
989 |
|
990 |
log ("getting rpm error class") |
991 |
errors = rpmErrorClass(instLog) |
992 |
pkgTimer = timer.Timer(start = 0) |
993 |
|
994 |
id.instProgress.setSizes(total, totalSize, totalFiles) |
995 |
id.instProgress.processEvents() |
996 |
|
997 |
cb = InstallCallback(intf.messageWindow, id.instProgress, pkgTimer, |
998 |
method, intf.progressWindow, instLog, modeText, |
999 |
ts) |
1000 |
|
1001 |
# write out migrate adjusted fstab so kernel RPM can get initrd right |
1002 |
if upgrade: |
1003 |
id.fsset.migratewrite(instPath) |
1004 |
if id.upgradeDeps: |
1005 |
instLog.write(_("\n\nThe following packages were automatically\n" |
1006 |
"selected to be installed:" |
1007 |
"\n" |
1008 |
"%s" |
1009 |
"\n\n") % (id.upgradeDeps,)) |
1010 |
|
1011 |
cb.initWindow = intf.waitWindow(_("Install Starting"), |
1012 |
_("Starting install process, this may take several minutes...")) |
1013 |
|
1014 |
log ("setting problem filter") |
1015 |
ts.setProbFilter(~rpm.RPMPROB_FILTER_DISKSPACE) |
1016 |
problems = ts.run(cb.cb, 0) |
1017 |
|
1018 |
if problems: |
1019 |
# restore old fstab if we did anything for migrating |
1020 |
if upgrade: |
1021 |
id.fsset.restoreMigratedFstab(instPath) |
1022 |
|
1023 |
spaceneeded = {} |
1024 |
nodeneeded = {} |
1025 |
size = 12 |
1026 |
|
1027 |
for (descr, (type, mount, need)) in problems: |
1028 |
log("(%s, (%s, %s, %s))" %(descr, type, mount, need)) |
1029 |
if mount and mount.startswith(instPath): |
1030 |
mount = mount[len(instPath):] |
1031 |
if not mount: |
1032 |
mount = '/' |
1033 |
|
1034 |
if type == rpm.RPMPROB_DISKSPACE: |
1035 |
if spaceneeded.has_key (mount) and spaceneeded[mount] < need: |
1036 |
spaceneeded[mount] = need |
1037 |
else: |
1038 |
spaceneeded[mount] = need |
1039 |
elif type == nodeprob: |
1040 |
if nodeneeded.has_key (mount) and nodeneeded[mount] < need: |
1041 |
nodeneeded[mount] = need |
1042 |
else: |
1043 |
nodeneeded[mount] = need |
1044 |
else: |
1045 |
if descr is None: |
1046 |
descr = "no description" |
1047 |
log ("WARNING: unhandled problem returned from " |
1048 |
"transaction set type %d (%s)", |
1049 |
type, descr) |
1050 |
|
1051 |
probs = "" |
1052 |
if spaceneeded: |
1053 |
probs = probs + _("You don't appear to have enough disk space " |
1054 |
"to install the packages you've selected. " |
1055 |
"You need more space on the following " |
1056 |
"file systems:\n\n") |
1057 |
probs = probs + ("%-15s %s\n") % (_("Mount Point"), |
1058 |
_("Space Needed")) |
1059 |
|
1060 |
for (mount, need) in spaceneeded.items (): |
1061 |
log("(%s, %s)" %(mount, need)) |
1062 |
if need > (1024*1024): |
1063 |
need = (need + 1024 * 1024 - 1) / (1024 * 1024) |
1064 |
suffix = "M" |
1065 |
else: |
1066 |
need = (need + 1023) / 1024 |
1067 |
suffix = "k" |
1068 |
|
1069 |
prob = "%-15s %d %c\n" % (mount, need, suffix) |
1070 |
probs = probs + prob |
1071 |
if nodeneeded: |
1072 |
if probs: |
1073 |
probs = probs + '\n' |
1074 |
probs = probs + _("You don't appear to have enough file nodes " |
1075 |
"to install the packages you've selected. " |
1076 |
"You need more file nodes on the following " |
1077 |
"file systems:\n\n") |
1078 |
probs = probs + ("%-15s %s\n") % (_("Mount Point"), |
1079 |
_("Nodes Needed")) |
1080 |
|
1081 |
for (mount, need) in nodeneeded.items (): |
1082 |
prob = "%-15s %d\n" % (mount, need) |
1083 |
probs = probs + prob |
1084 |
|
1085 |
if len(probs) == 0: |
1086 |
probs = ("ERROR: NO! An unexpected problem has occurred with " |
1087 |
"your transaction set. Please see tty3 for more " |
1088 |
"information") |
1089 |
|
1090 |
intf.messageWindow (_("Disk Space"), probs) |
1091 |
|
1092 |
ts.closeDB() |
1093 |
del ts |
1094 |
instLog.close() |
1095 |
|
1096 |
if syslogname: |
1097 |
syslog.stop() |
1098 |
|
1099 |
method.systemUnmounted () |
1100 |
|
1101 |
return DISPATCH_BACK |
1102 |
|
1103 |
# This should close the RPM database so that you can |
1104 |
# do RPM ops in the chroot in a %post ks script |
1105 |
ts.closeDB() |
1106 |
del ts |
1107 |
|
1108 |
# make sure the window gets popped (#82862) |
1109 |
if not cb.beenCalled: |
1110 |
cb.initWindow.pop() |
1111 |
|
1112 |
method.filesDone () |
1113 |
|
1114 |
# rpm environment files go bye-bye |
1115 |
for file in ["__db.001", "__db.002", "__db.003"]: |
1116 |
try: |
1117 |
os.unlink("%s/var/lib/rpm/%s" %(instPath, file)) |
1118 |
except Exception, e: |
1119 |
log("failed to unlink /var/lib/rpm/%s: %s" %(file,e)) |
1120 |
# FIXME: remove the /var/lib/rpm symlink that keeps us from having |
1121 |
# db->close error messages shown. I don't really like this though :( |
1122 |
try: |
1123 |
os.unlink("/var/lib/rpm") |
1124 |
except Exception, e: |
1125 |
log("failed to unlink /var/lib/rpm: %s" %(e,)) |
1126 |
|
1127 |
instLog.close () |
1128 |
|
1129 |
id.instProgress = None |
1130 |
|
1131 |
def doPostInstall(method, id, intf, instPath): |
1132 |
if flags.test: |
1133 |
return |
1134 |
|
1135 |
upgrade = id.upgrade.get() |
1136 |
arch = iutil.getArch () |
1137 |
|
1138 |
if upgrade: |
1139 |
w = intf.progressWindow(_("Post Upgrade"), |
1140 |
_("Performing post upgrade configuration..."), 6) |
1141 |
logname = '/root/upgrade.log' |
1142 |
else: |
1143 |
w = intf.progressWindow(_("Post Install"), |
1144 |
_("Performing post install configuration..."), 6) |
1145 |
logname = '/root/install.log' |
1146 |
|
1147 |
instLogName = instPath + logname |
1148 |
instLog = open(instLogName, "a") |
1149 |
|
1150 |
try: |
1151 |
if not upgrade: |
1152 |
w.set(1) |
1153 |
|
1154 |
copyExtraModules(instPath, id.grpset, id.extraModules) |
1155 |
|
1156 |
w.set(2) |
1157 |
|
1158 |
# pcmcia is supported only on i386 at the moment |
1159 |
if arch == "i386": |
1160 |
pcmcia.createPcmciaConfig( |
1161 |
instPath + "/etc/sysconfig/pcmcia") |
1162 |
|
1163 |
# we need to write out the network bits before kudzu runs |
1164 |
# to avoid getting devices in the wrong order (#102276) |
1165 |
id.network.write(instPath) |
1166 |
|
1167 |
w.set(3) |
1168 |
|
1169 |
# blah. If we're on a serial mouse, and we have X, we need to |
1170 |
# close the mouse device, then run kudzu, then open it again. |
1171 |
|
1172 |
# turn it off |
1173 |
mousedev = None |
1174 |
|
1175 |
# XXX currently Bad Things (X async reply) happen when doing |
1176 |
# Mouse Magic on Sparc (Mach64, specificly) |
1177 |
# The s390 doesn't even have a mouse! |
1178 |
if os.environ.get('DISPLAY') == ':1' and arch != 'sparc': |
1179 |
try: |
1180 |
import xmouse |
1181 |
mousedev = xmouse.get()[0] |
1182 |
except RuntimeError: |
1183 |
pass |
1184 |
|
1185 |
if mousedev: |
1186 |
try: |
1187 |
os.rename (mousedev, "/dev/disablemouse") |
1188 |
except OSError: |
1189 |
pass |
1190 |
try: |
1191 |
xmouse.reopen() |
1192 |
except RuntimeError: |
1193 |
pass |
1194 |
|
1195 |
if arch != "s390" and flags.setupFilesystems: |
1196 |
# we need to unmount usbdevfs before mounting it |
1197 |
usbWasMounted = iutil.isUSBDevFSMounted() |
1198 |
if usbWasMounted: |
1199 |
isys.umount('/proc/bus/usb', removeDir = 0) |
1200 |
|
1201 |
# see if unmount suceeded, if not pretent it isnt mounted |
1202 |
# because we're screwed anywyas if system is going to |
1203 |
# lock up |
1204 |
if iutil.isUSBDevFSMounted(): |
1205 |
usbWasMounted = 0 |
1206 |
|
1207 |
unmountUSB = 0 |
1208 |
try: |
1209 |
isys.mount('/usbfs', instPath+'/proc/bus/usb', 'usbfs') |
1210 |
unmountUSB = 1 |
1211 |
except: |
1212 |
log("Mount of /proc/bus/usb in chroot failed") |
1213 |
pass |
1214 |
|
1215 |
argv = [ "/usr/sbin/kudzu", "-q" ] |
1216 |
if id.grpset.hdrlist.has_key("kernel"): |
1217 |
ver = "%s-%s" %(id.grpset.hdrlist["kernel"][rpm.RPMTAG_VERSION], |
1218 |
id.grpset.hdrlist["kernel"][rpm.RPMTAG_RELEASE]) |
1219 |
argv.extend(["-k", ver]) |
1220 |
|
1221 |
devnull = os.open("/dev/null", os.O_RDWR) |
1222 |
iutil.execWithRedirect(argv[0], argv, root = instPath, |
1223 |
stdout = devnull) |
1224 |
# turn it back on |
1225 |
if mousedev: |
1226 |
try: |
1227 |
os.rename ("/dev/disablemouse", mousedev) |
1228 |
except OSError: |
1229 |
pass |
1230 |
try: |
1231 |
xmouse.reopen() |
1232 |
except RuntimeError: |
1233 |
pass |
1234 |
|
1235 |
if unmountUSB: |
1236 |
try: |
1237 |
isys.umount(instPath + '/proc/bus/usb', removeDir = 0) |
1238 |
except SystemError: |
1239 |
# if we fail to unmount, then we should just not |
1240 |
# try to remount it. this protects us from random |
1241 |
# suckage |
1242 |
usbWasMounted = 0 |
1243 |
|
1244 |
if usbWasMounted: |
1245 |
isys.mount('/usbfs', '/proc/bus/usb', 'usbfs') |
1246 |
|
1247 |
w.set(4) |
1248 |
|
1249 |
if upgrade and id.dbpath is not None: |
1250 |
# remove the old rpmdb |
1251 |
try: |
1252 |
iutil.rmrf (id.dbpath) |
1253 |
except OSError: |
1254 |
pass |
1255 |
|
1256 |
if upgrade: |
1257 |
# needed for prior systems which were not xinetd based |
1258 |
migrateXinetd(instPath, instLogName) |
1259 |
|
1260 |
# needed for prior to 2.6 so that mice have some chance |
1261 |
# of working afterwards. FIXME: this is a hack |
1262 |
migrateMouseConfig(instPath, instLogName) |
1263 |
|
1264 |
if id.grpset.hdrlist.has_key("rhgb") and id.grpset.hdrlist["rhgb"].isSelected(): |
1265 |
log("rhgb installed, adding to boot loader config") |
1266 |
id.bootloader.args.append("rhgb quiet") |
1267 |
|
1268 |
w.set(5) |
1269 |
|
1270 |
# FIXME: hack to install the comps package |
1271 |
if (id.compspkg is not None and |
1272 |
os.access(id.compspkg, os.R_OK)): |
1273 |
log("found the comps package") |
1274 |
try: |
1275 |
# ugly hack |
1276 |
path = id.compspkg.split("/mnt/sysimage")[1] |
1277 |
args = ["/bin/rpm", "-Uvh", path] |
1278 |
rc = iutil.execWithRedirect(args[0], args, |
1279 |
stdout = "/dev/tty5", |
1280 |
stderr = "/dev/tty5", |
1281 |
root = instPath) |
1282 |
ts = rpm.TransactionSet() |
1283 |
ts.setVSFlags(~(rpm.RPMVSF_NORSA|rpm.RPMVSF_NODSA)) |
1284 |
ts.closeDB() |
1285 |
fd = os.open(id.compspkg, os.O_RDONLY) |
1286 |
h = ts.hdrFromFdno(fd) |
1287 |
os.close(fd) |
1288 |
if upgrade: |
1289 |
text = _("Upgrading %s.\n") |
1290 |
else: |
1291 |
text = _("Installing %s.\n") |
1292 |
instLog.write(text % (hdrlist.nevra(h))) |
1293 |
os.unlink(id.compspkg) |
1294 |
del ts |
1295 |
|
1296 |
except Exception, e: |
1297 |
log("comps.rpm failed to install: %s" %(e,)) |
1298 |
try: |
1299 |
os.unlink(id.compspkg) |
1300 |
except: |
1301 |
pass |
1302 |
else: |
1303 |
log("no comps package found") |
1304 |
|
1305 |
w.set(6) |
1306 |
|
1307 |
|
1308 |
finally: |
1309 |
pass |
1310 |
|
1311 |
if upgrade: |
1312 |
instLog.write(_("\n\nThe following packages were available in " |
1313 |
"this version but NOT upgraded:\n")) |
1314 |
else: |
1315 |
instLog.write(_("\n\nThe following packages were available in " |
1316 |
"this version but NOT installed:\n")) |
1317 |
|
1318 |
ts = rpm.TransactionSet(instPath) |
1319 |
ts.setVSFlags(~(rpm.RPMVSF_NORSA|rpm.RPMVSF_NODSA)) |
1320 |
|
1321 |
lines = [] |
1322 |
for p in id.grpset.hdrlist.values(): |
1323 |
if not p.isSelected(): |
1324 |
text = "%s" % (hdrlist.nevra(p)) |
1325 |
for f in ts.dbMatch('name', p.hdr[rpm.RPMTAG_NAME]): |
1326 |
if hdrlist.nevra(p) == hdrlist.nevra(f): |
1327 |
text = "%s (already installed)" % (text) |
1328 |
else: |
1329 |
text = "%s (%s installed)" % (text, hdrlist.nevra(f)) |
1330 |
lines.append("%s\n" % text) |
1331 |
lines.sort() |
1332 |
for line in lines: |
1333 |
instLog.write(line) |
1334 |
|
1335 |
|
1336 |
# XXX hack - we should really write a proper lvm "config". but for now |
1337 |
# just vgscan if they have /sbin/lvm and some appearance of volumes |
1338 |
if (os.access(instPath + "/sbin/lvm", os.X_OK) and |
1339 |
os.access(instPath + "/dev/mapper", os.X_OK) and |
1340 |
len(os.listdir("/dev/mapper")) > 1): |
1341 |
rc = iutil.execWithRedirect("/sbin/lvm", |
1342 |
["lvm", "vgscan", "-v"], |
1343 |
stdout = "/dev/tty5", |
1344 |
stderr = "/dev/tty5", |
1345 |
root = instPath, |
1346 |
searchPath = 1) |
1347 |
|
1348 |
# write out info on install method used |
1349 |
try: |
1350 |
if id.methodstr is not None: |
1351 |
if os.access (instPath + "/etc/sysconfig/installinfo", os.R_OK): |
1352 |
os.rename (instPath + "/etc/sysconfig/installinfo", |
1353 |
instPath + "/etc/sysconfig/installinfo.rpmsave") |
1354 |
|
1355 |
f = open(instPath + "/etc/sysconfig/installinfo", "w+") |
1356 |
f.write("INSTALLMETHOD=%s\n" % (string.split(id.methodstr, ':')[0],)) |
1357 |
|
1358 |
try: |
1359 |
ii = open("/tmp/isoinfo", "r") |
1360 |
il = ii.readlines() |
1361 |
ii.close() |
1362 |
for line in il: |
1363 |
f.write(line) |
1364 |
except: |
1365 |
pass |
1366 |
f.close() |
1367 |
else: |
1368 |
log("methodstr not set for some reason") |
1369 |
except: |
1370 |
log("Failed to write out installinfo") |
1371 |
|
1372 |
w.pop () |
1373 |
|
1374 |
sys.stdout.flush() |
1375 |
|
1376 |
if flags.setupFilesystems: |
1377 |
syslog.stop() |
1378 |
|
1379 |
# FIXME: this is a huge gross hack. hard coded list of files |
1380 |
# created by anaconda so that we can not be killed by selinux |
1381 |
def setFileCons(instPath, partitions): |
1382 |
import partRequests |
1383 |
|
1384 |
if flags.selinux: |
1385 |
log("setting SELinux contexts for anaconda created files") |
1386 |
|
1387 |
files = ["/etc/rpm/platform", "/etc/rpm/macros", |
1388 |
"/etc/lilo.conf", "/etc/lilo.conf.anaconda", |
1389 |
"/etc/mtab", "/etc/fstab", "/etc/resolv.conf", |
1390 |
"/etc/modprobe.conf", "/etc/modprobe.conf~", |
1391 |
"/var/log/wtmp", "/var/run/utmp", |
1392 |
"/dev/log", "/var/lib/rpm", "/", "/etc/raidtab", |
1393 |
"/etc/mdadm.conf"] |
1394 |
|
1395 |
vgs = [] |
1396 |
for entry in partitions.requests: |
1397 |
if isinstance(entry, partRequests.VolumeGroupRequestSpec): |
1398 |
vgs.append("/dev/%s" %(entry.volumeGroupName,)) |
1399 |
|
1400 |
# ugh, this is ugly |
1401 |
for dir in ["/var/lib/rpm", "/etc/lvm", "/dev/mapper"] + vgs: |
1402 |
def addpath(x): return dir + "/" + x |
1403 |
|
1404 |
if not os.path.isdir(instPath + dir): |
1405 |
continue |
1406 |
dirfiles = os.listdir(instPath + dir) |
1407 |
files.extend(map(addpath, dirfiles)) |
1408 |
files.append(dir) |
1409 |
|
1410 |
# blah, to work in a chroot, we need to actually be inside so the |
1411 |
# regexes will work |
1412 |
child = os.fork() |
1413 |
if (not child): |
1414 |
os.chroot(instPath) |
1415 |
for f in files: |
1416 |
if not os.access("%s" %(f,), os.R_OK): |
1417 |
log("%s doesn't exist" %(f,)) |
1418 |
continue |
1419 |
ret = isys.resetFileContext(f) |
1420 |
log("set fc of %s to %s" %(f, ret)) |
1421 |
os._exit(0) |
1422 |
|
1423 |
try: |
1424 |
os.waitpid(child, 0) |
1425 |
except OSError, (num, msg): |
1426 |
pass |
1427 |
|
1428 |
|
1429 |
return |
1430 |
|
1431 |
# XXX: large hack lies here |
1432 |
def migrateMouseConfig(instPath, instLog): |
1433 |
if not os.access (instPath + "/usr/sbin/fix-mouse-psaux", os.X_OK): |
1434 |
return |
1435 |
|
1436 |
argv = [ "/usr/sbin/fix-mouse-psaux" ] |
1437 |
|
1438 |
logfile = os.open (instLog, os.O_APPEND) |
1439 |
iutil.execWithRedirect(argv[0], argv, root = instPath, |
1440 |
stdout = logfile, stderr = logfile) |
1441 |
os.close(logfile) |
1442 |
|
1443 |
|
1444 |
def migrateXinetd(instPath, instLog): |
1445 |
if not os.access (instPath + "/usr/sbin/inetdconvert", os.X_OK): |
1446 |
return |
1447 |
|
1448 |
if not os.access (instPath + "/etc/inetd.conf.rpmsave", os.R_OK): |
1449 |
return |
1450 |
|
1451 |
argv = [ "/usr/sbin/inetdconvert", "--convertremaining", |
1452 |
"--inetdfile", "/etc/inetd.conf.rpmsave" ] |
1453 |
|
1454 |
logfile = os.open (instLog, os.O_APPEND) |
1455 |
iutil.execWithRedirect(argv[0], argv, root = instPath, |
1456 |
stdout = logfile, stderr = logfile) |
1457 |
os.close(logfile) |
1458 |
|
1459 |
def copyExtraModules(instPath, grpset, extraModules): |
1460 |
kernelVersions = grpset.kernelVersionList() |
1461 |
foundModule = 0 |
1462 |
|
1463 |
try: |
1464 |
f = open("/etc/arch") |
1465 |
arch = f.readline().strip() |
1466 |
del f |
1467 |
except IOError: |
1468 |
arch = os.uname()[2] |
1469 |
|
1470 |
for (path, name) in extraModules: |
1471 |
if not path: |
1472 |
path = "/modules.cgz" |
1473 |
pattern = "" |
1474 |
names = "" |
1475 |
for (n, tag) in kernelVersions: |
1476 |
if tag == "up": |
1477 |
pkg = "kernel" |
1478 |
else: |
1479 |
pkg = "kernel-%s" %(tag,) |
1480 |
arch = grpset.hdrlist[pkg][rpm.RPMTAG_ARCH] |
1481 |
# version 1 path |
1482 |
pattern = pattern + " %s/%s/%s.ko " % (n, arch, name) |
1483 |
# version 0 path |
1484 |
pattern = pattern + " %s/%s.ko " % (n, name) |
1485 |
names = names + " %s.ko" % (name,) |
1486 |
command = ("cd %s/lib/modules; gunzip < %s | " |
1487 |
"%s/bin/cpio --quiet -iumd %s" % |
1488 |
(instPath, path, instPath, pattern)) |
1489 |
log("running: '%s'" % (command, )) |
1490 |
os.system(command) |
1491 |
|
1492 |
for (n, tag) in kernelVersions: |
1493 |
if tag == "up": |
1494 |
pkg = "kernel" |
1495 |
else: |
1496 |
pkg = "kernel-%s" %(tag,) |
1497 |
|
1498 |
toDir = "%s/lib/modules/%s/updates" % \ |
1499 |
(instPath, n) |
1500 |
to = "%s/%s.ko" % (toDir, name) |
1501 |
|
1502 |
if (os.path.isdir("%s/lib/modules/%s" %(instPath, n)) and not |
1503 |
os.path.isdir("%s/lib/modules/%s/updates" %(instPath, n))): |
1504 |
os.mkdir("%s/lib/modules/%s/updates" %(instPath, n)) |
1505 |
if not os.path.isdir(toDir): |
1506 |
continue |
1507 |
|
1508 |
arch = grpset.hdrlist[pkg][rpm.RPMTAG_ARCH] |
1509 |
for p in ("%s/%s.ko" %(arch, name), "%s.ko" %(name,)): |
1510 |
fromFile = "%s/lib/modules/%s/%s" % (instPath, n, p) |
1511 |
|
1512 |
if (os.access(fromFile, os.R_OK)): |
1513 |
log("moving %s to %s" % (fromFile, to)) |
1514 |
os.rename(fromFile, to) |
1515 |
# the file might not have been owned by root in the cgz |
1516 |
os.chown(to, 0, 0) |
1517 |
foundModule = 1 |
1518 |
else: |
1519 |
log("missing DD module %s (this may be okay)" % |
1520 |
fromFile) |
1521 |
|
1522 |
if foundModule == 1: |
1523 |
for (n, tag) in kernelVersions: |
1524 |
recreateInitrd(n, instPath) |
1525 |
|
1526 |
|
1527 |
#Recreate initrd for use when driver disks add modules |
1528 |
def recreateInitrd (kernelTag, instRoot): |
1529 |
log("recreating initrd for %s" % (kernelTag,)) |
1530 |
iutil.execWithRedirect("/sbin/new-kernel-pkg", |
1531 |
[ "/sbin/new-kernel-pkg", "--mkinitrd", |
1532 |
"--depmod", "--install", kernelTag ], |
1533 |
stdout = None, stderr = None, |
1534 |
searchPath = 1, root = instRoot) |
1535 |
|
1536 |
# XXX Deprecated. Is this ever called anymore? |
1537 |
def depmodModules(comps, instPath): |
1538 |
kernelVersions = comps.kernelVersionList() |
1539 |
|
1540 |
for (version, tag) in kernelVersions: |
1541 |
iutil.execWithRedirect ("/sbin/depmod", |
1542 |
[ "/sbin/depmod", "-a", version, |
1543 |
"-F", "/boot/System.map-" + version ], |
1544 |
root = instPath, stderr = '/dev/null') |
1545 |
|
1546 |
|
1547 |
def betaNagScreen(intf, dir): |
1548 |
publicBetas = { "Red Hat Linux": "Red Hat Linux Public Beta", |
1549 |
"Red Hat Enterprise Linux": "Red Hat Enterprise Linux Public Beta", |
1550 |
"Fedora Core": "Fedora Core" } |
1551 |
|
1552 |
|
1553 |
if dir == DISPATCH_BACK: |
1554 |
return DISPATCH_NOOP |
1555 |
|
1556 |
fileagainst = None |
1557 |
for (key, val) in publicBetas.items(): |
1558 |
if productName.startswith(key): |
1559 |
fileagainst = val |
1560 |
if fileagainst is None: |
1561 |
fileagainst = "%s Beta" %(productName,) |
1562 |
|
1563 |
while 1: |
1564 |
rc = intf.messageWindow( _("Warning! This is pre-release software!"), |
1565 |
_("Thank you for downloading this " |
1566 |
"pre-release of %s.\n\n" |
1567 |
"This is not a final " |
1568 |
"release and is not intended for use " |
1569 |
"on production systems. The purpose of " |
1570 |
"this release is to collect feedback " |
1571 |
"from testers, and it is not suitable " |
1572 |
"for day to day usage.\n\n" |
1573 |
"To report feedback, please visit:\n\n" |
1574 |
" http://www.centos.orrg/bugs\n\n" |
1575 |
"and file a report against '%s'.\n" |
1576 |
%(productName, fileagainst)), |
1577 |
type="custom", custom_icon="warning", |
1578 |
custom_buttons=[_("_Exit"), _("_Install anyway")]) |
1579 |
|
1580 |
if not rc: |
1581 |
if flags.rootpath: |
1582 |
msg = _("The installer will now exit...") |
1583 |
buttons = [_("_Back"), _("_Exit")] |
1584 |
else: |
1585 |
msg = _("Your system will now be rebooted...") |
1586 |
buttons = [_("_Back"), _("_Reboot")] |
1587 |
rc = intf.messageWindow( _("Rebooting System"), |
1588 |
msg, |
1589 |
type="custom", custom_icon="warning", |
1590 |
custom_buttons=buttons) |
1591 |
if rc: |
1592 |
sys.exit(0) |
1593 |
else: |
1594 |
break |
1595 |
|
1596 |
# FIXME: this is a kind of poor way to do this, but it will work for now |
1597 |
def selectLanguageSupportGroups(grpset, langSupport): |
1598 |
sup = langSupport.supported |
1599 |
if len(sup) == 0: |
1600 |
sup = langSupport.getAllSupported() |
1601 |
|
1602 |
for group in grpset.groups.values(): |
1603 |
xmlgrp = grpset.compsxml.groups[group.basename] |
1604 |
langs = [] |
1605 |
for name in sup: |
1606 |
try: |
1607 |
lang = langSupport.langInfoByName[name][0] |
1608 |
langs.extend(language.expandLangs(lang)) |
1609 |
except: |
1610 |
continue |
1611 |
|
1612 |
if group.langonly is not None and group.langonly in langs: |
1613 |
group.select() |
1614 |
for package in xmlgrp.pkgConditionals.keys(): |
1615 |
req = xmlgrp.pkgConditionals[package] |
1616 |
if not grpset.hdrlist.has_key(package): |
1617 |
log("Missing %s which is in a langsupport conditional" %(package,)) |
1618 |
continue |
1619 |
# add to the deps in the dependencies structure for the |
1620 |
# package. this should take care of whenever we're |
1621 |
# selected |
1622 |
grpset.hdrlist[req].addDeps([package], main = 0) |
1623 |
if grpset.hdrlist[req].isSelected(): |
1624 |
grpset.hdrlist[package].select() |
1625 |
sys.stdout.flush() |
1626 |
grpset.hdrlist[package].usecount += grpset.hdrlist[req].usecount - 1 |
1627 |
group.selectDeps([package], uses = grpset.hdrlist[req].usecount) |
1628 |
|