[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]

[PATCH 4/6] Make split media image installs work.



Rework image.py into a support file with no InstallMethod subclasses in it.
Move the media switching code into a yum callback and make sure our base
repos have the correct attribute set to trigger using this callback.  Be more
careful to only attempt ejecting a CD when we're using a method that has a
CD device.
---
 image.py         |  625 ++++++++++++++++++------------------------------------
 installmethod.py |    4 +-
 yuminstall.py    |  179 ++++++++++++++--
 3 files changed, 371 insertions(+), 437 deletions(-)

diff --git a/image.py b/image.py
index 5cfaa54..ebdbd53 100644
--- a/image.py
+++ b/image.py
@@ -1,7 +1,7 @@
 #
-# image.py - Install method for disk image installs (CD & NFS)
+# Support methods for CD/DVD and ISO image installations.
 #
-# Copyright 1999-2007 Red Hat, Inc.
+# Copyright 2007 Red Hat, Inc.
 #
 # This software may be freely redistributed under the terms of the GNU
 # library public license.
@@ -10,23 +10,11 @@
 # along with this program; if not, write to the Free Software
 # Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 #
-
-from installmethod import InstallMethod
-import shutil
-import os
-import sys
 import isys
-import time
-import stat
-import kudzu
-import string
-import shutil
-import product
-import rhpl
-import sets
-
+import os, stat, string, sys
 from constants import *
 
+import rhpl
 from rhpl.translate import _
 
 import logging
@@ -39,6 +27,163 @@ if os.uname()[4] == "s390x":
 else:
     _arch = rhpl.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 = 1)
+            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/stage2.img
+                    if (num == 1 and not
+                        os.access("/mnt/cdimage/images/stage2.img", os.R_OK)):
+                        log.warning("%s doesn't have a stage2.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=0)
+        except SystemError:
+            pass
+
+        isys.unlosetup("/dev/loop2")
+
+    return discImages
+
+def getDiscNums(line):
+    # get the disc numbers for this disc
+    nums = line.split(",")
+    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 /tmp/isodir.
+def mountDirectory(methodstr, messageWindow):
+    if methodstr.startswith("hd://"):
+        method = methodstr[5:]
+        (device, fstype, path) = method.split(":", 3)
+        device = method[0:method.index(":")]
+    else:
+        return
+
+    # First check to see if /tmp/isodir is mounted.
+    f = open("/proc/mounts", "r")
+    lines = f.readlines()
+    f.close()
+
+    for l in lines:
+        s = string.split(l)
+        if s[0] == "/dev/" + device:
+            # It is, so there's no need to try again.
+            return
+
+    try:
+        isys.mount(device, "/tmp/isodir", fstype = fstype)
+    except SystemError, msg:
+        log.error("couldn't mount ISO source directory: %s" % msg)
+        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.")
+                      % (self.device,), type="custom", custom_icon="error",
+                      custom_buttons=[_("_Exit")])
+        sys.exit(0)
+
+def mountImage(tree, discnum, currentMedia, messageWindow, discImages={}):
+    if currentMedia:
+        raise SystemError, "trying to mount already-mounted iso image!"
+
+    if discImages == {}:
+        discImages = findIsoImages("/mnt/source", messageWindow)
+
+    while True:
+        try:
+            isoImage = "/mnt/source/%s" % (discImages[discnum])
+            isys.losetup("/dev/loop1", isoImage, readOnly = 1)
+            isys.mount("/dev/loop1", tree, fstype = 'iso9660', readOnly = 1);
+            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("/mnt/source", messageWindow)
+
 # given groupset containing information about selected packages, use
 # the disc number info in the headers to come up with message describing
 # the required CDs
@@ -49,13 +194,13 @@ def presentRequiredMediaMessage(anaconda):
 
     # if only one CD required no need to pop up a message
     if len(reqcds) < 2:
-	return
+        return
 
     # check what discs our currently mounted one provides
-    if os.access("/mnt/source/.discinfo", os.R_OK):
+    if os.access("/.discinfo" % anaconda.backend.ayum.tree, os.R_OK):
         discNums = []
         try:
