aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorwiktor w brodlo <wiktor@brodlo.net>2011-06-15 16:59:54 +0000
committerwiktor w brodlo <wiktor@brodlo.net>2011-06-15 16:59:54 +0000
commit2590d96369d0217e31dc2812690dde61dac417b5 (patch)
tree82276f787b08a28548e342c7921486f1acefab9f /upgrade.py
parentfirst commit (diff)
downloadanaconda-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.py342
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")