Files
freeipa/ipa_server/test_server
2008-09-30 19:37:35 -06:00

163 lines
5.1 KiB
Python
Executable File

#!/usr/bin/env python
import sys
sys.path.insert(0, "..")
sys.path.insert(0, ".")
import SimpleXMLRPCServer
import logging
import xmlrpclib
import re
import threading
import commands
from ipalib import api
import conn
from ipa_server.servercore import context
import ipalib.load_plugins
import traceback
PORT=8888
class StoppableXMLRPCServer(SimpleXMLRPCServer.SimpleXMLRPCServer):
"""Override of TIME_WAIT"""
allow_reuse_address = True
def serve_forever(self):
self.stop = False
while not self.stop:
self.handle_request()
class LoggingSimpleXMLRPCRequestHandler(SimpleXMLRPCServer.SimpleXMLRPCRequestHandler):
"""Overides the default SimpleXMLRPCRequestHander to support logging.
Logs client IP and the XML request and response.
"""
def parse(self, given):
"""Convert the incoming arguments into the format IPA expects"""
args = []
kw = {}
for g in given:
kw[g] = unicode(given[g])
return (args, kw)
def _dispatch(self, method, params):
"""Dispatches the XML-RPC method.
Methods beginning with an '_' are considered private and will
not be called.
"""
# this is fine for our test server
uid = commands.getoutput('/usr/bin/id -u')
krbccache = "FILE:/tmp/krb5cc_" + uid
func = None
try:
# FIXME: don't hardcode host and port
context.conn = conn.IPAConn("localhost", 389, krbccache)
try:
# check to see if a matching function has been registered
func = funcs[method]
except KeyError:
raise Exception('method "%s" is not supported' % method)
if len(params) > 1 and isinstance(params[-1], dict):
kw = params[-1]
params = params[:-1]
return func(*params, **kw)
else:
return func(*params)
finally:
# Clean up any per-request data and connections
# for k in context.__dict__.keys():
# del context.__dict__[k]
pass
def _marshaled_dispatch(self, data, dispatch_method = None):
try:
params, method = xmlrpclib.loads(data)
# generate response
if dispatch_method is not None:
response = dispatch_method(method, params)
else:
response = self._dispatch(method, params)
# wrap response in a singleton tuple
response = (response,)
response = xmlrpclib.dumps(response, methodresponse=1)
except:
# report exception back to client. This is needed to report
# tracebacks found in server code.
e_class, e = sys.exc_info()[:2]
# FIXME, need to get this number from somewhere...
faultCode = getattr(e_class,'faultCode',1)
tb_str = ''.join(traceback.format_exception(*sys.exc_info()))
faultString = tb_str
response = xmlrpclib.dumps(xmlrpclib.Fault(faultCode, faultString))
return response
def do_POST(self):
clientIP, port = self.client_address
# Log client IP and Port
logger.info('Client IP: %s - Port: %s' % (clientIP, port))
try:
# get arguments
data = self.rfile.read(int(self.headers["content-length"]))
# unmarshal the XML data
params, method = xmlrpclib.loads(data)
# Log client request
logger.info('Client request: \n%s\n' % data)
# response = self.server._marshaled_dispatch(
response = self._marshaled_dispatch(
data, getattr(self, '_dispatch', None))
# Log server response
logger.info('Server response: \n%s\n' % response)
except Exception, e:
# This should only happen if the module is buggy
# internal error, report as HTTP server error
print e
self.send_response(500)
self.end_headers()
else:
# got a valid XML-RPC response
self.send_response(200)
self.send_header("Content-type", "text/xml")
self.send_header("Content-length", str(len(response)))
self.end_headers()
self.wfile.write(response)
# shut down the connection
self.wfile.flush()
self.connection.shutdown(1)
# Set up our logger
logger = logging.getLogger('xmlrpcserver')
hdlr = logging.FileHandler('xmlrpcserver.log')
formatter = logging.Formatter("%(asctime)s %(levelname)s %(message)s")
hdlr.setFormatter(formatter)
logger.addHandler(hdlr)
logger.setLevel(logging.INFO)
# Set up the server
XMLRPCServer = StoppableXMLRPCServer(("",PORT), LoggingSimpleXMLRPCRequestHandler)
XMLRPCServer.register_introspection_functions()
# Get and register all the methods
api.finalize()
for cmd in api.Method:
logger.info("registering %s" % cmd)
XMLRPCServer.register_function(api.Method[cmd], cmd)
funcs = XMLRPCServer.funcs
print "Listening on port %d" % PORT
try:
XMLRPCServer.serve_forever()
except KeyboardInterrupt:
XMLRPCServer.server_close()
print "Server shutdown."