summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPetr Viktorin <pviktori@redhat.com>2013-01-17 10:50:16 -0500
committerMartin Kosek <mkosek@redhat.com>2013-03-01 16:59:43 +0100
commitdf4ed77962e906b2456c99e57084314000768569 (patch)
tree96d9fedd4d071e3d298b38b44d8d9ecaa58b4cb3
parent9d41ee4b318f925b3b10c7b2fa1a14e5f8d9e66c (diff)
downloadfreeipa-df4ed77962e906b2456c99e57084314000768569.tar.gz
freeipa-df4ed77962e906b2456c99e57084314000768569.tar.xz
freeipa-df4ed77962e906b2456c99e57084314000768569.zip
Start LDAPConnection, a common base for ldap2 and IPAdmin
The first method to be extracted is handle_errors Part of the work for: https://fedorahosted.org/freeipa/ticket/2660
-rw-r--r--ipaserver/ipaldap.py142
-rw-r--r--ipaserver/plugins/ldap2.py82
2 files changed, 101 insertions, 123 deletions
diff --git a/ipaserver/ipaldap.py b/ipaserver/ipaldap.py
index 13d363c82..76e66cc99 100644
--- a/ipaserver/ipaldap.py
+++ b/ipaserver/ipaldap.py
@@ -816,18 +816,104 @@ class Entry(LDAPEntry):
super(Entry, self).__init__(dn, data)
-class IPAdmin(IPAEntryLDAPObject):
+class LDAPConnection(object):
+ """LDAP backend class
+
+ This class abstracts a LDAP connection, providing methods that work with
+ LADPEntries.
+
+ This class is not intended to be used directly; instead, use one of its
+ subclasses, IPAdmin or the ldap2 plugin.
+ """
+ def __init__(self, ldap_uri):
+ self.ldap_uri = ldap_uri
+ self.log = log_mgr.get_logger(self)
+
+ def handle_errors(self, e, arg_desc=None):
+ """Universal LDAPError handler
+
+ :param e: The error to be raised
+ :param url: The URL of the server
+ """
+ if not isinstance(e, _ldap.TIMEOUT):
+ desc = e.args[0]['desc'].strip()
+ info = e.args[0].get('info', '').strip()
+ if arg_desc is not None:
+ info = "%s arguments: %s" % (info, arg_desc)
+ else:
+ desc = ''
+ info = ''
+
+ try:
+ # re-raise the error so we can handle it
+ raise e
+ except _ldap.NO_SUCH_OBJECT:
+ raise errors.NotFound(reason=arg_desc or 'no such entry')
+ except _ldap.ALREADY_EXISTS:
+ raise errors.DuplicateEntry()
+ except _ldap.CONSTRAINT_VIOLATION:
+ # This error gets thrown by the uniqueness plugin
+ _msg = 'Another entry with the same attribute value already exists'
+ if info.startswith(_msg):
+ raise errors.DuplicateEntry()
+ else:
+ raise errors.DatabaseError(desc=desc, info=info)
+ except _ldap.INSUFFICIENT_ACCESS:
+ raise errors.ACIError(info=info)
+ except _ldap.INVALID_CREDENTIALS:
+ raise errors.ACIError(info="%s %s" % (info, desc))
+ except _ldap.NO_SUCH_ATTRIBUTE:
+ # this is raised when a 'delete' attribute isn't found.
+ # it indicates the previous attribute was removed by another
+ # update, making the oldentry stale.
+ raise errors.MidairCollision()
+ except _ldap.INVALID_SYNTAX:
+ raise errors.InvalidSyntax(attr=info)
+ except _ldap.OBJECT_CLASS_VIOLATION:
+ raise errors.ObjectclassViolation(info=info)
+ except _ldap.ADMINLIMIT_EXCEEDED:
+ raise errors.LimitsExceeded()
+ except _ldap.SIZELIMIT_EXCEEDED:
+ raise errors.LimitsExceeded()
+ except _ldap.TIMELIMIT_EXCEEDED:
+ raise errors.LimitsExceeded()
+ except _ldap.NOT_ALLOWED_ON_RDN:
+ raise errors.NotAllowedOnRDN(attr=info)
+ except _ldap.FILTER_ERROR:
+ raise errors.BadSearchFilter(info=info)
+ except _ldap.NOT_ALLOWED_ON_NONLEAF:
+ raise errors.NotAllowedOnNonLeaf()
+ except _ldap.SERVER_DOWN:
+ raise errors.NetworkError(uri=self.ldap_uri,
+ error=u'LDAP Server Down')
+ except _ldap.LOCAL_ERROR:
+ raise errors.ACIError(info=info)
+ except _ldap.SUCCESS:
+ pass
+ except _ldap.LDAPError, e:
+ if 'NOT_ALLOWED_TO_DELEGATE' in info:
+ raise errors.ACIError(
+ info="KDC returned NOT_ALLOWED_TO_DELEGATE")
+ self.log.info('Unhandled LDAPError: %s' % str(e))
+ raise errors.DatabaseError(desc=desc, info=info)
+
+
+class IPAdmin(LDAPConnection, IPAEntryLDAPObject):
def __localinit(self):
if self.protocol == 'ldaps':
- IPAEntryLDAPObject.__init__(self,'ldaps://%s' % format_netloc(self.host, self.port))
+ ldap_uri = 'ldaps://%s' % format_netloc(self.host, self.port)
elif self.protocol == 'ldapi':
- IPAEntryLDAPObject.__init__(self,'ldapi://%%2fvar%%2frun%%2fslapd-%s.socket' % "-".join(self.realm.split(".")))
+ ldap_uri = 'ldapi://%%2fvar%%2frun%%2fslapd-%s.socket' % (
+ "-".join(self.realm.split(".")))
elif self.protocol == 'ldap':
- IPAEntryLDAPObject.__init__(self,'ldap://%s' % format_netloc(self.host, self.port))
+ ldap_uri = 'ldap://%s' % format_netloc(self.host, self.port)
else:
raise ValueError('Protocol %r not supported' % self.protocol)
+ LDAPConnection.__init__(self, ldap_uri)
+ IPAEntryLDAPObject.__init__(self, ldap_uri)
+
def __guess_protocol(self):
"""Return the protocol to use based on flags passed to the constructor
@@ -913,51 +999,7 @@ class IPAdmin(IPAEntryLDAPObject):
return sctrl
def __handle_errors(self, e, **kw):
- """
- Centralize error handling in one place.
-
- e is the error to be raised
- **kw is an exception-specific list of options
- """
- if not isinstance(e,ldap.TIMEOUT):
- desc = e.args[0]['desc'].strip()
- info = e.args[0].get('info','').strip()
- arg_desc = kw.get('arg_desc')
- if arg_desc is not None:
- info += " arguments: %s" % arg_desc
- else:
- desc = ''
- info = ''
-
- try:
- # re-raise the error so we can handle it
- raise e
- except ldap.NO_SUCH_OBJECT, e:
- arg_desc = kw.get('arg_desc', "entry not found")
- raise errors.NotFound(reason=arg_desc)
- except ldap.ALREADY_EXISTS, e:
- raise errors.DuplicateEntry()
- except ldap.CONSTRAINT_VIOLATION, e:
- # This error gets thrown by the uniqueness plugin
- if info.startswith('Another entry with the same attribute value already exists'):
- raise errors.DuplicateEntry()
- else:
- raise errors.DatabaseError(desc=desc,info=info)
- except ldap.INSUFFICIENT_ACCESS, e:
- raise errors.ACIError(info=info)
- except ldap.NO_SUCH_ATTRIBUTE:
- # this is raised when a 'delete' attribute isn't found.
- # it indicates the previous attribute was removed by another
- # update, making the oldentry stale.
- raise errors.MidairCollision()
- except ldap.ADMINLIMIT_EXCEEDED, e:
- raise errors.LimitsExceeded()
- except ldap.SIZELIMIT_EXCEEDED, e:
- raise errors.LimitsExceeded()
- except ldap.TIMELIMIT_EXCEEDED, e:
- raise errors.LimitsExceeded()
- except ldap.LDAPError, e:
- raise errors.DatabaseError(desc=desc,info=info)
+ return self.handle_errors(e, **kw)
def __wait_for_connection(self, timeout):
lurl = ldapurl.LDAPUrl(self.uri)
@@ -1189,7 +1231,7 @@ class IPAdmin(IPAEntryLDAPObject):
attrlist.append(attr)
timeout += int(time.time())
- if isinstance(dn,Entry):
+ if isinstance(dn, LDAPEntry):
dn = dn.dn
assert isinstance(dn, DN)
diff --git a/ipaserver/plugins/ldap2.py b/ipaserver/plugins/ldap2.py
index 63d39ccb6..12b815139 100644
--- a/ipaserver/plugins/ldap2.py
+++ b/ipaserver/plugins/ldap2.py
@@ -37,11 +37,10 @@ import krbV
import ldap as _ldap
import ldap.filter as _ldap_filter
-from ipapython.ipa_log_manager import log_mgr
from ipapython.dn import DN, RDN
-from ipalib.errors import NetworkError
from ipaserver.ipaldap import (
- SASL_AUTH, unicode_from_utf8, value_to_utf8, IPASimpleLDAPObject)
+ SASL_AUTH, unicode_from_utf8, value_to_utf8, IPASimpleLDAPObject,
+ LDAPConnection)
try:
@@ -70,7 +69,7 @@ MEMBERS_DIRECT = 1
MEMBERS_INDIRECT = 2
-class ldap2(CrudBackend):
+class ldap2(LDAPConnection, CrudBackend):
"""
LDAP Backend Take 2.
"""
@@ -90,12 +89,14 @@ class ldap2(CrudBackend):
def __init__(self, shared_instance=True, ldap_uri=None, base_dn=None,
schema=None):
- CrudBackend.__init__(self, shared_instance=shared_instance)
- self.log = log_mgr.get_logger(self)
try:
- self.ldap_uri = ldap_uri or api.env.ldap_uri
+ ldap_uri = ldap_uri or api.env.ldap_uri
except AttributeError:
- self.ldap_uri = 'ldap://example.com'
+ ldap_uri = 'ldap://example.com'
+
+ CrudBackend.__init__(self, shared_instance=shared_instance)
+ LDAPConnection.__init__(self, ldap_uri)
+
try:
if base_dn is not None:
self.base_dn = DN(base_dn)
@@ -115,71 +116,6 @@ class ldap2(CrudBackend):
return self.conn.schema
schema = property(_get_schema, None, None, 'schema associated with this LDAP server')
- # universal LDAPError handler
- def handle_errors(self, e):
- """
- Centralize error handling in one place.
-
- e is the error to be raised
- """
- if not isinstance(e, _ldap.TIMEOUT):
- desc = e.args[0]['desc'].strip()
- info = e.args[0].get('info', '').strip()
- else:
- desc = ''
- info = ''
-
- try:
- # re-raise the error so we can handle it
- raise e
- except _ldap.NO_SUCH_OBJECT:
- raise errors.NotFound(reason='no such entry')
- except _ldap.ALREADY_EXISTS:
- raise errors.DuplicateEntry()
- except _ldap.CONSTRAINT_VIOLATION:
- # This error gets thrown by the uniqueness plugin
- if info.startswith('Another entry with the same attribute value already exists'):
- raise errors.DuplicateEntry()
- else:
- raise errors.DatabaseError(desc=desc, info=info)
- except _ldap.INSUFFICIENT_ACCESS:
- raise errors.ACIError(info=info)
- except _ldap.INVALID_CREDENTIALS:
- raise errors.ACIError(info="%s %s" % (info, desc))
- except _ldap.NO_SUCH_ATTRIBUTE:
- # this is raised when a 'delete' attribute isn't found.
- # it indicates the previous attribute was removed by another
- # update, making the oldentry stale.
- raise errors.MidairCollision()
- except _ldap.INVALID_SYNTAX:
- raise errors.InvalidSyntax(attr=info)
- except _ldap.OBJECT_CLASS_VIOLATION:
- raise errors.ObjectclassViolation(info=info)
- except _ldap.ADMINLIMIT_EXCEEDED:
- raise errors.LimitsExceeded()
- except _ldap.SIZELIMIT_EXCEEDED:
- raise errors.LimitsExceeded()
- except _ldap.TIMELIMIT_EXCEEDED:
- raise errors.LimitsExceeded()
- except _ldap.NOT_ALLOWED_ON_RDN:
- raise errors.NotAllowedOnRDN(attr=info)
- except _ldap.FILTER_ERROR:
- raise errors.BadSearchFilter(info=info)
- except _ldap.NOT_ALLOWED_ON_NONLEAF:
- raise errors.NotAllowedOnNonLeaf()
- except _ldap.SERVER_DOWN:
- raise NetworkError(uri=self.ldap_uri,
- error=u'LDAP Server Down')
- except _ldap.LOCAL_ERROR:
- raise errors.ACIError(info=info)
- except _ldap.SUCCESS:
- pass
- except _ldap.LDAPError, e:
- if 'NOT_ALLOWED_TO_DELEGATE' in info:
- raise errors.ACIError(info="KDC returned NOT_ALLOWED_TO_DELEGATE")
- self.info('Unhandled LDAPError: %s' % str(e))
- raise errors.DatabaseError(desc=desc, info=info)
-
def get_syntax(self, attr, value):
if self.schema is None:
return None