diff options
author | Rob Crittenden <rcritten@redhat.com> | 2008-10-08 23:31:49 -0400 |
---|---|---|
committer | Rob Crittenden <rcritten@redhat.com> | 2008-10-10 03:36:56 -0400 |
commit | 83bb41faebc0a61269f2869e9123166254fff5b3 (patch) | |
tree | cfb1e62a7e770c35d230ed778b5808a221234fcf | |
parent | 672c07566df8d838b46edb6b80ba73ade2a27d55 (diff) | |
download | freeipa-83bb41faebc0a61269f2869e9123166254fff5b3.tar.gz freeipa-83bb41faebc0a61269f2869e9123166254fff5b3.tar.xz freeipa-83bb41faebc0a61269f2869e9123166254fff5b3.zip |
Mechanism to convert from xmlrpclib.Fault to an IPAError exception
Include slew of new exceptions, not all of which are used yet
-rw-r--r-- | ipa_server/ipaldap.py | 17 | ||||
-rw-r--r-- | ipa_server/servercore.py | 3 | ||||
-rw-r--r-- | ipalib/errors.py | 137 | ||||
-rw-r--r-- | ipalib/plugins/b_xmlrpc.py | 3 | ||||
-rw-r--r-- | ipalib/plugins/f_user.py | 48 |
5 files changed, 173 insertions, 35 deletions
diff --git a/ipa_server/ipaldap.py b/ipa_server/ipaldap.py index 7ee31465c..a76040213 100644 --- a/ipa_server/ipaldap.py +++ b/ipa_server/ipaldap.py @@ -32,7 +32,7 @@ import ldap.sasl from ldap.controls import LDAPControl,DecodeControlTuples,EncodeControlTuples from ldap.ldapobject import SimpleLDAPObject from ipa_server import ipautil - +from ipalib import errors # Global variable to define SASL auth sasl_auth = ldap.sasl.sasl({},'GSSAPI') @@ -279,12 +279,12 @@ class IPAdmin(SimpleLDAPObject): res = self.search(*args) objtype, obj = self.result(res) except ldap.NO_SUCH_OBJECT, e: - raise e + raise errors.NotFound, notfound(args) except ldap.LDAPError, e: - raise e + raise errors.DatabaseError, e if not obj: - raise ldap.NO_SUCH_OBJECT + raise errors.NotFound, notfound(args) elif isinstance(obj,Entry): return obj @@ -308,7 +308,7 @@ class IPAdmin(SimpleLDAPObject): raise e if not obj: - raise ldap.NO_SUCH_OBJECT + raise errors.NotFound, notfound(args) entries = [] for s in obj: @@ -345,7 +345,7 @@ class IPAdmin(SimpleLDAPObject): raise e if not entries: - raise ldap.NO_SUCH_OBJECT + raise errors.NotFound, notfound(args) if partial == 1: counter = -1 @@ -408,10 +408,9 @@ class IPAdmin(SimpleLDAPObject): # it indicates the previous attribute was removed by another # update, making the oldentry stale. except ldap.NO_SUCH_ATTRIBUTE: - # FIXME: better error - raise SyntaxError("mid-air collision") + raise ipaldap.MidairCollision except ldap.LDAPError, e: - raise e + raise ipaldap.DatabaseError, e return True def generateModList(self, old_entry, new_entry): diff --git a/ipa_server/servercore.py b/ipa_server/servercore.py index a391c5cf9..d842a8c77 100644 --- a/ipa_server/servercore.py +++ b/ipa_server/servercore.py @@ -22,6 +22,7 @@ import string import re from ipa_server.context import context import ipautil +from ipalib import errors # temporary import krbV @@ -335,6 +336,6 @@ def get_ipa_config(): config = get_sub_entry("cn=etc," + basedn, searchfilter) except ldap.NO_SUCH_OBJECT, e: # FIXME - raise e + raise errors.NotFound return config diff --git a/ipalib/errors.py b/ipalib/errors.py index 097747ac7..c00db9dc6 100644 --- a/ipalib/errors.py +++ b/ipalib/errors.py @@ -240,3 +240,140 @@ class MissingOverrideError(RegistrationError): def __str__(self): return self.msg % (self.base.__name__, self.cls.__name__, self.cls) + +class GenericError(IPAError): + """Base class for our custom exceptions""" + faultCode = 1000 + fromFault = False + def __str__(self): + try: + return str(self.args[0]['args'][0]) + except: + try: + return str(self.args[0]) + except: + return str(self.__dict__) + +class DatabaseError(GenericError): + """A database error has occurred""" + faultCode = 1001 + +class MidairCollision(GenericError): + """Change collided with another change""" + faultCode = 1002 + +class NotFound(GenericError): + """Entry not found""" + faultCode = 1003 + +class Duplicate(GenericError): + """This entry already exists""" + faultCode = 1004 + +class MissingDN(GenericError): + """The distinguished name (DN) is missing""" + faultCode = 1005 + +class EmptyModlist(GenericError): + """No modifications to be performed""" + faultCode = 1006 + +class InputError(GenericError): + """Error on input""" + faultCode = 1007 + +class SameGroupError(InputError): + """You can't add a group to itself""" + faultCode = 1008 + +class AdminsImmutable(InputError): + """The admins group cannot be renamed""" + faultCode = 1009 + +class UsernameTooLong(InputError): + """The requested username is too long""" + faultCode = 1010 + +class PrincipalError(GenericError): + """There is a problem with the kerberos principal""" + faultCode = 1011 + +class MalformedServicePrincipal(PrincipalError): + """The requested service principal is not of the form: service/fully-qualified host name""" + faultCode = 1012 + +class RealmMismatch(PrincipalError): + """The realm for the principal does not match the realm for this IPA server""" + faultCode = 1013 + +class PrincipalRequired(PrincipalError): + """You cannot remove IPA server service principals""" + faultCode = 1014 + +class InactivationError(GenericError): + """This entry cannot be inactivated""" + faultCode = 1015 + +class ConnectionError(GenericError): + """Connection to database failed""" + faultCode = 1016 + +class NoCCacheError(GenericError): + """No Kerberos credentials cache is available. Connection cannot be made""" + faultCode = 1017 + +class GSSAPIError(GenericError): + """GSSAPI Authorization error""" + faultCode = 1018 + +class ServerUnwilling(GenericError): + """Account inactivated. Server is unwilling to perform""" + faultCode = 1018 + +class ConfigurationError(GenericError): + """A configuration error occurred""" + faultCode = 1019 + +class DefaultGroup(ConfigurationError): + """You cannot remove the default users group""" + faultCode = 1020 + +class FunctionDeprecated(GenericError): + """Raised by a deprecated function""" + faultCode = 2000 + +def convertFault(fault): + """Convert a fault to the corresponding Exception type, if possible""" + code = getattr(fault,'faultCode',None) + if code is None: + return fault + for v in globals().values(): + if type(v) == type(Exception) and issubclass(v,GenericError) and \ + code == getattr(v,'faultCode',None): + ret = v(fault.faultString) + ret.fromFault = True + return ret + #otherwise... + return fault + +def listFaults(): + """Return a list of faults + + Returns a list of dictionaries whose keys are: + faultCode: the numeric code used in fault conversion + name: the name of the exception + desc: the description of the exception (docstring) + """ + ret = [] + for n,v in globals().items(): + if type(v) == type(Exception) and issubclass(v,GenericError): + code = getattr(v,'faultCode',None) + if code is None: + continue + info = {} + info['faultCode'] = code + info['name'] = n + info['desc'] = getattr(v,'__doc__',None) + ret.append(info) + ret.sort(lambda a,b: cmp(a['faultCode'],b['faultCode'])) + return ret diff --git a/ipalib/plugins/b_xmlrpc.py b/ipalib/plugins/b_xmlrpc.py index feb87556b..442afebfd 100644 --- a/ipalib/plugins/b_xmlrpc.py +++ b/ipalib/plugins/b_xmlrpc.py @@ -29,6 +29,7 @@ import socket from ipalib.backend import Backend from ipalib.util import xmlrpc_marshal from ipalib import api +from ipalib import errors class xmlrpc(Backend): """ @@ -51,5 +52,7 @@ class xmlrpc(Backend): except socket.error, e: print e[1] return False + except xmlrpclib.Fault, e: + raise errors.convertFault(e) api.register(xmlrpc) diff --git a/ipalib/plugins/f_user.py b/ipalib/plugins/f_user.py index f87ddea1f..8a1c3045d 100644 --- a/ipalib/plugins/f_user.py +++ b/ipalib/plugins/f_user.py @@ -25,6 +25,7 @@ from ipalib import frontend from ipalib import crud from ipalib.frontend import Param from ipalib import api +from ipalib import errors from ipa_server import servercore from ipa_server import ipaldap import ldap @@ -32,7 +33,7 @@ import ldap # Command to get the idea how plugins will interact with api.env class envtest(frontend.Command): 'Show current environment.' - def run(*args, **kw): + def run(self, *args, **kw): print "" print "Environment variables:" for var in api.env: @@ -87,18 +88,12 @@ class user_add(crud.Add): user = kw - if not isinstance(user, dict): - # FIXME, need proper error - raise SyntaxError - user['uid'] = args[0] if servercore.user_exists(user['uid']): - # FIXME, specific error - raise SyntaxError("user already exists") + raise errors.Duplicate("user already exists") if servercore.uid_too_long(user['uid']): - # FIXME, specific error - raise SyntaxError("uid is too long") + raise errors.UsernameTooLong # dn is set here, not by the user try: @@ -139,17 +134,15 @@ class user_add(crud.Add): 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 errors.NotFound: + # Fake an LDAP error so we can return something useful to the user + raise ipalib.NotFound, "The default group for new users, '%s', cannot be found." % config.get('ipadefaultprimarygroup') except Exception, e: - # FIXME + # catch everything else raise e if user.get('krbprincipalname') is None: - user['krbprincipalname'] = "%s@%s" % (user.get('uid'), self.realm) + user['krbprincipalname'] = "%s@%s" % (user.get('uid'), servercore.realm) # FIXME. This is a hack so we can request separate First and Last # name in the GUI. @@ -169,7 +162,7 @@ class user_add(crud.Add): return result def forward(self, *args, **kw): result = super(crud.Add, self).forward(*args, **kw) - if result != False: + if result: print "User %s added" % args[0] api.register(user_add) @@ -190,17 +183,18 @@ class user_del(crud.Del): """ uid = args[0] if uid == "admin": - raise ipaerror.gen_exception(ipaerror.INPUT_ADMIN_REQUIRED) + # FIXME: do we still want a "special" user? + raise SyntaxError("admin required") +# raise ipaerror.gen_exception(ipaerror.INPUT_ADMIN_REQUIRED) # logging.info("IPA: delete_user '%s'" % uid) user = servercore.get_user_by_uid(uid, ['dn', 'uid']) if not user: - # FIXME, specific error - raise SyntaxError("user doesn't exist") + raise errors.NotFound return servercore.delete_entry(user['dn']) def forward(self, *args, **kw): result = super(crud.Del, self).forward(*args, **kw) - if result != False: + if result: print "User %s removed" % args[0] api.register(user_del) @@ -224,7 +218,7 @@ class user_mod(crud.Mod): return result def forward(self, *args, **kw): result = super(crud.Mod, self).forward(*args, **kw) - if result != False: + if result: print "User %s modified" % args[0] api.register(user_mod) @@ -259,7 +253,11 @@ class user_show(crud.Get): 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] + try: + result = super(crud.Get, self).forward(*args, **kw) + if not result: return + for a in result: + print a, ": ", result[a] + except errors.NotFound: + print "User %s not found" % args[0] api.register(user_show) |