diff options
author | 2011-06-15 16:59:54 +0000 | |
---|---|---|
committer | 2011-06-15 16:59:54 +0000 | |
commit | 2590d96369d0217e31dc2812690dde61dac417b5 (patch) | |
tree | 82276f787b08a28548e342c7921486f1acefab9f /upgrade.py | |
parent | first commit (diff) | |
download | anaconda-2590d96369d0217e31dc2812690dde61dac417b5.tar.gz anaconda-2590d96369d0217e31dc2812690dde61dac417b5.tar.bz2 anaconda-2590d96369d0217e31dc2812690dde61dac417b5.zip |
Initial import from Sabayon (ver 0.9.9.56)
Diffstat (limited to 'upgrade.py')
-rw-r--r-- | upgrade.py | 342 |
1 files changed, 342 insertions, 0 deletions
diff --git a/upgrade.py b/upgrade.py new file mode 100644 index 0000000..6ee61cc --- /dev/null +++ b/upgrade.py @@ -0,0 +1,342 @@ +# +# upgrade.py - Existing install probe and upgrade procedure +# +# Copyright (C) 2001, 2002, 2003, 2004, 2005, 2006, 2007 Red Hat, Inc. +# All rights reserved. +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. +# +# Author(s): Matt Wilson <msw@redhat.com> +# + +import isys +import os +import iutil +import time +import sys +import os.path +import shutil +import string +import selinux +from flags import flags +from constants import * +from product import productName +from storage import findExistingRootDevices, getReleaseString +from storage import mountExistingSystem +from storage.formats import getFormat + +import gettext +_ = lambda x: gettext.ldgettext("anaconda", x) + +import logging +log = logging.getLogger("anaconda") + +def queryUpgradeContinue(anaconda): + if anaconda.dir == DISPATCH_FORWARD: + return + + rc = anaconda.intf.messageWindow(_("Proceed with upgrade?"), + _("The file systems of the Linux installation " + "you have chosen to upgrade have already been " + "mounted. You cannot go back past this point. " + "\n\n") + + _("Would you like to continue with the upgrade?"), + type="custom", custom_icon=["error","error"], + custom_buttons=[_("_Exit installer"), _("_Continue")]) + if rc == 0: + sys.exit(0) + return DISPATCH_FORWARD + +def setUpgradeRoot(anaconda): + anaconda.upgradeRoot = [] + root_device = None + # kickstart can pass device as device name or uuid. No quotes allowed. + if anaconda.ksdata and anaconda.ksdata.upgrade.root_device is not None: + root_device = anaconda.ksdata.upgrade.root_device + for (dev, label) in anaconda.rootParts: + if ((root_device is not None) and + (root_device == dev.name or root_device == "UUID=%s" % dev.format.uuid)): + anaconda.upgradeRoot.insert(0, (dev,label)) + else: + anaconda.upgradeRoot.append((dev,label)) + +def findRootParts(anaconda): + if anaconda.dir == DISPATCH_BACK: + return + if anaconda.rootParts is None: + anaconda.rootParts = findExistingRoots(anaconda, + flags.cmdline.has_key("upgradeany")) + + setUpgradeRoot(anaconda) + + if anaconda.rootParts is not None and len(anaconda.rootParts) > 0: + anaconda.dispatch.skipStep("findinstall", skip = 0) + if productName.find("Red Hat Enterprise Linux") == -1: + anaconda.dispatch.skipStep("installtype", skip = 1) + else: + anaconda.dispatch.skipStep("findinstall", skip = 1) + anaconda.dispatch.skipStep("installtype", skip = 0) + +def findExistingRoots(anaconda, upgradeany=False): + rootparts = findExistingRootDevices(anaconda, upgradeany=upgradeany) + return rootparts + +def bindMountDevDirectory(instPath): + getFormat("bind", + device="/dev", + mountpoint="/dev", + exists=True).mount(chroot=instPath) + +# returns None if no filesystem exist to migrate +def upgradeMigrateFind(anaconda): + migents = anaconda.storage.migratableDevices + if not migents or len(migents) < 1: + anaconda.dispatch.skipStep("upgrademigratefs") + else: + anaconda.dispatch.skipStep("upgrademigratefs", skip = 0) + +def copyFromSysimage(rootPath, filename): + """Mirrors filename from the sysimage on the ramdisk.""" + sysfile = os.path.normpath("%s/%s" % (rootPath, filename)) + if os.access(sysfile, os.R_OK): + try: + # remove our copy if we have one (think liveinstall) + os.remove(filename) + except OSError: + pass + try: + shutil.copyfile(sysfile, filename) + except OSError as e: + log.error("Error copying %s to sysimage: %s" %(sysfile, e.strerror)) + return False + else: + log.error("Error copying %s to sysimage, file not accessible." % sysfile) + return False + return True + +def restoreTime(anaconda): + """Load time setup for upgrade install. + + We need to find out the timezone and the UTC parameter of the old system and + set the system time accordingly, so timestamps are set correctly for the + files the upgrade procedure will create. + + This is pretty much what packages.setupTimezone() does in reverse. + """ + if anaconda.dir == DISPATCH_BACK: + return + if os.environ.has_key("TZ"): + del os.environ["TZ"] + copyFromSysimage(anaconda.rootPath, '/etc/localtime') + copyFromSysimage(anaconda.rootPath, '/etc/adjtime') + if iutil.isS390(): + return + args = [ "--hctosys" ] + try: + iutil.execWithRedirect("/sbin/hwclock", args,stdout = "/dev/tty5", + stderr = "/dev/tty5") + except RuntimeError: + log.error("Failed to set the clock.") + +# returns None if no more swap is needed +def upgradeSwapSuggestion(anaconda): + # mem is in kb -- round it up to the nearest 4Mb + mem = iutil.memInstalled() + rem = mem % 16384 + if rem: + mem = mem + (16384 - rem) + mem = mem / 1024 + + anaconda.dispatch.skipStep("addswap", 0) + + # don't do this if we have more then 250 MB + if mem > 250: + anaconda.dispatch.skipStep("addswap", 1) + return + + swap = iutil.swapAmount() / 1024 + + # if we have twice as much swap as ram and at least 192 megs + # total, we're safe + if (swap >= (mem * 1.5)) and (swap + mem >= 192): + anaconda.dispatch.skipStep("addswap", 1) + return + + # if our total is 512 megs or more, we should be safe + if (swap + mem >= 512): + anaconda.dispatch.skipStep("addswap", 1) + return + + fsList = [] + + for device in anaconda.storage.fsset.devices: + if not device.format: + continue + if device.format.mountable and device.format.linuxNative: + if not device.format.status: + continue + space = isys.pathSpaceAvailable(anaconda.rootPath + device.format.mountpoint) + if space > 16: + info = (device, space) + fsList.append(info) + + suggestion = mem * 2 - swap + if (swap + mem + suggestion) < 192: + suggestion = 192 - (swap + mem) + if suggestion < 32: + suggestion = 32 + suggSize = 0 + suggMnt = None + for (device, size) in fsList: + if (size > suggSize) and (size > (suggestion + 100)): + suggDev = device + + anaconda.upgradeSwapInfo = (fsList, suggestion, suggDev) + +# XXX handle going backwards +def upgradeMountFilesystems(anaconda): + # mount everything and turn on swap + + try: + mountExistingSystem(anaconda, anaconda.upgradeRoot[0], allowDirty = 0) + except ValueError as e: + log.error("Error mounting filesystem: %s" % e) + anaconda.intf.messageWindow(_("Mount failed"), + _("The following error occurred when mounting the file " + "systems listed in /etc/fstab. Please fix this problem " + "and try to upgrade again.\n%s" % e)) + sys.exit(0) + except IndexError as e: + # The upgrade root is search earlier but we give the message here. + log.debug("No upgrade root was found.") + if anaconda.ksdata and anaconda.ksdata.upgrade.upgrade: + anaconda.intf.messageWindow(_("Upgrade root not found"), + _("The root for the previously installed system was not " + "found."), type="custom", + custom_icon="info", + custom_buttons=[_("Exit installer")]) + sys.exit(0) + else: + rc = anaconda.intf.messageWindow(_("Upgrade root not found"), + _("The root for the previously installed system was not " + "found. You can exit installer or backtrack to choose " + "installation instead of upgrade."), + type="custom", + custom_buttons = [ _("_Back"), + _("_Exit installer") ], + custom_icon="question") + if rc == 0: + return DISPATCH_BACK + elif rc == 1: + sys.exit(0) + + checkLinks = ( '/etc', '/var', '/var/lib', '/var/lib/rpm', + '/boot', '/tmp', '/var/tmp', '/root', + '/bin/sh', '/usr/tmp') + badLinks = [] + for n in checkLinks: + if not os.path.islink(anaconda.rootPath + n): continue + l = os.readlink(anaconda.rootPath + n) + if l[0] == '/': + badLinks.append(n) + + if badLinks: + message = _("The following files are absolute symbolic " + "links, which we do not support during an " + "upgrade. Please change them to relative " + "symbolic links and restart the upgrade.\n\n") + for n in badLinks: + message = message + '\t' + n + '\n' + anaconda.intf.messageWindow(_("Absolute Symlinks"), message) + sys.exit(0) + + # fix for 80446 + badLinks = [] + mustBeLinks = ( '/usr/tmp', ) + for n in mustBeLinks: + if not os.path.islink(anaconda.rootPath + n): + badLinks.append(n) + + if badLinks: + message = _("The following are directories which should instead " + "be symbolic links, which will cause problems with the " + "upgrade. Please return them to their original state " + "as symbolic links and restart the upgrade.\n\n") + for n in badLinks: + message = message + '\t' + n + '\n' + anaconda.intf.messageWindow(_("Invalid Directories"), message) + sys.exit(0) + + anaconda.storage.turnOnSwap(upgrading=True) + anaconda.storage.mkDevRoot() + + # Move /etc/rpm/platform out of the way. + if os.path.exists(anaconda.rootPath + "/etc/rpm/platform"): + shutil.move(anaconda.rootPath + "/etc/rpm/platform", + anaconda.rootPath + "/etc/rpm/platform.rpmsave") + + # if they've been booting with selinux disabled, then we should + # disable it during the install as well (#242510) + try: + if os.path.exists(anaconda.rootPath + "/.autorelabel"): + ctx = selinux.getfilecon(anaconda.rootPath + "/.autorelabel")[1] + if not ctx or ctx == "unlabeled": + flags.selinux = False + log.info("Disabled SELinux for upgrade based on /.autorelabel") + except Exception, e: + log.warning("error checking selinux state: %s" %(e,)) + +def setSteps(anaconda): + dispatch = anaconda.dispatch + dispatch.setStepList( + "language", + "keyboard", + "welcome", + "filtertype", + "filter", + "cleardiskssel", + "installtype", + "storageinit", + "findrootparts", + "findinstall", + "upgrademount", + "restoretime", + "upgrademigfind", + "upgrademigratefs", + "enablefilesystems", + "upgradecontinue", + "reposetup", + "upgbootloader", + "checkdeps", + "dependencies", + "confirmupgrade", + "postselection", + "reipl", + "install", + "preinstallconfig", + "installpackages", + "postinstallconfig", + "writeconfig", + "instbootloader", + "dopostaction", + "methodcomplete", + "postscripts", + "copylogs", + "complete" + ) + + dispatch.skipStep("bootloader", permanent=1) + + if not iutil.isX86(): + dispatch.skipStep("upgbootloader") |