Re: [Freeipa-devel] [PATCHES 399-401] Allow multiple API instances

2015-03-05 Thread Tomas Babej


On 03/04/2015 11:55 AM, Martin Kosek wrote:

On 03/04/2015 11:13 AM, Jan Cholasta wrote:

Dne 3.3.2015 v 16:11 Martin Kosek napsal(a):

On 03/03/2015 04:09 PM, Jan Cholasta wrote:

Dne 3.3.2015 v 16:04 Tomas Babej napsal(a):

On 03/03/2015 04:01 PM, Martin Kosek wrote:

On 03/03/2015 03:49 PM, Jan Cholasta wrote:

Hi,

the attached patches provide an attempt to fix
https://fedorahosted.org/freeipa/ticket/3090.

Patch 401 serves as an example and modifies ipa-advise to use its own
API
instance for Advice plugins.

Honza

Thanks. At least patches 399 and 400 look reasonable short for 4.2.

So with these patches, could we also get rid of
temporary_ldap2_connection we
have in ipa-replica-install? Petr3 may have other examples he met in
the past...

I think we can. Shall I prepare a patch?

If it is reasonable simple, I would go for it. It would be another selling
point for your patches.

Done.


Thanks, this looks great! It proves the point with the separate API object.
LGTM, I will let Tomas to continue with standard review then.

Martin


Codewise looks good to me.

I tested the server and replica installation, which went well. And of 
course, our ipa-advise tests detected no breakage, hence it's a ACK.


Pushed to master: 8713c5a6953e92f72d9ea7aad40588c284011025

Tomas

___
Freeipa-devel mailing list
Freeipa-devel@redhat.com
https://www.redhat.com/mailman/listinfo/freeipa-devel


Re: [Freeipa-devel] [PATCHES 399-401] Allow multiple API instances

2015-03-04 Thread Jan Cholasta

Dne 3.3.2015 v 16:11 Martin Kosek napsal(a):

On 03/03/2015 04:09 PM, Jan Cholasta wrote:

Dne 3.3.2015 v 16:04 Tomas Babej napsal(a):


On 03/03/2015 04:01 PM, Martin Kosek wrote:

On 03/03/2015 03:49 PM, Jan Cholasta wrote:

Hi,

the attached patches provide an attempt to fix
https://fedorahosted.org/freeipa/ticket/3090.

Patch 401 serves as an example and modifies ipa-advise to use its own
API
instance for Advice plugins.

Honza

Thanks. At least patches 399 and 400 look reasonable short for 4.2.

So with these patches, could we also get rid of
temporary_ldap2_connection we
have in ipa-replica-install? Petr3 may have other examples he met in
the past...


I think we can. Shall I prepare a patch?


If it is reasonable simple, I would go for it. It would be another selling
point for your patches.


Done.

--
Jan Cholasta
From 2d92312d314569b9d5acdfb45b1cae54421e62f9 Mon Sep 17 00:00:00 2001
From: Jan Cholasta jchol...@redhat.com
Date: Wed, 4 Mar 2015 09:32:44 +
Subject: [PATCH 4/5] ldap2: Use self API instance instead of ipalib.api

---
 ipaserver/plugins/ldap2.py | 45 -
 1 file changed, 32 insertions(+), 13 deletions(-)

diff --git a/ipaserver/plugins/ldap2.py b/ipaserver/plugins/ldap2.py
index ec491e9..3211b33 100644
--- a/ipaserver/plugins/ldap2.py
+++ b/ipaserver/plugins/ldap2.py
@@ -63,21 +63,40 @@ class ldap2(LDAPClient, CrudBackend):
 
 def __init__(self, shared_instance=True, ldap_uri=None, base_dn=None,
  schema=None):
-try:
-ldap_uri = ldap_uri or api.env.ldap_uri
-except AttributeError:
-ldap_uri = 'ldap://example.com'
+self.__ldap_uri = None
 
 CrudBackend.__init__(self, shared_instance=shared_instance)
 LDAPClient.__init__(self, ldap_uri)
 
+self.__base_dn = base_dn
+
+@property
+def api(self):
+self_api = super(ldap2, self).api
+if self_api is None:
+self_api = api
+return self_api
+
+@property
+def ldap_uri(self):
+try:
+return self.__ldap_uri or self.api.env.ldap_uri
+except AttributeError:
+return 'ldap://example.com'
+
+@ldap_uri.setter
+def ldap_uri(self, value):
+self.__ldap_uri = value
+
+@property
+def base_dn(self):
 try:
-if base_dn is not None:
-self.base_dn = DN(base_dn)
+if self.__base_dn is not None:
+return DN(self.__base_dn)
 else:
