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

Source Code for Module backend.server.apacheHandler

  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 sys 
 17  import os 
 18  import time 
 19  import string 
 20   
 21  from spacewalk.common import apache, rhnApache, rhnTB, rhnFlags 
 22  from spacewalk.common.rhnException import rhnException, rhnFault 
 23  from spacewalk.common.rhnConfig import CFG, initCFG 
 24  from spacewalk.common.rhnLog import log_debug, log_error, initLOG, log_setreq 
 25   
 26  # local module imports 
 27  import rhnSQL 
 28   
 29  from apacheRequest import apacheGET, apachePOST, HandlerNotFoundError 
 30  import rhnCapability 
 31   
 32  # a lame timer function for pretty logs 
 33   
 34   
35 -def timer(last):
36 if not last: 37 return 0 38 log_debug(2, "%.2f sec" % (time.time() - last,)) 39 return 0
40 41
42 -class apacheSession(rhnApache):
43 44 """ a class that extends rhnApache with several support functions used 45 by the main handler class. This class deals with the processing of 46 the request and setup for the real action handled in the 47 apacheHandler class below. """ 48 _lang_catalog = "server"
49 50
51 -class apacheHandler(apacheSession):
52 53 """ main Apache XMLRPC point of entry for the server """ 54
55 - def __init__(self):
56 # First call the inherited constructor: 57 apacheSession.__init__(self) 58 self._req_processor = None
59 60 ### 61 # HANDLERS, in the order which they are called: 62 # headerParserHandler, handler, and cleanupHandler. 63 ### 64
65 - def headerParserHandler(self, req):
66 67 log_setreq(req) 68 # We need to init CFG and Logging 69 options = req.get_options() 70 # if we are initializing out of a <Location> handler don't 71 # freak out 72 if "RHNComponentType" not in options: 73 # clearly nothing to do 74 return apache.OK 75 initCFG(options["RHNComponentType"]) 76 initLOG(CFG.LOG_FILE, CFG.DEBUG) 77 78 """ parse the request, init database and figure out what can we call """ 79 log_debug(2, req.the_request) 80 # call method from inherited class 81 ret = apacheSession.headerParserHandler(self, req) 82 if ret != apache.OK: 83 return ret 84 # make sure we have DB connection 85 if not CFG.SEND_MESSAGE_TO_ALL: 86 try: 87 rhnSQL.initDB() 88 except rhnSQL.SQLConnectError: 89 rhnTB.Traceback(mail=1, req=req, severity="schema") 90 return apache.HTTP_INTERNAL_SERVER_ERROR 91 else: 92 # If in outage mode, close the DB connections 93 rhnSQL.closeDB() 94 95 # Store client capabilities 96 client_cap_header = 'X-RHN-Client-Capability' 97 if client_cap_header in req.headers_in: 98 client_caps = req.headers_in[client_cap_header] 99 client_caps = [_f for _f in list(map(string.strip, string.split(client_caps, ","))) if _f] 100 rhnCapability.set_client_capabilities(client_caps) 101 102 # Enabling the input header flags associated with the redirects/newer clients 103 redirect_support_flags = ['X-RHN-Redirect', 'X-RHN-Transport-Capability'] 104 for flag in redirect_support_flags: 105 if flag in req.headers_in: 106 rhnFlags.set(flag, str(req.headers_in[flag])) 107 108 return apache.OK
109
110 - def _init_request_processor(self, req):
111 log_debug(3) 112 # Override the parent class's behaviour 113 # figure out what kind of request handler we need to instantiate 114 if req.method == "POST": 115 self._req_processor = apachePOST(self.clientVersion, req) 116 return apache.OK 117 if req.method == "GET": 118 try: 119 self._req_processor = apacheGET(self.clientVersion, req) 120 except HandlerNotFoundError: 121 e = sys.exc_info()[1] 122 log_error("Unable to handle GET request for server %s" % 123 (e.args[0], )) 124 return apache.HTTP_METHOD_NOT_ALLOWED 125 token = self._setSessionToken(req.headers_in) 126 if token is None: 127 return apache.HTTP_METHOD_NOT_ALLOWED 128 return apache.OK 129 130 log_error("Method not allowed", req.method) 131 return apache.HTTP_METHOD_NOT_ALLOWED
132
134 """ Clean up the request processor """ 135 self._req_processor = None 136 return apache.OK
137
138 - def handler(self, req):
139 """ main Apache handler """ 140 log_debug(2) 141 ret = apacheSession.handler(self, req) 142 if ret != apache.OK: 143 return ret 144 145 if not CFG.SEND_MESSAGE_TO_ALL: 146 # Need to get any string template overrides here, before any app 147 # code gets executed, as the rhnFault error messages use the 148 # templates 149 # If send_message_to_all, we don't have DB connectivity though 150 h = rhnSQL.prepare("select label, value from rhnTemplateString") 151 h.execute() 152 153 templateStrings = {} 154 while 1: 155 row = h.fetchone_dict() 156 if not row: 157 break 158 159 templateStrings[row['label']] = row['value'] 160 161 if templateStrings: 162 rhnFlags.set('templateOverrides', templateStrings) 163 164 log_debug(4, "template strings: %s" % templateStrings) 165 166 if not CFG.SECRET_KEY: 167 # Secret key not defined, complain loudly 168 try: 169 raise rhnException("Secret key not found!") 170 except: 171 rhnTB.Traceback(mail=1, req=req, severity="schema") 172 req.status = 500 173 req.send_http_header() 174 return apache.OK 175 176 # Try to authenticate the proxy if it this request passed 177 # through a proxy. 178 if self.proxyVersion: 179 try: 180 ret = self._req_processor.auth_proxy() 181 except rhnFault: 182 f = sys.exc_info()[1] 183 return self._req_processor.response(f.getxml()) 184 185 # Decide what to do with the request: try to authenticate the client. 186 # NOTE: only upon GET requests is there Signature information to 187 # authenticate. XMLRPC requests DO NOT use signature 188 # authentication. 189 if req.method == "GET": 190 try: 191 ret = self._req_processor.auth_client() 192 except rhnFault: 193 f = sys.exc_info()[1] 194 return self._req_processor.response(f.getxml()) 195 # be safe rather than sorry 196 if not ret: 197 log_error("Got a GET call, but auth_client declined", 198 req.path_info) 199 return apache.HTTP_METHOD_NOT_ALLOWED 200 201 # Avoid leaving Oracle deadlocks 202 try: 203 ret = self._req_processor.process() 204 rhnSQL.rollback() 205 except: 206 if not CFG.SEND_MESSAGE_TO_ALL: 207 rhnSQL.rollback() 208 raise 209 log_debug(4, "Leave with return value", ret) 210 return ret
211
212 - def cleanupHandler(self, req):
213 """ Clean up stuff before we close down the session when we are called 214 from apacheServer.Cleanup() """ 215 log_debug(2) 216 # kill all of our child processes (if any) 217 while 1: 218 pid = status = -1 219 try: 220 (pid, status) = os.waitpid(-1, 0) 221 except OSError: 222 break 223 else: 224 log_error("Reaped child process %d with status %d" % ( 225 pid, status)) 226 ret = apacheSession.cleanupHandler(self, req) 227 return ret
228