-            f = open("/mnt/source/.discinfo")
+            f = open("%s/.discinfo", anaconda.backend.ayum.tree)
             stamp = f.readline().strip()
             descr = f.readline().strip()
             arch = f.readline().strip()
@@ -79,10 +224,10 @@ def presentRequiredMediaMessage(anaconda):
     for cdnum in reqcds:
         if cdnum == -99: # non-CD bits
             continue
-	reqcdstr += "\t\t%s %s disc #%d\n" % (product.productName, product.productVersion, cdnum,)
-		
+        reqcdstr += "\t\t%s %s disc #%d\n" % (product.productName, product.productVersion, cdnum,)
+
     return anaconda.intf.messageWindow( _("Required Install Media"),
-				        _("The software you have selected to "
+                                        _("The software you have selected to "
                                           "install will require the following discs:\n\n"
                                           "%s\nPlease "
                                           "have these ready before proceeding with "
@@ -92,413 +237,57 @@ def presentRequiredMediaMessage(anaconda):
                                           type="custom", custom_icon="warning",
                                           custom_buttons=[_("_Reboot"), _("_Back"), _("_Continue")])
 
-
-
-class ImageInstallMethod(InstallMethod):
-
-    def switchMedia(self, mediano, filename=""):
+def umountDirectory(self):
+    try:
+        isys.umount("/tmp/isodir", removeDir=0)
+    except:
         pass
 
-    def getMethodUri(self):
-        return "file://%s" % (self.tree,)
-
-    def __init__(self, tree, rootPath, intf):
-	InstallMethod.__init__(self, tree, rootPath, intf)
-	self.tree = tree
-	self.isoPath = tree
-
-class CdromInstallMethod(ImageInstallMethod):
-
-    def unmountCD(self):
-        done = 0
-        while done == 0:
-            try:
-                isys.umount("/mnt/source")
-                self.currentMedia = []
-                break
-            except Exception, e:
-                log.error("exception in unmountCD: %s" %(e,))
-                self.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.")
-                                   % ("/mnt/source",))
-
-    def systemMounted(self, fsset, chroot):
-        if not os.path.exists("%s/images/stage2.img" %(self.tree,)):
-            log.debug("Not copying non-existent stage2.img")
-            return
-
-	self.loopbackFile = "%s%s%s" % (chroot,
-                                        fsset.filesystemSpace(chroot)[0][0],
-                                        "/rhinstall-stage2.img")
-
-	try:
-            win = self.waitWindow (_("Copying File"),
-                                   _("Transferring install image to hard drive..."))
-	    shutil.copyfile("%s/images/stage2.img" % (self.tree,), 
-			    self.loopbackFile)
-            win.pop()
-        except Exception, e:
-            if win:
-                win.pop()
-
-            log.critical("error transferring stage2.img: %s" %(e,))
+def umountImage(tree, currentMedia):
+    if currentMedia is not None:
+        isys.umount(tree, removeDir=0)
+        isys.unlosetup("/dev/loop1")
 
-            if isinstance(e, IOError) and e.errno == 5:
-                msg = _("An error occurred transferring the install image "
-                        "to your hard drive.  This is probably due to "
-                        "bad media.")
-            else:
-                msg = _("An error occurred transferring the install image "
-                        "to your hard drive. You are probably out of disk "
-                        "space.")
+def unmountCD(tree, messageWindow):
+    if not tree:
+        return
 
-            self.messageWindow(_("Error"), msg)
-	    os.unlink(self.loopbackFile)
-	    return 1
-
-	isys.lochangefd("/dev/loop0", self.loopbackFile)
-
-    def switchMedia(self, mediano, filename=""):
-        log.info("switching from CD %s to %s for %s" %(self.currentMedia, mediano, filename))
-        if mediano in self.currentMedia:
-            return
-        if os.access("/mnt/source/.discinfo", os.R_OK):
-            f = open("/mnt/source/.discinfo")
-            timestamp = f.readline().strip()
-            f.close()
-        else:
-            timestamp = self.timestamp
-
-        if self.timestamp is None:
-            self.timestamp = timestamp
-
-        needed = mediano
-
-        # if self.currentMedia is empty, then we shouldn't have anything
-        # mounted.  double-check by trying to unmount, but we don't want
-        # to get into a loop of trying to unmount forever.  if
-        # self.currentMedia is set, then it should still be mounted and
-        # we want to loop until it unmounts successfully
-        if not self.currentMedia:
-            try:
-                isys.umount("/mnt/source")
-            except:
-                pass
-        else:
-            self.unmountCD()
-
-        done = 0
-
-        cdlist = []
-        for (dev, something, descript) in \
-                kudzu.probe(kudzu.CLASS_CDROM, kudzu.BUS_UNSPEC, 0):
-            cdlist.append(dev)
-
-        for dev in cdlist:
-            try:
-                if not isys.mount(dev, "/mnt/source", fstype = "iso9660", 
-                           readOnly = 1):
-                    if os.access("/mnt/source/.discinfo", os.R_OK):
-                        f = open("/mnt/source/.discinfo")
-                        newStamp = f.readline().strip()
-                        try:
-                            descr = f.readline().strip()
-                        except:
-                            descr = None
-                        try:
-                            arch = f.readline().strip()
-                        except:
-                            arch = None
-                        try:
-                            discNum = getDiscNums(f.readline().strip())
-                        except:
-                            discNum = [ 0 ]
-                        f.close()
-                        if (newStamp == timestamp and
-                            arch == _arch and
-                            needed in discNum):
-                            done = 1
-                            self.currentMedia = discNum
-
-                    if not done:
-                        isys.umount("/mnt/source")
-            except:
-                pass
-
-            if done:
-                break
-
-        if not done:
-            isys.ejectCdrom(self.device)
-
-        while not done:
-            if self.intf is not None:
-                self.intf.beep()
-
-            self.messageWindow(_("Change Disc"), 
-                _("Please insert %s disc %d to continue.") % (productName,
-                                                              needed))
-            try:
-                if isys.mount(self.device, "/mnt/source", 
-                              fstype = "iso9660", readOnly = 1):
-                    time.sleep(3)
-                    isys.mount(self.device, "/mnt/source", 
-                               fstype = "iso9660", readOnly = 1)
-
-                if os.access("/mnt/source/.discinfo", os.R_OK):
-                    f = open("/mnt/source/.discinfo")
-                    newStamp = f.readline().strip()
-                    try:
-                        descr = f.readline().strip()
-                    except:
-                        descr = None
-                    try:
-                        arch = f.readline().strip()
-                    except:
-                        arch = None
-                    try:
-                        discNum = getDiscNums(f.readline().strip())
-                    except:
-                        discNum = [ 0 ]
-                    f.close()
-                    if (newStamp == timestamp and
-                        arch == _arch and
-                        needed in discNum):
-                        done = 1
-                        self.currentMedia = discNum
-                        # make /tmp/cdrom again so cd gets ejected
-                        isys.makeDevInode(self.device, "/tmp/cdrom")
-
-                if not done:
-                    self.messageWindow(_("Wrong Disc"),
-                            _("That's not the correct %s disc.")
-                                       % (productName,))
-                    isys.umount("/mnt/source")
-                    isys.ejectCdrom(self.device)
-            except:
-                self.messageWindow(_("Error"), 
-                        _("Unable to access the disc."))
-
-    def filesDone(self):
+    while True:
         try:
-            shutil.copyfile("/mnt/source/media.repo", "%s/etc/yum.repos.d/%s-install-media.repo" %(self.rootPath, productName))
+            isys.umount(tree, removeDir=0)
+            break
         except Exception, e:
-            log.debug("Error copying media.repo: %s" %(e,))
-        
-        # we're trying to unmount the CD here.  if it fails, oh well,
-        # they'll reboot soon enough I guess :)
-        try:
-            isys.umount("/mnt/source")
-        except Exception, e:
-            log.error("unable to unmount source in filesDone: %s" %(e,))
-        
-        if not self.loopbackFile: return
-
-	try:
-	    # this isn't the exact right place, but it's close enough
-	    os.unlink(self.loopbackFile)
-	except SystemError:
-	    pass
-
-    def __init__(self, method, rootPath, intf):
-        """@param method cdrom://device:/path"""
-        url = method[8:]
-	(self.device, tree) = string.split(url, ":", 1)
-        if not tree.startswith("/"):
-            tree = "/%s" %(tree,)
-	self.messageWindow = intf.messageWindow
-	self.progressWindow = intf.progressWindow
-	self.waitWindow = intf.waitWindow
-        self.loopbackFile = None
-
-        # figure out which disc is in.  if we fail for any reason,
-        # assume it's just disc1.
-        if os.access("/mnt/source/.discinfo", os.R_OK):
-            f = open("/mnt/source/.discinfo")
-            try:
-                self.timestamp = f.readline().strip()
-                f.readline() # descr
-                f.readline() # arch
-            except:
-                self.timestamp = None
-
-            try:
-                self.currentMedia = getDiscNums(f.readline().strip())
-            except:
-                self.currentMedia = [ 1 ]
-            
-            f.close()
-        else:                
-            self.currentMedia = [ 1 ]
-        
-	ImageInstallMethod.__init__(self, tree, rootPath, intf)
-
-class NfsInstallMethod(ImageInstallMethod):
-
-    def __init__(self, method, rootPath, intf):
-        """@param method: nfs:/mnt/source"""
-        tree = method[5:]
-	ImageInstallMethod.__init__(self, tree, rootPath, intf)
-        self.currentMedia = []
-
-def getDiscNums(line):
-    # get the disc numbers for this disc
-    nums = line.split(",")
-    discNums = []
-    for num in nums:
-        discNums.append(int(num))
-    return discNums
-
-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
+            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.")
+                          % (tree,))
 