-self.base_dn = DN(api.env.basedn)
+return DN(self.api.env.basedn)
 except AttributeError:
-self.base_dn = DN()
+return DN()
 
 def _init_connection(self):
 # Connectible.conn is a proxy to thread-local storage;
@@ -124,11 +143,11 @@ class ldap2(LDAPClient, CrudBackend):
 _ldap.set_option(_ldap.OPT_DEBUG_LEVEL, debug_level)
 
 with self.error_handler():
-force_updates = api.env.context in ('installer', 'updates')
+force_updates = self.api.env.context in ('installer', 'updates')
 conn = IPASimpleLDAPObject(
 self.ldap_uri, force_schema_updates=force_updates)
 if self.ldap_uri.startswith('ldapi://') and ccache:
-conn.set_option(_ldap.OPT_HOST_NAME, api.env.host)
+conn.set_option(_ldap.OPT_HOST_NAME, self.api.env.host)
 minssf = conn.get_option(_ldap.OPT_X_SASL_SSF_MIN)
 maxssf = conn.get_option(_ldap.OPT_X_SASL_SSF_MAX)
 # Always connect with at least an SSF of 56, confidentiality
@@ -297,7 +316,7 @@ class ldap2(LDAPClient, CrudBackend):
 def get_ipa_config(self, attrs_list=None):
 Returns the IPA configuration entry (dn, entry_attrs).
 
-dn = api.Object.config.get_dn()
+dn = self.api.Object.config.get_dn()
 assert isinstance(dn, DN)
 
 try:
@@ -334,7 +353,7 @@ class ldap2(LDAPClient, CrudBackend):
 
 
 upg_dn = DN(('cn', 'UPG Definition'), ('cn', 'Definitions'), ('cn', 'Managed Entries'),
-('cn', 'etc'), api.env.basedn)
+('cn', 'etc'), self.api.env.basedn)
 
 try:
 upg_entries = self.conn.search_s(upg_dn, _ldap.SCOPE_BASE,
@@ -359,7 +378,7 @@ class ldap2(LDAPClient, CrudBackend):
 
 principal = getattr(context, 'principal')
 entry = self.find_entry_by_attr(krbprincipalname, principal,
-krbPrincipalAux, base_dn=api.env.basedn)
+krbPrincipalAux, base_dn=self.api.env.basedn)
 sctrl = [GetEffectiveRightsControl(True, dn:  + str(entry.dn))]
 self.conn.set_option(_ldap.OPT_SERVER_CONTROLS, sctrl)
 try:
-- 
2.1.0

From 4982e5dfaab377eb438c7adda9314937a71931ca Mon Sep 17 00:00:00 2001
From: Jan Cholasta jchol...@redhat.com
Date: Wed, 4 Mar 2015 09:35:06 +
Subject: [PATCH 5/5] replica-install: Use different API instance 

Re: [Freeipa-devel] [PATCHES 399-401] Allow multiple API instances

2015-03-04 Thread Martin Kosek
On 03/04/2015 11:13 AM, Jan Cholasta wrote:
 Dne 3.3.2015 v 16:11 Martin Kosek napsal(a):
 On 03/03/2015 04:09 PM, Jan Cholasta wrote:
 Dne 3.3.2015 v 16:04 Tomas Babej napsal(a):

 On 03/03/2015 04:01 PM, Martin Kosek wrote:
 On 03/03/2015 03:49 PM, Jan Cholasta wrote:
 Hi,

 the attached patches provide an attempt to fix
 https://fedorahosted.org/freeipa/ticket/3090.

 Patch 401 serves as an example and modifies ipa-advise to use its own
 API
 instance for Advice plugins.

 Honza
 Thanks. At least patches 399 and 400 look reasonable short for 4.2.

 So with these patches, could we also get rid of
 temporary_ldap2_connection we
 have in ipa-replica-install? Petr3 may have other examples he met in
 the past...

 I think we can. Shall I prepare a patch?

 If it is reasonable simple, I would go for it. It would be another selling
 point for your patches.
 
 Done.
 

Thanks, this looks great! It proves the point with the separate API object.
LGTM, I will let Tomas to continue with standard review then.

Martin

___
Freeipa-devel mailing list
Freeipa-devel@redhat.com
https://www.redhat.com/mailman/listinfo/freeipa-devel


Re: [Freeipa-devel] [PATCHES 399-401] Allow multiple API instances

2015-03-03 Thread Tomas Babej


On 03/03/2015 04:01 PM, Martin Kosek wrote:

On 03/03/2015 03:49 PM, Jan Cholasta wrote:

Hi,

the attached patches provide an attempt to fix
https://fedorahosted.org/freeipa/ticket/3090.

