summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJason Gerard DeRose <jderose@redhat.com>2009-01-22 17:03:48 -0700
committerRob Crittenden <rcritten@redhat.com>2009-02-03 15:29:01 -0500
commit833088955c0e6c606bc8ea96a05ddf6c3a34bc6b (patch)
treee34931d760a5341befd59a9623bf8e256af4b284
parent24b6cb89d443384cb432f01265c45bc18d9cf2fc (diff)
downloadfreeipa-833088955c0e6c606bc8ea96a05ddf6c3a34bc6b.tar.gz
freeipa-833088955c0e6c606bc8ea96a05ddf6c3a34bc6b.tar.xz
freeipa-833088955c0e6c606bc8ea96a05ddf6c3a34bc6b.zip
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
-rwxr-xr-xipa9
-rw-r--r--ipalib/cli.py28
-rw-r--r--ipalib/errors2.py14
-rw-r--r--ipalib/rpc.py5
-rw-r--r--ipaserver/rpcserver.py5
-rwxr-xr-xlite-xmlrpc2.py36
6 files changed, 58 insertions, 39 deletions
diff --git a/ipa b/ipa
index cab12b6ba..d06abe37a 100755
--- a/ipa
+++ b/ipa
@@ -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())
diff --git a/ipalib/cli.py b/ipalib/cli.py
index 62b8b9304..6b3ab7e5b 100644
--- a/ipalib/cli.py
+++ b/ipalib/cli.py
@@ -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(
diff --git a/ipalib/errors2.py b/ipalib/errors2.py
index dccdbe6a3..042580936 100644
--- a/ipalib/errors2.py
+++ b/ipalib/errors2.py
@@ -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
diff --git a/ipalib/rpc.py b/ipalib/rpc.py
index aa8002094..55f3ea954 100644
--- a/ipalib/rpc.py
+++ b/ipalib/rpc.py
@@ -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])
diff --git a/ipaserver/rpcserver.py b/ipaserver/rpcserver.py
index f5fb3c623..7bc57751d 100644
--- a/ipaserver/rpcserver.py
+++ b/ipaserver/rpcserver.py
@@ -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)
diff --git a/lite-xmlrpc2.py b/lite-xmlrpc2.py
index cb216456c..49aa6828b 100755
--- a/lite-xmlrpc2.py
+++ b/lite-xmlrpc2.py
@@ -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.')