aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'packages.py')
-rw-r--r--packages.py359
1 files changed, 359 insertions, 0 deletions
diff --git a/packages.py b/packages.py
new file mode 100644
index 0000000..aa0ea81
--- /dev/null
+++ b/packages.py
@@ -0,0 +1,359 @@
+#
+# packages.py: package management - mainly package installation
+#
+# Copyright (C) 2001, 2002, 2003, 2004, 2005, 2006 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): Erik Troan <ewt@redhat.com>
+# Matt Wilson <msw@redhat.com>
+# Michael Fulbright <msf@redhat.com>
+# Jeremy Katz <katzj@redhat.com>
+#
+
+import glob
+import iutil
+import isys
+import os
+import time
+import sys
+import string
+import language
+import shutil
+import traceback
+from flags import flags
+from product import *
+from constants import *
+from upgrade import bindMountDevDirectory
+from storage.errors import *
+
+import logging
+log = logging.getLogger("anaconda")
+
+import gettext
+_ = lambda x: gettext.ldgettext("anaconda", x)
+
+def doPostAction(anaconda):
+ anaconda.instClass.postAction(anaconda)
+
+def firstbootConfiguration(anaconda):
+ if anaconda.firstboot == FIRSTBOOT_RECONFIG:
+ f = open(anaconda.rootPath + '/etc/reconfigSys', 'w+')
+ f.close()
+ elif anaconda.firstboot == FIRSTBOOT_SKIP:
+ f = open(anaconda.rootPath + '/etc/sysconfig/firstboot', 'w+')
+ f.write('RUN_FIRSTBOOT=NO')
+ f.close()
+
+ return
+
+def writeKSConfiguration(anaconda):
+ log.info("Writing autokickstart file")
+ fn = anaconda.rootPath + "/root/anaconda-ks.cfg"
+
+ anaconda.writeKS(fn)
+
+def copyAnacondaLogs(anaconda):
+ log.info("Copying anaconda logs")
+ for (fn, dest) in (("/tmp/anaconda.log", "anaconda.log"),
+ ("/tmp/syslog", "anaconda.syslog"),
+ ("/tmp/X.log", "anaconda.xlog"),
+ ("/tmp/program.log", "anaconda.program.log"),
+ ("/tmp/storage.log", "anaconda.storage.log"),
+ ("/tmp/yum.log", "anaconda.yum.log")):
+ if os.access(fn, os.R_OK):
+ try:
+ shutil.copyfile(fn, "%s/var/log/%s" %(anaconda.rootPath, dest))
+ os.chmod("%s/var/log/%s" %(anaconda.rootPath, dest), 0600)
+ except:
+ pass
+
+def turnOnFilesystems(anaconda):
+ if anaconda.dir == DISPATCH_BACK:
+ if not anaconda.upgrade:
+ log.info("unmounting filesystems")
+ anaconda.storage.umountFilesystems()
+ return DISPATCH_NOOP
+
+ if not anaconda.upgrade:
+ if not anaconda.storage.fsset.active:
+ # turn off any swaps that we didn't turn on
+ # needed for live installs
+ iutil.execWithRedirect("swapoff", ["-a"],
+ stdout = "/dev/tty5", stderr="/dev/tty5")
+ anaconda.storage.devicetree.teardownAll()
+
+ upgrade_migrate = False
+ if anaconda.upgrade:
+ for d in anaconda.storage.migratableDevices:
+ if d.format.migrate:
+ upgrade_migrate = True
+
+ title = None
+ message = None
+ details = None
+
+ try:
+ anaconda.storage.doIt()
+ except FSResizeError as (msg, device):
+ title = _("Resizing Failed")
+ message = _("There was an error encountered while "
+ "resizing the device %s.") % (device,)
+
+ if os.path.exists("/tmp/resize.out"):
+ details = open("/tmp/resize.out", "r").read()
+ else:
+ details = "%s" %(msg,)
+ except FSMigrateError as (msg, device):
+ title = _("Migration Failed")
+ message = _("An error was encountered while "
+ "migrating filesystem on device %s.") % (device,)
+ details = msg
+ except Exception as e:
+ raise
+
+ if title:
+ rc = anaconda.intf.detailedMessageWindow(title, message, details,
+ type = "custom",
+ custom_buttons = [_("_File Bug"), _("_Exit installer")])
+
+ if rc == 0:
+ raise
+ elif rc == 1:
+ sys.exit(1)
+
+ if not anaconda.upgrade:
+ anaconda.storage.turnOnSwap()
+ anaconda.storage.mountFilesystems(raiseErrors=False,
+ readOnly=False,
+ skipRoot=anaconda.backend.skipFormatRoot)
+ else:
+ if upgrade_migrate:
+ # we should write out a new fstab with the migrated fstype
+ shutil.copyfile("%s/etc/fstab" % anaconda.rootPath,
+ "%s/etc/fstab.anaconda" % anaconda.rootPath)
+ anaconda.storage.fsset.write(anaconda.rootPath)
+
+ # and make sure /dev is mounted so we can read the bootloader
+ bindMountDevDirectory(anaconda.rootPath)
+
+
+def setupTimezone(anaconda):
+ # we don't need this on an upgrade or going backwards
+ if anaconda.upgrade or anaconda.dir == DISPATCH_BACK:
+ return
+
+ os.environ["TZ"] = anaconda.timezone.tz
+ tzfile = "/usr/share/zoneinfo/" + anaconda.timezone.tz
+ tzlocalfile = "/etc/localtime"
+ if not os.access(tzfile, os.R_OK):
+ log.error("unable to set timezone")
+ else:
+ try:
+ os.remove(tzlocalfile)
+ except OSError:
+ pass
+ try:
+ shutil.copyfile(tzfile, tzlocalfile)
+ except OSError as e:
+ log.error("Error copying timezone (from %s): %s" %(tzfile, e.strerror))
+
+ if iutil.isS390():
+ return
+ args = [ "--hctosys" ]
+ if anaconda.timezone.utc:
+ args.append("-u")
+
+ try:
+ iutil.execWithRedirect("/sbin/hwclock", args, stdin = None,
+ stdout = "/dev/tty5", stderr = "/dev/tty5")
+ except RuntimeError:
+ log.error("Failed to set clock")
+
+
+# FIXME: this is a huge gross hack. hard coded list of files
+# created by anaconda so that we can not be killed by selinux
+def setFileCons(anaconda):
+ if flags.selinux:
+ log.info("setting SELinux contexts for anaconda created files")
+
+ files = ["/etc/rpm/macros",
+ "/etc/lilo.conf.anaconda", "/lib64", "/usr/lib64",
+ "/etc/blkid.tab", "/etc/blkid.tab.old",
+ "/etc/mtab", "/etc/fstab", "/etc/resolv.conf",
+ "/etc/modprobe.conf", "/etc/modprobe.conf~",
+ "/var/log/wtmp", "/var/run/utmp", "/etc/crypttab",
+ "/dev/log", "/var/lib/rpm", "/", "/etc/raidtab",
+ "/etc/mdadm.conf", "/etc/sysconfig/network",
+ "/etc/udev/rules.d/70-persistent-net.rules",
+ "/root/install.log", "/root/install.log.syslog",
+ "/etc/shadow", "/etc/shadow-", "/etc/gshadow"] + \
+ glob.glob('/etc/dhclient-*.conf')
+
+ vgs = ["/dev/%s" % vg.name for vg in anaconda.storage.vgs]
+
+ # ugh, this is ugly
+ for dir in ["/etc/sysconfig/network-scripts", "/var/lib/rpm", "/etc/lvm", "/dev/mapper", "/etc/iscsi", "/var/lib/iscsi", "/root", "/var/log", "/etc/modprobe.d", "/etc/sysconfig" ] + vgs:
+ def addpath(x): return dir + "/" + x
+
+ if not os.path.isdir(anaconda.rootPath + dir):
+ continue
+ dirfiles = os.listdir(anaconda.rootPath + dir)
+ files.extend(map(addpath, dirfiles))
+ files.append(dir)
+
+ for f in files:
+ if not os.access("%s/%s" %(anaconda.rootPath, f), os.R_OK):
+ log.warning("%s doesn't exist" %(f,))
+ continue
+ ret = isys.resetFileContext(os.path.normpath(f),
+ anaconda.rootPath)
+ log.info("set fc of %s to %s" %(f, ret))
+
+ return
+
+# FIXME: using rpm directly here is kind of lame, but in the yum backend
+# we don't want to use the metadata as the info we need would require
+# the filelists. and since we only ever call this after an install is
+# done, we can be guaranteed this will work. put here because it's also
+# used for livecd installs
+def rpmKernelVersionList(rootPath = "/"):
+ import rpm
+
+ def get_version(header):
+ for f in header['filenames']:
+ if f.startswith('/boot/vmlinuz-'):
+ return f[14:]
+ elif f.startswith('/boot/efi/EFI/redhat/vmlinuz-'):
+ return f[29:]
+ return ""
+
+ def get_tag(header):
+ if header['name'] == "kernel":
+ return "base"
+ elif header['name'].startswith("kernel-"):
+ return header['name'][7:]
+ return ""
+
+ versions = []
+
+ iutil.resetRpmDb(rootPath)
+ ts = rpm.TransactionSet(rootPath)
+
+ mi = ts.dbMatch('provides', 'kernel')
+ for h in mi:
+ v = get_version(h)
+ tag = get_tag(h)
+ if v == "" or tag == "":
+ log.warning("Unable to determine kernel type/version for %s-%s-%s.%s" %(h['name'], h['version'], h['release'], h['arch']))
+ continue
+ # rpm really shouldn't return the same kernel more than once... but
+ # sometimes it does (#467822)
+ if (v, h['arch'], tag) in versions:
+ continue
+ versions.append( (v, h['arch'], tag) )
+
+ return versions
+
+def rpmSetupGraphicalSystem(anaconda):
+ import rpm
+
+ iutil.resetRpmDb(anaconda.rootPath)
+ ts = rpm.TransactionSet(anaconda.rootPath)
+
+ # Only add "rhgb quiet" on non-s390, non-serial installs
+ if iutil.isConsoleOnVirtualTerminal() and \
+ ts.dbMatch('provides', 'rhgb').count() or \
+ ts.dbMatch('provides', 'plymouth').count():
+ anaconda.bootloader.args.append("rhgb quiet")
+
+ if ts.dbMatch('provides', 'service(graphical-login)').count() and \
+ anaconda.displayMode == 'g' and not flags.usevnc:
+ anaconda.desktop.setDefaultRunLevel(5)
+
+#Recreate initrd for use when driver disks add modules
+def recreateInitrd (kernelTag, instRoot):
+ log.info("recreating initrd for %s" % (kernelTag,))
+ iutil.execWithRedirect("/sbin/new-kernel-pkg",
+ [ "--mkinitrd", "--dracut", "--depmod", "--install", kernelTag ],
+ stdout = "/dev/null", stderr = "/dev/null",
+ root = instRoot)
+
+def betaNagScreen(anaconda):
+ publicBetas = { "Red Hat Linux": "Red Hat Linux Public Beta",
+ "Red Hat Enterprise Linux": "Red Hat Enterprise Linux Public Beta",
+ "Fedora Core": "Fedora Core",
+ "Fedora": "Fedora" }
+
+
+ if anaconda.dir == DISPATCH_BACK:
+ return DISPATCH_NOOP
+
+ fileagainst = None
+ for (key, val) in publicBetas.items():
+ if productName.startswith(key):
+ fileagainst = val
+ if fileagainst is None:
+ fileagainst = "%s Beta" %(productName,)
+
+ while 1:
+ rc = anaconda.intf.messageWindow( _("Warning! This is pre-release software!"),
+ _("Thank you for downloading this "
+ "pre-release of %(productName)s.\n\n"
+ "This is not a final "
+ "release and is not intended for use "
+ "on production systems. The purpose of "
+ "this release is to collect feedback "
+ "from testers, and it is not suitable "
+ "for day to day usage.\n\n"
+ "To report feedback, please visit:\n\n"
+ " %(bugzillaUrl)s\n\n"
+ "and file a report against '%(fileagainst)s'.\n")
+ % {'productName': productName,
+ 'bugzillaUrl': bugzillaUrl,
+ 'fileagainst': fileagainst},
+ type="custom", custom_icon="warning",
+ custom_buttons=[_("_Exit"), _("_Install anyway")])
+
+ if not rc:
+ msg = _("Your system will now be rebooted...")
+ buttons = [_("_Back"), _("_Reboot")]
+ rc = anaconda.intf.messageWindow( _("Warning! This is pre-release software!"),
+ msg,
+ type="custom", custom_icon="warning",
+ custom_buttons=buttons)
+ if rc:
+ sys.exit(0)
+ else:
+ break
+
+def doReIPL(anaconda):
+# # This is here as an example to fix the screen during the TUI debugging path
+# anaconda.intf.screen.suspend ()
+# import pdb
+# pdb.set_trace ()
+
+ if not iutil.isS390() or anaconda.dir == DISPATCH_BACK:
+ return DISPATCH_NOOP
+
+ messageInfo = iutil.reIPL(anaconda, os.getppid())
+
+ if messageInfo:
+ (errorMessage, rebootInstr) = messageInfo
+
+ # errorMessage intentionally not shown in UI
+ anaconda.reIPLMessage = rebootInstr
+
+ return DISPATCH_FORWARD