summaryrefslogtreecommitdiffstats
path: root/ipalib
diff options
context:
space:
mode:
Diffstat (limited to 'ipalib')
-rw-r--r--ipalib/errors2.py41
-rw-r--r--ipalib/parameters.py5
-rw-r--r--ipalib/rpc.py50
3 files changed, 81 insertions, 15 deletions
diff --git a/ipalib/errors2.py b/ipalib/errors2.py
index 4c8acd5d..7e2eea05 100644
--- a/ipalib/errors2.py
+++ b/ipalib/errors2.py
@@ -275,10 +275,27 @@ class VersionError(PublicError):
format = _('%(cver)s client incompatible with %(sver)s server at %(server)r')
+class UnknownError(PublicError):
+ """
+ **902** Raised when client does not know error it caught from server.
+
+ For example:
+
+ >>> raise UnknownError(code=57, server='localhost', error=u'a new error')
+ ...
+ Traceback (most recent call last):
+ ...
+ UnknownError: unknown error 57 from localhost: a new error
+
+ """
+
+ errno = 902
+ format = _('unknown error %(code)d from %(server)s: %(error)s')
+
class InternalError(PublicError):
"""
- **902** Raised to conceal a non-public exception.
+ **903** Raised to conceal a non-public exception.
For example:
@@ -288,7 +305,7 @@ class InternalError(PublicError):
InternalError: an internal error has occured
"""
- errno = 902
+ errno = 903
format = _('an internal error has occured')
def __init__(self, message=None):
@@ -300,7 +317,7 @@ class InternalError(PublicError):
class ServerInternalError(PublicError):
"""
- **903** Raised when client catches an `InternalError` from server.
+ **904** Raised when client catches an `InternalError` from server.
For example:
@@ -310,13 +327,13 @@ class ServerInternalError(PublicError):
ServerInternalError: an internal error has occured on server at 'https://localhost'
"""
- errno = 903
+ errno = 904
format = _('an internal error has occured on server at %(server)r')
class CommandError(PublicError):
"""
- **904** Raised when an unknown command is called.
+ **905** Raised when an unknown command is called.
For example:
@@ -326,13 +343,13 @@ class CommandError(PublicError):
CommandError: unknown command 'foobar'
"""
- errno = 904
+ errno = 905
format = _('unknown command %(name)r')
class ServerCommandError(PublicError):
"""
- **905** Raised when client catches a `CommandError` from server.
+ **906** Raised when client catches a `CommandError` from server.
For example:
@@ -343,13 +360,13 @@ class ServerCommandError(PublicError):
ServerCommandError: error on server 'https://localhost': unknown command 'foobar'
"""
- errno = 905
+ errno = 906
format = _('error on server %(server)r: %(error)s')
class NetworkError(PublicError):
"""
- **906** Raised when a network connection cannot be created.
+ **907** Raised when a network connection cannot be created.
For example:
@@ -359,13 +376,13 @@ class NetworkError(PublicError):
NetworkError: cannot connect to 'ldap://localhost:389'
"""
- errno = 906
+ errno = 907
format = _('cannot connect to %(uri)r')
class ServerNetworkError(PublicError):
"""
- **907** Raised when client catches a `NetworkError` from server.
+ **908** Raised when client catches a `NetworkError` from server.
For example:
@@ -376,7 +393,7 @@ class ServerNetworkError(PublicError):
ServerNetworkError: error on server 'https://localhost': cannot connect to 'ldap://localhost:389'
"""
- errno = 907
+ errno = 908
format = _('error on server %(server)r: %(error)s')
diff --git a/ipalib/parameters.py b/ipalib/parameters.py
index 7cc93e90..76d88347 100644
--- a/ipalib/parameters.py
+++ b/ipalib/parameters.py
@@ -490,13 +490,12 @@ class Param(ReadOnly):
:param value: A proposed value for this parameter.
"""
- # FIXME: this should be after 'if value is None:'
- if self.query:
- return
if value is None:
if self.required:
raise RequirementError(name=self.name)
return
+ if self.query:
+ return
if self.multivalue:
if type(value) is not tuple:
raise TypeError(
diff --git a/ipalib/rpc.py b/ipalib/rpc.py
index acfdae95..e7823ef9 100644
--- a/ipalib/rpc.py
+++ b/ipalib/rpc.py
@@ -30,7 +30,11 @@ Also see the `ipaserver.rpcserver` module.
"""
from types import NoneType
+import threading
from xmlrpclib import Binary, Fault, dumps, loads
+from ipalib.backend import Backend
+from ipalib.errors2 import public_errors, PublicError, UnknownError
+from ipalib.request import context
def xml_wrap(value):
@@ -155,3 +159,49 @@ def xml_loads(data):
"""
(params, method) = loads(data)
return (xml_unwrap(params), method)
+
+
+class xmlclient(Backend):
+ """
+ Forwarding backend for XML-RPC client.
+ """
+
+ def __init__(self):
+ super(xmlclient, self).__init__()
+ self.__errors = dict((e.errno, e) for e in public_errors)
+
+ def forward(self, name, *args, **kw):
+ """
+ Forward call to command named ``name`` over XML-RPC.
+
+ This method will encode and forward an XML-RPC request, and will then
+ decode and return the corresponding XML-RPC response.
+
+ :param command: The name of the command being forwarded.
+ :param args: Positional arguments to pass to remote command.
+ :param kw: Keyword arguments to pass to remote command.
+ """
+ if name not in self.Command:
+ raise ValueError(
+ '%s.forward(): %r not in api.Command' % (self.name, name)
+ )
+ if not hasattr(context, 'xmlconn'):
+ raise StandardError(
+ '%s.forward(%r): need context.xmlconn in thread %r' % (
+ self.name, name, threading.currentThread().getName()
+ )
+ )
+ command = getattr(context.xmlconn, name)
+ params = args + (kw,)
+ try:
+ response = command(xml_wrap(params))
+ return xml_unwrap(response)
+ except Fault, e:
+ if e.faultCode in self.__errors:
+ error = self.__errors[e.faultCode]
+ raise error(message=e.faultString)
+ raise UnknownError(
+ code=e.faultCode,
+ error=e.faultString,
+ server=self.env.xmlrpc_uri,
+ )