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

Source Code for Module backend.server.rhnLib

  1  # 
  2  # Copyright (c) 2008--2020 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 hashlib 
 18  import string 
 19  import base64 
 20  import posixpath 
 21   
 22  from spacewalk.common.rhnLib import parseRPMName, parseDEBName 
 23  from spacewalk.common.rhnLog import log_debug 
 24  from spacewalk.common.rhnException import rhnFault 
 25   
 26  # architecture work 
 27  from rhnMapping import check_package_arch 
 28   
 29   
30 -def computeSignature(*fields):
31 # Init the hash 32 m = hashlib.new('sha256') 33 for i in fields: 34 # use str(i) since some of the fields may be non-string 35 m.update(str(i) + "\n") 36 return base64.encodestring(m.digest()).rstrip()
37 38 39 # 'n_n-n-v.v.v-r_r.r:e.ARCH.rpm' ---> [n,v,r,e,a]
40 -def parseRPMFilename(pkgFilename):
41 """ 42 IN: Package Name: xxx-yyy-ver.ver.ver-rel.rel_rel:e.ARCH.rpm (string) 43 Understood rules: 44 o Name can have nearly any char, but end in a - (well seperated by). 45 Any character; may include - as well. 46 o Version cannot have a -, but ends in one. 47 o Release should be an actual number, and can't have any -'s. 48 o Release can include the Epoch, e.g.: 2:4 (4 is the epoch) 49 o Epoch: Can include anything except a - and the : seperator??? 50 XXX: Is epoch info above correct? 51 OUT: [n,e,v,r, arch]. 52 """ 53 if type(pkgFilename) != type(''): 54 raise rhnFault(21, str(pkgFilename)) # Invalid arg. 55 56 pkgFilename = os.path.basename(pkgFilename) 57 58 # Check that this is a package NAME (with arch.rpm) and strip 59 # that crap off. 60 pkg = string.split(pkgFilename, '.') 61 62 dist = string.lower(pkg[-1]) 63 64 # 'rpm' at end? 65 if dist not in ['rpm', 'deb']: 66 raise rhnFault(21, 'neither an rpm nor a deb package name: %s' % pkgFilename) 67 68 # Valid architecture next? 69 if check_package_arch(pkg[-2]) is None: 70 raise rhnFault(21, 'Incompatible architecture found: %s' % pkg[-2]) 71 72 _arch = pkg[-2] 73 74 # Nuke that arch.rpm. 75 pkg = string.join(pkg[:-2], '.') 76 77 if dist == "deb": 78 ret = list(parseDEBName(pkg)) 79 else: 80 ret = list(parseRPMName(pkg)) 81 82 if ret: 83 ret.append(_arch) 84 return ret
85 86 # XXX TBD where to place this function - it has to be accessible from several 87 # places 88 89
90 -def normalize_server_arch(arch):
91 log_debug(4, 'server arch', arch) 92 93 if arch is None: 94 return '' 95 arch = str(arch) 96 if '-' in arch: 97 # Already normalized 98 return arch 99 100 # Fix the arch if need be 101 suffix = '-redhat-linux' 102 arch = arch + suffix 103 return arch
104 105
106 -class InvalidAction(Exception):
107 108 """ An error class to signal when we can not handle an action """ 109 pass
110 111
112 -class EmptyAction(Exception):
113 114 """ An error class that signals that we encountered an internal error 115 trying to handle an action through no fault of the client 116 """ 117 pass
118 119
120 -class ShadowAction(Exception):
121 122 """ An error class for actions that should not get to the client """ 123 pass
124 125
126 -def transpose_to_hash(arr, column_names):
127 """ Handy function to transpose an array from row-based to column-based, 128 with named columns. 129 """ 130 result = [] 131 for c in column_names: 132 result.append([]) 133 134 colnum = len(column_names) 135 for r in arr: 136 if len(r) != colnum: 137 raise Exception( 138 "Mismatching number of columns: expected %s, got %s; %s" % ( 139 colnum, len(r), r)) 140 for i in range(len(r)): 141 result[i].append(r[i]) 142 143 # Now build the hash labeled with the column names 144 rh = {} 145 for i in range(len(column_names)): 146 rh[column_names[i]] = result[i] 147 148 return rh
149 150
151 -def get_package_path(nevra, org_id, source=0, prepend="", omit_epoch=None, 152 package_type='rpm', checksum_type=None, checksum=None):
153 """ Computes a package path, optionally prepending a prefix 154 The path will look like 155 <prefix>/<org_id>/checksum[:3]/n/e:v-r/a/checksum/n-v-r.a.rpm if not omit_epoch 156 <prefix>/<org_id>/checksum[:3]/n/v-r/a/checksum/n-v-r.a.rpm if omit_epoch 157 """ 158 name, epoch, version, release, pkgarch = nevra 159 160 # dirarch and pkgarch are special-cased for source rpms 161 if source: 162 dirarch = 'SRPMS' 163 else: 164 dirarch = pkgarch 165 166 if org_id in ['', None]: 167 org = "NULL" 168 else: 169 org = org_id 170 171 if not omit_epoch and epoch not in [None, '']: 172 version = str(epoch) + ':' + version 173 # normpath sanitizes the path (removing duplicated / and such) 174 template = os.path.normpath(prepend + 175 "/%s/%s/%s/%s-%s/%s/%s/%s-%s-%s.%s.%s") 176 return template % (org, checksum[:3], name, version, release, dirarch, checksum, 177 name, nevra[2], release, pkgarch, package_type)
178 179 180 # bug #161989 181 # It seems that our software was written specifically for rpms in far too many 182 # ways. Here's a little bit of a hack function that will return the package path 183 # (as in from get_package_path) but without the filename appended. 184 # This enables us to append an arbitrary file name that is not restricted to the 185 # form: name-version-release.arch.type
186 -def get_package_path_without_package_name(nevra, org_id, prepend="", 187 checksum_type=None, checksum=None):
188 """return a package path without the package name appended""" 189 return os.path.dirname(get_package_path(nevra, org_id, prepend=prepend, 190 checksum_type=checksum_type, checksum=checksum))
191 192
193 -class CallableObj:
194 195 """ Generic callable object """ 196
197 - def __init__(self, name, func):
198 self.func = func 199 self.name = name
200
201 - def __call__(self, *args, **kwargs):
202 return self.func(self.name, *args, **kwargs)
203 204
205 -def make_evr(nvre, source=False):
206 """ IN: 'e:name-version-release' or 'name-version-release:e' 207 OUT: {'name':name, 'version':version, 'release':release, 'epoch':epoch } 208 """ 209 if ":" in nvre: 210 nvr, epoch = nvre.rsplit(":", 1) 211 if "-" in epoch: 212 nvr, epoch = epoch, nvr 213 else: 214 nvr, epoch = nvre, "" 215 216 nvr_parts = nvr.rsplit("-", 2) 217 if len(nvr_parts) != 3: 218 raise rhnFault(err_code=21, err_text="NVRE is missing name, version, or release.") 219 220 result = dict(zip(["name", "version", "release"], nvr_parts)) 221 result["epoch"] = epoch 222 223 if source and result["release"].endswith(".src"): 224 result["release"] = result["release"][:-4] 225 226 return result
227 228
229 -def _is_secure_path(path):
230 path = posixpath.normpath(path) 231 return not (path.startswith('/') or path.startswith('../'))
232 233
234 -def get_crash_path(org_id, system_id, crash):
235 """For a given org_id, system_id and crash, return relative path to a crash directory.""" 236 237 path = os.path.join('systems', org_id, system_id, 'crashes', crash) 238 239 if _is_secure_path(path): 240 return path 241 else: 242 return None
243 244
245 -def get_crashfile_path(org_id, system_id, crash, filename):
246 """For a given org_id, system_id, crash and filename, return relative path to a crash file.""" 247 path = os.path.join(get_crash_path(org_id, system_id, crash), filename) 248 249 if _is_secure_path(path): 250 return path 251 else: 252 return None
253 254
255 -def get_action_path(org_id, system_id, action_id):
256 """For a given org_id, system_id, and action_id, return relative path to a store directory.""" 257 path = os.path.join('systems', str(org_id), str(system_id), 'actions', str(action_id)) 258 if _is_secure_path(path): 259 return path
260 261
262 -def get_actionfile_path(org_id, system_id, action_id, filename):
263 """For a given org_id, system_id, action_id, and file, return relative path to a file.""" 264 path = os.path.join(get_action_path(org_id, system_id, action_id), str(filename)) 265 266 if _is_secure_path(path): 267 return path
268