Rebase XML-RPC client and server

Fix error handling in server to return exceptions generated in library code
This commit is contained in:
Rob Crittenden 2008-09-25 23:53:53 -04:00 committed by Jason Gerard DeRose
parent afdc721038
commit b965e558b5
4 changed files with 62 additions and 17 deletions

View File

@ -25,8 +25,12 @@ import frontend, errors
class Add(frontend.Method): class Add(frontend.Method):
def get_args(self):
yield self.obj.primary_key
def get_options(self): def get_options(self):
return self.obj.params() for param in self.obj.params_minus_pk():
yield param.__clone__(required=False)
class Get(frontend.Method): class Get(frontend.Method):

View File

@ -26,7 +26,8 @@ from ipalib import frontend
from ipalib import crud from ipalib import crud
from ipalib.frontend import Param from ipalib.frontend import Param
from ipalib import api from ipalib import api
from ipalib import servercore
import ldap
class user(frontend.Object): class user(frontend.Object):
'User object' 'User object'
@ -78,6 +79,8 @@ api.register(envtest)
# Register some methods for the 'user' object: # Register some methods for the 'user' object:
class user_add(crud.Add): class user_add(crud.Add):
'Add a new user.' 'Add a new user.'
def execute(self, *args, **kw):
return 1
api.register(user_add) api.register(user_add)
class user_del(crud.Del): class user_del(crud.Del):
@ -90,6 +93,10 @@ api.register(user_mod)
class user_find(crud.Find): class user_find(crud.Find):
'Search the users.' 'Search the users.'
def execute(self, *args, **kw):
uid=args[0]
result = servercore.get_sub_entry(servercore.basedn, "uid=%s" % uid, ["*"])
return result
api.register(user_find) api.register(user_find)
class user_show(crud.Get): class user_show(crud.Get):

View File

@ -5,12 +5,19 @@ import xmlrpclib
server = xmlrpclib.ServerProxy("http://localhost:8888/") server = xmlrpclib.ServerProxy("http://localhost:8888/")
print server.system.listMethods() print server.system.listMethods()
#print server.system.methodHelp("user_add") print server.system.methodHelp("user_add")
user = {'givenname':'Joe', 'sn':'Smith'} try:
result = server.user_add(user) args="admin"
print "returned %s" % result kw = {'givenname':'Joe', 'sn':'Smith'}
result = server.user_add(args, kw)
print "returned %s" % result
except xmlrpclib.Fault, e:
print e.faultString
user = {'givenname':'Joe', 'sn':'Smith', 'uid':'admin'} try:
result = server.user_find(user) args="admin"
print "returned %s" % result result = server.user_find(args)
print "returned %s" % result
except xmlrpclib.Fault, e:
print e.faultString

View File

@ -12,6 +12,7 @@ import commands
from ipalib import api, conn from ipalib import api, conn
from ipalib.conn import context from ipalib.conn import context
import ipalib.load_plugins import ipalib.load_plugins
import traceback
PORT=8888 PORT=8888
@ -43,11 +44,6 @@ class LoggingSimpleXMLRPCRequestHandler(SimpleXMLRPCServer.SimpleXMLRPCRequestHa
Methods beginning with an '_' are considered private and will Methods beginning with an '_' are considered private and will
not be called. not be called.
""" """
if (params):
(args, kw) = self.parse(*params)
else:
args = []
kw = {}
# this is fine for our test server # this is fine for our test server
uid = commands.getoutput('/usr/bin/id -u') uid = commands.getoutput('/usr/bin/id -u')
@ -62,12 +58,41 @@ class LoggingSimpleXMLRPCRequestHandler(SimpleXMLRPCServer.SimpleXMLRPCRequestHa
func = funcs[method] func = funcs[method]
except KeyError: except KeyError:
raise Exception('method "%s" is not supported' % method) raise Exception('method "%s" is not supported' % method)
return func(**kw) if len(params) > 1 and isinstance(params[-1], dict):
kw = params[-1]
params = params[:-1]
return func(*params, **kw)
else:
return func(*params)
finally: finally:
# Clean up any per-request data and connections # Clean up any per-request data and connections
for k in context.__dict__.keys(): for k in context.__dict__.keys():
del context.__dict__[k] 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): def do_POST(self):
clientIP, port = self.client_address clientIP, port = self.client_address
# Log client IP and Port # Log client IP and Port
@ -82,14 +107,16 @@ class LoggingSimpleXMLRPCRequestHandler(SimpleXMLRPCServer.SimpleXMLRPCRequestHa
# Log client request # Log client request
logger.info('Client request: \n%s\n' % data) logger.info('Client request: \n%s\n' % data)
response = self.server._marshaled_dispatch( # response = self.server._marshaled_dispatch(
response = self._marshaled_dispatch(
data, getattr(self, '_dispatch', None)) data, getattr(self, '_dispatch', None))
# Log server response # Log server response
logger.info('Server response: \n%s\n' % response) logger.info('Server response: \n%s\n' % response)
except: except Exception, e:
# This should only happen if the module is buggy # This should only happen if the module is buggy
# internal error, report as HTTP server error # internal error, report as HTTP server error
print e
self.send_response(500) self.send_response(500)
self.end_headers() self.end_headers()
else: else: