summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJason Gerard DeRose <jderose@redhat.com>2008-10-07 17:00:36 -0600
committerJason Gerard DeRose <jderose@redhat.com>2008-10-07 17:00:36 -0600
commitc747c12fb2249e987d327f764bf9f1ddb5e60ee6 (patch)
tree96c689843f2e6abdd5c3506783268fb0dfc36816
parent439d9c305b7a2353ecb9373cf14c4e926522aaa3 (diff)
parentdb9d8dd3e0924bb9c7f9c89a56e6b6057dabc710 (diff)
downloadfreeipa-c747c12fb2249e987d327f764bf9f1ddb5e60ee6.tar.gz
freeipa-c747c12fb2249e987d327f764bf9f1ddb5e60ee6.tar.xz
freeipa-c747c12fb2249e987d327f764bf9f1ddb5e60ee6.zip
Merge branch 'master' of git://git.engineering.redhat.com/users/rcritten/freeipa2
-rw-r--r--ipa_server/ipaldap.py18
-rw-r--r--ipa_server/ipautil.py11
-rw-r--r--ipa_server/servercore.py209
-rw-r--r--ipalib/plugins/b_xmlrpc.py9
-rw-r--r--ipalib/plugins/f_group.py116
-rw-r--r--ipalib/plugins/f_user.py153
-rwxr-xr-xsimple-server.py2
-rwxr-xr-xtest_server (renamed from ipa_server/test_server)15
8 files changed, 501 insertions, 32 deletions
diff --git a/ipa_server/ipaldap.py b/ipa_server/ipaldap.py
index c1d134a00..4ab0d759c 100644
--- a/ipa_server/ipaldap.py
+++ b/ipa_server/ipaldap.py
@@ -33,7 +33,8 @@ import struct
import ldap.sasl
from ldap.controls import LDAPControl,DecodeControlTuples,EncodeControlTuples
from ldap.ldapobject import SimpleLDAPObject
-import ipautil
+from ipa_server import ipautil
+
# Global variable to define SASL auth
sasl_auth = ldap.sasl.sasl({},'GSSAPI')
@@ -108,7 +109,20 @@ class Entry:
"""Convert the attrs and values to a list of 2-tuples. The first element
of the tuple is the attribute name. The second element is either a
single value or a list of values."""
- return self.data.items()
+ r = []
+ for i in self.data.iteritems():
+ n = ipautil.utf8_encode_values(i[1])
+ r.append((i[0], n))
+ return r
+
+ def toDict(self):
+ """Convert the attrs and values to a dict. The dict is keyed on the
+ attribute name. The value is either single value or a list of values."""
+ result = ipautil.CIDict(self.data)
+ for i in result.keys():
+ result[i] = ipautil.utf8_encode_values(result[i])
+ result['dn'] = self.dn
+ return result
def __str__(self):
"""Convert the Entry to its LDIF representation"""
diff --git a/ipa_server/ipautil.py b/ipa_server/ipautil.py
index 6b0e2c892..6422fe5a6 100644
--- a/ipa_server/ipautil.py
+++ b/ipa_server/ipautil.py
@@ -188,3 +188,14 @@ def get_gsserror(e):
secondary = e[0][1]
return (primary[0], secondary[0])
+
+def utf8_encode_value(value):
+ if isinstance(value,unicode):
+ return value.encode('utf-8')
+ return value
+
+def utf8_encode_values(values):
+ if isinstance(values,list) or isinstance(values,tuple):
+ return map(utf8_encode_value, values)
+ else:
+ return utf8_encode_value(values)
diff --git a/ipa_server/servercore.py b/ipa_server/servercore.py
index eeecd4b03..f0d3dd9aa 100644
--- a/ipa_server/servercore.py
+++ b/ipa_server/servercore.py
@@ -17,10 +17,9 @@
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#
-import sys
-sys.path.insert(0, ".")
-sys.path.insert(0, "..")
import ldap
+import string
+import re
from ipa_server.context import context
import ipautil
@@ -31,6 +30,10 @@ krbctx = krbV.default_context()
realm = krbctx.default_realm
basedn = ipautil.realm_to_suffix(realm)
+DefaultUserContainer = "cn=users,cn=accounts"
+DefaultGroupContainer = "cn=groups,cn=accounts"
+DefaultServiceContainer = "cn=services,cn=accounts"
+
def convert_entry(ent):
entry = dict(ent.data)
entry['dn'] = ent.dn
@@ -55,6 +58,30 @@ def convert_scalar_values(orig_dict):
return new_dict
+def generate_match_filters(search_fields, criteria_words):
+ """Generates a search filter based on a list of words and a list
+ of fields to search against.
+
+ Returns a tuple of two filters: (exact_match, partial_match)"""
+
+ # construct search pattern for a single word
+ # (|(f1=word)(f2=word)...)
+ search_pattern = "(|"
+ for field in search_fields:
+ search_pattern += "(" + field + "=%(match)s)"
+ search_pattern += ")"
+ gen_search_pattern = lambda word: search_pattern % {'match':word}
+
+ # construct the giant match for all words
+ exact_match_filter = "(&"
+ partial_match_filter = "(|"
+ for word in criteria_words:
+ exact_match_filter += gen_search_pattern(word)
+ partial_match_filter += gen_search_pattern("*%s*" % word)
+ exact_match_filter += ")"
+ partial_match_filter += ")"
+
+ return (exact_match_filter, partial_match_filter)
# TODO: rethink the get_entry vs get_list API calls.
# they currently restrict the data coming back without
@@ -95,14 +122,160 @@ def get_list (base, searchfilter, sattrs=None):
return map(convert_entry, entries)
-def update_entry (oldentry, newentry):
+# General searches
+
+def get_entry_by_dn (dn, sattrs=None):
+ """Get a specific entry. Return as a dict of values.
+ Multi-valued fields are represented as lists.
+ """
+ searchfilter = "(objectClass=*)"
+# logging.info("IPA: get_entry_by_dn '%s'" % dn)
+ return get_base_entry(dn, searchfilter, sattrs)
+
+# User support
+
+def is_user_unique(uid):
+ """Return True if the uid is unique in the tree, False otherwise."""
+ # FIXME
+# uid = self.__safe_filter(uid)
+ searchfilter = "(&(uid=%s)(objectclass=posixAccount))" % uid
+
+ try:
+ entry = get_sub_entry("cn=accounts," + basedn, searchfilter, ['dn','uid'])
+ return False
+# except ipaerror.exception_for(ipaerror.LDAP_NOT_FOUND):
+ except Exception:
+ return True
+
+def get_user_by_uid (uid, sattrs):
+ """Get a specific user's entry. Return as a dict of values.
+ Multi-valued fields are represented as lists.
+ """
+
+ if not isinstance(uid,basestring) or len(uid) == 0:
+ raise SyntaxError("uid is not a string")
+# raise ipaerror.gen_exception(ipaerror.INPUT_INVALID_PARAMETER)
+ if sattrs is not None and not isinstance(sattrs,list):
+ raise SyntaxError("sattrs is not a list")
+# raise ipaerror.gen_exception(ipaerror.INPUT_INVALID_PARAMETER)
+# logging.info("IPA: get_user_by_uid '%s'" % uid)
+# uid = self.__safe_filter(uid)
+ searchfilter = "(uid=" + uid + ")"
+ return get_sub_entry("cn=accounts," + basedn, searchfilter, sattrs)
+
+def uid_too_long(uid):
+ """Verify that the new uid is within the limits we set. This is a
+ very narrow test.
+
+ Returns True if it is longer than allowed
+ False otherwise
+ """
+ if not isinstance(uid,basestring) or len(uid) == 0:
+ # It is bad, but not too long
+ return False
+# logging.debug("IPA: __uid_too_long(%s)" % uid)
+ try:
+ config = get_ipa_config()
+ maxlen = int(config.get('ipamaxusernamelength', 0))
+ if maxlen > 0 and len(uid) > maxlen:
+ return True
+ except Exception, e:
+# logging.debug("There was a problem " + str(e))
+ pass
+
+ return False
+
+def find_users (criteria, sattrs, sizelimit=-1, timelimit=-1):
+ """Returns a list: counter followed by the results.
+ If the results are truncated, counter will be set to -1."""
+
+ """
+ if not isinstance(criteria,basestring) or len(criteria) == 0:
+ raise ipaerror.gen_exception(ipaerror.INPUT_INVALID_PARAMETER)
+ if sattrs is not None and not isinstance(sattrs, list):
+ raise ipaerror.gen_exception(ipaerror.INPUT_INVALID_PARAMETER)
+ if not isinstance(sizelimit,int):
+ raise ipaerror.gen_exception(ipaerror.INPUT_INVALID_PARAMETER)
+ if not isinstance(timelimit,int):
+ raise ipaerror.gen_exception(ipaerror.INPUT_INVALID_PARAMETER)
+ """
+
+# logging.info("IPA: find_users '%s'" % criteria)
+ config = get_ipa_config()
+ if timelimit < 0:
+ timelimit = float(config.get('ipasearchtimelimit'))
+ if sizelimit < 0:
+ sizelimit = int(config.get('ipasearchrecordslimit'))
+
+ # Assume the list of fields to search will come from a central
+ # configuration repository. A good format for that would be
+ # a comma-separated list of fields
+ search_fields_conf_str = config.get('ipausersearchfields')
+ search_fields = string.split(search_fields_conf_str, ",")
+
+# criteria = self.__safe_filter(criteria)
+ criteria_words = re.split(r'\s+', criteria)
+ criteria_words = filter(lambda value:value!="", criteria_words)
+ if len(criteria_words) == 0:
+ return [0]
+
+ (exact_match_filter, partial_match_filter) = generate_match_filters(
+ search_fields, criteria_words)
+
+ #
+ # further constrain search to just the objectClass
+ # TODO - need to parameterize this into generate_match_filters,
+ # and work it into the field-specification search feature
+ #
+ exact_match_filter = "(&(objectClass=person)%s)" % exact_match_filter
+ partial_match_filter = "(&(objectClass=person)%s)" % partial_match_filter
+
+ try:
+ exact_results = context.conn.getConn().getListAsync("cn=accounts," + basedn, ldap.SCOPE_SUBTREE, exact_match_filter, sattrs, 0, None, None, timelimit, sizelimit)
+# except ipaerror.exception_for(ipaerror.LDAP_NOT_FOUND):
+ except Exception:
+ exact_results = [0]
+
+ try:
+ partial_results = context.conn.getConn().getListAsync("cn=accounts," + basedn, ldap.SCOPE_SUBTREE, partial_match_filter, sattrs, 0, None, None, timelimit, sizelimit)
+# except ipaerror.exception_for(ipaerror.LDAP_NOT_FOUND):
+ except Exception:
+ partial_results = [0]
+
+ exact_counter = exact_results[0]
+ partial_counter = partial_results[0]
+
+ exact_results = exact_results[1:]
+ partial_results = partial_results[1:]
+
+ # Remove exact matches from the partial_match list
+ exact_dns = set(map(lambda e: e.dn, exact_results))
+ partial_results = filter(lambda e: e.dn not in exact_dns,
+ partial_results)
+
+ if (exact_counter == -1) or (partial_counter == -1):
+ counter = -1
+ else:
+ counter = len(exact_results) + len(partial_results)
+
+ users = [counter]
+ for u in exact_results + partial_results:
+ users.append(convert_entry(u))
+
+ return users
+
+def update_entry (entry):
"""Update an LDAP entry
- oldentry is a dict
- newentry is a dict
+ entry is a dict
+
+ This refreshes the record from LDAP in order to obtain the list of
+ attributes that has changed.
"""
- oldentry = convert_scalar_values(oldentry)
- newentry = convert_scalar_values(newentry)
+ attrs = entry.keys()
+ o = get_base_entry(entry['dn'], "objectclass=*", attrs)
+ oldentry = convert_scalar_values(o)
+ newentry = convert_scalar_values(entry)
# Should be able to get this from either the old or new entry
# but just in case someone has decided to try changing it, use the
@@ -113,13 +286,16 @@ def update_entry (oldentry, newentry):
# FIXME: return a missing DN error message
raise e
- res = context.conn.getConn().updateEntry(moddn, oldentry, newentry)
- return res
+ return context.conn.getConn().updateEntry(moddn, oldentry, newentry)
+
+def add_entry(entry):
+ """Add a new entry"""
+ return context.conn.getConn().addEntry(entry)
def uniq_list(x):
"""Return a unique list, preserving order and ignoring case"""
myset = {}
- return [set.setdefault(e.lower(),e) for e in x if e.lower() not in myset]
+ return [myset.setdefault(e.lower(),e) for e in x if e.lower() not in myset]
def get_schema():
"""Retrieves the current LDAP schema from the LDAP server."""
@@ -146,3 +322,14 @@ def get_objectclasses():
result.append(oc[3].replace("'",""))
return result
+
+def get_ipa_config():
+ """Retrieve the IPA configuration"""
+ searchfilter = "cn=ipaconfig"
+ try:
+ config = get_sub_entry("cn=etc," + basedn, searchfilter)
+ except ldap.NO_SUCH_OBJECT, e:
+ # FIXME
+ raise e
+
+ return config
diff --git a/ipalib/plugins/b_xmlrpc.py b/ipalib/plugins/b_xmlrpc.py
index 61935f013..d7cbd8560 100644
--- a/ipalib/plugins/b_xmlrpc.py
+++ b/ipalib/plugins/b_xmlrpc.py
@@ -24,6 +24,7 @@ Lightwieght XML-RPC client using Python standard library xmlrpclib.
"""
import xmlrpclib
+import socket
from ipalib.backend import Backend
from ipalib.util import xmlrpc_marshal
from ipalib import api
@@ -35,7 +36,7 @@ class xmlrpc(Backend):
def get_client(self):
# FIXME: The server uri should come from self.api.env.server_uri
- return xmlrpclib.ServerProxy('http://localhost:8080', allow_none=True)
+ return xmlrpclib.ServerProxy('http://localhost:8888', allow_none=True)
def forward_call(self, name, *args, **kw):
"""
@@ -44,6 +45,10 @@ class xmlrpc(Backend):
client = self.get_client()
command = getattr(client, name)
params = xmlrpc_marshal(*args, **kw)
- return command(*params)
+ try:
+ return command(*params)
+ except socket.error, e:
+ print e[1]
+ return False
api.register(xmlrpc)
diff --git a/ipalib/plugins/f_group.py b/ipalib/plugins/f_group.py
new file mode 100644
index 000000000..c5a37e725
--- /dev/null
+++ b/ipalib/plugins/f_group.py
@@ -0,0 +1,116 @@
+# 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
+
+"""
+Frontend plugins for group (Identity).
+"""
+
+from ipalib import frontend
+from ipalib import crud
+from ipalib.frontend import Param
+from ipalib import api
+from ipa_server import servercore
+from ipa_server import ipaldap
+import ldap
+
+
+class group(frontend.Object):
+ """
+ Group object.
+ """
+ takes_params = (
+ 'description',
+ Param('cn',
+ primary_key=True,
+ normalize=lambda value: value.lower(),
+ )
+ )
+api.register(group)
+
+
+class group_add(crud.Add):
+ 'Add a new group.'
+ def execute(self, *args, **kw):
+ """args[0] = uid of the group to add
+ kw{container} is the location in the DIT to add the group, not
+ required
+ kw otherwise contains all the attributes
+ """
+ # FIXME: ug, really?
+ if not kw.get('container'):
+ group_container = servercore.DefaultGroupContainer
+ else:
+ group_container = kw['container']
+ del kw['container']
+
+ group = kw
+
+ group['cn'] = args[0]
+
+ # Get our configuration
+ config = servercore.get_ipa_config()
+
+ dn="cn=%s,%s,%s" % (ldap.dn.escape_dn_chars(group['cn']),
+ group_container,servercore.basedn)
+
+ entry = ipaldap.Entry(dn)
+
+ # some required objectclasses
+ entry.setValues('objectClass', (config.get('ipagroupobjectclasses')))
+
+ # No need to explicitly set gidNumber. The dna_plugin will do this
+ # for us if the value isn't provided by the user.
+
+ # fill in our new entry with everything sent by the user
+ for g in group:
+ entry.setValues(g, group[g])
+
+ result = servercore.add_entry(entry)
+ return result
+
+
+api.register(group_add)
+
+
+class group_del(crud.Del):
+ 'Delete an existing group.'
+api.register(group_del)
+
+
+class group_mod(crud.Mod):
+ 'Edit an existing group.'
+api.register(group_mod)
+
+
+class group_find(crud.Find):
+ 'Search the groups.'
+ def execute(self, *args, **kw):
+ cn=args[0]
+ result = servercore.get_sub_entry(servercore.basedn, "cn=%s" % cn, ["*"])
+ return result
+ def forward(self, *args, **kw):
+ result = super(crud.Find, self).forward(*args, **kw)
+ for a in result:
+ print a, ": ", result[a]
+api.register(group_find)
+
+
+class group_show(crud.Get):
+ 'Examine an existing group.'
+api.register(group_show)
diff --git a/ipalib/plugins/f_user.py b/ipalib/plugins/f_user.py
index 150d48ead..b006c24b2 100644
--- a/ipalib/plugins/f_user.py
+++ b/ipalib/plugins/f_user.py
@@ -25,7 +25,9 @@ from ipalib import frontend
from ipalib import crud
from ipalib.frontend import Param
from ipalib import api
-
+from ipa_server import servercore
+from ipa_server import ipaldap
+import ldap
# Command to get the idea how plugins will interact with api.env
class envtest(frontend.Command):
@@ -71,7 +73,105 @@ api.register(user)
class user_add(crud.Add):
'Add a new user.'
def execute(self, *args, **kw):
- return 1
+ """args[0] = uid of the user to add
+ kw{container} is the location in the DIT to add the user, not
+ required
+ kw otherwise contains all the attributes
+ """
+ # FIXME: ug, really?
+ if not kw.get('container'):
+ user_container = servercore.DefaultUserContainer
+ else:
+ user_container = kw['container']
+ del kw['container']
+
+ user = kw
+
+ if not isinstance(user, dict):
+ # FIXME, need proper error
+ raise SyntaxError
+
+ user['uid'] = args[0]
+
+ if not servercore.is_user_unique(user['uid']):
+ # FIXME, specific error
+ raise SyntaxError("user already exists")
+ if servercore.uid_too_long(user['uid']):
+ # FIXME, specific error
+ raise SyntaxError("uid is too long")
+
+ # dn is set here, not by the user
+ try:
+ del user['dn']
+ except KeyError:
+ pass
+
+ # No need to set empty fields, and they can cause issues when they
+ # get to LDAP, like:
+ # TypeError: ('expected a string in the list', None)
+ for k in user.keys():
+ if not user[k] or len(user[k]) == 0 or (isinstance(user[k],list) and len(user[k]) == 1 and '' in user[k]):
+ del user[k]
+
+ dn="uid=%s,%s,%s" % (ldap.dn.escape_dn_chars(user['uid']),
+ user_container,servercore.basedn)
+
+ entry = ipaldap.Entry(dn)
+
+ # Get our configuration
+ config = servercore.get_ipa_config()
+
+ # Let us add in some missing attributes
+ if user.get('homedirectory') is None:
+ user['homedirectory'] = '%s/%s' % (config.get('ipahomesrootdir'), user.get('uid'))
+ user['homedirectory'] = user['homedirectory'].replace('//', '/')
+ user['homedirectory'] = user['homedirectory'].rstrip('/')
+ if user.get('loginshell') is None:
+ user['loginshell'] = config.get('ipadefaultloginshell')
+ if user.get('gecos') is None:
+ user['gecos'] = user['uid']
+
+ # If uidnumber is blank the the FDS dna_plugin will automatically
+ # assign the next value. So we don't have to do anything with it.
+
+ group_dn="cn=%s,%s,%s" % (config.get('ipadefaultprimarygroup'), servercore.DefaultGroupContainer, servercore.basedn)
+ try:
+ default_group = servercore.get_entry_by_dn(group_dn, ['dn','gidNumber'])
+ if default_group:
+ user['gidnumber'] = default_group.get('gidnumber')
+# except ipaerror.exception_for(ipaerror.LDAP_DATABASE_ERROR), e:
+# raise ipaerror.gen_exception(ipaerror.LDAP_DATABASE_ERROR, message=None, nested_exception=e.detail)
+# except ipaerror.exception_for(ipaerror.LDAP_NOT_FOUND):
+# # Fake an LDAP error so we can return something useful to the user
+# raise ipaerror.gen_exception(ipaerror.LDAP_NOT_FOUND, "The default group for new users, '%s', cannot be found." % config.get('ipadefaultprimarygroup'))
+ except Exception, e:
+ # FIXME
+ raise e
+
+ if user.get('krbprincipalname') is None:
+ user['krbprincipalname'] = "%s@%s" % (user.get('uid'), self.realm)
+
+ # FIXME. This is a hack so we can request separate First and Last
+ # name in the GUI.
+ if user.get('cn') is None:
+ user['cn'] = "%s %s" % (user.get('givenname'),
+ user.get('sn'))
+
+ # some required objectclasses
+ entry.setValues('objectClass', (config.get('ipauserobjectclasses')))
+ # entry.setValues('objectClass', ['top', 'person', 'organizationalPerson', 'inetOrgPerson', 'inetUser', 'posixAccount', 'krbPrincipalAux'])
+
+ # fill in our new entry with everything sent by the user
+ for u in user:
+ entry.setValues(u, user[u])
+
+ result = servercore.add_entry(entry)
+ return result
+ def forward(self, *args, **kw):
+ result = super(crud.Add, self).forward(*args, **kw)
+ if result != False:
+ print "User %s added" % args[0]
+
api.register(user_add)
@@ -82,18 +182,59 @@ api.register(user_del)
class user_mod(crud.Mod):
'Edit an existing user.'
+ def execute(self, *args, **kw):
+ uid=args[0]
+ result = servercore.get_sub_entry(servercore.basedn, "uid=%s" % uid, ["*"])
+
+ user = kw
+ dn = result.get('dn')
+ del result['dn']
+ entry = ipaldap.Entry((dn, servercore.convert_scalar_values(result)))
+
+ for u in user:
+ entry.setValues(u, user[u])
+
+ result = servercore.update_entry(entry.toDict())
+
+ return result
+ def forward(self, *args, **kw):
+ result = super(crud.Mod, self).forward(*args, **kw)
+ if result != False:
+ print "User %s modified" % args[0]
api.register(user_mod)
class user_find(crud.Find):
'Search the users.'
-# def execute(self, *args, **kw):
-# uid=args[0]
-# result = servercore.get_sub_entry(servercore.basedn, "uid=%s" % uid, ["*"])
-# return result
+ def execute(self, *args, **kw):
+ uid=args[0]
+ result = servercore.find_users(uid, ["*"])
+ return result
+ def forward(self, *args, **kw):
+ users = super(crud.Find, self).forward(*args, **kw)
+ counter = users[0]
+ users = users[1:]
+ if counter == 0:
+ print "No entries found for", args[0]
+ return
+ elif counter == -1:
+ print "These results are truncated."
+ print "Please refine your search and try again."
+
+ for u in users:
+ for a in u.keys():
+ print "%s: %s" % (a, u[a])
api.register(user_find)
class user_show(crud.Get):
'Examine an existing user.'
+ def execute(self, *args, **kw):
+ uid=args[0]
+ result = servercore.get_user_by_uid(uid, ["*"])
+ return result
+ def forward(self, *args, **kw):
+ result = super(crud.Get, self).forward(*args, **kw)
+ for a in result:
+ print a, ": ", result[a]
api.register(user_show)
diff --git a/simple-server.py b/simple-server.py
index 2f0d92266..6d29d74ab 100755
--- a/simple-server.py
+++ b/simple-server.py
@@ -43,7 +43,7 @@ class Dispatch(object):
return self.__cmd(*args, **kw)
-server = SimpleXMLRPCServer(('localhost', 8080), allow_none=True)
+server = SimpleXMLRPCServer(('localhost', 8880), allow_none=True)
server.register_introspection_functions()
for cmd in api.Command():
server.register_function(Dispatch(cmd), cmd.name)
diff --git a/ipa_server/test_server b/test_server
index a67263699..0ee250ad7 100755
--- a/ipa_server/test_server
+++ b/test_server
@@ -1,8 +1,6 @@
#!/usr/bin/env python
import sys
-sys.path.insert(0, "..")
-sys.path.insert(0, ".")
import SimpleXMLRPCServer
import logging
import xmlrpclib
@@ -10,9 +8,10 @@ import re
import threading
import commands
from ipalib import api
-import conn
+from ipa_server import conn
from ipa_server.servercore import context
import ipalib.load_plugins
+from ipalib.util import xmlrpc_unmarshal
import traceback
PORT=8888
@@ -59,12 +58,8 @@ class LoggingSimpleXMLRPCRequestHandler(SimpleXMLRPCServer.SimpleXMLRPCRequestHa
func = funcs[method]
except KeyError:
raise Exception('method "%s" is not supported' % method)
- if len(params) > 1 and isinstance(params[-1], dict):
- kw = params[-1]
- params = params[:-1]
- return func(*params, **kw)
- else:
- return func(*params)
+ (args, kw) = xmlrpc_unmarshal(*params)
+ return func(*args, **kw)
finally:
# Clean up any per-request data and connections
# for k in context.__dict__.keys():
@@ -109,7 +104,6 @@ class LoggingSimpleXMLRPCRequestHandler(SimpleXMLRPCServer.SimpleXMLRPCRequestHa
# Log client request
logger.info('Client request: \n%s\n' % data)
-# response = self.server._marshaled_dispatch(
response = self._marshaled_dispatch(
data, getattr(self, '_dispatch', None))
@@ -147,6 +141,7 @@ XMLRPCServer = StoppableXMLRPCServer(("",PORT), LoggingSimpleXMLRPCRequestHandle
XMLRPCServer.register_introspection_functions()
# Get and register all the methods
+api.env.server_context = True
api.finalize()
for cmd in api.Method:
logger.info("registering %s" % cmd)