-	try:
-	    isys.mount("/dev/loop2", "/mnt/cdimage", fstype = "iso9660",
-		       readOnly = 1)
-	    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/stage2.img
-                    if (num == 1 and not
-                        os.access("/mnt/cdimage/images/stage2.img", os.R_OK)):
-                        log.warning("%s doesn't have a stage2.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)
+def verifyMedia(tree, discnum, timestamp):
+    if os.access("%s/.discinfo" % tree, os.R_OK):
+        f = open("%s/.discinfo" % tree)
 
-		    discImages[num] = file
+        newStamp = f.readline().strip()
 
-	    isys.umount("/mnt/cdimage")
-	except SystemError:
-	    pass
-
-	isys.unlosetup("/dev/loop2")
-
-    return discImages
+        try:
+            descr = f.readline().strip()
+        except:
+            descr = None
 
-class NfsIsoInstallMethod(NfsInstallMethod):
-
-    def getMethodUri(self):
-        return "file:///tmp/isomedia/"
-
-    def switchMedia(self, mediano, filename=""):
-	if mediano not in self.currentMedia:
-            log.info("switching from iso %s to %s for %s" %(self.currentMedia, mediano, filename))
-	    self.umountImage()
-	    self.mountImage(mediano)
-
-    def umountImage(self):
-	if self.currentMedia:
-	    isys.umount(self.mntPoint)
-	    isys.unlosetup("/dev/loop3")
-	    self.mntPoint = None
-	    self.currentMedia = []
-
-    def mountImage(self, cdNum):
-	if (self.currentMedia):
-	    raise SystemError, "trying to mount already-mounted iso image!"
-
-	retrymount = True
-	while retrymount:
-	    try:
-	        isoImage = self.isoPath + '/' + self.discImages[cdNum]
-
-	        isys.losetup("/dev/loop3", isoImage, readOnly = 1)
-	
-	        isys.mount("/dev/loop3", "/tmp/isomedia", fstype = 'iso9660', readOnly = 1);
-	        self.mntPoint = "/tmp/isomedia/"
-	        self.currentMedia = [ cdNum ]
-
-	        retrymount = False
-	    except:
-	        ans = self.messageWindow( _("Missing ISO 9660 Image"),
-	                                  _("The installer has tried to mount "
-	                                    "image #%s, but cannot find it on "
-	                                    "the server.\n\n"
-	                                    "Please copy this image to the "
-	                                    "remote server's share path and "
-	                                    "click Retry. Click Exit to "
-	                                    "abort the installation.")
-	                                    % (cdNum,), type="custom",
-	                                    custom_icon="warning",
-	                                    custom_buttons=[_("_Exit"),
-	                                                    _("_Retry")])
-	        if ans == 0:
-	            sys.exit(0)
-	        elif ans == 1:
-	            self.discImages = findIsoImages(self.isoPath, self.messageWindow)
-
-    def filesDone(self):
-        # if we can't unmount the cd image, we really don't care much
-        # let them go along and don't complain
         try:
-            self.umountImage()
-        except Exception, e:
-            log.error("unable to unmount image in filesDone: %s" %(e,))
-            pass
+            arch = f.readline().strip()
+        except:
+            arch = None
 
-    def __init__(self, method, rootPath, intf):
-        """@param method: nfsiso:/mnt/source"""
-        tree = method[8:]
-	ImageInstallMethod.__init__(self, "/%s" % tree, rootPath, intf)
-	self.messageWindow = intf.messageWindow
+        try:
+            discs = getDiscNums(f.readline().strip())
+        except:
+            discs = [ 0 ]
 
-	# the tree points to the directory that holds the iso images
-	# even though we already have the main one mounted once, it's
-	# easiest to just mount it again so that we can treat all of the
-	# images the same way -- we use loop3 for everything
-        self.currentMedia = []
+        f.close()
+        if (newStamp == timestamp and arch == _arch and discnum in discs):
+            return True
 
-	self.discImages = findIsoImages(tree, self.messageWindow)
-	self.mountImage(1)
+    return False
diff --git a/installmethod.py b/installmethod.py
index 9eb7d32..c5ea871 100644
--- a/installmethod.py
+++ b/installmethod.py
@@ -38,8 +38,8 @@ def doMethodComplete(anaconda):
         except SystemError:
             pass
 
-    if not anaconda.isKickstart:
-        isys.ejectCdrom(anaconda.method.device, makeDevice=1)
+    if not anaconda.isKickstart and anaconda.mediaDevice:
+        isys.ejectCdrom(anaconda.mediaDevice, makeDevice=1)
 
     mtab = "/dev/root / ext3 ro 0 0\n"
     for ent in anaconda.id.fsset.entries:
diff --git a/yuminstall.py b/yuminstall.py
index 904b316..5b2375f 100644
--- a/yuminstall.py
+++ b/yuminstall.py
@@ -35,6 +35,7 @@ from backend import AnacondaBackend
 from product import productName, productStamp
 from sortedtransaction import SplitMediaTransactionData
 from constants import *
+from image import *
 from rhpl.translate import _
 
 # specspo stuff
@@ -253,16 +254,31 @@ class AnacondaYumRepo(YumRepository):
 class YumSorter(yum.YumBase):
     def _transactionDataFactory(self):
         return SplitMediaTransactionData()
-  
+
 class AnacondaYum(YumSorter):
     def __init__(self, anaconda):
         YumSorter.__init__(self)
         self.anaconda = anaconda
-        self.method = anaconda.method
-        self.prevmedia = None
+        self.methodstr = anaconda.methodstr
+        self._loopbackFile = None
+
+        # The loader mounts the first disc for us, so don't remount it.
+        self.currentMedia = 1
+        self.mediagrabber = self.mediaHandler
+
+        # Only needed for hard drive and nfsiso installs.
+        self._discImages = {}
+
+        # Where is the source media mounted?
+        if self.methodstr.find("source2") != -1:
+            self.tree = "/mnt/source2"
+        else:
+            self.tree = "/mnt/source"
+
         self.doConfigSetup(root=anaconda.rootPath)
         self.conf.installonlypkgs = []
         self.macros = {}
+
         if flags.selinux:
             for directory in ("/tmp/updates", "/mnt/source/RHupdates",
                         "/etc/selinux/targeted/contexts/files",
@@ -280,6 +296,139 @@ class AnacondaYum(YumSorter):
         self.updates = []
         self.localPackages = []
 
+    def systemMounted(self, fsset, chroot):
+        if not os.path.exists("%s/images/stage2.img" %(self.tree,)):
+            log.debug("Not copying stage2.img as we can't find it")
+            return
+
+        self._loopbackFile = "%s%s/rhinstall-stage2.img" % (chroot,
+                             fsset.filesystemSpace(chroot)[0][0])
+
+        try:
+            win = self.anaconda.intf.waitWindow (_("Copying File"),
+                    _("Transferring install image to hard drive..."))
+            shutil.copyfile("%s/images/stage2.img" % (self.tree,),
+                            self._loopbackFile)
+            win.pop()
+        except Exception, e:
+            if win:
+                win.pop()
+
+            log.critical("error transferring stage2.img: %s" %(e,))
+
+            if isinstance(e, IOError) and e.errno == 5:
+                msg = _("An error occurred transferring the install image "
+                        "to your hard drive.  This is probably due to "
+                        "bad media.")
+            else:
+                msg = _("An error occurred transferring the install image "
+                        "to your hard drive. You are probably out of disk "
+                        "space.")
+
+        while True:
+            try:
+                isys.umount(self.tree)
+                self.currentMedia = None
+                break
+            except Exception, e:
+                log.error("exception in _unmountCD: %s" %(e,))
+                self.anaconda.intf.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.")
+                                   % (self.tree,))
+
+
+    def mediaHandler(self, *args, **kwargs):
+        mediaid = kwargs["mediaid"]
+        discnum = kwargs["discnum"]
+        relative = kwargs["relative"]
+
+        # The package exists on media other than what's mounted right now.
+        if discnum != self.currentMedia:
+            log.info("switching from media #%s to #%s for %s" %
+                     (self.currentMedia, discnum, relative))
+
+            # Unmount any currently mounted ISO images and mount the one
+            # containing the requested packages.  If this is the first time
+            # through, /mnt/source is not going to be mounted yet so we first
+            # need to do that.
+            if self.tree.find("source2") != -1:
+                umountImage(self.tree, self.currentMedia)
+                self.currentMedia = None
+
+                # mountDirectory checks before doing anything, so it's safe to
+                # call this repeatedly.
+                mountDirectory(self.methodstr, self.anaconda.intf.messageWindow)
+
+                mountImage(self.tree, discnum, self.currentMedia,
+                           self.anaconda.intf.messageWindow,
+                           discImages=self._discImages)
+                self.currentMedia = discnum
+            else:
+                if os.access("%s/.discinfo" % self.tree, os.R_OK):
+                    f = open("%s/.discinfo" % self.tree)
+                    timestamp = f.readline().strip()
+                    f.close()
+                else:
+                    timestamp = self.timestamp
+
+                if self.timestamp is None:
+                    self.timestamp = timestamp
+
+                # if self.currentMedia is None, then we shouldn't have anything
+                # mounted.  double-check by trying to unmount, but we don't want
+                # to get into a loop of trying to unmount forever.  if
+                # self.currentMedia is set, then it should still be mounted and
+                # we want to loop until it unmounts successfully
+                if self.currentMedia is None:
+                    try:
+                        isys.umount(self.tree)
+                    except:
+                        pass
+                else:
+                    unmountCD(self.tree, self.anaconda.intf.messageWindow)
+                    self.currentMedia = None
+
+                isys.ejectCdrom(self.anaconda.mediaDevice)
+
+                while True:
+                    if self.anaconda.intf:
+                        self.anaconda.intf.beep()
+
+                    self.anaconda.intf.messageWindow(_("Change Disc"),
+                        _("Please insert %s disc %d to continue.") % (productName,
+                                                                      discnum))
+
+                    try:
+                        if isys.mount(self.anaconda.mediaDevice, self.tree,
+                                      fstype = "iso9660", readOnly = 1):
+                            time.sleep(3)
+                            isys.mount(self.anaconda.mediaDevice, self.tree,
+                                       fstype = "iso9660", readOnly = 1)
+
+                        if verifyMedia(self.tree, discnum, self.timestamp):
+                            self.currentMedia = discnum
+                            # make /tmp/cdrom again so cd gets ejected
+                            isys.makeDevInode(self.anaconda.mediaDevice, "/tmp/cdrom")
+                            break
+
+                        if not done:
+                            self.anaconda.intf.messageWindow(_("Wrong Disc"),
+                                    _("That's not the correct %s disc.")
+                                      % (productName,))
+                            isys.umount(self.tree)
+                            isys.ejectCdrom(self.anaconda.mediaDevice)
+                    except:
+                        self.anaconda.intf.messageWindow(_("Error"),
+                                _("Unable to access the disc."))
+
+        ug = URLGrabber(checkfunc=kwargs["checkfunc"])
+        ug.urlgrab("%s/%s" % (self.tree, kwargs["relative"]), kwargs["local"],
+                   text=kwargs["text"], range=kwargs["range"], copy_local=1)
+        return kwargs["local"]
+
     def doConfigSetup(self, fn='/etc/yum.conf', root='/'):
         self.conf = yum.config.YumConf()
         self.conf.installroot = root
@@ -295,12 +444,17 @@ class AnacondaYum(YumSorter):
         map(lambda x: ylog.addHandler(x), log.handlers)
 
         # add default repos
-        for (name, uri) in self.anaconda.id.instClass.getPackagePaths(self.method.getMethodUri()).items():
+        for (name, uri) in self.anaconda.id.instClass.getPackagePaths(self.anaconda.methodstr).items():
             repo = AnacondaYumRepo(uri, addon=False,
                                    repoid="anaconda-%s-%s" %(name,
                                                              productStamp),
                                    root = root)
             repo.cost = 100
+
+            if self.anaconda.mediaDevice or self.anaconda.methodstr.find("source2") != -1:
+                repo.mediaid = getMediaId(self.tree)
+                log.info("set mediaid of repo to: %s" % repo.mediaid)
+
             repo.enable()
             self.repos.add(repo)
 
@@ -380,9 +534,6 @@ class AnacondaYum(YumSorter):
 
         if rc == 0:
             sys.exit(0)
-        else:
-            if self.prevmedia:
-                self.method.switchMedia(self.prevmedia)
 
     def mirrorFailureCB (self, obj, *args, **kwargs):
         # This gets called when a mirror fails, but it cannot know whether
@@ -395,11 +546,9 @@ class AnacondaYum(YumSorter):
                     "or downloaded file is corrupt" % (obj.url, grab._next + 1,
                                                        len(grab.mirrors)))
 
