From 77e6c99f9d8e34e85add7671d89bf7698a4fe5c2 Mon Sep 17 00:00:00 2001 From: Rob Crittenden Date: Tue, 30 Sep 2008 00:48:53 -0400 Subject: Migrate to new source tree layoute --- ipa_server/conn.py | 5 +- ipa_server/context.py | 29 +++++++++ ipa_server/servercore.py | 4 +- ipa_server/test_client | 28 ++++++++ ipa_server/test_server | 162 ++++++++++++++++++++++++++++++++++++++++++++++ ipalib/plugins/example.py | 3 +- server/test_client | 23 ------- server/test_server | 160 --------------------------------------------- 8 files changed, 223 insertions(+), 191 deletions(-) create mode 100644 ipa_server/context.py create mode 100755 ipa_server/test_client create mode 100755 ipa_server/test_server delete mode 100755 server/test_client delete mode 100755 server/test_server diff --git a/ipa_server/conn.py b/ipa_server/conn.py index f8f5306f..fb00ad99 100644 --- a/ipa_server/conn.py +++ b/ipa_server/conn.py @@ -18,12 +18,9 @@ # import krbV -import threading import ldap import ldap.dn -from ipalib import ipaldap - -context = threading.local() +import ipaldap class IPAConn: def __init__(self, host, port, krbccache, debug=None): diff --git a/ipa_server/context.py b/ipa_server/context.py new file mode 100644 index 00000000..e20587cc --- /dev/null +++ b/ipa_server/context.py @@ -0,0 +1,29 @@ +# Authors: Rob Crittenden +# +# Copyright (C) 2008 Red Hat +# see file 'COPYING' for use and warranty information +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License as +# published by the Free Software Foundation; version 2 only +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +# + +# This should only be imported once. Importing again will cause the +# a new instance to be created in the same thread + +# To use: +# from ipa_server.context import context +# context.foo = "bar" + +import threading + +context = threading.local() diff --git a/ipa_server/servercore.py b/ipa_server/servercore.py index 8626c04b..eeecd4b0 100644 --- a/ipa_server/servercore.py +++ b/ipa_server/servercore.py @@ -21,8 +21,8 @@ import sys sys.path.insert(0, ".") sys.path.insert(0, "..") import ldap -from ipalib.conn import context -from ipalib import ipautil +from ipa_server.context import context +import ipautil # temporary import krbV diff --git a/ipa_server/test_client b/ipa_server/test_client new file mode 100755 index 00000000..364fd3b8 --- /dev/null +++ b/ipa_server/test_client @@ -0,0 +1,28 @@ +#!/usr/bin/python + +import xmlrpclib + +def user_find(uid): + try: + args=uid + result = server.user_find(args) + print "returned %s" % result + except xmlrpclib.Fault, e: + print e.faultString + +# main +server = xmlrpclib.ServerProxy("http://localhost:8888/") + +print server.system.listMethods() +print server.system.methodHelp("user_add") + +try: + args="admin" + kw = {'givenname':'Joe', 'sn':'Smith'} + result = server.user_add(args, kw) + print "returned %s" % result +except xmlrpclib.Fault, e: + print e.faultString + +user_find("admin") +user_find("notfound") diff --git a/ipa_server/test_server b/ipa_server/test_server new file mode 100755 index 00000000..a6726369 --- /dev/null +++ b/ipa_server/test_server @@ -0,0 +1,162 @@ +#!/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." diff --git a/ipalib/plugins/example.py b/ipalib/plugins/example.py index c7d16160..6113c117 100644 --- a/ipalib/plugins/example.py +++ b/ipalib/plugins/example.py @@ -21,12 +21,11 @@ Some example plugins. """ - from ipalib import frontend from ipalib import crud from ipalib.frontend import Param from ipalib import api -from ipalib import servercore +from ipa_server import servercore import ldap class user(frontend.Object): diff --git a/server/test_client b/server/test_client deleted file mode 100755 index 79945a96..00000000 --- a/server/test_client +++ /dev/null @@ -1,23 +0,0 @@ -#!/usr/bin/python - -import xmlrpclib - -server = xmlrpclib.ServerProxy("http://localhost:8888/") - -print server.system.listMethods() -print server.system.methodHelp("user_add") - -try: - args="admin" - kw = {'givenname':'Joe', 'sn':'Smith'} - result = server.user_add(args, kw) - print "returned %s" % result -except xmlrpclib.Fault, e: - print e.faultString - -try: - args="admin" - result = server.user_find(args) - print "returned %s" % result -except xmlrpclib.Fault, e: - print e.faultString diff --git a/server/test_server b/server/test_server deleted file mode 100755 index 2af83399..00000000 --- a/server/test_server +++ /dev/null @@ -1,160 +0,0 @@ -#!/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, conn -from ipalib.conn 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] - - 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." -- cgit