Package pulp :: Package server :: Module upload
[hide private]
[frames] | no frames]

Source Code for Module pulp.server.upload

  1  #!/usr/bin/env python 
  2  # -*- coding: utf-8 -*- 
  3  # 
  4  # Copyright © 2010 Red Hat, Inc. 
  5  # 
  6  # This software is licensed to you under the GNU General Public License, 
  7  # version 2 (GPLv2). There is NO WARRANTY for this software, express or 
  8  # implied, including the implied warranties of MERCHANTABILITY or FITNESS 
  9  # FOR A PARTICULAR PURPOSE. You should have received a copy of GPLv2 
 10  # along with this software; if not, see 
 11  # http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt. 
 12  # 
 13  # Red Hat trademarks are not licensed under GPLv2. No permission is 
 14  # granted to use or replicate Red Hat trademarks that are incorporated 
 15  # in this software or its documentation. 
 16   
 17  import base64 
 18  import commands 
 19  import hashlib 
 20  import logging 
 21  import os 
 22  import tempfile 
 23   
 24  from pulp.server import util 
 25  from pulp.server.api.repo_sync import BaseSynchronizer 
 26  from pulp.server import config 
 27  from pulp.server.pexceptions import PulpException 
 28   
 29  log = logging.getLogger(__name__) 
 30   
 31  REPOS_LOCATION = "%s/%s" % (config.config.get('paths', 'local_storage'), "repos") 
 32  PACKAGE_LOCATION = "%s/%s" % (config.config.get('paths', 'local_storage'), "packages") 
 33   
34 -class PackageUpload:
35 - def __init__(self, repo, pkginfo, payload):
36 self.pkginfo = pkginfo 37 self.stream = payload 38 self.pkgname = pkginfo['pkgname'] 39 self.repo_dir = "%s/%s/" % (REPOS_LOCATION, repo['id']) 40 self.repo = repo
41
42 - def upload(self):
43 (name, version, release, epoch, arch) = self.pkginfo['nvrea'] 44 pkg_path = "%s/%s/%s/%s/%s/%s" % (PACKAGE_LOCATION, name, version, release, arch, self.pkgname) 45 repo_path = "%s/%s" % (self.repo_dir, self.pkgname) 46 47 imp_pkg = None 48 try: 49 if util.check_package_exists(pkg_path, self.pkginfo['checksum'], self.pkginfo['hashtype']): 50 log.error("Package %s Already Exists on the server skipping upload." % self.pkgname) 51 else: 52 store_package(self.stream, pkg_path, repo_path, self.pkginfo['size'], self.pkginfo['checksum'], self.pkginfo['hashtype']) 53 # create symlinks to repo directory 54 55 if not os.path.islink(repo_path): 56 repo_rel_dir = os.path.dirname(repo_path) 57 if not os.path.exists(repo_rel_dir): 58 os.makedirs(repo_rel_dir) 59 log.info("Create a link in repo directory for the package at %s" % repo_path) 60 os.symlink(pkg_path, repo_path) 61 # update/create the repodata for the repo 62 create_repo(self.repo_dir) 63 imp_pkg = self.bindPackageToRepo(self.repo_dir, pkg_path, self.repo) 64 except IOError, e: 65 log.error("Error writing file to filesystem %s " % e) 66 raise 67 except CreateRepoError, e: 68 log.error("Error running createrepo on repo %s. Error: %s" % (self.repo['id'], e)) 69 # XXX do we want to re-raise here? 70 except Exception, e: 71 log.error("Unexpected Error %s " % e) 72 raise 73 return imp_pkg, self.repo
74
75 - def bindPackageToRepo(self, repo_path, pkg_path, repo):
76 log.debug("Binding package [%s] to repo [%s]" % (pkg_path, repo)) 77 bsync = BaseSynchronizer() 78 file_name = os.path.basename(pkg_path) 79 packageInfo = util.get_repo_package(repo_path, file_name) 80 pkg = bsync.import_package(packageInfo, repo) 81 return pkg
82
83 -def create_repo(dir, groups=None):
84 cmd = "createrepo --update %s" % (dir) 85 if groups: 86 cmd = "createrepo -g %s --update %s" % (groups, dir) 87 status, out = commands.getstatusoutput(cmd) 88 89 if status != 0: 90 log.error("createrepo on %s failed" % dir) 91 raise CreateRepoError(out) 92 log.info("createrepo on %s finished" % dir) 93 return status, out
94
95 -def modify_repo(dir, new_file):
96 cmd = "modifyrepo %s %s" % (new_file, dir) 97 status, out = commands.getstatusoutput(cmd) 98 if status != 0: 99 log.error("modifyrepo on %s failed" % dir) 100 raise ModifyRepoError(out) 101 log.info("modifyrepo with %s on %s finished" % (new_file, dir)) 102 return status, out
103 104 105
106 -def store_package(pkgstream, pkg_path, repo_path, size, checksum, hashtype, force=None):
107 """ 108 Write the package stream to a file under repo location 109 """ 110 stream = base64.b64decode(pkgstream) 111 rel_dir = os.path.dirname(pkg_path) 112 113 if not os.path.exists(rel_dir): 114 try: 115 os.makedirs(rel_dir) 116 except IOError, e: 117 log.error("Unable to create repo directory %s" % rel_dir) 118 tmpstream = tempfile.TemporaryFile() 119 tmpstream.write(stream) 120 chunk_size = 65536 121 total_bytes = 0 122 hashsum = hashlib.new(hashtype) 123 file = open(pkg_path, "wb") 124 tmpstream.seek(0, 0) 125 while 1: 126 buffer = tmpstream.read(chunk_size) 127 if not buffer: 128 break 129 file.write(buffer) 130 hashsum.update(buffer) 131 total_bytes += len(buffer) 132 file.close() 133 savedChecksum = hashsum.hexdigest() 134 if total_bytes != int(size): 135 os.remove(pkg_path) 136 raise UploadError(" %s size mismatch, read: %s bytes, was expecting %s bytes" % (os.path.basename(pkg_path), str(total_bytes), str(size))) 137 elif savedChecksum != checksum: 138 os.remove(pkg_path) 139 raise UploadError("%s md5sum mismatch, read md5sum of: %s expected md5sum of %s" % (os.path.basename(pkg_path), savedChecksum, checksum))
140 141 142
143 -class UploadError(PulpException):
144 pass
145
146 -class PackageExistsError(PulpException):
147 pass
148
149 -class CreateRepoError(PulpException):
150 - def __init__(self, output):
151 self.output = output
152
153 - def __str__(self):
154 return self.output
155
156 -class ModifyRepoError(CreateRepoError):
157 pass
158