From 7d0bd4b8951ef7894668ad3c63607769e208c9d0 Mon Sep 17 00:00:00 2001 From: Pavel Zuna Date: Thu, 23 Apr 2009 14:51:59 +0200 Subject: Rename errors2.py to errors.py. Modify all affected files. --- ipalib/__init__.py | 2 +- ipalib/backend.py | 2 +- ipalib/cli.py | 2 +- ipalib/errors.py | 1077 +++++++++++++++++++++++++++++++++++++++++++ ipalib/errors2.py | 1077 ------------------------------------------- ipalib/frontend.py | 4 +- ipalib/parameters.py | 2 +- ipalib/plugable.py | 20 +- ipalib/plugins/aci.py | 28 +- ipalib/plugins/automount.py | 12 +- ipalib/plugins/basegroup.py | 4 +- ipalib/plugins/group.py | 4 +- ipalib/plugins/host.py | 6 +- ipalib/plugins/join.py | 8 +- ipalib/plugins/passwd.py | 4 +- ipalib/plugins/service.py | 10 +- ipalib/plugins/user.py | 6 +- ipalib/plugins/user2.py | 14 +- ipalib/rpc.py | 18 +- ipalib/util.py | 4 +- 20 files changed, 1152 insertions(+), 1152 deletions(-) create mode 100644 ipalib/errors.py delete mode 100644 ipalib/errors2.py (limited to 'ipalib') diff --git a/ipalib/__init__.py b/ipalib/__init__.py index b2fc1f857..a657ea974 100644 --- a/ipalib/__init__.py +++ b/ipalib/__init__.py @@ -878,7 +878,7 @@ from frontend import Object, Method, Property from crud import Create, Retrieve, Update, Delete, Search from parameters import DefaultFrom, Bool, Flag, Int, Float, Bytes, Str, Password,List from parameters import BytesEnum, StrEnum -from errors2 import SkipPluginModule +from errors import SkipPluginModule try: import uuid diff --git a/ipalib/backend.py b/ipalib/backend.py index 7bd9a29f8..03dae1ced 100644 --- a/ipalib/backend.py +++ b/ipalib/backend.py @@ -23,7 +23,7 @@ Base classes for all backed-end plugins. import threading import plugable -from errors2 import PublicError, InternalError, CommandError +from errors import PublicError, InternalError, CommandError from request import context, Connection, destroy_context diff --git a/ipalib/cli.py b/ipalib/cli.py index 6a1a6d0ff..4949a9b9f 100644 --- a/ipalib/cli.py +++ b/ipalib/cli.py @@ -36,7 +36,7 @@ import frontend import backend import plugable import util -from errors2 import PublicError, CommandError, HelpError, InternalError, NoSuchNamespaceError, ValidationError +from errors import PublicError, CommandError, HelpError, InternalError, NoSuchNamespaceError, ValidationError from constants import CLI_TAB from parameters import Password, Bytes from request import ugettext as _ diff --git a/ipalib/errors.py b/ipalib/errors.py new file mode 100644 index 000000000..f626f359d --- /dev/null +++ b/ipalib/errors.py @@ -0,0 +1,1077 @@ +# Authors: +# Jason Gerard DeRose +# +# Copyright (C) 2008 Red Hat +# see file 'COPYING' for use and warranty inmsgion +# +# 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 + +""" +Custom exception classes (some which are RPC transparent). + +`PrivateError` and its subclasses are custom IPA excetions that will *never* be +forwarded in a Remote Procedure Call (RPC) response. + +On the other hand, `PublicError` and its subclasses can be forwarded in an RPC +response. These public errors each carry a unique integer error code as well as +a gettext translated error message (translated at the time the exception is +raised). The purpose of the public errors is to relay information about +*expected* user errors, service availability errors, and so on. They should +*never* be used for *unexpected* programmatic or run-time errors. + +For security reasons it is *extremely* important that arbitrary exceptions *not* +be forwarded in an RPC response. Unexpected exceptions can easily contain +compromising information in their error messages. Any time the server catches +any exception that isn't a `PublicError` subclass, it should raise an +`InternalError`, which itself always has the same, static error message (and +therefore cannot be populated with information about the true exception). + +The public errors are arranging into five main blocks of error code ranges: + + ============= ======================================== + Error codes Exceptions + ============= ======================================== + 1000 - 1999 `AuthenticationError` and its subclasses + 2000 - 2999 `AuthorizationError` and its subclasses + 3000 - 3999 `InvocationError` and its subclasses + 4000 - 4999 `ExecutionError` and its subclasses + 5000 - 5999 `GenericError` and its subclasses + ============= ======================================== + +Within these five blocks some sub-ranges are already allocated for certain types +of error messages, while others are reserved for future use. Here are the +current block assignments: + + - **900-5999** `PublicError` and its subclasses + + - **901 - 907** Assigned to special top-level public errors + + - **908 - 999** *Reserved for future use* + + - **1000 - 1999** `AuthenticationError` and its subclasses + + - **1001 - 1099** Open for general authentication errors + + - **1100 - 1199** `KerberosError` and its subclasses + + - **1200 - 1999** *Reserved for future use* + + - **2000 - 2999** `AuthorizationError` and its subclasses + + - **2001 - 2099** Open for general authorization errors + + - **2100 - 2199** `ACIError` and its subclasses + + - **2200 - 2999** *Reserved for future use* + + - **3000 - 3999** `InvocationError` and its subclasses + + - **3001 - 3099** Open for general invocation errors + + - **3100 - 3199** *Reserved for future use* + + - **4000 - 4999** `ExecutionError` and its subclasses + + - **4001 - 4099** Open for general execution errors + + - **4100 - 4199** `BuiltinError` and its subclasses + + - **4200 - 4299** `LDAPError` and its subclasses + + - **4300 - 4999** *Reserved for future use* + + - **5000 - 5999** `GenericError` and its subclasses + + - **5001 - 5099** Open for generic errors + + - **5100 - 5999** *Reserved for future use* +""" + +from inspect import isclass +from request import ugettext, ungettext +from constants import TYPE_ERROR + + +class PrivateError(StandardError): + """ + Base class for exceptions that are *never* forwarded in an RPC response. + """ + + format = '' + + def __init__(self, **kw): + self.message = self.format % kw + for (key, value) in kw.iteritems(): + assert not hasattr(self, key), 'conflicting kwarg %s.%s = %r' % ( + self.__class__.__name__, key, value, + ) + setattr(self, key, value) + StandardError.__init__(self, self.message) + + +class SubprocessError(PrivateError): + """ + Raised when ``subprocess.call()`` returns a non-zero exit status. + + This custom exception is needed because Python 2.4 doesn't have the + ``subprocess.CalledProcessError`` exception (which was added in Python 2.5). + + For example: + + >>> raise SubprocessError(returncode=2, argv=('ls', '-lh', '/no-foo/')) + Traceback (most recent call last): + ... + SubprocessError: return code 2 from ('ls', '-lh', '/no-foo/') + + The exit code of the sub-process is available via the ``returncode`` + instance attribute. For example: + + >>> e = SubprocessError(returncode=1, argv=('/bin/false',)) + >>> e.returncode + 1 + >>> e.argv # argv is also available + ('/bin/false',) + """ + + format = 'return code %(returncode)d from %(argv)r' + + +class PluginSubclassError(PrivateError): + """ + Raised when a plugin doesn't subclass from an allowed base. + + For example: + + >>> raise PluginSubclassError(plugin='bad', bases=('base1', 'base2')) + Traceback (most recent call last): + ... + PluginSubclassError: 'bad' not subclass of any base in ('base1', 'base2') + + """ + + format = '%(plugin)r not subclass of any base in %(bases)r' + + +class PluginDuplicateError(PrivateError): + """ + Raised when the same plugin class is registered more than once. + + For example: + + >>> raise PluginDuplicateError(plugin='my_plugin') + Traceback (most recent call last): + ... + PluginDuplicateError: 'my_plugin' was already registered + """ + + format = '%(plugin)r was already registered' + + +class PluginOverrideError(PrivateError): + """ + Raised when a plugin overrides another without using ``override=True``. + + For example: + + >>> raise PluginOverrideError(base='Command', name='env', plugin='my_env') + Traceback (most recent call last): + ... + PluginOverrideError: unexpected override of Command.env with 'my_env' + """ + + format = 'unexpected override of %(base)s.%(name)s with %(plugin)r' + + +class PluginMissingOverrideError(PrivateError): + """ + Raised when a plugin overrides another that has not been registered. + + For example: + + >>> raise PluginMissingOverrideError(base='Command', name='env', plugin='my_env') + Traceback (most recent call last): + ... + PluginMissingOverrideError: Command.env not registered, cannot override with 'my_env' + """ + + format = '%(base)s.%(name)s not registered, cannot override with %(plugin)r' + + +class SkipPluginModule(PrivateError): + """ + Raised to abort the loading of a plugin module. + """ + + format = '%(reason)s' + + +class PluginsPackageError(PrivateError): + """ + Raised when ``package.plugins`` is a module instead of a sub-package. + """ + + format = '%(name)s must be sub-package, not module: %(file)r' + + +############################################################################## +# Public errors: + +__messages = [] + +def _(message): + __messages.append(message) + return message + + +class PublicError(StandardError): + """ + **900** Base class for exceptions that can be forwarded in an RPC response. + """ + + errno = 900 + format = None + + def __init__(self, format=None, message=None, **kw): + name = self.__class__.__name__ + if self.format is not None and format is not None: + raise ValueError( + 'non-generic %r needs format=None; got format=%r' % ( + name, format) + ) + if message is None: + if self.format is None: + if format is None: + raise ValueError( + '%s.format is None yet format=None, message=None' % name + ) + self.format = format + self.forwarded = False + self.message = self.format % kw + self.strerror = ugettext(self.format) % kw + else: + if type(message) is not unicode: + raise TypeError( + TYPE_ERROR % ('message', unicode, message, type(message)) + ) + self.forwarded = True + self.message = message + self.strerror = message + for (key, value) in kw.iteritems(): + assert not hasattr(self, key), 'conflicting kwarg %s.%s = %r' % ( + name, key, value, + ) + setattr(self, key, value) + StandardError.__init__(self, self.message) + + +class VersionError(PublicError): + """ + **901** Raised when client and server versions are incompatible. + + For example: + + >>> raise VersionError(cver='2.0', sver='2.1', server='https://localhost') + Traceback (most recent call last): + ... + VersionError: 2.0 client incompatible with 2.1 server at 'https://localhost' + + """ + + errno = 901 + 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): + """ + **903** Raised to conceal a non-public exception. + + For example: + + >>> raise InternalError() + Traceback (most recent call last): + ... + InternalError: an internal error has occured + """ + + errno = 903 + format = _('an internal error has occured') + + def __init__(self, message=None): + """ + Security issue: ignore any information given to constructor. + """ + PublicError.__init__(self) + + +class ServerInternalError(PublicError): + """ + **904** Raised when client catches an `InternalError` from server. + + For example: + + >>> raise ServerInternalError(server='https://localhost') + Traceback (most recent call last): + ... + ServerInternalError: an internal error has occured on server at 'https://localhost' + """ + + errno = 904 + format = _('an internal error has occured on server at %(server)r') + + +class CommandError(PublicError): + """ + **905** Raised when an unknown command is called. + + For example: + + >>> raise CommandError(name='foobar') + Traceback (most recent call last): + ... + CommandError: unknown command 'foobar' + """ + + errno = 905 + format = _('unknown command %(name)r') + + +class ServerCommandError(PublicError): + """ + **906** Raised when client catches a `CommandError` from server. + + For example: + + >>> e = CommandError(name='foobar') + >>> raise ServerCommandError(error=e.message, server='https://localhost') + Traceback (most recent call last): + ... + ServerCommandError: error on server 'https://localhost': unknown command 'foobar' + """ + + errno = 906 + format = _('error on server %(server)r: %(error)s') + + +class NetworkError(PublicError): + """ + **907** Raised when a network connection cannot be created. + + For example: + + >>> raise NetworkError(uri='ldap://localhost:389', error='Connection refused') + Traceback (most recent call last): + ... + NetworkError: cannot connect to 'ldap://localhost:389': Connection refused + """ + + errno = 907 + format = _('cannot connect to %(uri)r: %(error)s') + + +class ServerNetworkError(PublicError): + """ + **908** Raised when client catches a `NetworkError` from server. + """ + + errno = 908 + format = _('error on server %(server)r: %(error)s') + + + +############################################################################## +# 1000 - 1999: Authentication errors +class AuthenticationError(PublicError): + """ + **1000** Base class for authentication errors (*1000 - 1999*). + """ + + errno = 1000 + + +class KerberosError(AuthenticationError): + """ + **1100** Base class for Kerberos authentication errors (*1100 - 1199*). + """ + + errno = 1100 + + +class CCacheError(KerberosError): + """ + **1101** Raised when sever does not recieve Kerberose credentials. + + For example: + + >>> raise CCacheError() + Traceback (most recent call last): + ... + CCacheError: did not receive Kerberos credentials + + """ + + errno = 1101 + format = _('did not receive Kerberos credentials') + + +class ServiceError(KerberosError): + """ + **1102** Raised when service is not found in Kerberos DB. + + For example: + + >>> raise ServiceError(service='HTTP@localhost') + Traceback (most recent call last): + ... + ServiceError: Service 'HTTP@localhost' not found in Kerberos database + """ + + errno = 1102 + format = _('Service %(service)r not found in Kerberos database') + + +class NoCCacheError(KerberosError): + """ + **1103** Raised when a client attempts to use Kerberos without a ccache. + + For example: + + >>> raise NoCCacheError() + Traceback (most recent call last): + ... + NoCCacheError: No credentials cache found + """ + + errno = 1103 + format = _('No credentials cache found') + + +class TicketExpired(KerberosError): + """ + **1104** Raised when a client attempts to use an expired ticket + + For example: + + >>> raise TicketExpired() + Traceback (most recent call last): + ... + TicketExpired: Ticket expired + """ + + errno = 1104 + format = _('Ticket expired') + + +class BadCCachePerms(KerberosError): + """ + **1105** Raised when a client has bad permissions on their ccache + + For example: + + >>> raise BadCCachePerms() + Traceback (most recent call last): + ... + BadCCachePerms: Credentials cache permissions incorrect + """ + + errno = 1105 + format = _('Credentials cache permissions incorrect') + + +class BadCCacheFormat(KerberosError): + """ + **1106** Raised when a client has a misformated ccache + + For example: + + >>> raise BadCCacheFormat() + Traceback (most recent call last): + ... + BadCCacheFormat: Bad format in credentials cache + """ + + errno = 1106 + format = _('Bad format in credentials cache') + + +class CannotResolveKDC(KerberosError): + """ + **1107** Raised when the KDC can't be resolved + + For example: + + >>> raise CannotResolveKDC() + Traceback (most recent call last): + ... + CannotResolveKDC: Cannot resolve KDC for requested realm + """ + + errno = 1107 + format = _('Cannot resolve KDC for requested realm') + + +############################################################################## +# 2000 - 2999: Authorization errors +class AuthorizationError(PublicError): + """ + **2000** Base class for authorization errors (*2000 - 2999*). + """ + + errno = 2000 + + +class ACIError(AuthorizationError): + """ + **2100** Base class for ACI authorization errors (*2100 - 2199*). + """ + + errno = 2100 + format = _('Insufficient access: %(info)r') + + + +############################################################################## +# 3000 - 3999: Invocation errors + +class InvocationError(PublicError): + """ + **3000** Base class for command invocation errors (*3000 - 3999*). + """ + + errno = 3000 + + +class EncodingError(InvocationError): + """ + **3001** Raised when received text is incorrectly encoded. + """ + + errno = 3001 + + +class BinaryEncodingError(InvocationError): + """ + **3002** Raised when received binary data is incorrectly encoded. + """ + + errno = 3002 + + +class ZeroArgumentError(InvocationError): + """ + **3003** Raised when a command is called with arguments but takes none. + + For example: + + >>> raise ZeroArgumentError(name='ping') + Traceback (most recent call last): + ... + ZeroArgumentError: command 'ping' takes no arguments + """ + + errno = 3003 + format = _('command %(name)r takes no arguments') + + +class MaxArgumentError(InvocationError): + """ + **3004** Raised when a command is called with too many arguments. + + For example: + + >>> raise MaxArgumentError(name='user_add', count=2) + Traceback (most recent call last): + ... + MaxArgumentError: command 'user_add' takes at most 2 arguments + """ + + errno = 3004 + + def __init__(self, message=None, **kw): + if message is None: + format = ungettext( + 'command %(name)r takes at most %(count)d argument', + 'command %(name)r takes at most %(count)d arguments', + kw['count'] + ) + else: + format = None + InvocationError.__init__(self, format, message, **kw) + + +class OptionError(InvocationError): + """ + **3005** Raised when a command is called with unknown options. + """ + + errno = 3005 + + +class OverlapError(InvocationError): + """ + **3006** Raised when arguments and options overlap. + + For example: + + >>> raise OverlapError(names=['givenname', 'login']) + Traceback (most recent call last): + ... + OverlapError: overlapping arguments and options: ['givenname', 'login'] + """ + + errno = 3006 + format = _('overlapping arguments and options: %(names)r') + + +class RequirementError(InvocationError): + """ + **3007** Raised when a required parameter is not provided. + + For example: + + >>> raise RequirementError(name='givenname') + Traceback (most recent call last): + ... + RequirementError: 'givenname' is required + """ + + errno = 3007 + format = _('%(name)r is required') + + +class ConversionError(InvocationError): + """ + **3008** Raised when parameter value can't be converted to correct type. + + For example: + + >>> raise ConversionError(name='age', error='must be an integer') + Traceback (most recent call last): + ... + ConversionError: invalid 'age': must be an integer + """ + + errno = 3008 + format = _('invalid %(name)r: %(error)s') + + +class ValidationError(InvocationError): + """ + **3009** Raised when a parameter value fails a validation rule. + + For example: + + >>> raise ValidationError(name='sn', error='can be at most 128 characters') + Traceback (most recent call last): + ... + ValidationError: invalid 'sn': can be at most 128 characters + """ + + errno = 3009 + format = _('invalid %(name)r: %(error)s') + + +class NoSuchNamespaceError(InvocationError): + """ + **3010** Raised when an unknown namespace is requested. + + For example: + + >>> raise NoSuchNamespaceError(name='Plugins') + Traceback (most recent call last): + ... + NoSuchNamespaceError: api has no such namespace: Plugins + """ + + errno = 3010 + format = _('api has no such namespace: %(name)r') + + +############################################################################## +# 4000 - 4999: Execution errors + +class ExecutionError(PublicError): + """ + **4000** Base class for execution errors (*4000 - 4999*). + """ + + errno = 4000 + +class NotFound(ExecutionError): + """ + **4001** Raised when an entry is not found. + + For example: + + >>> raise NotFound() + Traceback (most recent call last): + ... + NotFound: entry not found + + """ + + errno = 4001 + format = _('entry not found') + +class DuplicateEntry(ExecutionError): + """ + **4002** Raised when an entry already exists. + + For example: + + >>> raise DuplicateEntry + Traceback (most recent call last): + ... + DuplicateEntry: This entry already exists + + """ + + errno = 4002 + format = _('This entry already exists') + +class HostService(ExecutionError): + """ + **4003** Raised when a host service principal is requested + + For example: + + >>> raise HostService + Traceback (most recent call last): + ... + HostService: You must enroll a host in order to create a host service + + """ + + errno = 4003 + format = _('You must enroll a host in order to create a host service') + +class MalformedServicePrincipal(ExecutionError): + """ + **4004** Raised when a service principal is not of the form: service/fully-qualified host name + + For example: + + >>> raise MalformedServicePrincipal + Traceback (most recent call last): + ... + MalformedServicePrincipal: Service principal is not of the form: service/fully-qualified host name + + """ + + errno = 4004 + format = _('Service principal is not of the form: service/fully-qualified host name') + +class RealmMismatch(ExecutionError): + """ + **4005** Raised when the requested realm does not match the IPA realm + + For example: + + >>> raise RealmMismatch + Traceback (most recent call last): + ... + RealmMismatch: The realm for the principal does not match the realm for this IPA server + + """ + + errno = 4005 + format = _('The realm for the principal does not match the realm for this IPA server') + +class RequiresRoot(ExecutionError): + """ + **4006** Raised when a command requires the unix super-user to run + + For example: + + >>> raise RequiresRoot + Traceback (most recent call last): + ... + RequiresRoot: This command requires root access + + """ + + errno = 4006 + format = _('This command requires root access') + +class AlreadyPosixGroup(ExecutionError): + """ + **4007** Raised when a group is already a posix group + + For example: + + >>> raise AlreadyPosixGroup + Traceback (most recent call last): + ... + AlreadyPosixGroup: This is already a posix group + + """ + + errno = 4007 + format = _('This is already a posix group') + +class MalformedUserPrincipal(ExecutionError): + """ + **4008** Raised when a user principal is not of the form: user@REALM + + For example: + + >>> raise MalformedUserPrincipal(principal=jsmith@@EXAMPLE.COM) + Traceback (most recent call last): + ... + MalformedUserPrincipal: Principal is not of the form user@REALM: jsmith@@EXAMPLE.COM + + """ + + errno = 4008 + format = _('Principal is not of the form user@REALM: %(principal)r') + +class AlreadyActive(ExecutionError): + """ + **4009** Raised when an entry is made active that is already active + + For example: + + >>> raise AlreadyActive() + Traceback (most recent call last): + ... + AlreadyActive: This entry is already unlocked + + """ + + errno = 4009 + format = _('This entry is already unlocked') + +class AlreadyInactive(ExecutionError): + """ + **4010** Raised when an entry is made inactive that is already inactive + + For example: + + >>> raise AlreadyInactive() + Traceback (most recent call last): + ... + AlreadyInactive: This entry is already locked + + """ + + errno = 4010 + format = _('This entry is already locked') + +class HasNSAccountLock(ExecutionError): + """ + **4011** Raised when an entry has the nsAccountLock attribute set + + For example: + + >>> raise HasNSAccountLock() + Traceback (most recent call last): + ... + HasNSAccountLock: This entry has nsAccountLock set, it cannot be locked or unlocked + + """ + + errno = 4011 + format = _('This entry has nsAccountLock set, it cannot be locked or unlocked') + +class NotGroupMember(ExecutionError): + """ + **4012** Raised when a non-member is attempted to be removed from a group + + For example: + + >>> raise NotGroupMember() + Traceback (most recent call last): + ... + NotGroupMember: This entry is not a member of the group + + """ + + errno = 4012 + format = _('This entry is not a member of the group') + +class RecursiveGroup(ExecutionError): + """ + **4013** Raised when a group is added as a member of itself + + For example: + + >>> raise RecursiveGroup() + Traceback (most recent call last): + ... + RecursiveGroup: A group may not be a member of itself + + """ + + errno = 4013 + format = _('A group may not be a member of itself') + +class AlreadyGroupMember(ExecutionError): + """ + **4014** Raised when a member is attempted to be re-added to a group + + For example: + + >>> raise AlreadyGroupMember() + Traceback (most recent call last): + ... + AlreadyGroupMember: This entry is already a member of the group + + """ + + errno = 4014 + format = _('This entry is already a member of the group') + +class BuiltinError(ExecutionError): + """ + **4100** Base class for builtin execution errors (*4100 - 4199*). + """ + + errno = 4100 + + +class HelpError(BuiltinError): + """ + **4101** Raised when requesting help for an unknown topic. + + For example: + + >>> raise HelpError(topic='newfeature') + Traceback (most recent call last): + ... + HelpError: no command nor help topic 'newfeature' + """ + + errno = 4101 + format = _('no command nor help topic %(topic)r') + + +class LDAPError(ExecutionError): + """ + **4200** Base class for LDAP execution errors (*4200 - 4299*). + """ + + errno = 4200 + + +class MidairCollision(ExecutionError): + """ + **4201** Raised when a change collides with another change + + For example: + + >>> raise MidairCollision() + Traceback (most recent call last): + ... + MidairCollision: change collided with another change + """ + + errno = 4201 + format = _('change collided with another change') + + +class EmptyModlist(ExecutionError): + """ + **4202** Raised when an LDAP update makes no changes + + For example: + + >>> raise EmptyModlist() + Traceback (most recent call last): + ... + EmptyModlist: no modifications to be performed + """ + + errno = 4202 + format = _('no modifications to be performed') + + +class DatabaseError(ExecutionError): + """ + **4203** Raised when an LDAP error is not otherwise handled + + For example: + + >>> raise DatabaseError(desc="Can't contact LDAP server", info="") + Traceback (most recent call last): + ... + DatabaseError: Can't contact LDAP server: + """ + + errno = 4203 + format = _('%(desc)r:%(info)r') + + +class LimitsExceeded(ExecutionError): + """ + **4204** Raised when search limits are exceeded. + + For example: + + >>> raise LimitsExceeded() + Traceback (most recent call last): + ... + LimitsExceeded: limits exceeded for this query + """ + + errno = 4204 + format = _('limits exceeded for this query') + + +############################################################################## +# 5000 - 5999: Generic errors + +class GenericError(PublicError): + """ + **5000** Base class for errors that don't fit elsewhere (*5000 - 5999*). + """ + + errno = 5000 + + + +def __errors_iter(): + """ + Iterate through all the `PublicError` subclasses. + """ + for (key, value) in globals().items(): + if key.startswith('_') or not isclass(value): + continue + if issubclass(value, PublicError): + yield value + +public_errors = tuple( + sorted(__errors_iter(), key=lambda E: E.errno) +) + +if __name__ == '__main__': + for klass in public_errors: + print '%d\t%s' % (klass.code, klass.__name__) + print '(%d public errors)' % len(public_errors) diff --git a/ipalib/errors2.py b/ipalib/errors2.py deleted file mode 100644 index f626f359d..000000000 --- a/ipalib/errors2.py +++ /dev/null @@ -1,1077 +0,0 @@ -# Authors: -# Jason Gerard DeRose -# -# Copyright (C) 2008 Red Hat -# see file 'COPYING' for use and warranty inmsgion -# -# 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 - -""" -Custom exception classes (some which are RPC transparent). - -`PrivateError` and its subclasses are custom IPA excetions that will *never* be -forwarded in a Remote Procedure Call (RPC) response. - -On the other hand, `PublicError` and its subclasses can be forwarded in an RPC -response. These public errors each carry a unique integer error code as well as -a gettext translated error message (translated at the time the exception is -raised). The purpose of the public errors is to relay information about -*expected* user errors, service availability errors, and so on. They should -*never* be used for *unexpected* programmatic or run-time errors. - -For security reasons it is *extremely* important that arbitrary exceptions *not* -be forwarded in an RPC response. Unexpected exceptions can easily contain -compromising information in their error messages. Any time the server catches -any exception that isn't a `PublicError` subclass, it should raise an -`InternalError`, which itself always has the same, static error message (and -therefore cannot be populated with information about the true exception). - -The public errors are arranging into five main blocks of error code ranges: - - ============= ======================================== - Error codes Exceptions - ============= ======================================== - 1000 - 1999 `AuthenticationError` and its subclasses - 2000 - 2999 `AuthorizationError` and its subclasses - 3000 - 3999 `InvocationError` and its subclasses - 4000 - 4999 `ExecutionError` and its subclasses - 5000 - 5999 `GenericError` and its subclasses - ============= ======================================== - -Within these five blocks some sub-ranges are already allocated for certain types -of error messages, while others are reserved for future use. Here are the -current block assignments: - - - **900-5999** `PublicError` and its subclasses - - - **901 - 907** Assigned to special top-level public errors - - - **908 - 999** *Reserved for future use* - - - **1000 - 1999** `AuthenticationError` and its subclasses - - - **1001 - 1099** Open for general authentication errors - - - **1100 - 1199** `KerberosError` and its subclasses - - - **1200 - 1999** *Reserved for future use* - - - **2000 - 2999** `AuthorizationError` and its subclasses - - - **2001 - 2099** Open for general authorization errors - - - **2100 - 2199** `ACIError` and its subclasses - - - **2200 - 2999** *Reserved for future use* - - - **3000 - 3999** `InvocationError` and its subclasses - - - **3001 - 3099** Open for general invocation errors - - - **3100 - 3199** *Reserved for future use* - - - **4000 - 4999** `ExecutionError` and its subclasses - - - **4001 - 4099** Open for general execution errors - - - **4100 - 4199** `BuiltinError` and its subclasses - - - **4200 - 4299** `LDAPError` and its subclasses - - - **4300 - 4999** *Reserved for future use* - - - **5000 - 5999** `GenericError` and its subclasses - - - **5001 - 5099** Open for generic errors - - - **5100 - 5999** *Reserved for future use* -""" - -from inspect import isclass -from request import ugettext, ungettext -from constants import TYPE_ERROR - - -class PrivateError(StandardError): - """ - Base class for exceptions that are *never* forwarded in an RPC response. - """ - - format = '' - - def __init__(self, **kw): - self.message = self.format % kw - for (key, value) in kw.iteritems(): - assert not hasattr(self, key), 'conflicting kwarg %s.%s = %r' % ( - self.__class__.__name__, key, value, - ) - setattr(self, key, value) - StandardError.__init__(self, self.message) - - -class SubprocessError(PrivateError): - """ - Raised when ``subprocess.call()`` returns a non-zero exit status. - - This custom exception is needed because Python 2.4 doesn't have the - ``subprocess.CalledProcessError`` exception (which was added in Python 2.5). - - For example: - - >>> raise SubprocessError(returncode=2, argv=('ls', '-lh', '/no-foo/')) - Traceback (most recent call last): - ... - SubprocessError: return code 2 from ('ls', '-lh', '/no-foo/') - - The exit code of the sub-process is available via the ``returncode`` - instance attribute. For example: - - >>> e = SubprocessError(returncode=1, argv=('/bin/false',)) - >>> e.returncode - 1 - >>> e.argv # argv is also available - ('/bin/false',) - """ - - format = 'return code %(returncode)d from %(argv)r' - - -class PluginSubclassError(PrivateError): - """ - Raised when a plugin doesn't subclass from an allowed base. - - For example: - - >>> raise PluginSubclassError(plugin='bad', bases=('base1', 'base2')) - Traceback (most recent call last): - ... - PluginSubclassError: 'bad' not subclass of any base in ('base1', 'base2') - - """ - - format = '%(plugin)r not subclass of any base in %(bases)r' - - -class PluginDuplicateError(PrivateError): - """ - Raised when the same plugin class is registered more than once. - - For example: - - >>> raise PluginDuplicateError(plugin='my_plugin') - Traceback (most recent call last): - ... - PluginDuplicateError: 'my_plugin' was already registered - """ - - format = '%(plugin)r was already registered' - - -class PluginOverrideError(PrivateError): - """ - Raised when a plugin overrides another without using ``override=True``. - - For example: - - >>> raise PluginOverrideError(base='Command', name='env', plugin='my_env') - Traceback (most recent call last): - ... - PluginOverrideError: unexpected override of Command.env with 'my_env' - """ - - format = 'unexpected override of %(base)s.%(name)s with %(plugin)r' - - -class PluginMissingOverrideError(PrivateError): - """ - Raised when a plugin overrides another that has not been registered. - - For example: - - >>> raise PluginMissingOverrideError(base='Command', name='env', plugin='my_env') - Traceback (most recent call last): - ... - PluginMissingOverrideError: Command.env not registered, cannot override with 'my_env' - """ - - format = '%(base)s.%(name)s not registered, cannot override with %(plugin)r' - - -class SkipPluginModule(PrivateError): - """ - Raised to abort the loading of a plugin module. - """ - - format = '%(reason)s' - - -class PluginsPackageError(PrivateError): - """ - Raised when ``package.plugins`` is a module instead of a sub-package. - """ - - format = '%(name)s must be sub-package, not module: %(file)r' - - -############################################################################## -# Public errors: - -__messages = [] - -def _(message): - __messages.append(message) - return message - - -class PublicError(StandardError): - """ - **900** Base class for exceptions that can be forwarded in an RPC response. - """ - - errno = 900 - format = None - - def __init__(self, format=None, message=None, **kw): - name = self.__class__.__name__ - if self.format is not None and format is not None: - raise ValueError( - 'non-generic %r needs format=None; got format=%r' % ( - name, format) - ) - if message is None: - if self.format is None: - if format is None: - raise ValueError( - '%s.format is None yet format=None, message=None' % name - ) - self.format = format - self.forwarded = False - self.message = self.format % kw - self.strerror = ugettext(self.format) % kw - else: - if type(message) is not unicode: - raise TypeError( - TYPE_ERROR % ('message', unicode, message, type(message)) - ) - self.forwarded = True - self.message = message - self.strerror = message - for (key, value) in kw.iteritems(): - assert not hasattr(self, key), 'conflicting kwarg %s.%s = %r' % ( - name, key, value, - ) - setattr(self, key, value) - StandardError.__init__(self, self.message) - - -class VersionError(PublicError): - """ - **901** Raised when client and server versions are incompatible. - - For example: - - >>> raise VersionError(cver='2.0', sver='2.1', server='https://localhost') - Traceback (most recent call last): - ... - VersionError: 2.0 client incompatible with 2.1 server at 'https://localhost' - - """ - - errno = 901 - 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): - """ - **903** Raised to conceal a non-public exception. - - For example: - - >>> raise InternalError() - Traceback (most recent call last): - ... - InternalError: an internal error has occured - """ - - errno = 903 - format = _('an internal error has occured') - - def __init__(self, message=None): - """ - Security issue: ignore any information given to constructor. - """ - PublicError.__init__(self) - - -class ServerInternalError(PublicError): - """ - **904** Raised when client catches an `InternalError` from server. - - For example: - - >>> raise ServerInternalError(server='https://localhost') - Traceback (most recent call last): - ... - ServerInternalError: an internal error has occured on server at 'https://localhost' - """ - - errno = 904 - format = _('an internal error has occured on server at %(server)r') - - -class CommandError(PublicError): - """ - **905** Raised when an unknown command is called. - - For example: - - >>> raise CommandError(name='foobar') - Traceback (most recent call last): - ... - CommandError: unknown command 'foobar' - """ - - errno = 905 - format = _('unknown command %(name)r') - - -class ServerCommandError(PublicError): - """ - **906** Raised when client catches a `CommandError` from server. - - For example: - - >>> e = CommandError(name='foobar') - >>> raise ServerCommandError(error=e.message, server='https://localhost') - Traceback (most recent call last): - ... - ServerCommandError: error on server 'https://localhost': unknown command 'foobar' - """ - - errno = 906 - format = _('error on server %(server)r: %(error)s') - - -class NetworkError(PublicError): - """ - **907** Raised when a network connection cannot be created. - - For example: - - >>> raise NetworkError(uri='ldap://localhost:389', error='Connection refused') - Traceback (most recent call last): - ... - NetworkError: cannot connect to 'ldap://localhost:389': Connection refused - """ - - errno = 907 - format = _('cannot connect to %(uri)r: %(error)s') - - -class ServerNetworkError(PublicError): - """ - **908** Raised when client catches a `NetworkError` from server. - """ - - errno = 908 - format = _('error on server %(server)r: %(error)s') - - - -############################################################################## -# 1000 - 1999: Authentication errors -class AuthenticationError(PublicError): - """ - **1000** Base class for authentication errors (*1000 - 1999*). - """ - - errno = 1000 - - -class KerberosError(AuthenticationError): - """ - **1100** Base class for Kerberos authentication errors (*1100 - 1199*). - """ - - errno = 1100 - - -class CCacheError(KerberosError): - """ - **1101** Raised when sever does not recieve Kerberose credentials. - - For example: - - >>> raise CCacheError() - Traceback (most recent call last): - ... - CCacheError: did not receive Kerberos credentials - - """ - - errno = 1101 - format = _('did not receive Kerberos credentials') - - -class ServiceError(KerberosError): - """ - **1102** Raised when service is not found in Kerberos DB. - - For example: - - >>> raise ServiceError(service='HTTP@localhost') - Traceback (most recent call last): - ... - ServiceError: Service 'HTTP@localhost' not found in Kerberos database - """ - - errno = 1102 - format = _('Service %(service)r not found in Kerberos database') - - -class NoCCacheError(KerberosError): - """ - **1103** Raised when a client attempts to use Kerberos without a ccache. - - For example: - - >>> raise NoCCacheError() - Traceback (most recent call last): - ... - NoCCacheError: No credentials cache found - """ - - errno = 1103 - format = _('No credentials cache found') - - -class TicketExpired(KerberosError): - """ - **1104** Raised when a client attempts to use an expired ticket - - For example: - - >>> raise TicketExpired() - Traceback (most recent call last): - ... - TicketExpired: Ticket expired - """ - - errno = 1104 - format = _('Ticket expired') - - -class BadCCachePerms(KerberosError): - """ - **1105** Raised when a client has bad permissions on their ccache - - For example: - - >>> raise BadCCachePerms() - Traceback (most recent call last): - ... - BadCCachePerms: Credentials cache permissions incorrect - """ - - errno = 1105 - format = _('Credentials cache permissions incorrect') - - -class BadCCacheFormat(KerberosError): - """ - **1106** Raised when a client has a misformated ccache - - For example: - - >>> raise BadCCacheFormat() - Traceback (most recent call last): - ... - BadCCacheFormat: Bad format in credentials cache - """ - - errno = 1106 - format = _('Bad format in credentials cache') - - -class CannotResolveKDC(KerberosError): - """ - **1107** Raised when the KDC can't be resolved - - For example: - - >>> raise CannotResolveKDC() - Traceback (most recent call last): - ... - CannotResolveKDC: Cannot resolve KDC for requested realm - """ - - errno = 1107 - format = _('Cannot resolve KDC for requested realm') - - -############################################################################## -# 2000 - 2999: Authorization errors -class AuthorizationError(PublicError): - """ - **2000** Base class for authorization errors (*2000 - 2999*). - """ - - errno = 2000 - - -class ACIError(AuthorizationError): - """ - **2100** Base class for ACI authorization errors (*2100 - 2199*). - """ - - errno = 2100 - format = _('Insufficient access: %(info)r') - - - -############################################################################## -# 3000 - 3999: Invocation errors - -class InvocationError(PublicError): - """ - **3000** Base class for command invocation errors (*3000 - 3999*). - """ - - errno = 3000 - - -class EncodingError(InvocationError): - """ - **3001** Raised when received text is incorrectly encoded. - """ - - errno = 3001 - - -class BinaryEncodingError(InvocationError): - """ - **3002** Raised when received binary data is incorrectly encoded. - """ - - errno = 3002 - - -class ZeroArgumentError(InvocationError): - """ - **3003** Raised when a command is called with arguments but takes none. - - For example: - - >>> raise ZeroArgumentError(name='ping') - Traceback (most recent call last): - ... - ZeroArgumentError: command 'ping' takes no arguments - """ - - errno = 3003 - format = _('command %(name)r takes no arguments') - - -class MaxArgumentError(InvocationError): - """ - **3004** Raised when a command is called with too many arguments. - - For example: - - >>> raise MaxArgumentError(name='user_add', count=2) - Traceback (most recent call last): - ... - MaxArgumentError: command 'user_add' takes at most 2 arguments - """ - - errno = 3004 - - def __init__(self, message=None, **kw): - if message is None: - format = ungettext( - 'command %(name)r takes at most %(count)d argument', - 'command %(name)r takes at most %(count)d arguments', - kw['count'] - ) - else: - format = None - InvocationError.__init__(self, format, message, **kw) - - -class OptionError(InvocationError): - """ - **3005** Raised when a command is called with unknown options. - """ - - errno = 3005 - - -class OverlapError(InvocationError): - """ - **3006** Raised when arguments and options overlap. - - For example: - - >>> raise OverlapError(names=['givenname', 'login']) - Traceback (most recent call last): - ... - OverlapError: overlapping arguments and options: ['givenname', 'login'] - """ - - errno = 3006 - format = _('overlapping arguments and options: %(names)r') - - -class RequirementError(InvocationError): - """ - **3007** Raised when a required parameter is not provided. - - For example: - - >>> raise RequirementError(name='givenname') - Traceback (most recent call last): - ... - RequirementError: 'givenname' is required - """ - - errno = 3007 - format = _('%(name)r is required') - - -class ConversionError(InvocationError): - """ - **3008** Raised when parameter value can't be converted to correct type. - - For example: - - >>> raise ConversionError(name='age', error='must be an integer') - Traceback (most recent call last): - ... - ConversionError: invalid 'age': must be an integer - """ - - errno = 3008 - format = _('invalid %(name)r: %(error)s') - - -class ValidationError(InvocationError): - """ - **3009** Raised when a parameter value fails a validation rule. - - For example: - - >>> raise ValidationError(name='sn', error='can be at most 128 characters') - Traceback (most recent call last): - ... - ValidationError: invalid 'sn': can be at most 128 characters - """ - - errno = 3009 - format = _('invalid %(name)r: %(error)s') - - -class NoSuchNamespaceError(InvocationError): - """ - **3010** Raised when an unknown namespace is requested. - - For example: - - >>> raise NoSuchNamespaceError(name='Plugins') - Traceback (most recent call last): - ... - NoSuchNamespaceError: api has no such namespace: Plugins - """ - - errno = 3010 - format = _('api has no such namespace: %(name)r') - - -############################################################################## -# 4000 - 4999: Execution errors - -class ExecutionError(PublicError): - """ - **4000** Base class for execution errors (*4000 - 4999*). - """ - - errno = 4000 - -class NotFound(ExecutionError): - """ - **4001** Raised when an entry is not found. - - For example: - - >>> raise NotFound() - Traceback (most recent call last): - ... - NotFound: entry not found - - """ - - errno = 4001 - format = _('entry not found') - -class DuplicateEntry(ExecutionError): - """ - **4002** Raised when an entry already exists. - - For example: - - >>> raise DuplicateEntry - Traceback (most recent call last): - ... - DuplicateEntry: This entry already exists - - """ - - errno = 4002 - format = _('This entry already exists') - -class HostService(ExecutionError): - """ - **4003** Raised when a host service principal is requested - - For example: - - >>> raise HostService - Traceback (most recent call last): - ... - HostService: You must enroll a host in order to create a host service - - """ - - errno = 4003 - format = _('You must enroll a host in order to create a host service') - -class MalformedServicePrincipal(ExecutionError): - """ - **4004** Raised when a service principal is not of the form: service/fully-qualified host name - - For example: - - >>> raise MalformedServicePrincipal - Traceback (most recent call last): - ... - MalformedServicePrincipal: Service principal is not of the form: service/fully-qualified host name - - """ - - errno = 4004 - format = _('Service principal is not of the form: service/fully-qualified host name') - -class RealmMismatch(ExecutionError): - """ - **4005** Raised when the requested realm does not match the IPA realm - - For example: - - >>> raise RealmMismatch - Traceback (most recent call last): - ... - RealmMismatch: The realm for the principal does not match the realm for this IPA server - - """ - - errno = 4005 - format = _('The realm for the principal does not match the realm for this IPA server') - -class RequiresRoot(ExecutionError): - """ - **4006** Raised when a command requires the unix super-user to run - - For example: - - >>> raise RequiresRoot - Traceback (most recent call last): - ... - RequiresRoot: This command requires root access - - """ - - errno = 4006 - format = _('This command requires root access') - -class AlreadyPosixGroup(ExecutionError): - """ - **4007** Raised when a group is already a posix group - - For example: - - >>> raise AlreadyPosixGroup - Traceback (most recent call last): - ... - AlreadyPosixGroup: This is already a posix group - - """ - - errno = 4007 - format = _('This is already a posix group') - -class MalformedUserPrincipal(ExecutionError): - """ - **4008** Raised when a user principal is not of the form: user@REALM - - For example: - - >>> raise MalformedUserPrincipal(principal=jsmith@@EXAMPLE.COM) - Traceback (most recent call last): - ... - MalformedUserPrincipal: Principal is not of the form user@REALM: jsmith@@EXAMPLE.COM - - """ - - errno = 4008 - format = _('Principal is not of the form user@REALM: %(principal)r') - -class AlreadyActive(ExecutionError): - """ - **4009** Raised when an entry is made active that is already active - - For example: - - >>> raise AlreadyActive() - Traceback (most recent call last): - ... - AlreadyActive: This entry is already unlocked - - """ - - errno = 4009 - format = _('This entry is already unlocked') - -class AlreadyInactive(ExecutionError): - """ - **4010** Raised when an entry is made inactive that is already inactive - - For example: - - >>> raise AlreadyInactive() - Traceback (most recent call last): - ... - AlreadyInactive: This entry is already locked - - """ - - errno = 4010 - format = _('This entry is already locked') - -class HasNSAccountLock(ExecutionError): - """ - **4011** Raised when an entry has the nsAccountLock attribute set - - For example: - - >>> raise HasNSAccountLock() - Traceback (most recent call last): - ... - HasNSAccountLock: This entry has nsAccountLock set, it cannot be locked or unlocked - - """ - - errno = 4011 - format = _('This entry has nsAccountLock set, it cannot be locked or unlocked') - -class NotGroupMember(ExecutionError): - """ - **4012** Raised when a non-member is attempted to be removed from a group - - For example: - - >>> raise NotGroupMember() - Traceback (most recent call last): - ... - NotGroupMember: This entry is not a member of the group - - """ - - errno = 4012 - format = _('This entry is not a member of the group') - -class RecursiveGroup(ExecutionError): - """ - **4013** Raised when a group is added as a member of itself - - For example: - - >>> raise RecursiveGroup() - Traceback (most recent call last): - ... - RecursiveGroup: A group may not be a member of itself - - """ - - errno = 4013 - format = _('A group may not be a member of itself') - -class AlreadyGroupMember(ExecutionError): - """ - **4014** Raised when a member is attempted to be re-added to a group - - For example: - - >>> raise AlreadyGroupMember() - Traceback (most recent call last): - ... - AlreadyGroupMember: This entry is already a member of the group - - """ - - errno = 4014 - format = _('This entry is already a member of the group') - -class BuiltinError(ExecutionError): - """ - **4100** Base class for builtin execution errors (*4100 - 4199*). - """ - - errno = 4100 - - -class HelpError(BuiltinError): - """ - **4101** Raised when requesting help for an unknown topic. - - For example: - - >>> raise HelpError(topic='newfeature') - Traceback (most recent call last): - ... - HelpError: no command nor help topic 'newfeature' - """ - - errno = 4101 - format = _('no command nor help topic %(topic)r') - - -class LDAPError(ExecutionError): - """ - **4200** Base class for LDAP execution errors (*4200 - 4299*). - """ - - errno = 4200 - - -class MidairCollision(ExecutionError): - """ - **4201** Raised when a change collides with another change - - For example: - - >>> raise MidairCollision() - Traceback (most recent call last): - ... - MidairCollision: change collided with another change - """ - - errno = 4201 - format = _('change collided with another change') - - -class EmptyModlist(ExecutionError): - """ - **4202** Raised when an LDAP update makes no changes - - For example: - - >>> raise EmptyModlist() - Traceback (most recent call last): - ... - EmptyModlist: no modifications to be performed - """ - - errno = 4202 - format = _('no modifications to be performed') - - -class DatabaseError(ExecutionError): - """ - **4203** Raised when an LDAP error is not otherwise handled - - For example: - - >>> raise DatabaseError(desc="Can't contact LDAP server", info="") - Traceback (most recent call last): - ... - DatabaseError: Can't contact LDAP server: - """ - - errno = 4203 - format = _('%(desc)r:%(info)r') - - -class LimitsExceeded(ExecutionError): - """ - **4204** Raised when search limits are exceeded. - - For example: - - >>> raise LimitsExceeded() - Traceback (most recent call last): - ... - LimitsExceeded: limits exceeded for this query - """ - - errno = 4204 - format = _('limits exceeded for this query') - - -############################################################################## -# 5000 - 5999: Generic errors - -class GenericError(PublicError): - """ - **5000** Base class for errors that don't fit elsewhere (*5000 - 5999*). - """ - - errno = 5000 - - - -def __errors_iter(): - """ - Iterate through all the `PublicError` subclasses. - """ - for (key, value) in globals().items(): - if key.startswith('_') or not isclass(value): - continue - if issubclass(value, PublicError): - yield value - -public_errors = tuple( - sorted(__errors_iter(), key=lambda E: E.errno) -) - -if __name__ == '__main__': - for klass in public_errors: - print '%d\t%s' % (klass.code, klass.__name__) - print '(%d public errors)' % len(public_errors) diff --git a/ipalib/frontend.py b/ipalib/frontend.py index c2f68d471..aeae24ca0 100644 --- a/ipalib/frontend.py +++ b/ipalib/frontend.py @@ -28,7 +28,7 @@ from plugable import lock, check_name from parameters import create_param, Param, Str, Flag, Password from util import make_repr -from errors2 import ZeroArgumentError, MaxArgumentError, OverlapError +from errors import ZeroArgumentError, MaxArgumentError, OverlapError from constants import TYPE_ERROR @@ -294,7 +294,7 @@ class Command(plugable.Plugin): """ Validate all values. - If any value fails the validation, `ipalib.errors2.ValidationError` + If any value fails the validation, `ipalib.errors.ValidationError` (or a subclass thereof) will be raised. """ for param in self.params(): diff --git a/ipalib/parameters.py b/ipalib/parameters.py index e5f4e8ef1..13fd50b59 100644 --- a/ipalib/parameters.py +++ b/ipalib/parameters.py @@ -34,7 +34,7 @@ from types import NoneType from util import make_repr from request import ugettext from plugable import ReadOnly, lock, check_name -from errors2 import ConversionError, RequirementError, ValidationError +from errors import ConversionError, RequirementError, ValidationError from constants import NULLS, TYPE_ERROR, CALLABLE_ERROR import csv diff --git a/ipalib/plugable.py b/ipalib/plugable.py index 213b59783..c0a4c3567 100644 --- a/ipalib/plugable.py +++ b/ipalib/plugable.py @@ -34,7 +34,7 @@ import os from os import path import subprocess import optparse -import errors2 +import errors from config import Env import util from base import ReadOnly, NameSpace, lock, islocked, check_name @@ -283,7 +283,7 @@ class Plugin(ReadOnly): Call ``executable`` with ``args`` using subprocess.call(). If the call exits with a non-zero exit status, - `ipalib.errors2.SubprocessError` is raised, from which you can retrieve + `ipalib.errors.SubprocessError` is raised, from which you can retrieve the exit code by checking the SubprocessError.returncode attribute. This method does *not* return what ``executable`` sent to stdout... for @@ -293,7 +293,7 @@ class Plugin(ReadOnly): self.debug('Calling %r', argv) code = subprocess.call(argv) if code != 0: - raise errors2.SubprocessError(returncode=code, argv=argv) + raise errors.SubprocessError(returncode=code, argv=argv) def __repr__(self): """ @@ -450,7 +450,7 @@ class Registrar(DictProxy): """ Iterates through allowed bases that ``klass`` is a subclass of. - Raises `errors2.PluginSubclassError` if ``klass`` is not a subclass of + Raises `errors.PluginSubclassError` if ``klass`` is not a subclass of any allowed base. :param klass: The plugin class to find bases for. @@ -462,7 +462,7 @@ class Registrar(DictProxy): found = True yield (base, sub_d) if not found: - raise errors2.PluginSubclassError( + raise errors.PluginSubclassError( plugin=klass, bases=self.__allowed.keys() ) @@ -478,7 +478,7 @@ class Registrar(DictProxy): # Raise DuplicateError if this exact class was already registered: if klass in self.__registered: - raise errors2.PluginDuplicateError(plugin=klass) + raise errors.PluginDuplicateError(plugin=klass) # Find the base class or raise SubclassError: for (base, sub_d) in self.__findbases(klass): @@ -486,7 +486,7 @@ class Registrar(DictProxy): if klass.__name__ in sub_d: if not override: # Must use override=True to override: - raise errors2.PluginOverrideError( + raise errors.PluginOverrideError( base=base.__name__, name=klass.__name__, plugin=klass, @@ -494,7 +494,7 @@ class Registrar(DictProxy): else: if override: # There was nothing already registered to override: - raise errors2.PluginMissingOverrideError( + raise errors.PluginMissingOverrideError( base=base.__name__, name=klass.__name__, plugin=klass, @@ -667,7 +667,7 @@ class API(DictProxy): parent_dir = path.dirname(path.abspath(parent.__file__)) plugins_dir = path.dirname(path.abspath(plugins.__file__)) if parent_dir == plugins_dir: - raise errors2.PluginsPackageError( + raise errors.PluginsPackageError( name=subpackage, file=plugins.__file__ ) self.log.debug('importing all plugin modules in %r...', plugins_dir) @@ -676,7 +676,7 @@ class API(DictProxy): self.log.debug('importing plugin module %r', pyfile) try: __import__(fullname) - except errors2.SkipPluginModule, e: + except errors.SkipPluginModule, e: self.log.info( 'skipping plugin module %s: %s', fullname, e.reason ) diff --git a/ipalib/plugins/aci.py b/ipalib/plugins/aci.py index 6a2a1c2d7..8587e2ae9 100644 --- a/ipalib/plugins/aci.py +++ b/ipalib/plugins/aci.py @@ -21,7 +21,7 @@ Frontend plugins for managing DS ACIs """ -from ipalib import api, crud, errors2 +from ipalib import api, crud, errors from ipalib import Object, Command # Plugin base classes from ipalib import Str, Flag, Int, StrEnum # Parameter types from ipalib.aci import ACI @@ -35,7 +35,7 @@ type_map = { def make_aci(current, aciname, kw): try: taskgroup = api.Command['taskgroup_show'](kw['taskgroup']) - except errors2.NotFound: + except errors.NotFound: # The task group doesn't exist, let's be helpful and add it tgkw = {'description':aciname} taskgroup = api.Command['taskgroup_add'](kw['taskgroup'], **tgkw) @@ -81,7 +81,7 @@ def search_by_name(acis, aciname): # FIXME: need to log syntax errors, ignore for now pass - raise errors2.NotFound() + raise errors.NotFound() def search_by_attr(acis, attrlist): """ @@ -105,7 +105,7 @@ def search_by_attr(acis, attrlist): if results: return results - raise errors2.NotFound() + raise errors.NotFound() def search_by_taskgroup(acis, tgdn): """ @@ -126,7 +126,7 @@ def search_by_taskgroup(acis, tgdn): if results: return results - raise errors2.NotFound() + raise errors.NotFound() def search_by_perm(acis, permlist): """ @@ -148,7 +148,7 @@ def search_by_perm(acis, permlist): if results: return results - raise errors2.NotFound() + raise errors.NotFound() def search_by_memberof(acis, memberoffilter): """ @@ -174,7 +174,7 @@ def search_by_memberof(acis, memberoffilter): if results: return results - raise errors2.NotFound() + raise errors.NotFound() class aci(Object): """ @@ -241,7 +241,7 @@ class aci_add(crud.Create): try: b = ACI(a) if newaci.isequal(b): - raise errors2.DuplicateEntry() + raise errors.DuplicateEntry() except SyntaxError: pass acilist.append(str(newaci)) @@ -318,7 +318,7 @@ class aci_find(crud.Search): results = [a] if kw.get('and'): currentaci = results - except errors2.NotFound: + except errors.NotFound: if kw.get('and'): results = [] currentaci = [] @@ -335,7 +335,7 @@ class aci_find(crud.Search): currentaci = results else: results = results + a - except errors2.NotFound: + except errors.NotFound: if kw.get('and'): results = [] currentaci = [] @@ -345,7 +345,7 @@ class aci_find(crud.Search): if kw.get('taskgroup'): try: tg = api.Command['taskgroup_show'](kw.get('taskgroup')) - except errors2.NotFound: + except errors.NotFound: # FIXME, need more precise error raise try: @@ -355,7 +355,7 @@ class aci_find(crud.Search): currentaci = results else: results = results + a - except errors2.NotFound: + except errors.NotFound: if kw.get('and'): results = [] currentaci = [] @@ -372,7 +372,7 @@ class aci_find(crud.Search): currentaci = results else: results = results + a - except errors2.NotFound: + except errors.NotFound: if kw.get('and'): results = [] currentaci = [] @@ -387,7 +387,7 @@ class aci_find(crud.Search): results = results + a if kw.get('and'): currentaci = results - except errors2.NotFound: + except errors.NotFound: if kw.get('and'): results = [] currentaci = [] diff --git a/ipalib/plugins/automount.py b/ipalib/plugins/automount.py index b4b696d10..6378a1385 100644 --- a/ipalib/plugins/automount.py +++ b/ipalib/plugins/automount.py @@ -86,7 +86,7 @@ automountInformation: -ro,soft,rsize=8192,wsize=8192 nfs.example.com:/vol/arch """ from ldap import explode_dn -from ipalib import crud, errors2 +from ipalib import crud, errors from ipalib import api, Str, Flag, Object, Command map_attributes = ['automountMapName', 'description', ] @@ -251,7 +251,7 @@ class automount_delmap(crud.Del): try: infodn = ldap.find_entry_dn("automountinformation", mapname, "automount", api.env.container_automount) ldap.delete(infodn) - except errors2.NotFound: + except errors.NotFound: # direct maps may not have this pass @@ -291,7 +291,7 @@ class automount_delkey(crud.Del): keydn = k.get('dn') break if not keydn: - raise errors2.NotFound(msg='Entry not found') + raise errors.NotFound(msg='Entry not found') return ldap.delete(keydn) def output_for_cli(self, textui, result, *args, **options): """ @@ -369,7 +369,7 @@ class automount_modkey(crud.Mod): keydn = k.get('dn') break if not keydn: - raise errors2.NotFound(msg='Entry not found') + raise errors.NotFound(msg='Entry not found') return ldap.update(keydn, **kw) def output_for_cli(self, textui, result, *args, **options): @@ -517,7 +517,7 @@ class automount_showkey(crud.Get): keydn = k.get('dn') break if not keydn: - raise errors2.NotFound(msg='Entry not found') + raise errors.NotFound(msg='Entry not found') # FIXME: should kw contain the list of attributes to display? if kw.get('all', False): return ldap.retrieve(keydn) @@ -558,7 +558,7 @@ class automount_getkeys(Command): dn = ldap.find_entry_dn("automountmapname", mapname, "automountmap", api.env.container_automount) try: keys = ldap.get_one_entry(dn, 'objectclass=*', ['*']) - except errors2.NotFound: + except errors.NotFound: keys = [] return keys diff --git a/ipalib/plugins/basegroup.py b/ipalib/plugins/basegroup.py index b93fdc8d9..733a6c384 100644 --- a/ipalib/plugins/basegroup.py +++ b/ipalib/plugins/basegroup.py @@ -21,7 +21,7 @@ Base plugin for groups. """ -from ipalib import api, crud, errors2 +from ipalib import api, crud, errors from ipalib import Object, Command # Plugin base classes from ipalib import Str, Int, Flag, List # Parameter types from ldap.dn import escape_dn_chars @@ -50,7 +50,7 @@ def find_members(ldap, failed, members, attribute, filter=None, base=None): try: member_dn = ldap.find_entry_dn(attribute, m, filter, base) found.append(member_dn) - except errors2.NotFound: + except errors.NotFound: failed.append(m) return found, failed diff --git a/ipalib/plugins/group.py b/ipalib/plugins/group.py index 3bf5221fe..766d1679f 100644 --- a/ipalib/plugins/group.py +++ b/ipalib/plugins/group.py @@ -119,7 +119,7 @@ class group_del(basegroup_del): default_group = ldap.find_entry_dn("cn", config.get('ipadefaultprimarygroup'), self.filter_class) if dn == default_group: raise errors.DefaultGroup - except errors2.NotFound: + except errors.NotFound: pass return super(group_del, self).execute(cn, **kw) @@ -160,7 +160,7 @@ class group_mod(basegroup_mod): groupkw = {'all': True} oldgroup = api.Command['group_show'](cn, **groupkw) if oldgroup.get('gidnumber'): - raise errors2.AlreadyPosixGroup + raise errors.AlreadyPosixGroup else: oldgroup['objectclass'].append('posixgroup') kw['objectclass'] = oldgroup['objectclass'] diff --git a/ipalib/plugins/host.py b/ipalib/plugins/host.py index 13a0254e3..87180733f 100644 --- a/ipalib/plugins/host.py +++ b/ipalib/plugins/host.py @@ -21,7 +21,7 @@ Frontend plugins for host/machine Identity. """ -from ipalib import api, crud, errors2, util +from ipalib import api, crud, errors, util from ipalib import Object # Plugin base class from ipalib import Str, Flag # Parameter types import sys, os, platform @@ -39,7 +39,7 @@ def get_host(hostname): hostname = hostname[:-1] try: dn = ldap.find_entry_dn("cn", hostname, "ipaHost") - except errors2.NotFound: + except errors.NotFound: dn = ldap.find_entry_dn("serverhostname", hostname, "ipaHost") return dn @@ -138,7 +138,7 @@ class host_add(crud.Add): current = util.get_current_principal() if not current: - raise errors2.NotFound('Unable to determine current user') + raise errors.NotFound('Unable to determine current user') kw['enrolledby'] = ldap.find_entry_dn("krbPrincipalName", current, "posixAccount") # Get our configuration diff --git a/ipalib/plugins/join.py b/ipalib/plugins/join.py index 1230d5bcc..d75043fdd 100644 --- a/ipalib/plugins/join.py +++ b/ipalib/plugins/join.py @@ -23,7 +23,7 @@ Machine join from ipalib import api, util from ipalib import Command, Str, Int -from ipalib import errors2 +from ipalib import errors import krbV import os, subprocess @@ -74,10 +74,10 @@ class join(Command): try: host = api.Command['host_show'](hostname) - except errors2.NotFound: + except errors.NotFound: pass else: - raise errors2.DuplicateEntry + raise errors.DuplicateEntry return api.Command['host_add'](hostname) @@ -91,7 +91,7 @@ class join(Command): """ if not self.env.in_server: # if os.getegid() != 0: -# raise errors2.RequiresRoot +# raise errors.RequiresRoot result = self.forward(*args, **options) else: return self.execute(*args, **options) diff --git a/ipalib/plugins/passwd.py b/ipalib/plugins/passwd.py index cc7ab5861..bb6e637a9 100644 --- a/ipalib/plugins/passwd.py +++ b/ipalib/plugins/passwd.py @@ -21,7 +21,7 @@ Frontend plugins for password changes. """ -from ipalib import api, errors2, util +from ipalib import api, errors, util from ipalib import Command # Plugin base classes from ipalib import Str, Password # Parameter types @@ -54,7 +54,7 @@ class passwd(Command): if principal.find('@') > 0: u = principal.split('@') if len(u) > 2: - raise errors2.MalformedUserPrincipal(principal=principal) + raise errors.MalformedUserPrincipal(principal=principal) else: principal = principal+"@"+self.api.env.realm dn = self.Backend.ldap.find_entry_dn( diff --git a/ipalib/plugins/service.py b/ipalib/plugins/service.py index 4c6f5bd80..c9f00deb2 100644 --- a/ipalib/plugins/service.py +++ b/ipalib/plugins/service.py @@ -22,7 +22,7 @@ Frontend plugins for service (Identity). """ -from ipalib import api, crud, errors2 +from ipalib import api, crud, errors from ipalib import Object # Plugin base classes from ipalib import Str, Flag # Parameter types @@ -73,11 +73,11 @@ class service_add(crud.Add): # may not include the realm. sp = principal.split('/') if len(sp) != 2: - raise errors2.MalformedServicePrincipal + raise errors.MalformedServicePrincipal service = sp[0] if service.lower() == "host": - raise errors2.HostService + raise errors.HostService sr = sp[1].split('@') if len(sr) == 1: @@ -87,7 +87,7 @@ class service_add(crud.Add): hostname = sr[0].lower() realm = sr[1] else: - raise errors2.MalformedServicePrincipal + raise errors.MalformedServicePrincipal """ FIXME once DNS client is done @@ -103,7 +103,7 @@ class service_add(crud.Add): # At some point we'll support multiple realms if (realm != self.api.env.realm): - raise errors2.RealmMismatch + raise errors.RealmMismatch # Put the principal back together again princ_name = service + "/" + hostname + "@" + realm diff --git a/ipalib/plugins/user.py b/ipalib/plugins/user.py index e4e1cdaf1..be70e7bee 100644 --- a/ipalib/plugins/user.py +++ b/ipalib/plugins/user.py @@ -21,7 +21,7 @@ Frontend plugins for user (Identity). """ -from ipalib import api, crud, errors2 +from ipalib import api, crud, errors from ipalib import Object, Command # Plugin base classes from ipalib import Str, Password, Flag, Int # Parameter types @@ -158,9 +158,9 @@ class user_add(crud.Create): default_group = ldap.retrieve(group_dn, ['cn', 'dn','gidNumber']) if default_group: kw['gidnumber'] = default_group.get('gidnumber') - except errors2.NotFound: + except errors.NotFound: # Fake an LDAP error so we can return something useful to the kw - raise errors2.NotFound("The default group for new users, '%s', cannot be found." % config.get('ipadefaultprimarygroup')) + raise errors.NotFound("The default group for new users, '%s', cannot be found." % config.get('ipadefaultprimarygroup')) except Exception, e: # catch everything else raise e diff --git a/ipalib/plugins/user2.py b/ipalib/plugins/user2.py index 13bd37f5a..b322aa87d 100644 --- a/ipalib/plugins/user2.py +++ b/ipalib/plugins/user2.py @@ -21,7 +21,7 @@ Users (Identity) """ -from ipalib import api, crud, errors2 +from ipalib import api, crud, errors from ipalib import Command, Object from ipalib import Flag, Int, Password, Str @@ -146,9 +146,9 @@ class user2_create(crud.Create): # try to retrieve the group's gidNumber try: (group_dn, group_attrs) = ldap.get_entry(group_dn, ['gidNumber']) - except errors2.NotFound: + except errors.NotFound: error_msg = 'Default group for new users not found.' - raise errors2.NotFound(error_msg) + raise errors.NotFound(error_msg) # fill default group's gidNumber entry_attrs['gidnumber'] = group_attrs['gidNumber'] @@ -184,7 +184,7 @@ class user2_delete(crud.Delete): if uid == 'admin': # FIXME: add a specific exception for this? - raise errors2.ExecutionError('Cannot delete user "admin".') + raise errors.ExecutionError('Cannot delete user "admin".') # build entry DN rdn = ldap.make_rdn_from_attr('uid', uid) @@ -276,7 +276,7 @@ class user2_find(crud.Search): entries = ldap.find_entries( filter, attrs_list, _container_dn, ldap.SCOPE_ONELEVEL ) - except errors2.NotFound: + except errors.NotFound: entries = tuple() return entries @@ -355,7 +355,7 @@ class user2_lock(Command): # lock! try: ldap.deactivate_entry(dn) - except errors2.AlreadyInactive: + except errors.AlreadyInactive: pass # return something positive @@ -391,7 +391,7 @@ class user2_unlock(Command): # unlock! try: ldap.activate_entry(dn) - except errors2.AlreadyActive: + except errors.AlreadyActive: pass # return something positive diff --git a/ipalib/rpc.py b/ipalib/rpc.py index b0b55ce59..48ac16b5a 100644 --- a/ipalib/rpc.py +++ b/ipalib/rpc.py @@ -38,8 +38,8 @@ import errno from xmlrpclib import Binary, Fault, dumps, loads, ServerProxy, Transport import kerberos from ipalib.backend import Connectible -from ipalib.errors2 import public_errors, PublicError, UnknownError, NetworkError -from ipalib import errors2 +from ipalib.errors import public_errors, PublicError, UnknownError, NetworkError +from ipalib import errors from ipalib.request import context from ipapython import ipautil from OpenSSL import SSL @@ -316,19 +316,19 @@ class KerbTransport(SSLTransport): def _handle_exception(self, e, service=None): (major, minor) = ipautil.get_gsserror(e) if minor[1] == KRB5KDC_ERR_S_PRINCIPAL_UNKNOWN: - raise errors2.ServiceError(service=service) + raise errors.ServiceError(service=service) elif minor[1] == KRB5_FCC_NOFILE: - raise errors2.NoCCacheError() + raise errors.NoCCacheError() elif minor[1] == KRB5KRB_AP_ERR_TKT_EXPIRED: - raise errors2.TicketExpired() + raise errors.TicketExpired() elif minor[1] == KRB5_FCC_PERM: - raise errors2.BadCCachePerms() + raise errors.BadCCachePerms() elif minor[1] == KRB5_CC_FORMAT: - raise errors2.BadCCacheFormat() + raise errors.BadCCacheFormat() elif minor[1] == KRB5_REALM_CANT_RESOLVE: - raise errors2.CannotResolveKDC() + raise errors.CannotResolveKDC() else: - raise errors2.KerberosError(major=major, minor=minor) + raise errors.KerberosError(major=major, minor=minor) def get_host_info(self, host): (host, extra_headers, x509) = SSLTransport.get_host_info(self, host) diff --git a/ipalib/util.py b/ipalib/util.py index 54529b14c..5ea13dc8c 100644 --- a/ipalib/util.py +++ b/ipalib/util.py @@ -28,7 +28,7 @@ import logging import time import krbV import socket -from ipalib import errors2 +from ipalib import errors def get_current_principal(): @@ -36,7 +36,7 @@ def get_current_principal(): return unicode(krbV.default_context().default_ccache().principal().name) except krbV.Krb5Error: #TODO: do a kinit? - raise errors2.CCacheError() + raise errors.CCacheError() def get_fqdn(): fqdn = "" -- cgit