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 /image.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 'image.py')
-rw-r--r--image.py326
1 files changed, 326 insertions, 0 deletions
diff --git a/image.py b/image.py
new file mode 100644
index 0000000..60f03aa
--- /dev/null
+++ b/image.py
@@ -0,0 +1,326 @@
+#
+# image.py: Support methods for CD/DVD and ISO image installations.
+#
+# Copyright (C) 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/>.
+#
+
+import isys, iutil
+import os, os.path, stat, string, sys
+from constants import *
+
+import gettext
+_ = lambda x: gettext.ldgettext("anaconda", x)
+
+import logging
+log = logging.getLogger("anaconda")
+
+_arch = iutil.getArch()
+
+def findIsoImages(path, messageWindow):
+ flush = os.stat(path)
+ files = os.listdir(path)
+ arch = _arch
+ discImages = {}
+
+ for file in files:
+ what = path + '/' + file
+ if not isys.isIsoImage(what):
+ continue
+
+ try:
+ isys.losetup("/dev/loop2", what, readOnly = 1)
+ except SystemError:
+ continue
+
+ try:
+ isys.mount("/dev/loop2", "/mnt/cdimage", fstype = "iso9660",
+ readOnly = True)
+ for num in range(1, 10):
+ if os.access("/mnt/cdimage/.discinfo", os.R_OK):
+ f = open("/mnt/cdimage/.discinfo")
+ try:
+ f.readline() # skip timestamp
+ f.readline() # skip release description
+ discArch = string.strip(f.readline()) # read architecture
+ discNum = getDiscNums(f.readline().strip())
+ except:
+ discArch = None
+ discNum = [ 0 ]
+
+ f.close()
+
+ if num not in discNum or discArch != arch:
+ continue
+
+ # if it's disc1, it needs to have images/install.img
+ if (num == 1 and not
+ os.access("/mnt/cdimage/images/install.img", os.R_OK)):
+ log.warning("%s doesn't have a install.img, skipping" %(what,))
+ continue
+ # we only install binary packages, so let's look for a
+ # product/ dir and hope that this avoids getting
+ # discs from the src.rpm set
+ if not os.path.isdir("/mnt/cdimage/%s" %(productPath,)):
+ log.warning("%s doesn't have binary RPMS, skipping" %(what,))
+ continue
+
+ # warn user if images appears to be wrong size
+ if os.stat(what)[stat.ST_SIZE] % 2048:
+ rc = messageWindow(_("Warning"),
+ _("The ISO image %s has a size which is not "
+ "a multiple of 2048 bytes. This may mean "
+ "it was corrupted on transfer to this computer."
+ "\n\n"
+ "It is recommended that you exit and abort your "
+ "installation, but you can choose to continue if "
+ "you think this is in error.") % (file,),
+ type="custom", custom_icon="warning",
+ custom_buttons= [_("_Exit installer"),
+ _("_Continue")])
+ if rc == 0:
+ sys.exit(0)
+
+ discImages[num] = file
+
+ isys.umount("/mnt/cdimage", removeDir=False)
+ except SystemError:
+ pass
+
+ isys.unlosetup("/dev/loop2")
+
+ return discImages
+
+def getDiscNums(line):
+ # get the disc numbers for this disc
+ nums = line.split(",")
+ if nums == ['ALL']: # Treat "ALL" DVD as disc 1
+ return [1]
+ discNums = []
+ for num in nums:
+ discNums.append(int(num))
+ return discNums
+
+def getMediaId(path):
+ if os.access("%s/.discinfo" % path, os.R_OK):
+ f = open("%s/.discinfo" % path)
+ newStamp = f.readline().strip()
+ f.close()
+
+ return newStamp
+ else:
+ return None
+
+# This mounts the directory containing the iso images, and places the
+# mount point in /mnt/isodir.
+def mountDirectory(methodstr, messageWindow):
+ if methodstr.startswith("hd:"):
+ method = methodstr[3:]
+ if method.count(":") == 1:
+ (device, path) = method.split(":")
+ fstype = "auto"
+ else:
+ (device, fstype, path) = method.split(":")
+
+ if not device.startswith("/dev/") and not device.startswith("UUID=") \
+ and not device.startswith("LABEL="):
+ device = "/dev/%s" % device
+ elif methodstr.startswith("nfsiso:"):
+ device = methodstr[7:]
+ fstype = "nfs"
+ else:
+ return
+
+ # No need to mount it again.
+ if os.path.ismount("/mnt/isodir"):
+ return
+
+ while True:
+ try:
+ isys.mount(device, "/mnt/isodir", fstype = fstype)
+ break
+ except SystemError, msg:
+ log.error("couldn't mount ISO source directory: %s" % msg)
+ ans = messageWindow(_("Couldn't Mount ISO Source"),
+ _("An error occurred mounting the source "
+ "device %s. This may happen if your ISO "
+ "images are located on an advanced storage "
+ "device like LVM or RAID, or if there was a "
+ "problem mounting a partition. Click exit "
+ "to abort the installation.")
+ % (device,), type="custom", custom_icon="error",
+ custom_buttons=[_("_Exit"), _("_Retry")])
+
+ if ans == 0:
+ sys.exit(0)
+ else:
+ continue
+
+def mountImage(isodir, tree, discnum, messageWindow, discImages={}):
+ if os.path.ismount(tree):
+ raise SystemError, "trying to mount already-mounted iso image!"
+
+ if discImages == {}:
+ discImages = findIsoImages(isodir, messageWindow)
+
+ while True:
+ try:
+ isoImage = "%s/%s" % (isodir, discImages[discnum])
+ isys.losetup("/dev/loop1", isoImage, readOnly = 1)
+ isys.mount("/dev/loop1", tree, fstype = 'iso9660', readOnly = True)
+ break
+ except:
+ ans = messageWindow(_("Missing ISO 9660 Image"),
+ _("The installer has tried to mount "
+ "image #%s, but cannot find it on "
+ "the hard drive.\n\n"
+ "Please copy this image to the "
+ "drive and click Retry. Click Exit "
+ "to abort the installation.")
+ % (discnum,), type="custom",
+ custom_icon="warning",
+ custom_buttons=[_("_Exit"), _("_Retry")])
+ if ans == 0:
+ sys.exit(0)
+ elif ans == 1:
+ discImages = findIsoImages(isodir, messageWindow)
+
+ return discImages
+
+# given groupset containing information about selected packages, use
+# the disc number info in the headers to come up with message describing
+# the required CDs
+#
+# dialog returns a value of 0 if user selected to abort install
+def presentRequiredMediaMessage(anaconda):
+ reqcds = anaconda.backend.getRequiredMedia()
+
+ # if only one CD required no need to pop up a message
+ if len(reqcds) < 2:
+ return
+
+ # check what discs our currently mounted one provides
+ if os.access("%s/.discinfo" % anaconda.backend.ayum.tree, os.R_OK):
+ discNums = []
+ try:
+ f = open("%s/.discinfo" % anaconda.backend.ayum.tree)
+ stamp = f.readline().strip()
+ descr = f.readline().strip()
+ arch = f.readline().strip()
+ discNums = getDiscNums(f.readline().strip())
+ f.close()
+ except Exception, e:
+ log.critical("Exception reading discinfo: %s" %(e,))
+
+ log.info("discNums is %s" %(discNums,))
+ haveall = 0
+ s = set(reqcds)
+ t = set(discNums)
+ if s.issubset(t):
+ haveall = 1
+
+ if haveall == 1:
+ return
+
+ reqcds.sort()
+ reqcds = map(lambda disc: "#%s" % disc, filter(lambda disc: disc != -99, reqcds))
+ reqcdstr = ", ".join(reqcds)
+
+ return anaconda.intf.messageWindow(_("Required Install Media"),
+ _("The software you have selected to install will require the "
+ "following %(productName)s %(productVersion)s "
+ "discs:\n\n%(reqcdstr)s\nPlease have these ready "
+ "before proceeding with the installation. If you need to "
+ "abort the installation and exit please select "
+ "\"Reboot\".") % {'productName': product.productName,
+ 'productVersion': product.productVersion,
+ 'reqcdstr': reqcdstr},
+ type="custom", custom_icon="warning",
+ custom_buttons=[_("_Reboot"), _("_Back"), _("_Continue")])
+
+# Find an attached CD/DVD drive with media in it that contains packages,
+# and return that device name.
+def scanForMedia(tree, storage):
+ for dev in storage.devicetree.devices:
+ if dev.type != "cdrom":
+ continue
+
+ storage.devicetree.updateDeviceFormat(dev)
+ try:
+ dev.format.mount(mountpoint=tree)
+ except:
+ continue
+
+ if not verifyMedia(tree, 1):
+ dev.format.unmount()
+ continue
+
+ return dev.name
+
+ return None
+
+def umountImage(tree, currentMedia):
+ if currentMedia is not None:
+ isys.umount(tree, removeDir=False)
+ isys.unlosetup("/dev/loop1")
+
+def unmountCD(dev, messageWindow):
+ if not dev:
+ return
+
+ while True:
+ try:
+ dev.format.unmount()
+ break
+ except Exception, e:
+ log.error("exception in _unmountCD: %s" %(e,))
+ messageWindow(_("Error"),
+ _("An error occurred unmounting the disc. "
+ "Please make sure you're not accessing "
+ "%s from the shell on tty2 "
+ "and then click OK to retry.")
+ % (dev.path,))
+
+def verifyMedia(tree, discnum, timestamp=None):
+ if os.access("%s/.discinfo" % tree, os.R_OK):
+ f = open("%s/.discinfo" % tree)
+
+ newStamp = f.readline().strip()
+
+ try:
+ descr = f.readline().strip()
+ except:
+ descr = None
+
+ try:
+ arch = f.readline().strip()
+ except:
+ arch = None
+
+ try:
+ discs = getDiscNums(f.readline().strip())
+ except:
+ discs = [ 0 ]
+
+ f.close()
+
+ if timestamp is not None:
+ if newStamp == timestamp and arch == _arch and discnum in discs:
+ return True
+ else:
+ if arch == _arch and discnum in discs:
+ return True
+
+ return False