More xmlrpc tweaks: xmlserver.execute() now logs non-public exceptions; xmlclient.forward() now handles socket error; fixed some Python 2.4 problems in lite-xmlrpc2.py

This commit is contained in:
Jason Gerard DeRose 2009-01-22 17:03:48 -07:00 committed by Rob Crittenden
parent 24b6cb89d4
commit 833088955c
6 changed files with 58 additions and 39 deletions

9
ipa
View File

@ -30,12 +30,5 @@ from ipalib import api
from ipalib.cli import CLI
if __name__ == '__main__':
# If we can't explicitly determin the encoding, we assume UTF-8:
if sys.stdin.encoding is None:
encoding = 'UTF-8'
else:
encoding = sys.stdin.encoding
cli = CLI(api,
(s.decode(encoding) for s in sys.argv[1:])
)
cli = CLI(api, sys.argv[1:])
sys.exit(cli.run())

View File

@ -34,12 +34,11 @@ import struct
import frontend
import backend
import errors
import errors2
import plugable
import util
from errors2 import PublicError, CommandError
from constants import CLI_TAB
from parameters import Password
from parameters import Password, Bytes
def to_cli(name):
@ -120,9 +119,10 @@ class textui(backend.Backend):
"""
Decode text from stdin.
"""
assert type(str_buffer) is str
encoding = self.__get_encoding(sys.stdin)
return str_buffer.decode(encoding)
if type(str_buffer) is str:
encoding = self.__get_encoding(sys.stdin)
return str_buffer.decode(encoding)
return str_buffer
def encode(self, unicode_text):
"""
@ -535,7 +535,7 @@ class CLI(object):
print ''
self.api.log.info('operation aborted')
sys.exit()
except errors2.PublicError, e:
except PublicError, e:
self.api.log.error(e.strerror)
sys.exit(e.errno)
@ -573,7 +573,7 @@ class CLI(object):
return
key = self.cmd_argv[0]
if key not in self:
raise errors.UnknownCommandError(key)
raise CommandError(name=key)
self.run_cmd(self[key])
# FIXME: Stuff that might need special handling still:
@ -782,7 +782,17 @@ class CLI(object):
list(self.cmd_argv[1:]), KWCollector()
)
options = kwc.__todict__()
return cmd.args_options_2_params(*args, **options)
kw = cmd.args_options_2_params(*args, **options)
return dict(self.params_iter(cmd, kw))
def params_iter(self, cmd, kw):
for (key, value) in kw.iteritems():
param = cmd.params[key]
if isinstance(param, Bytes):
yield (key, value)
else:
yield (key, self.textui.decode(value))
def build_parser(self, cmd):
parser = optparse.OptionParser(

View File

@ -370,27 +370,19 @@ class NetworkError(PublicError):
For example:
>>> raise NetworkError(uri='ldap://localhost:389')
>>> raise NetworkError(uri='ldap://localhost:389', error='Connection refused')
Traceback (most recent call last):
...
NetworkError: cannot connect to 'ldap://localhost:389'
NetworkError: cannot connect to 'ldap://localhost:389': Connection refused
"""
errno = 907
format = _('cannot connect to %(uri)r')
format = _('cannot connect to %(uri)r: %(error)s')
class ServerNetworkError(PublicError):
"""
**908** Raised when client catches a `NetworkError` from server.
For example:
>>> e = NetworkError(uri='ldap://localhost:389')
>>> raise ServerNetworkError(error=e.message, server='https://localhost')
Traceback (most recent call last):
...
ServerNetworkError: error on server 'https://localhost': cannot connect to 'ldap://localhost:389'
"""
errno = 908

View File

@ -32,10 +32,11 @@ Also see the `ipaserver.rpcserver` module.
from types import NoneType
import threading
import socket
from xmlrpclib import Binary, Fault, dumps, loads, ServerProxy, SafeTransport
import kerberos
from ipalib.backend import Backend
from ipalib.errors2 import public_errors, PublicError, UnknownError
from ipalib.errors2 import public_errors, PublicError, UnknownError, NetworkError
from ipalib.request import context
@ -265,3 +266,5 @@ class xmlclient(Backend):
error=e.faultString,
server=self.env.xmlrpc_uri,
)
except socket.error, e:
raise NetworkError(uri=self.env.xmlrpc_uri, error=e.args[1])

View File

@ -66,8 +66,11 @@ class xmlserver(Backend):
print 'okay'
except Exception, e:
if not isinstance(e, PublicError):
self.exception(
'%s: %s', e.__class__.__name__, str(e)
)
e = InternalError()
assert isinstance(e, PublicError)
self.debug('Returning %r exception', e.__class__.__name__)
self.info('%s: %s', e.__class__.__name__, str(e))
response = Fault(e.errno, e.strerror)
return xml_dumps(response, methodresponse=True)

View File

@ -1,4 +1,4 @@
#!/usr/bin/env python
#!/usr/bin/python2.4
# Authors:
# Jason Gerard DeRose <jderose@redhat.com>
@ -23,7 +23,8 @@
In-tree XML-RPC server using SimpleXMLRPCServer.
"""
from SimpleXMLRPCServer import SimpleXMLRPCServer, SimpleXMLRPCRequestHandler
import sys
from SimpleXMLRPCServer import SimpleXMLRPCServer
from ipalib import api
api.bootstrap_with_global_options(context='server')
@ -31,24 +32,41 @@ api.finalize()
class Instance(object):
"""
Just used for `Instance._listMethods()`.
"""
def _listMethods(self):
"""
Provides list of names for ``system.listMethods``.
"""
return list(api.Command)
class Server(SimpleXMLRPCServer):
"""
Custom server implementing `Server._marshaled_dispatch()`.
"""
def _marshaled_dispatch(self, data, dispatch_method=None):
"""
Use `ipaserver.rpcserver.xmlserver.execute()` to do the real work.
"""
return api.Backend.xmlserver.execute(data)
address = ('', api.env.lite_xmlrpc_port)
server = Server(address,
logRequests=False,
allow_none=True,
encoding='UTF-8',
)
kw = dict(logRequests=False)
if sys.version_info[:2] != (2, 4):
kw.update(dict(encoding='UTF-8', allow_none=True))
server = Server(('', api.env.lite_xmlrpc_port), **kw)
api.log.info('Logging to file %r', api.env.log)
api.log.info('Listening on port %d', api.env.lite_xmlrpc_port)
server.register_introspection_functions()
server.register_instance(Instance())
try:
server.serve_forever()
except KeyboardInterrupt:
api.log.info('Server stopped')
api.log.info('KeyboardInterrupt: shutting down server...')
server.server_close()
api.log.info('Server shutdown.')