mirror of
https://salsa.debian.org/freeipa-team/freeipa.git
synced 2025-01-23 23:03:19 -06:00
Further migration toward new xmlrcp code; fixed problem with unicode Fault.faultString; fixed problem where ServerProxy method was not called correctly
This commit is contained in:
parent
9f48612a56
commit
24b6cb89d4
@ -455,7 +455,7 @@ class NameSpace(ReadOnly):
|
||||
|
||||
:param key: The name or index of a member, or a slice object.
|
||||
"""
|
||||
if type(key) is str:
|
||||
if isinstance(key, basestring):
|
||||
return self.__map[key]
|
||||
if type(key) in (int, slice):
|
||||
return self.__members[key]
|
||||
|
@ -35,6 +35,7 @@ import struct
|
||||
import frontend
|
||||
import backend
|
||||
import errors
|
||||
import errors2
|
||||
import plugable
|
||||
import util
|
||||
from constants import CLI_TAB
|
||||
@ -534,9 +535,9 @@ class CLI(object):
|
||||
print ''
|
||||
self.api.log.info('operation aborted')
|
||||
sys.exit()
|
||||
except errors.IPAError, e:
|
||||
self.api.log.error(unicode(e))
|
||||
sys.exit(e.faultCode)
|
||||
except errors2.PublicError, e:
|
||||
self.api.log.error(e.strerror)
|
||||
sys.exit(e.errno)
|
||||
|
||||
def run_real(self):
|
||||
"""
|
||||
@ -620,6 +621,8 @@ class CLI(object):
|
||||
(c.name.replace('_', '-'), c) for c in self.api.Command()
|
||||
)
|
||||
self.textui = self.api.Backend.textui
|
||||
if self.api.env.in_server is False and 'xmlclient' in self.api.Backend:
|
||||
self.api.Backend.xmlclient.connect()
|
||||
|
||||
def load_plugins(self):
|
||||
"""
|
||||
|
@ -96,14 +96,14 @@ class Command(plugable.Plugin):
|
||||
If not in a server context, the call will be forwarded over
|
||||
XML-RPC and the executed an the nearest IPA server.
|
||||
"""
|
||||
self.debug(make_repr(self.name, *args, **options))
|
||||
params = self.args_options_2_params(*args, **options)
|
||||
params = self.normalize(**params)
|
||||
params = self.convert(**params)
|
||||
params.update(self.get_default(**params))
|
||||
self.validate(**params)
|
||||
(args, options) = self.params_2_args_options(**params)
|
||||
self.debug(make_repr(self.name, *args, **options))
|
||||
# FIXME: don't log passords!
|
||||
self.info(make_repr(self.name, *args, **options))
|
||||
result = self.run(*args, **options)
|
||||
self.debug('%s result: %r', self.name, result)
|
||||
return result
|
||||
@ -200,6 +200,11 @@ class Command(plugable.Plugin):
|
||||
(k, self.params[k].convert(v)) for (k, v) in kw.iteritems()
|
||||
)
|
||||
|
||||
def __convert_iter(self, kw):
|
||||
for param in self.params():
|
||||
if kw.get(param.name, None) is None:
|
||||
continue
|
||||
|
||||
def get_default(self, **kw):
|
||||
"""
|
||||
Return a dictionary of defaults for all missing required values.
|
||||
@ -245,7 +250,7 @@ class Command(plugable.Plugin):
|
||||
elif param.required:
|
||||
raise errors.RequirementError(param.name)
|
||||
|
||||
def run(self, *args, **kw):
|
||||
def run(self, *args, **options):
|
||||
"""
|
||||
Dispatch to `Command.execute` or `Command.forward`.
|
||||
|
||||
@ -258,11 +263,8 @@ class Command(plugable.Plugin):
|
||||
performs is executed remotely.
|
||||
"""
|
||||
if self.api.env.in_server:
|
||||
target = self.execute
|
||||
else:
|
||||
target = self.forward
|
||||
object.__setattr__(self, 'run', target)
|
||||
return target(*args, **kw)
|
||||
return self.execute(*args, **options)
|
||||
return self.forward(*args, **options)
|
||||
|
||||
def execute(self, *args, **kw):
|
||||
"""
|
||||
@ -283,7 +285,7 @@ class Command(plugable.Plugin):
|
||||
"""
|
||||
Forward call over XML-RPC to this same command on server.
|
||||
"""
|
||||
return self.Backend.xmlrpc.forward_call(self.name, *args, **kw)
|
||||
return self.Backend.xmlclient.forward(self.name, *args, **kw)
|
||||
|
||||
def finalize(self):
|
||||
"""
|
||||
|
@ -22,7 +22,7 @@ Misc frontend plugins.
|
||||
"""
|
||||
|
||||
import re
|
||||
from ipalib import api, LocalOrRemote
|
||||
from ipalib import api, LocalOrRemote, Bytes
|
||||
|
||||
|
||||
|
||||
|
@ -135,8 +135,13 @@ def xml_dumps(params, methodname=None, methodresponse=False, encoding='UTF-8'):
|
||||
allow_none=True,
|
||||
)
|
||||
|
||||
def decode_fault(e, encoding='UTF-8'):
|
||||
assert isinstance(e, Fault)
|
||||
if type(e.faultString) is str:
|
||||
return Fault(e.faultCode, e.faultString.decode(encoding))
|
||||
return e
|
||||
|
||||
def xml_loads(data):
|
||||
def xml_loads(data, encoding='UTF-8'):
|
||||
"""
|
||||
Decode the XML-RPC packet in ``data``, transparently unwrapping its params.
|
||||
|
||||
@ -159,8 +164,11 @@ def xml_loads(data):
|
||||
|
||||
:param data: The XML-RPC packet to decode.
|
||||
"""
|
||||
(params, method) = loads(data)
|
||||
return (xml_unwrap(params), method)
|
||||
try:
|
||||
(params, method) = loads(data)
|
||||
return (xml_unwrap(params), method)
|
||||
except Fault, e:
|
||||
raise decode_fault(e)
|
||||
|
||||
|
||||
class KerbTransport(SafeTransport):
|
||||
@ -211,8 +219,8 @@ class xmlclient(Backend):
|
||||
)
|
||||
)
|
||||
conn = ServerProxy(self.env.xmlrpc_uri,
|
||||
transport=KerbTransport(),
|
||||
allow_none=True,
|
||||
encoding='UTF-8',
|
||||
)
|
||||
setattr(context, self.connection_name, conn)
|
||||
|
||||
@ -243,9 +251,10 @@ class xmlclient(Backend):
|
||||
command = getattr(context.xmlconn, name)
|
||||
params = args + (kw,)
|
||||
try:
|
||||
response = command(xml_wrap(params))
|
||||
response = command(*xml_wrap(params))
|
||||
return xml_unwrap(response)
|
||||
except Fault, e:
|
||||
e = decode_fault(e)
|
||||
self.debug('Caught fault %d from server %s: %s', e.faultCode,
|
||||
self.env.xmlrpc_uri, e.faultString)
|
||||
if e.faultCode in self.__errors:
|
||||
|
@ -27,6 +27,7 @@ from xmlrpclib import Fault
|
||||
from ipalib import Backend
|
||||
from ipalib.errors2 import PublicError, InternalError, CommandError
|
||||
from ipalib.rpc import xml_dumps, xml_loads
|
||||
from ipalib.util import make_repr
|
||||
|
||||
|
||||
def params_2_args_options(params):
|
||||
@ -47,21 +48,26 @@ class xmlserver(Backend):
|
||||
self.debug('Received RPC call to %r', method)
|
||||
if method not in self.Command:
|
||||
raise CommandError(name=method)
|
||||
self.info('params = %r', params)
|
||||
(args, options) = params_2_args_options(params)
|
||||
self.info('args = %r', args)
|
||||
self.info('options = %r', options)
|
||||
self.debug(make_repr(method, *args, **options))
|
||||
result = self.Command[method](*args, **options)
|
||||
return (result,) # Must wrap XML-RPC response in a tuple singleton
|
||||
|
||||
def execute(self, data, ccache=None, client_version=None,
|
||||
client_ip=None, languages=None):
|
||||
def execute(self, data):
|
||||
"""
|
||||
Execute the XML-RPC request in contained in ``data``.
|
||||
"""
|
||||
try:
|
||||
(params, method) = xml_loads(data)
|
||||
response = self.dispatch(method, params)
|
||||
print 'okay'
|
||||
except Exception, e:
|
||||
if not isinstance(e, PublicError):
|
||||
e = InternalError()
|
||||
assert isinstance(e, PublicError)
|
||||
self.debug('Returning %r exception', e.__class__.__name__)
|
||||
response = Fault(e.errno, e.strerror)
|
||||
return dumps(response)
|
||||
return xml_dumps(response, methodresponse=True)
|
||||
|
54
lite-xmlrpc2.py
Executable file
54
lite-xmlrpc2.py
Executable file
@ -0,0 +1,54 @@
|
||||
#!/usr/bin/env python
|
||||
|
||||
# Authors:
|
||||
# Jason Gerard DeRose <jderose@redhat.com>
|
||||
#
|
||||
# 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
|
||||
|
||||
"""
|
||||
In-tree XML-RPC server using SimpleXMLRPCServer.
|
||||
"""
|
||||
|
||||
from SimpleXMLRPCServer import SimpleXMLRPCServer, SimpleXMLRPCRequestHandler
|
||||
from ipalib import api
|
||||
|
||||
api.bootstrap_with_global_options(context='server')
|
||||
api.finalize()
|
||||
|
||||
|
||||
class Instance(object):
|
||||
def _listMethods(self):
|
||||
return list(api.Command)
|
||||
|
||||
|
||||
class Server(SimpleXMLRPCServer):
|
||||
def _marshaled_dispatch(self, data, dispatch_method=None):
|
||||
return api.Backend.xmlserver.execute(data)
|
||||
|
||||
|
||||
address = ('', api.env.lite_xmlrpc_port)
|
||||
server = Server(address,
|
||||
logRequests=False,
|
||||
allow_none=True,
|
||||
encoding='UTF-8',
|
||||
)
|
||||
server.register_introspection_functions()
|
||||
server.register_instance(Instance())
|
||||
try:
|
||||
server.serve_forever()
|
||||
except KeyboardInterrupt:
|
||||
api.log.info('Server stopped')
|
@ -378,7 +378,6 @@ class test_Command(ClassChecker):
|
||||
o.set_api(api)
|
||||
assert o.run.im_func is self.cls.run.im_func
|
||||
assert ('execute', args, kw) == o.run(*args, **kw)
|
||||
assert o.run.im_func is my_cmd.execute.im_func
|
||||
|
||||
# Test in non-server context
|
||||
(api, home) = create_test_api(in_server=False)
|
||||
@ -387,7 +386,6 @@ class test_Command(ClassChecker):
|
||||
o.set_api(api)
|
||||
assert o.run.im_func is self.cls.run.im_func
|
||||
assert ('forward', args, kw) == o.run(*args, **kw)
|
||||
assert o.run.im_func is my_cmd.forward.im_func
|
||||
|
||||
|
||||
class test_LocalOrRemote(ClassChecker):
|
||||
|
@ -335,6 +335,7 @@ class test_Param(ClassChecker):
|
||||
o = Subclass('my_param')
|
||||
for value in NULLS:
|
||||
assert o.convert(value) is None
|
||||
assert o.convert(None) is None
|
||||
for value in okay:
|
||||
assert o.convert(value) is value
|
||||
|
||||
@ -821,6 +822,7 @@ class test_Str(ClassChecker):
|
||||
assert e.name == 'my_str'
|
||||
assert e.index == 18
|
||||
assert_equal(e.error, u'must be Unicode text')
|
||||
assert o.convert(None) is None
|
||||
|
||||
def test_rule_minlength(self):
|
||||
"""
|
||||
|
@ -171,11 +171,13 @@ def test_xml_loads():
|
||||
assert_equal(tup[0], params)
|
||||
|
||||
# Test un-serializing an RPC response containing a Fault:
|
||||
fault = Fault(69, unicode_str)
|
||||
data = dumps(fault, methodresponse=True, allow_none=True)
|
||||
e = raises(Fault, f, data)
|
||||
assert e.faultCode == 69
|
||||
assert_equal(e.faultString, unicode_str)
|
||||
for error in (unicode_str, u'hello'):
|
||||
fault = Fault(69, error)
|
||||
data = dumps(fault, methodresponse=True, allow_none=True, encoding='UTF-8')
|
||||
e = raises(Fault, f, data)
|
||||
assert e.faultCode == 69
|
||||
assert_equal(e.faultString, error)
|
||||
assert type(e.faultString) is unicode
|
||||
|
||||
|
||||
class test_xmlclient(PluginTester):
|
||||
@ -227,19 +229,19 @@ class test_xmlclient(PluginTester):
|
||||
context.xmlconn = DummyClass(
|
||||
(
|
||||
'user_add',
|
||||
(rpc.xml_wrap(params),),
|
||||
rpc.xml_wrap(params),
|
||||
{},
|
||||
rpc.xml_wrap(result),
|
||||
),
|
||||
(
|
||||
'user_add',
|
||||
(rpc.xml_wrap(params),),
|
||||
rpc.xml_wrap(params),
|
||||
{},
|
||||
Fault(3007, u"'four' is required"), # RequirementError
|
||||
),
|
||||
(
|
||||
'user_add',
|
||||
(rpc.xml_wrap(params),),
|
||||
rpc.xml_wrap(params),
|
||||
{},
|
||||
Fault(700, u'no such error'), # There is no error 700
|
||||
),
|
||||
|
Loading…
Reference in New Issue
Block a user