Package backend :: Package server :: Module rhnPackageUpload
[hide private]
[frames] | no frames]

Source Code for Module backend.server.rhnPackageUpload

  1  # 
  2  # Copyright (c) 2008--2016 Red Hat, Inc. 
  3  # 
  4  # This software is licensed to you under the GNU General Public License, 
  5  # version 2 (GPLv2). There is NO WARRANTY for this software, express or 
  6  # implied, including the implied warranties of MERCHANTABILITY or FITNESS 
  7  # FOR A PARTICULAR PURPOSE. You should have received a copy of GPLv2 
  8  # along with this software; if not, see 
  9  # http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt. 
 10  # 
 11  # Red Hat trademarks are not licensed under GPLv2. No permission is 
 12  # granted to use or replicate Red Hat trademarks that are incorporated 
 13  # in this software or its documentation. 
 14  # 
 15   
 16  import os 
 17  import sys 
 18  import tempfile 
 19   
 20  from spacewalk.common.usix import raise_with_tb 
 21  from spacewalk.common import rhn_mpm, rhn_deb, rhn_pkg 
 22  from spacewalk.common.rhnLog import log_debug 
 23  from spacewalk.common.rhnConfig import CFG 
 24  from spacewalk.common.rhnException import rhnFault 
 25  from spacewalk.common.rhn_rpm import get_header_byte_range 
 26   
 27  from spacewalk.server import rhnSQL 
 28  from spacewalk.server.importlib.backendOracle import SQLBackend 
 29  from spacewalk.server.importlib import importLib, userAuth, mpmSource, \ 
 30      packageImport, errataCache 
 31  from spacewalk.server.rhnLib import get_package_path, \ 
 32      get_package_path_without_package_name 
 33  from spacewalk.server.rhnServer import server_packages 
 34   
 35   