Patch 401 serves as an example and modifies ipa-advise to use its own API
instance for Advice plugins.

Honza

Thanks. At least patches 399 and 400 look reasonable short for 4.2.

So with these patches, could we also get rid of temporary_ldap2_connection we
have in ipa-replica-install? Petr3 may have other examples he met in the past...

Martin

___
Freeipa-devel mailing list
Freeipa-devel@redhat.com
https://www.redhat.com/mailman/listinfo/freeipa-devel


401 seems reasonable enough to me too, the bulk of the code is mostly 
just moving the code around and renaming variables.


Plus we have a very extensive (100%) coverage for the advise tool, so I 
wouldn't exclude it from the patchset.


Tomas

___
Freeipa-devel mailing list
Freeipa-devel@redhat.com
https://www.redhat.com/mailman/listinfo/freeipa-devel


Re: [Freeipa-devel] [PATCHES 399-401] Allow multiple API instances

2015-03-03 Thread Martin Kosek
On 03/03/2015 04:09 PM, Jan Cholasta wrote:
 Dne 3.3.2015 v 16:04 Tomas Babej napsal(a):

 On 03/03/2015 04:01 PM, Martin Kosek wrote:
 On 03/03/2015 03:49 PM, Jan Cholasta wrote:
 Hi,

 the attached patches provide an attempt to fix
 https://fedorahosted.org/freeipa/ticket/3090.

 Patch 401 serves as an example and modifies ipa-advise to use its own
 API
 instance for Advice plugins.

 Honza
 Thanks. At least patches 399 and 400 look reasonable short for 4.2.

 So with these patches, could we also get rid of
 temporary_ldap2_connection we
 have in ipa-replica-install? Petr3 may have other examples he met in
 the past...
 
 I think we can. Shall I prepare a patch?

If it is reasonable simple, I would go for it. It would be another selling
point for your patches.

 

 Martin

 401 seems reasonable enough to me too, the bulk of the code is mostly
 just moving the code around and renaming variables.
 
 Right.
 

 Plus we have a very extensive (100%) coverage for the advise tool, so I
 wouldn't exclude it from the patchset.
 
 +1

Martin

___
Freeipa-devel mailing list
Freeipa-devel@redhat.com
https://www.redhat.com/mailman/listinfo/freeipa-devel


Re: [Freeipa-devel] [PATCHES 399-401] Allow multiple API instances

2015-03-03 Thread Jan Cholasta

Dne 3.3.2015 v 16:04 Tomas Babej napsal(a):


On 03/03/2015 04:01 PM, Martin Kosek wrote:

On 03/03/2015 03:49 PM, Jan Cholasta wrote:

Hi,

the attached patches provide an attempt to fix
https://fedorahosted.org/freeipa/ticket/3090.

Patch 401 serves as an example and modifies ipa-advise to use its own
API
instance for Advice plugins.

Honza

Thanks. At least patches 399 and 400 look reasonable short for 4.2.

So with these patches, could we also get rid of
temporary_ldap2_connection we
have in ipa-replica-install? Petr3 may have other examples he met in
the past...


I think we can. Shall I prepare a patch?



Martin


401 seems reasonable enough to me too, the bulk of the code is mostly
just moving the code around and renaming variables.


Right.



Plus we have a very extensive (100%) coverage for the advise tool, so I
wouldn't exclude it from the patchset.


+1



Tomas


--
Jan Cholasta

___
Freeipa-devel mailing list
Freeipa-devel@redhat.com
https://www.redhat.com/mailman/listinfo/freeipa-devel


Re: [Freeipa-devel] [PATCHES 399-401] Allow multiple API instances

2015-03-03 Thread Martin Kosek
On 03/03/2015 03:49 PM, Jan Cholasta wrote:
 Hi,
 
 the attached patches provide an attempt to fix
 https://fedorahosted.org/freeipa/ticket/3090.
 
 Patch 401 serves as an example and modifies ipa-advise to use its own API
 instance for Advice plugins.
 
 Honza

Thanks. At least patches 399 and 400 look reasonable short for 4.2.

So with these patches, could we also get rid of temporary_ldap2_connection we
have in ipa-replica-install? Petr3 may have other examples he met in the past...

Martin

___
Freeipa-devel mailing list
Freeipa-devel@redhat.com
https://www.redhat.com/mailman/listinfo/freeipa-devel


[Freeipa-devel] [PATCHES 399-401] Allow multiple API instances

2015-03-03 Thread Jan Cholasta

Hi,

the attached patches provide an attempt to fix 
https://fedorahosted.org/freeipa/ticket/3090.


Patch 401 serves as an example and modifies ipa-advise to use its own 
API instance for Advice plugins.


Honza

