Package backend :: Package satellite_exporter :: Module satexport
[hide private]
[frames] | no frames]

Source Code for Module backend.satellite_exporter.satexport

  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  # Server-side uploading code 
 16   
 17  import time 
 18  import sys 
 19  try: 
 20      #  python 2 
 21      import xmlrpclib 
 22  except ImportError: 
 23      #  python3 
 24      import xmlrpc.client as xmlrpclib  # pylint: disable=F0401 
 25   
 26  from rhn.connections import idn_puny_to_unicode 
 27   
 28  from spacewalk.common import apache 
 29   
 30  from spacewalk.common.usix import raise_with_tb 
 31  from spacewalk.common import rhnFlags 
 32  from spacewalk.common.rhnLog import log_debug, log_error, log_setreq, initLOG 
 33  from spacewalk.common.rhnConfig import CFG, initCFG 
 34  from spacewalk.common.rhnTranslate import _ 
 35  from spacewalk.common.rhnTB import Traceback 
 36  from spacewalk.common.rhnException import rhnException, rhnFault 
 37  from spacewalk.server import rhnSQL, rhnImport 
 38  from spacewalk.satellite_tools.disk_dumper.dumper import ClosedConnectionError 
 39  from spacewalk.satellite_tools import constants 
40 41 42 -class BaseApacheServer:
43
44 - def __init__(self):
45 # Init log to stderr 46 initLOG() 47 self.start_time = 0 48 self._cleanup()
49
50 - def headerParserHandler(self, req):
51 # pylint: disable=W0201 52 log_setreq(req) 53 self.start_time = time.time() 54 # init configuration options with proper component 55 options = req.get_options() 56 # if we are initializing out of a <Location> handler don't 57 # freak out 58 if "RHNComponentType" not in options: 59 # clearly nothing to do 60 return apache.OK 61 initCFG(options["RHNComponentType"]) 62 initLOG(CFG.LOG_FILE, CFG.DEBUG) 63 # short-circuit everything if sending a system-wide message. 64 if CFG.SEND_MESSAGE_TO_ALL: 65 # Drop the database connection 66 # pylint: disable=W0702 67 try: 68 rhnSQL.closeDB() 69 except: 70 pass 71 72 # Fetch global message being sent to clients if applicable. 73 msg = open(CFG.MESSAGE_TO_ALL).read() 74 log_debug(3, "Sending message to all clients: %s" % msg) 75 return self._send_xmlrpc(req, rhnFault(-1, 76 _("IMPORTANT MESSAGE FOLLOWS:\n%s") % msg, explain=0)) 77 78 rhnSQL.initDB() 79 self.server = options['SERVER'] 80 81 self.server_classes = rhnImport.load("satellite_exporter/handlers") 82 83 if self.server not in self.server_classes: 84 # XXX do something interesting here 85 log_error("Missing server", self.server) 86 return apache.HTTP_NOT_FOUND 87 88 return self._wrapper(req, self._headerParserHandler)
89
90 - def handler(self, req):
91 return self._wrapper(req, self._handler)
92
93 - def cleanupHandler(self, req):
94 self._timer() 95 retval = self._wrapper(req, self._cleanupHandler) 96 self._cleanup() 97 # Reset the logger to stderr 98 initLOG() 99 return retval
100
101 - def _cleanup(self):
102 # pylint: disable=W0201 103 self.server = None 104 self.server_classes = None 105 self.server_instance = {}
106 107 # Virtual functions 108 # pylint: disable=R0201
109 - def _headerParserHandler(self, _req):
110 return apache.OK
111
112 - def _handler(self, _req):
113 return apache.OK
114
115 - def _cleanupHandler(self, _req):
116 return apache.OK
117
118 - def _wrapper(self, req, function):
119 try: 120 ret = function(req) 121 except rhnFault: 122 e = sys.exc_info()[1] 123 return self._send_xmlrpc(req, e) 124 except ClosedConnectionError: 125 # The error code most likely doesn't matter, the client won't see 126 # it anyway 127 return apache.HTTP_NOT_ACCEPTABLE 128 except Exception: # pylint: disable=E0012, W0703 129 Traceback("satexport._wrapper", req=req) 130 return apache.HTTP_INTERNAL_SERVER_ERROR 131 return ret
132
133 - def _send_xmlrpc(self, req, data):
134 log_debug(1) 135 req.content_type = "text/xml" 136 if isinstance(data, rhnFault): 137 data = data.getxml() 138 else: 139 data = (data, ) 140 ret = xmlrpclib.dumps(data, methodresponse=1) 141 req.headers_out['Content-Length'] = str(len(ret)) 142 req.send_http_header() 143 req.write(ret) 144 return apache.OK
145
146 - def _timer(self):
147 if not self.start_time: 148 return 0 149 log_debug(2, "%.2f sec" % (time.time() - self.start_time)) 150 return 0
151
152 153 -class ApacheServer(BaseApacheServer):
154
155 - def __init__(self):
157
158 - def _headerParserHandler(self, req):
159 log_debug(3, "Method", req.method) 160 self._validate_version(req) 161 return apache.OK
162
163 - def _handler(self, req):
164 log_debug(3, "Method", req.method) 165 166 # Read all the request 167 data = req.read() 168 log_debug(7, "Received", data) 169 170 # Decode the data 171 try: 172 params, methodname = xmlrpclib.loads(data) 173 except: 174 raise 175 176 log_debug(5, params, methodname) 177 178 try: 179 f = self.get_function(methodname, req) 180 except FunctionRetrievalError: 181 e = sys.exc_info()[1] 182 Traceback(methodname, req) 183 return self._send_xmlrpc(req, rhnFault(3008, str(e), explain=0)) 184 185 if len(params) < 2: 186 params = [] 187 else: 188 params = params[1:] 189 190 result = f(*params) 191 192 if result: 193 # Error of some sort 194 return self._send_xmlrpc(req, rhnFault(3009)) 195 196 # Presumably the function did all the sending 197 log_debug(4, "Exiting OK") 198 return apache.OK
199 200 # pylint: disable=R0201
201 - def get_function(self, method_name, req):
202 iss_slave_condition = self.auth_system(req) 203 # Get the module name 204 idx = method_name.rfind('.') 205 module_name, function_name = method_name[:idx], method_name[idx + 1:] 206 log_debug(5, module_name, function_name) 207 208 handler_classes = self.server_classes[self.server] 209 if module_name not in handler_classes: 210 raise FunctionRetrievalError("Module %s not found" % module_name) 211 212 mod = handler_classes[module_name](req) 213 mod.set_exportable_orgs(iss_slave_condition) 214 f = mod.get_function(function_name) 215 if f is None: 216 raise FunctionRetrievalError( 217 "Module %s: function %s not found" % 218 (module_name, function_name)) 219 return f
220
221 - def auth_system(self, req):
222 if CFG.DISABLE_ISS: 223 raise rhnFault(2005, _('ISS is disabled on this satellite.')) 224 225 remote_hostname = req.get_remote_host(apache.REMOTE_DOUBLE_REV) 226 row = rhnSQL.fetchone_dict(""" 227 select id, allow_all_orgs 228 from rhnISSSlave 229 where slave = :hostname 230 and enabled = 'Y' 231 """, hostname=idn_puny_to_unicode(remote_hostname)) 232 if not row: 233 raise rhnFault(2004, 234 _('Server "%s" is not enabled for ISS.') 235 % remote_hostname) 236 iss_slave_condition = "select id from web_customer" 237 if not(row['allow_all_orgs'] == 'Y'): 238 iss_slave_condition = "select rhnISSSlaveOrgs.org_id from rhnISSSlaveOrgs where slave_id = %d" % row['id'] 239 return iss_slave_condition
240 241 @staticmethod
242 - def _validate_version(req):
243 server_version = constants.PROTOCOL_VERSION 244 vstr = 'X-RHN-Satellite-XML-Dump-Version' 245 if vstr not in req.headers_in: 246 raise rhnFault(3010, "Missing version string") 247 client_version = req.headers_in[vstr] 248 249 # set the client version through rhnFlags to access later 250 rhnFlags.set('X-RHN-Satellite-XML-Dump-Version', client_version) 251 252 log_debug(1, "Server version", server_version, "Client version", 253 client_version) 254 255 client_ver_arr = str(client_version).split(".") 256 server_ver_arr = str(server_version).split(".") 257 client_major = client_ver_arr[0] 258 server_major = server_ver_arr[0] 259 if len(client_ver_arr) >= 2: 260 client_minor = client_ver_arr[1] 261 else: 262 client_minor = 0 263 264 server_minor = server_ver_arr[1] 265 266 try: 267 client_major = int(client_major) 268 client_minor = int(client_minor) 269 except ValueError: 270 raise_with_tb(rhnFault(3011, "Invalid version string %s" % client_version), sys.exc_info()[2]) 271 272 try: 273 server_major = int(server_major) 274 server_minor = int(server_minor) 275 except ValueError: 276 raise_with_tb(rhnException("Invalid server version string %s" 277 % server_version), sys.exc_info()[2]) 278 279 if client_major != server_major: 280 raise rhnFault(3012, "Client version %s does not match" 281 " server version %s" % (client_version, server_version), 282 explain=0)
283
284 285 -class FunctionRetrievalError(Exception):
286 pass
287 288 289 apache_server = ApacheServer() 290 HeaderParserHandler = apache_server.headerParserHandler 291 Handler = apache_server.handler 292 CleanupHandler = apache_server.cleanupHandler 293