-        if self.method.currentMedia:
-            if kwargs.get("tsInfo") and kwargs["tsInfo"].curmedia > 0:
-                self.prevmedia = kwargs["tsInfo"].curmedia
-
-            self.method.unmountCD()
+        if self.currentMedia:
+            unmountCD(self.tree, self.anaconda.intf.messageWindow)
+            self.currentMedia = None
 
     def urlgrabberFailureCB (self, obj, *args, **kwargs):
         log.warning("Try %s/%s for %s failed" % (obj.tries, obj.retry, obj.url))
@@ -455,7 +604,6 @@ class AnacondaYum(YumSorter):
             self.tsInfo.curmedia = i
             if i > 0:
                 pkgtup = self.tsInfo.reqmedia[i][0]
-                self.method.switchMedia(i, filename=pkgtup)
             self.populateTs(keepold=0)
             self.ts.check()
             self.ts.order()
@@ -616,8 +764,6 @@ class YumBackend(AnacondaBackend):
         else:
             repos.extend(self.ayum.repos.listEnabled())
 
-        anaconda.method.switchMedia(1)
-
         if not os.path.exists("/tmp/cache"):
             iutil.mkdirChain("/tmp/cache/headers")
 
@@ -1009,9 +1155,8 @@ class YumBackend(AnacondaBackend):
                 log.info("renaming old modprobe.conf -> modprobe.conf.anacbak")
                 os.rename(anaconda.rootPath + "/etc/modprobe.conf",
                           anaconda.rootPath + "/etc/modprobe.conf.anacbak")
-                
 
-        if self.method.systemMounted (anaconda.id.fsset, anaconda.rootPath):
+        if self.ayum.systemMounted (anaconda.id.fsset, anaconda.rootPath):
             anaconda.id.fsset.umountFilesystems(anaconda.rootPath)
             return DISPATCH_BACK
 
-- 
1.5.3.4


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]