36 -def authenticate(username, password, channels=[], null_org=None, force=None):
37 log_debug(4, username, force) 38 authobj = userAuth.UserAuth() 39 authobj.auth(username, password) 40 return _authenticate(authobj, channels, null_org, force)
41 42
43 -def authenticate_session(session_string, channels=[], null_org=None, force=None):
44 log_debug(4, session_string, force) 45 authobj = userAuth.UserAuth() 46 authobj.auth_session(session_string) 47 return _authenticate(authobj, channels, null_org, force)
48 49
50 -def _authenticate(authobj, channels, null_org, force):
51 params = {} 52 if null_org: 53 params['orgId'] = '' 54 55 # XXX don't allow superusers to force stuff 56 if force: 57 raise rhnFault(4, "Cannot force push nullorg content", explain=0) 58 59 if force and not CFG.FORCE_PACKAGE_UPLOAD: 60 raise rhnFault(55, "Package Upload Failed", explain=0) 61 62 authobj.authzOrg(params) 63 if channels: 64 authobj.authzChannels(channels) 65 66 if null_org: 67 org_id = None 68 else: 69 org_id = authobj.org_id 70 71 return org_id, force
72 73
74 -def relative_path_from_header(header, org_id, checksum_type=None, checksum=None):
75 nevra = importLib.get_nevra(header) 76 if header.is_source: 77 # 4/18/05 wregglej. if 1051 is in the header's keys, then it's a nosrc package. 78 if 1051 in list(header.keys()): 79 nevra[4] = 'nosrc' 80 else: 81 nevra[4] = 'src' 82 83 log_debug(4, "NEVRA", nevra) 84 85 # if the package isn't an rpm and the package name is spelled out in the 86 # header, use it 87 if header.packaging == "mpm" and "package_name" in list(header.keys()) and \ 88 header["package_name"]: 89 90 rel_path = relative_path_from_nevra_without_package_name(nevra, org_id, 91 checksum_type, checksum) 92 return os.path.join(rel_path, header["package_name"]) 93 94 return relative_path_from_nevra(nevra, 95 org_id, header.packaging, checksum_type, checksum)
96 97
98 -def relative_path_from_nevra(nevra, org_id, package_type=None, checksum_type=None, checksum=None):
99 # 4/18/05 wregglej. if 1051 is in the header's keys, then it's a nosrc package. 100 if nevra[4] == 'src' or nevra[4] == 'nosrc': 101 is_source = 1 102 else: 103 is_source = 0 104 log_debug(4, nevra, is_source) 105 return get_package_path(nevra, org_id=org_id, source=is_source, 106 prepend=CFG.PREPENDED_DIR, omit_epoch=None, package_type=package_type, 107 checksum_type=checksum_type, checksum=checksum)
108 109 # bug #161989 - get the relative path from the nevra, but omit the package name 110 111
112 -def relative_path_from_nevra_without_package_name(nevra, org_id, checksum_type, checksum):
113 log_debug(4, nevra, "no package name") 114 return get_package_path_without_package_name(nevra, org_id, 115 CFG.PREPENDED_DIR, checksum_type, checksum)
116 117
118 -def push_package(a_pkg, org_id=None, force=None, channels=[], relative_path=None):
119 """Uploads a package""" 120 121 if relative_path: 122 # First write the package to the filesystem to final location 123 try: 124 importLib.move_package(a_pkg.payload_stream.name, basedir=CFG.MOUNT_POINT, 125 relpath=relative_path, 126 checksum_type=a_pkg.checksum_type, checksum=a_pkg.checksum, force=1) 127 except OSError: 128 e = sys.exc_info()[1] 129 raise_with_tb(rhnFault(50, "Package upload failed: %s" % e), sys.exc_info()[2]) 130 except importLib.FileConflictError: 131 raise_with_tb(rhnFault(50, "File already exists"), sys.exc_info()[2]) 132 except: 133 raise_with_tb(rhnFault(50, "File error"), sys.exc_info()[2]) 134 135 # Remove any pending scheduled file deletion for this package 136 h = rhnSQL.prepare(""" 137 delete from rhnPackageFileDeleteQueue where path = :path 138 """) 139 h.execute(path=relative_path) 140 141 pkg = mpmSource.create_package(a_pkg.header, size=a_pkg.payload_size, 142 checksum_type=a_pkg.checksum_type, checksum=a_pkg.checksum, 143 relpath=relative_path, org_id=org_id, header_start=a_pkg.header_start, 144 header_end=a_pkg.header_end, channels=channels) 145 146 batch = importLib.Collection() 147 batch.append(pkg) 148 149 backend = SQLBackend() 150 151 if force: 152 upload_force = 4 153 else: 154 upload_force = 0 155 importer = packageImport.packageImporter(batch, backend, 156 source=a_pkg.header.is_source, caller="server.app.uploadPackage") 157 importer.setUploadForce(upload_force) 158 importer.run() 159 160 package = batch[0] 161 log_debug(5, "Package diff", package.diff) 162 163 if package.diff and not force and package.diff.level > 1: 164 # Packages too different; bail out 165 log_debug(1, "Packages too different", package.toDict(), 166 "Level:", package.diff.level) 167 pdict = package.toDict() 168 orig_path = package['path'] 169 orig_path = os.path.join(CFG.MOUNT_POINT, orig_path) 170 log_debug(4, "Original package", orig_path) 171 172 # MPMs do not store their headers on disk, so we must avoid performing 173 # operations which rely on information only contained in the headers 174 # (such as header signatures). 175 if os.path.exists(orig_path) and a_pkg.header.packaging != 'mpm': 176 oh = rhn_pkg.get_package_header(orig_path) 177 _diff_header_sigs(a_pkg.header, oh, pdict['diff']['diff']) 178 179 return pdict, package.diff.level 180 181 if package.diff and not force and package.diff.level: 182 # No need to copy it - just the path is modified 183 # pkilambi bug#180347 184 # case 1:check if the path exists in the db and also on the file system. 185 # if it does then no need to copy 186 # case2: file exists on file system but path not in db.then add the 187 # realtive path in the db based on checksum of the pkg 188 # case3: if no file on file system but path exists.then we write the 189 # file to file system 190 # case4:no file exists on FS and no path in db .then we write both. 191 orig_path = package['path'] 192 orig_path = os.path.join(CFG.MOUNT_POINT, orig_path) 193 log_debug(3, "Original package", orig_path) 194 195 # check included to query for source and binary rpms 196 h_path_sql = """ 197 select ps.path path 198 from %s ps, 199 rhnChecksumView c 200 where 201 c.checksum = :csum 202 and c.checksum_type = :ctype 203 and ps.checksum_id = c.id 204 and (ps.org_id = :org_id or 205 (ps.org_id is null and :org_id is null) 206 ) 207 """ 208 if a_pkg.header.is_source: 209 h_package_table = 'rhnPackageSource' 210 else: 211 h_package_table = 'rhnPackage' 212 h_path = rhnSQL.prepare(h_path_sql % h_package_table) 213 h_path.execute(ctype=a_pkg.checksum_type, csum=a_pkg.checksum, org_id=org_id) 214 215 rs_path = h_path.fetchall_dict() 216 path_dict = {} 217 if rs_path: 218 path_dict = rs_path[0] 219 220 if os.path.exists(orig_path) and path_dict['path']: 221 return {}, 0 222 elif not path_dict['path']: 223 h_upd = rhnSQL.prepare(""" 224 update rhnpackage 225 set path = :path 226 where checksum_id = ( 227 select id from rhnChecksumView c 228 where c.checksum = :csum 229 and c.checksum_type = :ctype) 230 """) 231 h_upd.execute(path=relative_path, ctype=a_pkg.checksum_type, 232 csum=a_pkg.checksum) 233 234 # commit the transactions 235 rhnSQL.commit() 236 if not a_pkg.header.is_source: 237 # Process Package Key information 238 server_packages.processPackageKeyAssociations(a_pkg.header, 239 a_pkg.checksum_type, a_pkg.checksum) 240 241 if not a_pkg.header.is_source: 242 errataCache.schedule_errata_cache_update(importer.affected_channels) 243 244 log_debug(2, "Returning") 245 return {}, 0
246 247
248 -def _diff_header_sigs(h1, h2, diff_list):
249 # XXX This can be far more complicated if we take into account that 250 # signatures can be different 251 h1sigs = h1.signatures 252 h2sigs = h2.signatures 253 if not h1sigs and not h2sigs: 254 # No differences here 255 return 256 h1_key_ids = _key_ids(h1sigs) 257 h2_key_ids = _key_ids(h2sigs) 258 259 diff_list.append(['sig_key_id', h1_key_ids, h2_key_ids])
260 261
262 -def _key_ids(sigs):
263 h = {} 264 for sig in sigs: 265 h[sig['key_id']] = None 266 267 l = list(h.keys()) 268 l.sort() 269 return l
270 271
272 -def save_uploaded_package(stream, nevra, org_id, packaging, 273 checksum_type=None, checksum=None):
274 a_pkg = rhn_pkg.package_from_stream(stream, packaging=packaging) 275 a_pkg.read_header() 276 277 temp_dir = os.path.join(CFG.MOUNT_POINT, CFG.PREPENDED_DIR, org_id, 'stage') 278 if not os.path.isdir(temp_dir): 279 os.makedirs(temp_dir) 280 temp_stream = tempfile.NamedTemporaryFile(dir=temp_dir, 281 prefix='-'.join((nevra[0], nevra[2], nevra[3], nevra[4]))) 282 a_pkg.save_payload(temp_stream) 283 284 if checksum_type and checksum: 285 # verify checksum 286 if not (checksum_type == a_pkg.checksum_type 287 and checksum == a_pkg.checksum): 288 log_debug(1, "Mismatching checksums: expected %s:%s got %s:%s" % 289 (checksum_type, checksum, 290 a_pkg.checksum_type, a_pkg.checksum)) 291 raise rhnFault(104, "Mismatching information") 292 293 temp_stream.file.close() 294 temp_stream.close_called = True 295 return a_pkg
296 297
298 -def load_package(package_stream):
299 if package_stream.name.endswith('.deb'): 300 try: 301 header, payload_stream = rhn_deb.load(filename=package_stream.name) 302 except: 303 raise_with_tb(rhnFault(50, "Unable to load package", explain=0), sys.exc_info()[2]) 304 else: 305 try: 306 header, payload_stream = rhn_mpm.load(file=package_stream) 307 except: 308 raise_with_tb(rhnFault(50, "Unable to load package", explain=0), sys.exc_info()[2]) 309 310 payload_stream.seek(0, 0) 311 if header.packaging == "mpm" or header.packaging == "deb": 312 header.header_start = header.header_end = 0 313 (header_start, header_end) = (0, 0) 314 else: 315 (header_start, header_end) = get_header_byte_range(payload_stream) 316 payload_stream.seek(0, 0) 317 318 return header, payload_stream, header_start, header_end
319 320
321 -class AlreadyUploadedError(Exception):
322 pass
323