Trees | Indices | Help |
---|
|
1 # 2 # Copyright (c) 2008--2018 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 17 # system module imports 18 import os 19 import stat 20 import sys 21 22 from rhn import rpclib 23 24 # common modules imports 25 from spacewalk.common.usix import raise_with_tb 26 from spacewalk.common import rhnRepository, rhnFlags, rhnCache 27 from spacewalk.common.rhnLog import log_debug 28 from spacewalk.common.rhnConfig import CFG 29 from spacewalk.common.rhnException import rhnFault, redirectException 30 from spacewalk.common.rhnLib import rfc822time, timestamp 31 32 # local modules imports 33 from spacewalk.server import rhnChannel, rhnPackage, taskomatic, rhnSQL 34 from rhnServer import server_lib 35 from repomd import repository 36 3739 40 """ Cache class to perform RHN server file system and DB actions. 41 42 This class gets all data from the file system and oracle. 43 All the functions that are performed upon GET requests are here (and 44 since proxies perform these functions as well, a good chunk of code is 45 in common/rhnRepository.py) 46 47 The listall code is here too, because it performs a lot of disk caching 48 and here's the appropriate location for it 49 50 The dependency solving code is not handled in this repository - 51 all the code we need is already in xmlrpc/up2date 52 """ 5339955 """Initialize the class, setting channel name and server 56 57 ID, that serial number (w/o ID-), if necessary. 58 NOTE: server_id is a string. 59 """ 60 log_debug(3, channelName, server_id) 61 rhnRepository.Repository.__init__(self, channelName) 62 self.server_id = server_id 63 self.username = username 64 self.functions.append('listPackages') 65 self.functions.append('getObsoletes') 66 self.functions.append('getObsoletesBlacklist') 67 self.functions.append('listAllPackages') 68 self.functions.append('listAllPackagesChecksum') 69 self.functions.append('listAllPackagesComplete') 70 self.functions.append('repodata') 71 self.set_compress_headers(CFG.COMPRESS_HEADERS) 72 self.redirect_location = None7375 ret = rhnRepository.Repository.getPackageHeader(self, pkgFilename) 76 # Clean up the download-accelerator flag 77 rhnFlags.set("Download-Accelerator-Path", None) 78 return ret7981 """ Clients v2+ 82 returns a list of the channels the server is subscribed to, or 83 could subscribe to. 84 """ 85 return rhnChannel.channels_for_server(self.server_id)8688 """ Clients v2+. 89 Creates and/or serves up a cached copy of the package list for 90 this channel. 91 """ 92 log_debug(3, self.channelName, version) 93 # Check to see if the version they are requesting is the latest 94 95 # check the validity of what the client thinks about this channel 96 # or blow up 97 self.__check_channel(version) 98 99 packages = rhnChannel.list_packages(self.channelName) 100 101 # transport options... 102 transportOptions = rhnFlags.get('outputTransportOptions') 103 transportOptions['Last-Modified'] = rfc822time(timestamp(version)) 104 rhnFlags.set("compress_response", 1) 105 return packages106108 """ Returns a list of packages that obsolete other packages """ 109 log_debug(3, self.channelName, version) 110 # Check to see if the version they are requesting is the latest 111 112 # check the validity of what the client thinks about this channel 113 # or blow up 114 self.__check_channel(version) 115 116 obsoletes = rhnChannel.list_obsoletes(self.channelName) 117 118 # Set the transport options 119 transportOptions = rhnFlags.get('outputTransportOptions') 120 transportOptions['Last-Modified'] = rfc822time(timestamp(version)) 121 rhnFlags.set("compress_response", 1) 122 return obsoletes123125 """ Returns a list of packages that obsolete other packages 126 XXX Obsoleted 127 """ 128 log_debug(3, self.channelName, version) 129 # Check to see if the version they are requesting is the latest 130 131 # check the validity of what the client thinks about this channel 132 # or blow up 133 self.__check_channel(version) 134 135 # Set the transport options 136 transportOptions = rhnFlags.get('outputTransportOptions') 137 transportOptions['Last-Modified'] = rfc822time(timestamp(version)) 138 rhnFlags.set("compress_response", 1) 139 # Return nothing 140 return []141143 """ Creates and/or serves up a cached copy of all the packages for 144 this channel. 145 """ 146 log_debug(3, self.channelName, version) 147 # Check to see if the version they are requesting is the latest 148 149 # check the validity of what the client thinks about this channel 150 # or blow up 151 self.__check_channel(version) 152 153 packages = rhnChannel.list_all_packages(self.channelName) 154 155 # transport options... 156 transportOptions = rhnFlags.get('outputTransportOptions') 157 transportOptions['Last-Modified'] = rfc822time(timestamp(version)) 158 rhnFlags.set("compress_response", 1) 159 return packages160162 """ Creates and/or serves up a cached copy of all the packages for 163 this channel, including checksum information. 164 """ 165 log_debug(3, self.channelName, version) 166 # Check to see if the version they are requesting is the latest 167 168 # check the validity of what the client thinks about this channel 169 # or blow up 170 self.__check_channel(version) 171 172 packages = rhnChannel.list_all_packages_checksum(self.channelName) 173 174 # transport options... 175 transportOptions = rhnFlags.get('outputTransportOptions') 176 transportOptions['Last-Modified'] = rfc822time(timestamp(version)) 177 rhnFlags.set("compress_response", 1) 178 return packages179181 """ Creates and/or serves up a cached copy of all the packages for 182 this channel including requires, obsoletes, conflicts, etc. 183 """ 184 log_debug(3, self.channelName, version) 185 # Check to see if the version they are requesting is the latest 186 187 # check the validity of what the client thinks about this channel 188 # or blow up 189 self.__check_channel(version) 190 191 packages = rhnChannel.list_all_packages_complete(self.channelName) 192 193 # transport options... 194 transportOptions = rhnFlags.get('outputTransportOptions') 195 transportOptions['Last-Modified'] = rfc822time(timestamp(version)) 196 rhnFlags.set("compress_response", 1) 197 return packages198200 log_debug(3, 'repodata', file_name) 201 c_info = rhnChannel.channel_info(self.channelName) 202 repo = repository.get_repository(c_info) 203 204 output = None 205 content_type = "application/x-gzip" 206 207 if file_name == "repomd.xml": 208 content_type = "text/xml" 209 output = repo.get_repomd_file() 210 elif file_name == "primary.xml.gz": 211 output = repo.get_primary_xml_file() 212 elif file_name == "other.xml.gz": 213 output = repo.get_other_xml_file() 214 elif file_name == "filelists.xml.gz": 215 output = repo.get_filelists_xml_file() 216 elif file_name == "updateinfo.xml.gz": 217 output = repo.get_updateinfo_xml_file() 218 elif file_name == "comps.xml": 219 content_type = "text/xml" 220 output = repo.get_comps_file() 221 elif file_name == "modules.yaml": 222 output = repo.get_modules_file() 223 else: 224 log_debug(2, "Unknown repomd file requested: %s" % file_name) 225 raise rhnFault(6) 226 227 output = rpclib.transports.File(output, name=file_name) 228 229 rhnFlags.set('Content-Type', content_type) 230 231 return output232234 log_debug(3, 'repodata', file_name) 235 236 content_type = "application/x-gzip" 237 238 if file_name in ["repomd.xml", "comps.xml"]: 239 content_type = "text/xml" 240 elif file_name not in ["primary.xml.gz", "other.xml.gz", 241 "filelists.xml.gz", "updateinfo.xml.gz", "Packages.gz", "modules.yaml", 242 "InRelease", "Release", "Release.gpg"]: 243 log_debug(2, "Unknown repomd file requested: %s" % file_name) 244 raise rhnFault(6) 245 246 # XXX this won't be repconned or CDNd 247 if file_name in ["comps.xml", "modules.yaml"]: 248 return self._repodata_python(file_name) 249 250 file_path = "%s/%s/%s" % (CFG.REPOMD_PATH_PREFIX, self.channelName, file_name) 251 rhnFlags.set('Content-Type', content_type) 252 try: 253 rhnFlags.set('Download-Accelerator-Path', file_path) 254 return self._getFile(CFG.REPOMD_CACHE_MOUNT_POINT + "/" + file_path) 255 except IOError: 256 e = sys.exc_info()[1] 257 # For file not found, queue up a regen, and return 404 258 if e.errno == 2 and file_name != "comps.xml" and file_name != "modules.yaml": 259 taskomatic.add_to_repodata_queue(self.channelName, 260 "repodata request", file_name, bypass_filters=True) 261 rhnSQL.commit() 262 # This returns 404 to the client 263 raise_with_tb(rhnFault(6), sys.exc_info()[2]) 264 raise265267 # By default we're using taskomatic's repomd. But if the config 268 # value is present and set to anything other than 1, we'll use the 269 # old python code 270 use_taskomatic = True 271 try: 272 use_taskomatic = (CFG.USE_TASKOMATIC_REPOMD == 1) 273 except AttributeError: 274 pass 275 276 log_debug(4, "Using taskomatic for repomd generation: %s" 277 % use_taskomatic) 278 279 if use_taskomatic: 280 return self._repodata_taskomatic(file_name) 281 else: 282 return self._repodata_python(file_name)283 284 # Helper functions 285 # These functions are not private, they should be defined as 'protected', 286 # since the code that handles v2 package retrieval (plus headers) is in 287 # common/rhnRepository, and expects a definition for these functions to 288 # know where to take stuff from 289291 """ Retrieves package path 292 Overloads getPackagePath in common/rhnRepository. 293 checks if redirect and hosted; 294 makes a call to query the db for pkg_location 295 """ 296 297 log_debug(2, pkgFilename, redirect_capable) 298 # check for re-direct check flag from header to issue package 299 # request from client in order to avoid failover loops. 300 skip_redirect = rhnFlags.get('x-rhn-redirect') 301 log_debug(3, "check flag for X-RHN-REDIRECT ::", skip_redirect) 302 303 # get the redirect and local paths 304 remotepath, localpath = self.getAllPackagePaths(pkgFilename) 305 306 # check for redirect conditions and fail over checks 307 if redirect_capable and not CFG.SATELLITE and not skip_redirect \ 308 and remotepath is not None: 309 self.redirect_location = remotepath 310 # We've set self.redirect_location, we're done here 311 # we throw a redirectException in _getFile method. 312 return None 313 # Package cannot be served from the edge, we serve it ourselves 314 return localpath315317 """ 318 overwrites the common/rhnRepository._getFile to check for redirect 319 """ 320 if self.redirect_location: 321 raise redirectException(self.redirect_location) 322 return rhnRepository.Repository._getFile(self, path)323325 """ 326 retrives the package location if edge network location available 327 and its local path. 328 """ 329 log_debug(3, pkgFilename) 330 return rhnPackage.get_all_package_paths(self.server_id, pkgFilename, 331 self.channelName)332334 """ Retrieves package source path 335 Overloads getSourcePackagePath in common/rhnRepository. 336 """ 337 return rhnPackage.get_source_package_path(self.server_id, pkgFilename, 338 self.channelName)339 340 # Private methods 341343 """ check if the current channel version matches that of the client """ 344 channel_list = rhnChannel.channels_for_server(self.server_id) 345 # Check the subscription to this channel 346 for channel in channel_list: 347 if channel['label'] == self.channelName: 348 # Okay, we verified the subscription 349 # Check the version too 350 if channel['last_modified'] == version: 351 # Great 352 break 353 # Old version; should re-login to get the new version 354 raise rhnFault(41, "Invalid channel version") 355 else: 356 # Not subscribed 357 raise rhnFault(39, "No subscription to the specified channel") 358 return 1359 362364 """ Wraps around common.rhnRepository's method, adding a caching layer 365 If stat_info was already passed, don't re-stat the file 366 """ 367 log_debug(3, filePath) 368 if not CFG.CACHE_PACKAGE_HEADERS: 369 return rhnRepository.Repository._getHeaderFromFile(self, filePath, 370 stat_info=stat_info) 371 # Ignore stat_info for now - nobody sets it anyway 372 stat_info = None 373 try: 374 stat_info = os.stat(filePath) 375 except: 376 raise_with_tb(rhnFault(17, "Unable to read package %s" 377 % os.path.basename(filePath)), sys.exc_info()[2]) 378 lastModified = stat_info[stat.ST_MTIME] 379 380 # OK, file exists, check the cache 381 cache_key = os.path.normpath("headers/" + filePath) 382 header = rhnCache.get(cache_key, modified=lastModified, raw=1, 383 compressed=1) 384 if header: 385 # We're good to go 386 log_debug(2, "Header cache HIT for %s" % filePath) 387 extra_headers = { 388 'X-RHN-Package-Header': os.path.basename(filePath), 389 } 390 self._set_last_modified(lastModified, extra_headers=extra_headers) 391 return header 392 log_debug(3, "Header cache MISS for %s" % filePath) 393 header = rhnRepository.Repository._getHeaderFromFile(self, filePath, 394 stat_info=stat_info) 395 if header: 396 rhnCache.set(cache_key, header, modified=lastModified, raw=1, 397 compressed=1) 398 return header
Trees | Indices | Help |
---|
Generated by Epydoc 3.0.1 on Wed Mar 4 07:37:51 2020 | http://epydoc.sourceforge.net |