[Freeipa-devel] Redesigning LDAP code

Petr Viktorin pviktori at redhat.com
Fri Jan 11 11:59:04 UTC 2013


We had a small discussion off-list about how we want IPA's LDAP handling 
to look in the future.
To continue the discussion publicly I've summarized the results and 
added some of my own ideas to a page.
John gets credit for the overview (the mistakes & WTFs are mine).

The text is on http://freeipa.org/page/V3/LDAP_code, and echoed below.


-- 
Petr³


__NOTOC__

= Overview =

Ticket [https://fedorahosted.org/freeipa/ticket/2660 #2660] installer 
code should use ldap2

This is important to do.
We really should have just one API and set of classes for dealing with LDAP.
For the DN work we had to refactor a fair amount of code in order to 
force most
things to funnel through one common code location.
Because ldap is so decentralized and we had so many different APIs,
classes, etc it was a large chunk of work and is only partially completed,
it got a lot better but it wasn't finished.

The primary thing which needs to be resolved is our use of Entity and Entry
classes.
There never should have been two almost identical classes.
One or both of Entity/Entry needs to be removed.

As it stands now we have two basic ways we access ldap results.
In the installer code it's mostly via Entity/Entry objects.
But in the server code (ldpa2) it's done by accessing the data as 
returned by
the python ldap module (e.g. list of (DN, attr_dict) tuples).

We need to decide which of the two basic interfaces we're going to use and
converge on it.
Each approach has merits.
But 3 different APIs for interacting with ldap is 2 too many.


= Use Cases =

N/A

= Design=

== Entry representation ==

LDAP entries will be encapsulated in objects.
These will perform type checking and validation (ticket #2357).
They should grow from ldap2.LDAPEntry (which is currently just a "dn, data"
namedtuple).

These objects will behave like a dict of lists:

   entry[attrname] = [value]
   attrname in entry
   del entry[attrname]
   entry.keys(), .values(), .items()  # but NOT `for key in entry`, see 
below

The keys are case-insensitive but case-preserving.

We'll use lists for all attributes, even single-valued ones, because
"single-valuedness" can change.


QUESTION: Would having entry.dn as an alias for entry['dn'] be useful 
enough to
break the rules?


The object should also "rembember" its original set of attributes,
so we don't have to retrieve them from LDAP again when it's updated.



== The connection/backend class ==

We'll use the ldap2 class.

The class has some overly specific "helper" methods like 
remove_principal_key
or modify_password. We shouldn't add new ones, and the existing ones 
should be
moved away eventually.




== Backwards compatibility, porting ==

For compatibility with existing plugins, the LDAPEntry object will unpack to
a tuple:

dn, entry_attrs = entry
(the entry_attrs can be entry itself, so we keep the object's validation 
powers)
I'd rather not do keep indexing (dn = entry[0]; entry_attrs = entry[1]).

We'll also temporarily add the legacy Entry interface (toTupleList, toDict,
setValues, data, origDataDict, ...) to LDAPEntry.
The IPAdmin class will be subclassed from ldap2. All its uses will be
gradually converted to only use the ldap2 interface, at which point IPAdmin
can be removed.

The backwards compatibility stuff should be removed as soon as it's unused.

Of course code using the raw python-ldap API will also be converted to 
ldap2.

= Implementation =

No additional requirements or changes discovered during the 
implementation phase.

= Feature Managment =

N/A

= Major configuration options and enablement =

N/A

= Replication =

N/A

= Updates and Upgrades =

N/A

= Dependencies =

N/A

= External Impact =

N/A

= Design page authors =

~~~, jdennis




More information about the Freeipa-devel mailing list