Sundry work getting ready to switch to new XML-RPC client/server code

This commit is contained in:
Jason Gerard DeRose 2009-01-22 14:00:37 -07:00 committed by Rob Crittenden
parent 46c10d4608
commit 9f48612a56
5 changed files with 132 additions and 2 deletions
ipalib
ipaserver/plugins
tests

View File

@ -0,0 +1,29 @@
# Authors:
# Jason Gerard DeRose <jderose@redhat.com>
# Rob Crittenden <rcritten@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
"""
XML-RPC client plugin.
"""
from ipalib import api
if 'in_server' in api.env and api.env.in_server is False:
from ipalib.rpc import xmlclient
api.register(xmlclient)

View File

@ -1,5 +1,6 @@
# Authors:
# Jason Gerard DeRose <jderose@redhat.com>
# Rob Crittenden <rcritten@redhat.com>
#
# Copyright (C) 2008 Red Hat
# see file 'COPYING' for use and warranty information
@ -31,7 +32,8 @@ Also see the `ipaserver.rpcserver` module.
from types import NoneType
import threading
from xmlrpclib import Binary, Fault, dumps, loads
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.request import context
@ -161,15 +163,62 @@ def xml_loads(data):
return (xml_unwrap(params), method)
class KerbTransport(SafeTransport):
"""
Handles Kerberos Negotiation authentication to an XML-RPC server.
"""
def get_host_info(self, host):
(host, extra_headers, x509) = SafeTransport.get_host_info(self, host)
# Set the remote host principal
service = "HTTP@" + host.split(':')[0]
try:
(rc, vc) = kerberos.authGSSClientInit(service)
except kerberos.GSSError, e:
raise e # FIXME: raise a PublicError
try:
kerberos.authGSSClientStep(vc, "")
except kerberos.GSSError, e:
raise e # FIXME: raise a PublicError
extra_headers += [
('Authorization', 'negotiate %s' % kerberos.authGSSClientResponse(vc))
]
return (host, extra_headers, x509)
class xmlclient(Backend):
"""
Forwarding backend for XML-RPC client.
"""
connection_name = 'xmlconn'
def __init__(self):
super(xmlclient, self).__init__()
self.__errors = dict((e.errno, e) for e in public_errors)
def connect(self, ccache=None, user=None, password=None):
if hasattr(context, self.connection_name):
raise StandardError(
'%s.connect(): context.%s already exists in thread %r' % (
self.name, self.connection_name, threading.currentThread().getName()
)
)
conn = ServerProxy(self.env.xmlrpc_uri,
transport=KerbTransport(),
allow_none=True,
)
setattr(context, self.connection_name, conn)
def get_connection(self):
return getattr(context, self.connection_name)
def forward(self, name, *args, **kw):
"""
Forward call to command named ``name`` over XML-RPC.
@ -197,6 +246,8 @@ class xmlclient(Backend):
response = command(xml_wrap(params))
return xml_unwrap(response)
except 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:
error = self.__errors[e.faultCode]
raise error(message=e.faultString)

View File

@ -0,0 +1,29 @@
# Authors:
# Jason Gerard DeRose <jderose@redhat.com>
# Rob Crittenden <rcritten@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
"""
XML-RPC client plugin.
"""
from ipalib import api
if 'in_server' in api.env and api.env.in_server is True:
from ipaserver.rpcserver import xmlserver
api.register(xmlserver)

View File

@ -22,7 +22,7 @@ Test the `ipalib.rpc` module.
"""
import threading
from xmlrpclib import Binary, Fault, dumps, loads
from xmlrpclib import Binary, Fault, dumps, loads, ServerProxy
from tests.util import raises, assert_equal, PluginTester, DummyClass
from tests.data import binary_bytes, utf8_bytes, unicode_str
from ipalib.frontend import Command
@ -184,6 +184,20 @@ class test_xmlclient(PluginTester):
"""
_plugin = rpc.xmlclient
def test_connect(self):
(o, api, home) = self.instance('Backend', in_server=False)
# Test that StandardError is raised if conntext.xmlconn already exists:
context.xmlconn = 'The xmlrpclib.ServerProxy instance'
e = raises(StandardError, o.connect)
assert str(e) == '%s.connect(): context.%s already exists in thread %r' % (
'xmlclient', 'xmlconn', threading.currentThread().getName()
)
del context.xmlconn
o.connect()
assert isinstance(context.xmlconn, ServerProxy)
def test_forward(self):
"""
Test the `ipalib.rpc.xmlclient.forward` method.

View File

@ -295,6 +295,13 @@ class PluginTester(object):
o = api[namespace][self.plugin.__name__]
return (o, api, home)
def tearDown(self):
"""
nose tear-down fixture.
"""
for name in context.__dict__.keys():
delattr(context, name)
class dummy_ugettext(object):
__called = False