diff options
Diffstat (limited to 'yum-presto-legacy/shared/prestoDownload.py')
-rw-r--r-- | yum-presto-legacy/shared/prestoDownload.py | 188 |
1 files changed, 188 insertions, 0 deletions
diff --git a/yum-presto-legacy/shared/prestoDownload.py b/yum-presto-legacy/shared/prestoDownload.py new file mode 100644 index 0000000..1c29608 --- /dev/null +++ b/yum-presto-legacy/shared/prestoDownload.py @@ -0,0 +1,188 @@ +# 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 Library General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +# +# Copyright 2005 Duke University +# Copyright 2007 Jonathan Dieter + +import os +from yum import misc +from yum import Errors +from yum import types +from urlgrabber.grabber import URLGrabError +import deltarpm +import prestoThread +import Queue +import thread + +def verifyDelta(fo, po, conduit, raiseError): + """verifies the deltarpm is what we expect it to be + raiseError = defaults to 0 - if 1 then will raise + a URLGrabError if the file does not check out. + otherwise it returns false for a failure, true for success""" + + if type(fo) is types.InstanceType: + fo = fo.filename + + try: + verifyChecksum(fo, po.deltachecksumtype, po.deltachecksum) + except: + if raiseError: + raise URLGrabError(-1, 'Package does not match intended download') + else: + return False + + return True + + +def verifyChecksum(filename, checksumType, csum): + """Verify the checksum of the file versus the + provided checksum""" + + try: + + filesum = misc.checksum(checksumType, filename) + except Errors.MiscError, e: + raise URLGrabError(-3, 'Could not perform checksum') + + if filesum != csum: + raise URLGrabError(-1, 'Package does not match checksum') + + return 0 + +def reconstruct(conduit, po, log): + deltalocal = po.deltalocalpath + retlist = "" + + drpm = deltarpm.DeltaRpmWrapper(conduit) + + try: + drpm.apply(po.arch, po.localpath, deltalocal) + except: + retlist += "Error rebuilding rpm from %s! Will download full package.\n" % os.path.basename(deltalocal) + try: + os.unlink(po.localpath) + except: + pass + else: + # log success + log.log(po.oldpkg_string, po.newpkg_string, os.stat(po.localpath)[6], os.stat(deltalocal)[6]) + + #retlist += "Built %s from deltarpm\n" % os.path.basename(po.localpath) + # Check to see whether or not we should keep the drpms + # FIXME: Is there any way to see whether or not a Boolean option was not set? + if conduit.confBool('main', 'neverkeepdeltas'): + delete = True + elif conduit.confBool('main', 'keepdeltas'): + delete = False + elif conduit.getConf().keepcache != 0: + delete = False + else: + delete = True + + if delete: + try: + os.unlink(deltalocal) + except: + pass + return retlist + + + +def downloadPkgs(conduit, pkglist, log): + """download list of package objects handed to you, return errors""" + + opts, commands = conduit.getCmdLine() + + errors = {} + def adderror(po, msg): + errors.setdefault(po, []).append(msg) + + # Set up thread for applying drpms + queue = Queue.Queue(0) + lock = thread.allocate_lock() + curthread = prestoThread.ReconstructionThread(queue, lock, reconstruct) + curthread.start() + + # Check whether drpm is already downloaded + repo_cached = False + remote_pkgs = [] + for po in conduit.getDownloadPackages(): + if hasattr(po, 'has_drpm') and po.has_drpm: + local = po.deltalocalpath + if os.path.exists(local): + cursize = os.stat(local)[6] + totsize = long(po.deltasize) + try: + verifyChecksum(local, po.deltachecksumtype, po.deltachecksum) + except: + if po.repo.p_repo.cache: + repo_cached = True + adderror(po, 'package fails checksum but caching is ' + 'enabled for %s' % po.repo.p_repo.id) + + if cursize >= totsize: # otherwise keep it around for regetting + os.unlink(local) + else: + # Deltarpm is local and good, let's put it in the rebuild thread. + conduit.info(5, "using local copy of deltarpm for %s" % po) + queue.put((conduit, po, log)) + continue + remote_pkgs.append(po) + + # Download deltarpms and send them to another thread to be rebuilt + i = 0 + for po in remote_pkgs: + i += 1 + checkfunc = (verifyDelta, (po, conduit, 1), {}) + cache = po.repo.p_repo.http_caching != 'none' + dirstat = os.statvfs(po.repo.deltasdir) + if (dirstat.f_bavail * dirstat.f_bsize) <= long(po.size): + adderror(po, 'Insufficient space in download directory %s ' + 'to download' % po.repo.deltasdir) + continue + try: + text = '(%s/%s): %s' % (i, len(remote_pkgs), os.path.basename(po.deltarelativepath)) + deltalocal = po.repo.p_repo.getPackage(po, checkfunc=checkfunc, text=text, cache=cache) + except Errors.RepoError, e: + adderror(po, str(e)) + else: + queue.put((conduit, po, log)) + + if errors.has_key(po): + del errors[po] + + if hasattr(po, 'realpackagesize'): + po.packagesize = po.realpackagesize + del po.realpackagesize + + # Check for waiting messages from building thread + lock.acquire() + if curthread.messages != "": + conduit.info(2, curthread.messages[:-1]) + curthread.messages = "" + lock.release() + + conduit.info(2, "Rebuilding rpms from deltarpms") + + # Tell build thread that there are no more drpms and wait for it to exit + curthread.can_exit = True + queue.put(None) + curthread.join() + + if curthread.messages != "": + conduit.info(2, curthread.messages[:-1]) + curthread.messages = "" + + return errors + |