--
Jan Cholasta
From 3715c9b4ca43eab6c5ad01b34cd1b14838241bde Mon Sep 17 00:00:00 2001
From: Jan Cholasta jchol...@redhat.com
Date: Mon, 16 Feb 2015 13:11:38 +
Subject: [PATCH 1/3] ipalib: Allow multiple API instances

Merged the Registrar class into the Registry class. Plugins are now
registered globally instead of in ipalib.api and are instantiated per-API
instance. Different set of plugin base classes can be used in each API
instance.

https://fedorahosted.org/freeipa/ticket/3090
---
 ipalib/backend.py |   3 +
 ipalib/frontend.py|  10 +-
 ipalib/plugable.py| 204 --
 ipatests/test_ipalib/test_plugable.py | 119 
 4 files changed, 185 insertions(+), 151 deletions(-)

diff --git a/ipalib/backend.py b/ipalib/backend.py
index 2100589..4c1001d 100644
--- a/ipalib/backend.py
+++ b/ipalib/backend.py
@@ -27,7 +27,10 @@ import os
 from errors import PublicError, InternalError, CommandError
 from request import context, Connection, destroy_context
 
+register = plugable.Registry()
 
+
+@register.base()
 class Backend(plugable.Plugin):
 
 Base class for all backend plugins.
diff --git a/ipalib/frontend.py b/ipalib/frontend.py
index 98070b8..e82a03a 100644
--- a/ipalib/frontend.py
+++ b/ipalib/frontend.py
@@ -27,7 +27,7 @@ from distutils import version
 from ipapython.version import API_VERSION
 from ipapython.ipa_log_manager import root_logger
 from base import NameSpace
-from plugable import Plugin, is_production_mode
+from plugable import Plugin, Registry, is_production_mode
 from parameters import create_param, Param, Str, Flag, Password
 from output import Output, Entry, ListOfEntries
 from text import _
@@ -40,6 +40,9 @@ from textwrap import wrap
 
 RULE_FLAG = 'validation_rule'
 
+register = Registry()
+
+
 def rule(obj):
 assert not hasattr(obj, RULE_FLAG)
 setattr(obj, RULE_FLAG, True)
@@ -366,6 +369,7 @@ class HasParam(Plugin):
 setattr(self, name, namespace)
 
 
+@register.base()
 class Command(HasParam):
 
 A public IPA atomic operation.
@@ -1120,6 +1124,7 @@ class Local(Command):
 return self.forward(*args, **options)
 
 
+@register.base()
 class Object(HasParam):
 finalize_early = False
 
@@ -1278,6 +1283,7 @@ class Attribute(Plugin):
 super(Attribute, self)._on_finalize()
 
 
+@register.base()
 class Method(Attribute, Command):
 
 A command with an associated object.
@@ -1364,6 +1370,7 @@ class Method(Attribute, Command):
 yield param
 
 
+@register.base()
 class Updater(Method):
 
 An LDAP update with an associated object (always update).
@@ -1423,6 +1430,7 @@ class _AdviceOutput(object):
 self.content.append(line)
 
 
+@register.base()
 class Advice(Plugin):
 
 Base class for advices, plugins for ipa-advise.
diff --git a/ipalib/plugable.py b/ipalib/plugable.py
index a6504d1..aae7626 100644
--- a/ipalib/plugable.py
+++ b/ipalib/plugable.py
@@ -74,18 +74,94 @@ class Registry(object):
 For forward compatibility, make sure that the module-level instance of
 this object is named register.
 
-# TODO: Instead of auto-loading when plugin modules are imported,
-# plugins should be stored in this object.
-# The API should examine it and load plugins explicitly.
-def __call__(self):
-from ipalib import api
 
-def decorator(cls):
-api.register(cls)
-return cls
+__allowed = {}
+__registered = set()
+
+def base(self):
+def decorator(base):
+if not inspect.isclass(base):
+raise TypeError('plugin base must be a class; got %r' % base)
+
+if base in self.__allowed:
+raise errors.PluginDuplicateError(plugin=base)
+
+self.__allowed[base] = {}
+
+return base
+
+return decorator
+
+def __findbases(self, klass):
+
+Iterates through allowed bases that ``klass`` is 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.
+
+found = False
+for (base, sub_d) in self.__allowed.iteritems():
+if issubclass(klass, base):
+found = True
+yield (base, sub_d)
+if not found:
+raise errors.PluginSubclassError(
+plugin=klass, bases=self.__allowed.keys()
+)
+
+def __call__(self, override=False):
+def decorator(klass):
+if not inspect.isclass(klass):
+raise TypeError('plugin must be a class; got %r' % klass)
+
+# Raise DuplicateError if