def getPackage(self, pkgFilename, *args): """ Get rpm package. """ log_debug(3, pkgFilename) if args: pkg_spec = [pkgFilename] + list(args) else: pkg_spec = pkgFilename redirectsSupported = 0 # If we are talking to a proxy, determine whether it's a version that # supports redirects. proxyVersionString = rhnFlags.get('x-rhn-proxy-version') if proxyVersionString: redirectsSupported = 1 else: # Must be a client. We'll determine the redirect capability via # the x-rhn-transport-capability header instead. transport_cap = rhnFlags.get('x-rhn-transport-capability') if transport_cap: transport_cap_list = transport_cap.split('=') redirectsSupported = transport_cap_list[0] == 'follow-redirects' and transport_cap_list[1] >= 2 if redirectsSupported: log_debug(3, "Client supports redirects.") filePath = self.getPackagePath(pkg_spec, 1) else: # older clients just return the hosted url and download the package filePath = self.getPackagePath(pkg_spec) return self._getFile(filePath)
def auth_proxy(): """ Authenticates a proxy carrying a clients request. For a valid or unsigned request, this function returns 1 (OK), otherwise it raises rhnFault NOTE: X-RHN-Proxy-Auth described in proxy/broker/rhnProxyAuth.py """ log_debug(3) headers = rhnFlags.get('outputTransportOptions') if not rhnFlags.test('X-RHN-Proxy-Auth'): # No auth information; decline any action log_debug(4, "declined proxy authentication") headers['X-RHN-Proxy-Auth-Error'] = '%s:%s' % ( 1003, _("declined proxy authentication")) raise rhnFault(1003) # Invalid session key # NOTE: # - < v3.1 RHN proxies send only 1 token in this header # - > v3.1: we send the route of the requests via multiple tokens # "token1:hostname1,token2:hostname2" the first tuple is the first # proxy hit. tokens = string.split(rhnFlags.get('X-RHN-Proxy-Auth'), ',') tokens = filter(lambda token: token, tokens) for auth_token in tokens: _verifyProxyAuthToken(auth_token) # if no rhnFault was raised then the tokens all passed return 1
def auth_proxy(): """ Authenticates a proxy carrying a clients request. For a valid or unsigned request, this function returns 1 (OK), otherwise it raises rhnFault NOTE: X-RHN-Proxy-Auth described in proxy/broker/rhnProxyAuth.py """ log_debug(3) headers = rhnFlags.get('outputTransportOptions') if not rhnFlags.test('X-RHN-Proxy-Auth'): # No auth information; decline any action log_debug(4, "declined proxy authentication") headers['X-RHN-Proxy-Auth-Error'] = '%s:%s' % ( 1003, _("declined proxy authentication")) raise rhnFault(1003) # Invalid session key # NOTE: # - < v3.1 RHN proxies send only 1 token in this header # - > v3.1: we send the route of the requests via multiple tokens # "token1:hostname1,token2:hostname2" the first tuple is the first # proxy hit. tokens = string.split(rhnFlags.get('X-RHN-Proxy-Auth'), ',') tokens = [token for token in tokens if token] for auth_token in tokens: _verifyProxyAuthToken(auth_token) # if no rhnFault was raised then the tokens all passed return 1
def getPackage(self, pkgFilename, *args): """ Get rpm package. """ log_debug(3, pkgFilename) if args: pkg_spec = [pkgFilename] + list(args) else: pkg_spec = pkgFilename redirectsSupported = 0 # If we are talking to a proxy, determine whether it's a version that # supports redirects. proxyVersionString = rhnFlags.get('x-rhn-proxy-version') if proxyVersionString: redirectsSupported = 1 else: # Must be a client. We'll determine the redirect capability via # the x-rhn-transport-capability header instead. transport_cap = rhnFlags.get('x-rhn-transport-capability') if transport_cap: transport_cap_list = transport_cap.split('=') redirectsSupported = transport_cap_list[ 0] == 'follow-redirects' and transport_cap_list[1] >= 2 if redirectsSupported: log_debug(3, "Client supports redirects.") filePath = self.getPackagePath(pkg_spec, 1) else: # older clients just return the hosted url and download the package filePath = self.getPackagePath(pkg_spec) return self._getFile(filePath)
def response(self, response): log_debug(3) # pkilambi:if redirectException caught returns path(<str>) if isinstance(response, str): method, params = self._get_method_params() if method == "getPackage": return self.redirect(self.req, response) # GET requests resulting in a Fault receive special treatment # since we have to stick the error message in the HTTP header, # and to return an Apache error code if isinstance(response, xmlrpclib.Fault): log_debug(4, "Return FAULT", response.faultCode, response.faultString) retcode = apache.HTTP_NOT_FOUND if abs(response.faultCode) in (33, 34, 35, 37, 39, 41): retcode = apache.HTTP_UNAUTHORIZED self.req.headers_out["X-RHN-Fault-Code"] = str(response.faultCode) faultString = string.strip(base64.encodestring(response.faultString)) # Split the faultString into multiple lines for line in string.split(faultString, "\n"): self.req.headers_out.add("X-RHN-Fault-String", string.strip(line)) # And then send all the other things for k, v in rhnFlags.get("outputTransportOptions").items(): setHeaderValue(self.req.headers_out, k, v) return retcode # Otherwise we're pretty much fine with the standard response # handler # Copy the fields from the transport options, if necessary for k, v in rhnFlags.get("outputTransportOptions").items(): setHeaderValue(self.req.headers_out, k, v) # and jump into the base handler return apacheRequest.response(self, response)
def method_ref(self, method): log_debug(3, self.server, method) # Init the repository server_id = rhnFlags.get("AUTH_SESSION_TOKEN")["X-RHN-Server-Id"] username = rhnFlags.get("AUTH_SESSION_TOKEN")["X-RHN-Auth-User-Id"] repository = rhnRepository.Repository(self.channel, server_id, username) repository.set_qos() f = repository.get_function(method) if f is None: raise UnknownXML("function '%s' invalid; path_info is %s" % (method, self.req.path_info)) return f
def __callLocalRepository(self, channelName, funct, params): """ Contacts the local repository and retrieves files URI looks like: /$RHN/<channel>/<function>/<params> """ log_debug(2, channelName, funct, params) # Find the channel version version = None for c in self.authChannels: ch, ver = c[:2] if ch == channelName: version = ver break # NOTE: X-RHN-Proxy-Auth described in broker/rhnProxyAuth.py if rhnFlags.get('outputTransportOptions').has_key('X-RHN-Proxy-Auth'): self.cachedClientInfo['X-RHN-Proxy-Auth'] = rhnFlags.get('outputTransportOptions')['X-RHN-Proxy-Auth'] if rhnFlags.get('outputTransportOptions').has_key('Host'): self.cachedClientInfo['Host'] = rhnFlags.get('outputTransportOptions')['Host'] # We already know he's subscribed to this channel # channel, so the version is non-null rep = rhnRepository.Repository(channelName, version, self.cachedClientInfo, rhnParent=self.rhnParent, rhnParentXMLRPC=self.rhnParentXMLRPC, httpProxy=self.httpProxy, httpProxyUsername=self.httpProxyUsername, httpProxyPassword=self.httpProxyPassword, caChain=self.caChain) f = rep.get_function(funct) if not f: raise rhnFault(1000, _("RHN Proxy configuration error: invalid function %s") % funct) log_debug(3, "Calling %s(%s)" % (funct, params)) try: if params: ret = apply(f, params) else: ret = f() except rhnRepository.NotLocalError: # The package is not local return None return ret
def method_ref(self, method): log_debug(3, self.server, method) # Init the repository server_id = rhnFlags.get("AUTH_SESSION_TOKEN")['X-RHN-Server-Id'] username = rhnFlags.get("AUTH_SESSION_TOKEN")['X-RHN-Auth-User-Id'] repository = rhnRepository.Repository(self.channel, server_id, username) repository.set_qos() f = repository.get_function(method) if f is None: raise UnknownXML("function '%s' invalid; path_info is %s" % ( method, self.req.path_info)) return f
def __callLocalRepository(self, channelName, funct, params): """ Contacts the local repository and retrieves files URI looks like: /$RHN/<channel>/<function>/<params> """ log_debug(2, channelName, funct, params) # Find the channel version version = None for c in self.authChannels: ch, ver = c[:2] if ch == channelName: version = ver break # NOTE: X-RHN-Proxy-Auth described in broker/rhnProxyAuth.py if rhnFlags.get('outputTransportOptions').has_key('X-RHN-Proxy-Auth'): self.cachedClientInfo['X-RHN-Proxy-Auth'] = rhnFlags.get('outputTransportOptions')['X-RHN-Proxy-Auth'] if rhnFlags.get('outputTransportOptions').has_key('Host'): self.cachedClientInfo['Host'] = rhnFlags.get('outputTransportOptions')['Host'] # We already know he's subscribed to this channel # channel, so the version is non-null rep = rhnRepository.Repository(channelName, version, self.cachedClientInfo, rhnParent=self.rhnParent, rhnParentXMLRPC=self.rhnParentXMLRPC, httpProxy=self.httpProxy, httpProxyUsername=self.httpProxyUsername, httpProxyPassword=self.httpProxyPassword, caChain=self.caChain) f = rep.get_function(funct) if not f: raise rhnFault(1000, _("Spacewalk Proxy configuration error: invalid function %s") % funct) log_debug(3, "Calling %s(%s)" % (funct, params)) if params is None: params = () try: ret = f(*params) except rhnRepository.NotLocalError: # The package is not local return None return ret
def _verifyProxyAuthToken(auth_token): """ verifies the validity of a proxy auth token NOTE: X-RHN-Proxy-Auth described in proxy/broker/rhnProxyAuth.py """ log_debug(4, auth_token) token, hostname = splitProxyAuthToken(auth_token) hostname = hostname.strip() ipv4_regex = '^([01]?\\d\\d?|2[0-4]\\d|25[0-5])\\.([01]?\\d\\d?|2[0-4]\\d|25[0-5])\\.([01]?\\d\\d?|2[0-4]\\d|25[0-5])\\.([01]?\\d\\d?|2[0-4]\\d|25[0-5])$' # This ipv6 regex was develeoped by Stephen Ryan at Dataware. # (http://forums.intermapper.com/viewtopic.php?t=452) It is licenced # under a Creative Commons Attribution-ShareAlike 3.0 Unported # License, so we are free to use it as long as we attribute it to him. ipv6_regex = '^((([0-9A-Fa-f]{1,4}:){7}([0-9A-Fa-f]{1,4}|:))|(([0-9A-Fa-f]{1,4}:){6}(:[0-9A-Fa-f]{1,4}|((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3})|:))|(([0-9A-Fa-f]{1,4}:){5}(((:[0-9A-Fa-f]{1,4}){1,2})|:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3})|:))|(([0-9A-Fa-f]{1,4}:){4}(((:[0-9A-Fa-f]{1,4}){1,3})|((:[0-9A-Fa-f]{1,4})?:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){3}(((:[0-9A-Fa-f]{1,4}){1,4})|((:[0-9A-Fa-f]{1,4}){0,2}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){2}(((:[0-9A-Fa-f]{1,4}){1,5})|((:[0-9A-Fa-f]{1,4}){0,3}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){1}(((:[0-9A-Fa-f]{1,4}){1,6})|((:[0-9A-Fa-f]{1,4}){0,4}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(:(((:[0-9A-Fa-f]{1,4}){1,7})|((:[0-9A-Fa-f]{1,4}){0,5}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:)))(%.+)?$' hostname_is_ip_address = re.match(ipv4_regex, hostname) or re.match(ipv6_regex, hostname) headers = rhnFlags.get('outputTransportOptions') if len(token) < 5: # Bad auth information; decline any action log_debug(4, "incomplete proxy authentication token: %s" % auth_token) headers['X-RHN-Proxy-Auth-Error'] = '%s:%s' % ( 1003, _("incomplete proxy authentication token: %s") % auth_token) if not hostname_is_ip_address: headers['X-RHN-Proxy-Auth-Origin'] = hostname raise rhnFault(1003) # Invalid session key log_debug(5, "proxy auth token: %s, hostname: %s" % (repr(token), hostname or 'n/a')) proxyId, proxyUser, rhnServerTime, expireOffset, signature = token[:5] computed = computeSignature(CFG.SECRET_KEY, proxyId, proxyUser, rhnServerTime, expireOffset) if computed != signature: log_error("Proxy signature failed: proxy id='%s', proxy user='******'" % (proxyId, proxyUser)) log_debug(4, "Sent proxy signature %s does not match ours %s." % ( signature, computed)) headers['X-RHN-Proxy-Auth-Error'] = '%s:%s' % ( 1003, _("Sent proxy signature %s does not match ours %s.") % ( signature, computed)) if not hostname_is_ip_address: headers['X-RHN-Proxy-Auth-Origin'] = hostname raise rhnFault(1003) # Invalid session key # Convert the expiration/time to floats: rhnServerTime = float(rhnServerTime) expireOffset = float(expireOffset) if rhnServerTime + expireOffset < time.time(): log_debug(4, "Expired proxy authentication token") headers['X-RHN-Proxy-Auth-Error'] = '%s:%s' % (1004, "Expired") if not hostname_is_ip_address: headers['X-RHN-Proxy-Auth-Origin'] = hostname raise rhnFault(1004) # Expired client authentication token log_debug(4, "Proxy auth OK: sigs match; not an expired token") return 1
def handler(self): """ Main handler for all requests pumped through this server. """ log_debug(4, 'In redirect handler') self._prepHandler() # Rebuild the X-Forwarded-For header so that it reflects the actual # path of the request. We must do this because squid is unable to # determine the "real" client, and will make each entry in the chain # 127.0.0.1. _oto = rhnFlags.get('outputTransportOptions') _oto['X-Forwarded-For'] = _oto['X-RHN-IP-Path'] self.rhnParent = self.rhnParent or '' # paranoid log_debug(4, 'Connecting to parent...') self._connectToParent() # part 1 log_debug(4, 'Initiating communication with server...') status = self._serverCommo() # part 2 if (status != apache.OK) and (status != apache.HTTP_PARTIAL_CONTENT): log_debug(3, "Leaving handler with status code %s" % status) return status log_debug(4, 'Initiating communication with client...') # If we got this far, it has to be a good response return self._clientCommo(status)
def __redirectFailover(self): """ This routine resends the original request back to the satellite/hosted system if a redirect to a 3rd party failed. To prevent redirection loops from occurring, an "X-RHN-Redirect: 0" header is passed along with the request. This function will return apache.HTTP_OK if everything succeeded, otherwise it will return an appropriate HTTP error code. """ # Add a special header which will tell the server not to send us any # more redirects. headers = rhnFlags.get('outputTransportOptions') headers[rhnConstants.HEADER_RHN_REDIRECT] = '0' log_debug(4, "Added X-RHN-Redirect header to outputTransportOptions:", headers) # Reset the existing connection and reconnect to the RHN parent server. self.responseContext.clear() self._connectToParent() # We'll just call serverCommo once more. The X-RHN-Redirect constant # will prevent us from falling into an infinite loop. Only GETs are # redirected, so we can safely pass an empty string in as the request # body. status = self._serverCommo() # This little hack isn't pretty, but lets us normalize our result code. if status == apache.OK: status = apache.HTTP_OK return status
def _proxy2server(self): hdrs = rhnFlags.get('outputTransportOptions') log_debug(3, hdrs) size = -1 # Put the headers into the output connection object http_connection = self.responseContext.getConnection() for (k, vals) in hdrs.items(): if k.lower() in ['content_length', 'content-length']: try: size = int(vals) except ValueError: pass if k.lower() in ['content_length', 'content_type']: # mod_wsgi modifies incoming headers so we have to transform them back k = k.replace('_', '-') if not (k.lower()[:2] == 'x-' or k.lower() in [ # all but 'host', and 'via' 'accept', 'accept-charset', 'accept-encoding', 'accept-language', 'accept-ranges', 'age', 'allow', 'authorization', 'cache-control', 'connection', 'content-encoding', 'content-language', 'content-length', 'content-location', 'content-md5', 'content-range', 'content-type', 'date', 'etag', 'expect', 'expires', 'from', 'if-match', 'if-modified-since', 'if-none-match', 'if-range', 'if-unmodified-since', 'last-modified', 'location', 'max-forwards', 'pragma', 'proxy-authenticate', 'proxy-authorization', 'range', 'referer', 'retry-after', 'server', 'te', 'trailer', 'transfer-encoding', 'upgrade', 'user-agent', 'vary', 'warning', 'www-authenticate']): # filter out header we don't want to send continue if not isinstance(vals, (ListType, TupleType)): vals = [vals] for v in vals: log_debug(5, "Outgoing header", k, v) http_connection.putheader(k, v) http_connection.endheaders() # Send the body too if there is a body if size > 0: # reset file to beginning so it can be read again self.req.headers_in['wsgi.input'].seek(0, 0) if sys.version_info < (2, 6): data = self.req.headers_in['wsgi.input'].read(size) else: data = self.req.headers_in['wsgi.input'] http_connection.send(data) # At this point everything is sent to the server # We now wait for the response try: response = http_connection.getresponse() except TimeoutException: log_error("Connection timed out") return apache.HTTP_GATEWAY_TIME_OUT, None, None headers = response.msg status = response.status # Get the body of the request too - well, just a fd actually # in this case, the response object itself. bodyFd = response return status, headers, bodyFd
def _wrapper(self, req, function_name): #log_debug(1, "_wrapper", req, function_name) if not hasattr(self.server, function_name): log_error("%s doesn't have a %s function" % (self.server, function_name)) return apache.HTTP_NOT_FOUND function = getattr(self.server, function_name) try: log_debug(5, "Calling", function) ret = function(req) except rhnFault: e = sys.exc_info()[1] log_debug(4, "rhnFault caught: %s" % (e, )) error_string = self._exception_to_text(e) error_code = e.code self._error_to_headers(req.err_headers_out, error_code, error_string) ret = rhnFlags.get("apache-return-code") if not ret: ret = apache.HTTP_INTERNAL_SERVER_ERROR req.status = ret log_debug(4, "_wrapper %s exited with apache code %s" % (function_name, ret)) except rhnSession.ExpiredSessionError: e = sys.exc_info()[1] # if session expires we catch here and return a forbidden # abd make it re-authenticate log_debug(4, "Expire Session Error Caught: %s" % (e, )) return 403 except: Traceback("server.apacheUploadServer._wrapper", req=req) log_error("Unhandled exception") return apache.HTTP_INTERNAL_SERVER_ERROR return ret
def getPackageErratum(self, system_id, pkg): """ Clients v2+ - Get errata for a package given [n,v,r,e,a,...] format Sing-along: You say erratum(sing), I say errata(pl)! :) IN: pkg: [n,v,r,e,s,a,ch,...] RET: a hash by errata that applies to this package """ log_debug(5, system_id, pkg) if type(pkg) != type([]) or len(pkg) < 7: log_error("Got invalid package specification: %s" % str(pkg)) raise rhnFault(30, _("Expected a package, not: %s") % pkg) # Authenticate and decode server id. self.auth_system(system_id) # log the entry log_debug(1, self.server_id, pkg) # Stuff the action in the headers: transport = rhnFlags.get("outputTransportOptions") transport["X-RHN-Action"] = "getPackageErratum" name, ver, rel, epoch, arch, size, channel = pkg[:7] if epoch in ["", "none", "None"]: epoch = None # XXX: also, should arch/size/channel ever be used? # bug#186996:adding synopsis field to errata info # client side changes are needed to access this data. h = rhnSQL.prepare( """ select distinct e.id errata_id, e.advisory_type errata_type, e.advisory advisory, e.topic topic, e.description description, e.synopsis synopsis from rhnServerChannel sc, rhnChannelPackage cp, rhnChannelErrata ce, rhnErrata e, rhnErrataPackage ep, rhnPackage p where p.name_id = LOOKUP_PACKAGE_NAME(:name) and p.evr_id = LOOKUP_EVR(:epoch, :ver, :rel) -- map to a channel and p.id = cp.package_id -- map to an errata as well and p.id = ep.package_id and ep.errata_id = e.id -- the errata and the channel have to be linked and e.id = ce.errata_id and ce.channel_id = cp.channel_id -- and the server has to be subscribed to the channel and cp.channel_id = sc.channel_id and sc.server_id = :server_id """ ) # " emacs sucks h.execute(name=name, ver=ver, rel=rel, epoch=epoch, server_id=str(self.server_id)) return self._sanitize_result(h)
def _set_server_capabilities(): # XXX Will have to figure out how to define this capabilities = { 'registration.register_osad' : {'version' : 1, 'value' : 1}, 'registration.finish_message' : {'version' : 1, 'value' : 1}, 'registration.remaining_subscriptions' : {'version' : 1, 'value' : 1}, 'registration.update_contact_info' : {'version' : 1, 'value' : 1}, 'registration.delta_packages' : {'version' : 1, 'value' : 1}, 'registration.extended_update_support' : {'version' : 1, 'value' : 1}, 'registration.smbios' : {'version' : 1, 'value' : 1}, 'registration.update_systemid' : {'version' : 1, 'value' : 1}, 'applet.has_base_channel' : {'version' : 1, 'value' : 1}, 'xmlrpc.login.extra_data' : {'version' : 1, 'value' : 1}, 'rhncfg.content.base64_decode' : {'version' : 1, 'value' : 1}, 'rhncfg.filetype.directory' : {'version' : 1, 'value' : 1}, 'xmlrpc.packages.extended_profile' : {'version' : '1-2', 'value' : 1}, 'xmlrpc.packages.checksums' : {'version' : 1, 'value' : 1}, 'xmlrpc.errata.patch_names' : {'version' : 1, 'value' : 1}, 'staging_content' : {'version' : 1, 'value' : 1}, 'ipv6' : {'version' : 1, 'value' : 1}, 'abrt' : {'version' : 1, 'value' : 1}, 'cpu_sockets' : {'version' : 1, 'value' : 1}, } l = [] for name, hashval in capabilities.items(): l.append("%s(%s)=%s" % (name, hashval['version'], hashval['value'])) log_debug(4, "Setting capabilities", l) rhnFlags.get("outputTransportOptions")['X-RHN-Server-Capability'] = l
def process_kickstart_info(self): log_debug(4) tokens_obj = rhnFlags.get("registration_token") if not tokens_obj: log_debug(4, "no registration token found") # Nothing to do here return # If there are kickstart sessions associated with this system (other # than, possibly, the current one), mark them as failed history = server_kickstart.terminate_kickstart_sessions(self.getid()) for k, v in history: self.add_history(k, v) kickstart_session_id = tokens_obj.get_kickstart_session_id() if kickstart_session_id is None: log_debug( 4, "No kickstart_session_id associated with token %s (%s)" % (tokens_obj.get_names(), tokens_obj.tokens) ) # Nothing to do here return # Flush server actions self.flush_actions() server_id = self.getid() action_id = server_kickstart.schedule_kickstart_sync(server_id, kickstart_session_id) server_kickstart.subscribe_to_tools_channel(server_id, kickstart_session_id) server_kickstart.schedule_virt_pkg_install(server_id, kickstart_session_id) # Update the next action to the newly inserted one server_kickstart.update_ks_session_table(kickstart_session_id, "registered", action_id, server_id)
def load_token(self): # Fetch token tokens_obj = rhnFlags.get("registration_token") if not tokens_obj: # No tokens present return 0 # make sure we have reserved a server_id. most likely if this # is a new server object (just created from # registration.new_system) then we have no associated a # server["id"] yet -- and getid() will reserve that for us. self.getid() # pull in the extra information needed to fill in the # required registration fields using tokens user_id = tokens_obj.get_user_id() org_id = tokens_obj.get_org_id() self.user = rhnUser.User("", "") if user_id is not None: self.user.reload(user_id) self.server["creator_id"] = user_id self.server["org_id"] = org_id self.server["contact_method_id"] = tokens_obj.get_contact_method_id() return 0
def reboot(server_id, action_id, data={}): log_debug(3, action_id) action_status = rhnFlags.get('action_status') server_kickstart.update_kickstart_session(server_id, action_id, action_status, kickstart_state='restarted', next_action_type=None)
def getPackagePath(self, pkgFilename, redirect_capable=0): """ Retrieves package path Overloads getPackagePath in common/rhnRepository. checks if redirect and hosted; makes a call to query the db for pkg_location """ log_debug(2, pkgFilename, redirect_capable) # check for re-direct check flag from header to issue package # request from client in order to avoid failover loops. skip_redirect = rhnFlags.get('x-rhn-redirect') log_debug(3, "check flag for X-RHN-REDIRECT ::", skip_redirect) # get the redirect and local paths remotepath, localpath = self.getAllPackagePaths(pkgFilename) # check for redirect conditions and fail over checks if redirect_capable and not CFG.SATELLITE and not skip_redirect \ and remotepath is not None: self.redirect_location = remotepath # We've set self.redirect_location, we're done here # we throw a redirectException in _getFile method. return None # Package cannot be served from the edge, we serve it ourselves return localpath
def _proxy2server(self): hdrs = rhnFlags.get('outputTransportOptions') log_debug(3, hdrs) size = -1 # Put the headers into the output connection object http_connection = self.responseContext.getConnection() for (k, vals) in hdrs.items(): if k.lower() in ['content_length', 'content-length']: try: size = int(vals) except ValueError: pass if k.lower() in ['content_length', 'content_type']: # mod_wsgi modifies incoming headers so we have to transform them back k = k.replace('_', '-') if not (k.lower()[:2] == 'x-' or k.lower() in [ # all but 'host', and 'via' 'accept', 'accept-charset', 'accept-encoding', 'accept-language', 'accept-ranges', 'age', 'allow', 'authorization', 'cache-control', 'connection', 'content-encoding', 'content-language', 'content-length', 'content-location', 'content-md5', 'content-range', 'content-type', 'date', 'etag', 'expect', 'expires', 'from', 'if-match', 'if-modified-since', 'if-none-match', 'if-range', 'if-unmodified-since', 'last-modified', 'location', 'max-forwards', 'pragma', 'proxy-authenticate', 'proxy-authorization', 'range', 'referer', 'retry-after', 'server', 'te', 'trailer', 'transfer-encoding', 'upgrade', 'user-agent', 'vary', 'warning', 'www-authenticate']): # filter out header we don't want to send continue if type(vals) not in (ListType, TupleType): vals = [vals] for v in vals: log_debug(5, "Outgoing header", k, v) http_connection.putheader(k, v) http_connection.endheaders() # Send the body too if there is a body if size > 0: # reset file to beginning so it can be read again self.req.headers_in['wsgi.input'].seek(0, 0) if sys.version_info < (2, 6): data = self.req.headers_in['wsgi.input'].read(size) else: data = self.req.headers_in['wsgi.input'] http_connection.send(data) # At this point everything is sent to the server # We now wait for the response try: response = http_connection.getresponse() except TimeoutException: log_error("Connection timed out") return apache.HTTP_GATEWAY_TIME_OUT, None, None headers = response.msg status = response.status # Get the body of the request too - well, just a fd actually # in this case, the response object itself. bodyFd = response return status, headers, bodyFd
def getxml(self): # see if there were any template strings loaded from the db, # {label:value} templateOverrides = rhnFlags.get('templateOverrides') # update the templateValues in the module if templateOverrides: for label in templateOverrides.keys(): # only care about values we've defined defaults for... if label in templateValues: templateValues[label] = templateOverrides[label] s = StringIO() s.write("\n") if self.text: s.write(_("Error Message:\n %s\n") % self.text.strip()) if self.code: s.write(_("Error Class Code: %s\n") % self.code) if self.arrayText: cinfo = self.arrayText % templateValues s.write(_("Error Class Info: %s\n") % cinfo.rstrip()) if self.explain: s.write(_("Explanation: %s") % Explain) if not self.code: return xmlrpclib.Fault(1, s.getvalue()) return xmlrpclib.Fault(-self.code, s.getvalue())
def listChannels(self, system_id): """ Clients v2+ """ log_debug(5, system_id) # Authenticate the system certificate self.auth_system('listChannels', system_id) # log the entry log_debug(1, self.server_id) channelList = rhnChannel.channels_for_server(self.server_id) loginDict = { 'X-RHN-Server-Id': self.server_id, 'X-RHN-Auth-Channels': rhnChannel.getSubscribedChannels(self.server_id), } # Duplicate these values in the headers so that the proxy can # intercept and cache them without parseing the xmlrpc. transport = rhnFlags.get('outputTransportOptions') for k, v in list(loginDict.items()): # Special case for channels if k.lower() == 'x-rhn-auth-channels'.lower(): # Concatenate the channel information column-separated transport[k] = [':'.join(x) for x in v] else: transport[k] = v return channelList
def update(server_id, action_id, data={}): log_debug(3, server_id, action_id) action_status = rhnFlags.get('action_status') if action_status == 3: # Action failed kickstart_state = 'failed' next_action_type = None else: kickstart_state = 'deployed' #This is horrendous, but in order to fix it I would have to change almost all of the #actions code, which we don't have time to do for the 500 beta. --wregglej try: ks_session_type = server_kickstart.get_kickstart_session_type(server_id, action_id) except rhnException, re: ks_session_type = None if ks_session_type is None: next_action_type = "None" elif ks_session_type == 'para_guest': next_action_type = 'kickstart_guest.initiate' else: next_action_type = 'kickstart.initiate'
def initiate(server_id, action_id, data={}): log_debug(3, action_id) action_status = rhnFlags.get('action_status') server_kickstart.update_kickstart_session(server_id, action_id, action_status, kickstart_state='injected', next_action_type='reboot.reboot')
def _wrapper(self, req, function_name): #log_debug(1, "_wrapper", req, function_name) if not hasattr(self.server, function_name): log_error("%s doesn't have a %s function" % (self.server, function_name)) return apache.HTTP_NOT_FOUND function = getattr(self.server, function_name) try: log_debug(5, "Calling", function) ret = function(req) except rhnFault: e = sys.exc_info()[1] log_debug(4, "rhnFault caught: %s" % (e, )) error_string = self._exception_to_text(e) error_code = e.code self._error_to_headers(req.err_headers_out, error_code, error_string) ret = rhnFlags.get("apache-return-code") if not ret: ret = apache.HTTP_INTERNAL_SERVER_ERROR req.status = ret log_debug( 4, "_wrapper %s exited with apache code %s" % (function_name, ret)) except rhnSession.ExpiredSessionError: e = sys.exc_info()[1] # if session expires we catch here and return a forbidden # abd make it re-authenticate log_debug(4, "Expire Session Error Caught: %s" % (e, )) return 403 except: Traceback("server.apacheUploadServer._wrapper", req=req) log_error("Unhandled exception") return apache.HTTP_INTERNAL_SERVER_ERROR return ret
def _set_server_capabilities(): # XXX Will have to figure out how to define this capabilities = { "registration.register_osad": {"version": 1, "value": 1}, "registration.finish_message": {"version": 1, "value": 1}, "registration.remaining_subscriptions": {"version": 1, "value": 1}, "registration.update_contact_info": {"version": 1, "value": 1}, "registration.delta_packages": {"version": 1, "value": 1}, "registration.extended_update_support": {"version": 1, "value": 1}, "registration.smbios": {"version": 1, "value": 1}, "registration.update_systemid": {"version": 1, "value": 1}, "applet.has_base_channel": {"version": 1, "value": 1}, "xmlrpc.login.extra_data": {"version": 1, "value": 1}, "rhncfg.content.base64_decode": {"version": 1, "value": 1}, "rhncfg.filetype.directory": {"version": 1, "value": 1}, "xmlrpc.packages.extended_profile": {"version": "1-2", "value": 1}, "xmlrpc.packages.checksums": {"version": 1, "value": 1}, "xmlrpc.errata.patch_names": {"version": 1, "value": 1}, "staging_content": {"version": 1, "value": 1}, "ipv6": {"version": 1, "value": 1}, "abrt": {"version": 1, "value": 1}, "cpu_sockets": {"version": 1, "value": 1}, } l = [] for name, hashval in capabilities.items(): l.append("%s(%s)=%s" % (name, hashval["version"], hashval["value"])) log_debug(4, "Setting capabilities", l) rhnFlags.get("outputTransportOptions")["X-RHN-Server-Capability"] = l
def response(self, response): # Send the xml-rpc response back log_debug(3, type(response)) needs_xmlrpc_encoding = not rhnFlags.test("XMLRPC-Encoded-Response") compress_response = rhnFlags.test("compress_response") # Init an output object; we'll use it for sending data in various # formats if isinstance(response, transports.File): if not hasattr(response.file_obj, 'fileno') and compress_response: # This is a StringIO that has to be compressed, so read it in # memory; mark that we don't have to do any xmlrpc encoding response = response.file_obj.read() needs_xmlrpc_encoding = 0 else: # Just treat is as a file return self.response_file(response) output = transports.Output() # First, use the same encoding/transfer that the client used output.set_transport_flags( transfer=transports.lookupTransfer(self.input.transfer), encoding=transports.lookupEncoding(self.input.encoding)) if isinstance(response, xmlrpclib.Fault): log_debug(4, "Return FAULT", response.faultCode, response.faultString) # No compression for faults because we'd like them to pop # up in clear text on the other side just in case output.set_transport_flags(output.TRANSFER_NONE, output.ENCODE_NONE) elif compress_response: # check if we have to compress this result log_debug(4, "Compression on for client version", self.client) if self.client > 0: output.set_transport_flags(output.TRANSFER_BINARY, output.ENCODE_ZLIB) else: # original clients had the binary transport support broken output.set_transport_flags(output.TRANSFER_BASE64, output.ENCODE_ZLIB) # We simply add the transport options to the output headers output.headers.update(rhnFlags.get('outputTransportOptions').dict()) if needs_xmlrpc_encoding: # Normalize the response response = self.normalize(response) try: response = xmlrpclib.dumps(response, methodresponse=1) except TypeError, e: log_debug( 4, "Error \"%s\" encoding response = %s" % (e, response)) Traceback("apacheHandler.response", self.req, extra="Error \"%s\" encoding response = %s" % (e, response), severity="notification") return apache.HTTP_INTERNAL_SERVER_ERROR except:
def GetByPackage(self, pkg, osRel): """ Clients v1- Get errata for a package given "n-v-r" format IN: pkg: "n-v-r" (old client call) or [n,v,r] osRel: OS release RET: a hash by errata that applies to this package (ie, newer packages are available). We also limit the scope for a particular osRel. """ if type(pkg) == type(''): # Old client support. pkg = parseRPMName(pkg) log_debug(1, pkg, osRel) # Stuff the action in the headers: transport = rhnFlags.get('outputTransportOptions') transport['X-RHN-Action'] = 'GetByPackage' # now look up the errata if type(pkg[0]) != type(''): log_error("Invalid package name: %s %s" % (type(pkg[0]), pkg[0])) raise rhnFault(30, _("Expected a package name, not: %s") % pkg[0]) # bug#186996:adding synopsis field to advisory info # client side changes are needed to access this data. h = rhnSQL.prepare(""" select distinct e.id errata_id, e.advisory_type errata_type, e.advisory advisory, e.topic topic, e.description description, e.synopsis synopsis from rhnErrata e, rhnPublicChannelFamily pcf, rhnChannelFamilyMembers cfm, rhnErrataPackage ep, rhnChannelPackage cp, rhnChannelErrata ce, rhnDistChannelMap dcm, rhnPackage p where 1=1 and p.name_id = LOOKUP_PACKAGE_NAME(:name) -- map to a channel and p.id = cp.package_id and cp.channel_id = dcm.channel_id and dcm.release = :dist and dcm.org_id is null -- map to an errata as well and p.id = ep.package_id and ep.errata_id = e.id -- the errata and the channel have to be linked and ce.channel_id = cp.channel_id -- and the channel has to be public and cp.channel_id = cfm.channel_id and cfm.channel_family_id = pcf.channel_family_id -- and get the erratum and e.id = ce.errata_id """) h.execute(name=pkg[0], dist=str(osRel)) return self._sanitize_result(h)
def getPackageErratum(self, system_id, pkg): """ Clients v2+ - Get errata for a package given [n,v,r,e,a,...] format Sing-along: You say erratum(sing), I say errata(pl)! :) IN: pkg: [n,v,r,e,s,a,ch,...] RET: a hash by errata that applies to this package """ log_debug(5, system_id, pkg) if type(pkg) != type([]) or len(pkg) < 7: log_error("Got invalid package specification: %s" % str(pkg)) raise rhnFault(30, _("Expected a package, not: %s") % pkg) # Authenticate and decode server id. self.auth_system(system_id) # log the entry log_debug(1, self.server_id, pkg) # Stuff the action in the headers: transport = rhnFlags.get('outputTransportOptions') transport['X-RHN-Action'] = 'getPackageErratum' name, ver, rel, epoch, arch, size, channel = pkg[:7] if epoch in ['', 'none', 'None']: epoch = None # XXX: also, should arch/size/channel ever be used? # bug#186996:adding synopsis field to errata info # client side changes are needed to access this data. h = rhnSQL.prepare(""" select distinct e.id errata_id, e.advisory_type errata_type, e.advisory advisory, e.topic topic, e.description description, e.synopsis synopsis from rhnServerChannel sc, rhnChannelPackage cp, rhnChannelErrata ce, rhnErrata e, rhnErrataPackage ep, rhnPackage p where p.name_id = LOOKUP_PACKAGE_NAME(:name) and p.evr_id = LOOKUP_EVR(:epoch, :ver, :rel) -- map to a channel and p.id = cp.package_id -- map to an errata as well and p.id = ep.package_id and ep.errata_id = e.id -- the errata and the channel have to be linked and e.id = ce.errata_id and ce.channel_id = cp.channel_id -- and the server has to be subscribed to the channel and cp.channel_id = sc.channel_id and sc.server_id = :server_id """) # " emacs sucks h.execute(name=name, ver=ver, rel=rel, epoch=epoch, server_id=str(self.server_id)) return self._sanitize_result(h)
def __init__(self): # We store the security list in the global flags. This way, we don't # have to worry about clearing it up. if rhnFlags.test(self._flag_string): self.sec = rhnFlags.get(self._flag_string) else: self.sec = [] rhnFlags.set(self._flag_string, self.sec)
def deploy(server_id, action_id, data={}): log_debug(3) action_status = rhnFlags.get('action_status') server_kickstart.update_kickstart_session(server_id, action_id, action_status, kickstart_state='complete', next_action_type=None) return
def _prepHandler(self): """ Handler part 0 """ # Just to be on the safe side if self.req.main: # A subrequest return apache.DECLINE log_debug(4, rhnFlags.all()) if not self.rhnParent: raise rhnException("Oops, no proxy parent! Exiting") # Copy the headers. rhnFlags.get('outputTransportOptions').clear() rhnFlags.get('outputTransportOptions').update(self._getHeaders(self.req)) return apache.OK
def _prepHandler(self): """ Handler part 0 """ # Just to be on the safe side if self.req.main: # A subrequest return apache.DECLINED log_debug(4, rhnFlags.all()) if not self.rhnParent: raise rhnException("Oops, no proxy parent! Exiting") # Copy the headers. rhnFlags.get('outputTransportOptions').clear() rhnFlags.get('outputTransportOptions').update(self._getHeaders(self.req)) return apache.OK
def response_file(req, response): """ send a file out """ log_debug(1, response.name) # We may set the content type remotely if rhnFlags.test("Content-Type"): req.content_type = rhnFlags.get("Content-Type") else: # Safe default req.content_type = "application/octet-stream" # find out the size of the file if response.length == 0: response.file_obj.seek(0, 2) size = response.file_obj.tell() response.file_obj.seek(0, 0) else: size = response.length req.headers_out["Content-Length"] = str(size) # if we loaded this from a real fd, set it as the X-Replace-Content # check for "name" since sometimes we get xmlrpclib.File's that have # a stringIO as the file_obj, and they dont have a .name (ie, # fileLists...) if response.name: req.headers_out["X-Package-FileName"] = response.name # yum can request for HTTP_PARTIAL_CONTENT content if req.headers_in.has_key('Range'): (start, end) = parse_byteranges(req.headers_in['Range'], size) req.headers_out["Accept-Ranges"] = "bytes" req.headers_out["Content-Range"] = get_content_range( start, end, size) size = end - start + 1 response.file_obj.seek(start, 0) status = apache.HTTP_PARTIAL_CONTENT else: start = 0 end = size status = apache.OK # send the headers req.send_http_header() # and the file buffer_size = CFG.BUFFER_SIZE while 1: if buffer_size > size: buffer_size = size buf = response.read(buffer_size) size = size - buffer_size if not buf: break try: req.write(buf) except IOError: return apache.HTTP_BAD_REQUEST response.close() return status
def response_file(req, response): """ send a file out """ log_debug(1, response.name) # We may set the content type remotely if rhnFlags.test("Content-Type"): req.content_type = rhnFlags.get("Content-Type") else: # Safe default req.content_type = "application/octet-stream" # find out the size of the file if response.length == 0: response.file_obj.seek(0, 2) size = response.file_obj.tell() response.file_obj.seek(0, 0) else: size = response.length req.headers_out["Content-Length"] = str(size) # if we loaded this from a real fd, set it as the X-Replace-Content # check for "name" since sometimes we get xmlrpclib.File's that have # a stringIO as the file_obj, and they dont have a .name (ie, # fileLists...) if response.name: req.headers_out["X-Package-FileName"] = response.name # yum can request for HTTP_PARTIAL_CONTENT content if req.headers_in.has_key('Range'): (start, end)=parse_byteranges(req.headers_in['Range'], size) req.headers_out["Accept-Ranges"] = "bytes" req.headers_out["Content-Range"] = get_content_range(start, end, size) size = end - start + 1 response.file_obj.seek(start, 0) status = apache.HTTP_PARTIAL_CONTENT else: start = 0 end = size status = apache.OK # send the headers req.send_http_header() # and the file buffer_size = CFG.BUFFER_SIZE while 1: if buffer_size > size: buffer_size = size buf = response.read(buffer_size) size = size - buffer_size if not buf: break try: req.write(buf) except IOError: return apache.HTTP_BAD_REQUEST response.close() return status
def response(self, response): # Send the xml-rpc response back log_debug(3, type(response)) needs_xmlrpc_encoding = not rhnFlags.test("XMLRPC-Encoded-Response") compress_response = rhnFlags.test("compress_response") # Init an output object; we'll use it for sending data in various # formats if isinstance(response, transports.File): if not hasattr(response.file_obj, "fileno") and compress_response: # This is a StringIO that has to be compressed, so read it in # memory; mark that we don't have to do any xmlrpc encoding response = response.file_obj.read() needs_xmlrpc_encoding = 0 else: # Just treat is as a file return self.response_file(response) output = transports.Output() # First, use the same encoding/transfer that the client used output.set_transport_flags( transfer=transports.lookupTransfer(self.input.transfer), encoding=transports.lookupEncoding(self.input.encoding), ) if isinstance(response, xmlrpclib.Fault): log_debug(4, "Return FAULT", response.faultCode, response.faultString) # No compression for faults because we'd like them to pop # up in clear text on the other side just in case output.set_transport_flags(output.TRANSFER_NONE, output.ENCODE_NONE) elif compress_response: # check if we have to compress this result log_debug(4, "Compression on for client version", self.client) if self.client > 0: output.set_transport_flags(output.TRANSFER_BINARY, output.ENCODE_ZLIB) else: # original clients had the binary transport support broken output.set_transport_flags(output.TRANSFER_BASE64, output.ENCODE_ZLIB) # We simply add the transport options to the output headers output.headers.update(rhnFlags.get("outputTransportOptions").dict()) if needs_xmlrpc_encoding: # Normalize the response response = self.normalize(response) try: response = xmlrpclib.dumps(response, methodresponse=1) except TypeError, e: log_debug(4, 'Error "%s" encoding response = %s' % (e, response)) Traceback( "apacheHandler.response", self.req, extra='Error "%s" encoding response = %s' % (e, response), severity="notification", ) return apache.HTTP_INTERNAL_SERVER_ERROR except:
def _response_fault_get(req, response): req.err_headers_out["X-RHN-Fault-Code"] = str(response.faultCode) faultString = base64.encodestring(response.faultString).strip() # Split the faultString into multiple lines for line in faultString.split('\n'): req.err_headers_out.add("X-RHN-Fault-String", line.strip()) # And then send all the other things for k, v in rhnFlags.get('outputTransportOptions').items(): setHeaderValue(req.err_headers_out, k, v) return apache.HTTP_NOT_FOUND
def _response_fault_get(req, response): req.headers_out["X-RHN-Fault-Code"] = str(response.faultCode) faultString = base64.encodestring(response.faultString).strip() # Split the faultString into multiple lines for line in faultString.split('\n'): req.headers_out.add("X-RHN-Fault-String", line.strip()) # And then send all the other things for k, v in rhnFlags.get('outputTransportOptions').items(): setHeaderValue(req.headers_out, k, v) return apache.HTTP_NOT_FOUND
def __checkLegalRedirect(self): """ Check request to see if this coming from a RHN Proxy. THIS SHOULD NEVER FAIL!!! Probably not necessary, but stymies the casual abuser. """ if not rhnFlags.get('outputTransportOptions').has_key('X-RHN-Proxy-Version'): log_debug(-1, 'THIS SHOULD NEVER HAPPEN!!!') raise rhnFault(1000, _("RHN Proxy Error: No SSL Redirect Request found!"))
def terminate_kickstart_sessions(server_id): log_debug(3, server_id) history = [] tokens_obj = rhnFlags.get('registration_token') current_ks_session_id = tokens_obj.get_kickstart_session_id() # ks_session_id can be null h = rhnSQL.prepare(_query_lookup_pending_kickstart_sessions) h.execute(server_id=server_id, ks_session_id=current_ks_session_id) log_debug(4, "current_ks_session_id", current_ks_session_id) ks_session_ids = [] action_ids = [] while 1: row = h.fetchone_dict() if not row: break ks_session_ids.append(row['id']) action_ids.append(row['action_id']) if not ks_session_ids: # Nothing to do log_debug(4, "Nothing to do", server_id, current_ks_session_id) return [] ks_session_table = rhnSQL.Table('rhnKickstartSessionState', 'label') state_id_failed = ks_session_table['failed']['id'] state_ids = [state_id_failed] * len(ks_session_ids) # Add a history item for ks_session_id in ks_session_ids: log_debug(4, "Adding history entry for session id", ks_session_id) history.append( ("Kickstart session canceled", "A kickstart session for this system was canceled because " "the system was re-registered with token <strong>%s</strong>" % tokens_obj.get_names())) h = rhnSQL.prepare(_query_terminate_pending_kickstart_sessions) params = { 'kickstart_session_id': ks_session_ids, 'state_id': state_ids, } # Terminate pending actions log_debug(4, "Terminating sessions", params) h.execute_bulk(params) # Invalidate pending actions for action_id in action_ids: if action_id is None: continue rhnAction.invalidate_action(server_id, action_id) return history
def login(self, system_id, extra_data={}): """ Clients v2+ Log in routine. Return a dictionary of session token/channel information. Also sets this information in the headers. """ log_debug(5, system_id) # Authenticate the system certificate. We need the user record # to generate the tokens self.load_user = 1 server = self.auth_system('login', system_id) # log the entry log_debug(1, self.server_id) # Update the capabilities list rhnCapability.update_client_capabilities(self.server_id) # Fetch the channels this client is subscribed to channels = rhnChannel.getSubscribedChannels(self.server_id) rhnServerTime = str(time.time()) expireOffset = str(CFG.CLIENT_AUTH_TIMEOUT) signature = computeSignature(CFG.SECRET_KEY, self.server_id, self.user, rhnServerTime, expireOffset) loginDict = { 'X-RHN-Server-Id': self.server_id, 'X-RHN-Auth-User-Id': self.user, 'X-RHN-Auth': signature, 'X-RHN-Auth-Server-Time': rhnServerTime, 'X-RHN-Auth-Expire-Offset': expireOffset, # List of lists [[label,last_mod],...]: 'X-RHN-Auth-Channels': channels } # Duplicate these values in the headers so that the proxy can # intercept and cache them without parseing the xmlrpc. transport = rhnFlags.get('outputTransportOptions') for k, v in loginDict.items(): # Special case for channels if string.lower(k) == string.lower('X-RHN-Auth-Channels'): # Concatenate the channel information column-separated transport[k] = [string.join(x, ':') for x in v] else: transport[k] = v log_debug(5, "loginDict", loginDict, transport) # store route in DB (schema for RHN 3.1+ only!) server_route.store_client_route(self.server_id) return loginDict
def response(self, response): log_debug(3) # pkilambi:if redirectException caught returns path(<str>) if isinstance(response, str): method, params = self._get_method_params() if method == "getPackage": return self.redirect(self.req, response) # GET requests resulting in a Fault receive special treatment # since we have to stick the error message in the HTTP header, # and to return an Apache error code if isinstance(response, xmlrpclib.Fault): log_debug(4, "Return FAULT", response.faultCode, response.faultString) retcode = apache.HTTP_NOT_FOUND if abs(response.faultCode) in (33, 34, 35, 37, 39, 41): retcode = apache.HTTP_UNAUTHORIZED self.req.headers_out["X-RHN-Fault-Code"] = \ str(response.faultCode) faultString = string.strip(base64.encodestring( response.faultString)) # Split the faultString into multiple lines for line in string.split(faultString, '\n'): self.req.headers_out.add("X-RHN-Fault-String", string.strip(line)) # And then send all the other things for k, v in rhnFlags.get('outputTransportOptions').items(): setHeaderValue(self.req.headers_out, k, v) return retcode # Otherwise we're pretty much fine with the standard response # handler # Copy the fields from the transport options, if necessary for k, v in rhnFlags.get('outputTransportOptions').items(): setHeaderValue(self.req.headers_out, k, v) # and jump into the base handler return apacheRequest.response(self, response)
def runTransaction(server_id, action_id, data={}): log_debug(3, action_id) # If it's a kickstart-related transaction, mark the kickstart session as # completed action_status = rhnFlags.get('action_status') ks_session_id = _next_kickstart_step(server_id, action_id, action_status) # Cleanup package profile server_kickstart.cleanup_profile(server_id, action_id, ks_session_id, action_status) _mark_dep_failures(server_id, action_id, data)
def diff(server_id, action_id, data={}): log_debug(3) if not data: # Nothing to do here return status = rhnFlags.get('action_status') if status == 2: # Completed _reset_diff_errors(server_id, action_id) missing_files = data.get('missing_files') or [] _mark_missing_diff_files(server_id, action_id, missing_files) diffs = data.get('diffs') or {} _process_diffs(server_id, action_id, diffs)
def _set_proxy_info(self, req): """ Spacewalk Proxy stuff. """ proxyVersion = 'X-RHN-Proxy-Version' if proxyVersion in req.headers_in: self.proxyVersion = req.headers_in[proxyVersion] # Make sure the proxy version gets set in the headers. rhnFlags.get('outputTransportOptions')[proxyVersion] = str( self.proxyVersion) # Make sure the proxy auth-token gets set in global flags. if 'X-RHN-Proxy-Auth' in req.headers_in: rhnFlags.set('X-RHN-Proxy-Auth', req.headers_in['X-RHN-Proxy-Auth']) return apache.OK