Re: [Freeipa-devel] [PATCH] 810 speed up indirect member processing

2015-04-26 Thread Jan Cholasta

Dne 20.4.2015 v 11:59 Petr Vobornik napsal(a):

On 04/20/2015 09:51 AM, Jan Cholasta wrote:

Dne 9.4.2015 v 13:56 Petr Vobornik napsal(a):

On 04/08/2015 10:21 AM, Jan Cholasta wrote:

4) The processing of memberof should be done even when memberofindirect
is not requested, otherwise its value will depend on whether
memberofindirect was requested or not.


True, but it's the same behavior as before. Could be changed in other
patch.


OK. Should we file a ticket?


AFAIK, memberof and memberofindirect are requested always together atm.
Do we have a use case for this change?


It's a bug. Use case is when someone requests memberof only, they must 
get direct memberof values only.



In any case, I've opened a ticket
about more finer control of fetching members (as was discussed
previously in triage and dev mtgs), it might be part of it.

https://fedorahosted.org/freeipa/ticket/4995


OK.








5) I would prefer if all membership processing
(.convert_attribute_members() and .get_indirect_members()) was done
in a
single LDAPObject method.


Now, as before, get_indirect_members is called before post callbacks and
convert_attribute_members after. If it should be combined, it should be
done separately.


OK, but at least move get_indirect_members to LDAPObject.



Moved


Thanks, ACK.

Pushed to master: 4364ac08c538e3a4253804f523707092b34c2ed2

--
Jan Cholasta

--
Manage your subscription for the Freeipa-devel mailing list:
https://www.redhat.com/mailman/listinfo/freeipa-devel
Contribute to FreeIPA: http://www.freeipa.org/page/Contribute/Code


Re: [Freeipa-devel] [PATCH] 810 speed up indirect member processing

2015-04-20 Thread Jan Cholasta

Dne 9.4.2015 v 13:56 Petr Vobornik napsal(a):

On 04/08/2015 10:21 AM, Jan Cholasta wrote:

Hi,

Dne 31.3.2015 v 12:11 Petr Vobornik napsal(a):

the old implementation tried to get all entries which are member of
group. That means also user. User can't have any members therefore this
costly processing was unnecessary.

New implementation reduces the search only to entries which can have
entries.

Also page size was removed to avoid paging by small pages(default size:
100) which is very slow for many members.

https://fedorahosted.org/freeipa/ticket/4947

Useful to test with #809


1) To search for entries with members, you should search for entries
with the member attribute set ('(member=*)'), not for entries with some
arbitrary object class.


Replaced, new presence index added




2) I don't like how the search in get_memberindirect is limited to an
arbitrary hard-coded subtree. You should go through the object's
attribute_members to figure out which subtrees to search.



The subtree search was removed.



3) Since memberindirect and memberofindirect are not real attributes,
you must define their syntax in ipaldap before you cat set them using
.raw[], otherwise they will be decoded to wrong type.


Added.



4) The processing of memberof should be done even when memberofindirect
is not requested, otherwise its value will depend on whether
memberofindirect was requested or not.


True, but it's the same behavior as before. Could be changed in other
patch.


OK. Should we file a ticket?






5) I would prefer if all membership processing
(.convert_attribute_members() and .get_indirect_members()) was done in a
single LDAPObject method.


Now, as before, get_indirect_members is called before post callbacks and
convert_attribute_members after. If it should be combined, it should be
done separately.


OK, but at least move get_indirect_members to LDAPObject.






Honza




--
Jan Cholasta

--
Manage your subscription for the Freeipa-devel mailing list:
https://www.redhat.com/mailman/listinfo/freeipa-devel
Contribute to FreeIPA: http://www.freeipa.org/page/Contribute/Code


Re: [Freeipa-devel] [PATCH] 810 speed up indirect member processing

2015-04-20 Thread Petr Vobornik

On 04/20/2015 09:51 AM, Jan Cholasta wrote:

Dne 9.4.2015 v 13:56 Petr Vobornik napsal(a):

On 04/08/2015 10:21 AM, Jan Cholasta wrote:

Hi,

Dne 31.3.2015 v 12:11 Petr Vobornik napsal(a):

the old implementation tried to get all entries which are member of
group. That means also user. User can't have any members therefore this
costly processing was unnecessary.

New implementation reduces the search only to entries which can have
entries.

Also page size was removed to avoid paging by small pages(default size:
100) which is very slow for many members.

https://fedorahosted.org/freeipa/ticket/4947

Useful to test with #809


1) To search for entries with members, you should search for entries
with the member attribute set ('(member=*)'), not for entries with some
arbitrary object class.


Replaced, new presence index added




2) I don't like how the search in get_memberindirect is limited to an
arbitrary hard-coded subtree. You should go through the object's
attribute_members to figure out which subtrees to search.



The subtree search was removed.



3) Since memberindirect and memberofindirect are not real attributes,
you must define their syntax in ipaldap before you cat set them using
.raw[], otherwise they will be decoded to wrong type.


Added.



4) The processing of memberof should be done even when memberofindirect
is not requested, otherwise its value will depend on whether
memberofindirect was requested or not.


True, but it's the same behavior as before. Could be changed in other
patch.


OK. Should we file a ticket?


AFAIK, memberof and memberofindirect are requested always together atm. 
Do we have a use case for this change? In any case, I've opened a ticket 
about more finer control of fetching members (as was discussed 
previously in triage and dev mtgs), it might be part of it.


https://fedorahosted.org/freeipa/ticket/4995






5) I would prefer if all membership processing
(.convert_attribute_members() and .get_indirect_members()) was done in a
single LDAPObject method.


Now, as before, get_indirect_members is called before post callbacks and
convert_attribute_members after. If it should be combined, it should be
done separately.


OK, but at least move get_indirect_members to LDAPObject.



Moved
--
Petr Vobornik
From 68164aa2a5acba14dbfd6bb6d0f2b45cadf6a503 Mon Sep 17 00:00:00 2001
From: Petr Vobornik pvobo...@redhat.com
Date: Tue, 31 Mar 2015 10:59:37 +0200
Subject: [PATCH] speed up indirect member processing

the old implementation tried to get all entries which are member of group.
That means also user. User can't have any members therefore this costly
processing was unnecessary.

New implementation reduces the search only to entries which have members.

Also page size was removed to avoid paging by small pages(default size: 100)
which is very slow for many members.

https://fedorahosted.org/freeipa/ticket/4947
---
 install/updates/20-indices.update |  2 +-
 ipalib/plugins/baseldap.py| 72 +++
 ipalib/plugins/host.py|  2 +-
 ipalib/plugins/role.py|  8 ++--
 ipapython/ipaldap.py  |  2 +
 ipaserver/plugins/ldap2.py| 90 ---
 6 files changed, 81 insertions(+), 95 deletions(-)

diff --git a/install/updates/20-indices.update b/install/updates/20-indices.update
index a8a432d9c28a7fb4ca74582e36d4c39fd98df2cf..a9ec9f9eb9bcc228dcbb7eba99879ce5a8251e80 100644
--- a/install/updates/20-indices.update
+++ b/install/updates/20-indices.update
@@ -27,7 +27,7 @@ default:nsSystemIndex: false
 only:nsIndexType: eq,pres,sub
 
 dn: cn=member,cn=index,cn=userRoot,cn=ldbm database,cn=plugins,cn=config
-only:nsIndexType: eq,sub
+only:nsIndexType: eq,pres,sub
 
 dn: cn=uniquemember,cn=index,cn=userRoot,cn=ldbm database,cn=plugins,cn=config
 only:nsIndexType: eq,sub
diff --git a/ipalib/plugins/baseldap.py b/ipalib/plugins/baseldap.py
index ca4e54fd269aba9fdcf234f6450382fb7daabe42..b06b570cbc353aa903e5b2218932b8c6e59ce31b 100644
--- a/ipalib/plugins/baseldap.py
+++ b/ipalib/plugins/baseldap.py
@@ -663,6 +663,67 @@ class LDAPObject(Object):
 new_attr.append(new_value)
 break
 
+def get_indirect_members(self, entry_attrs, attrs_list):
+if 'memberindirect' in attrs_list:
+self.get_memberindirect(entry_attrs)
+if 'memberofindirect' in attrs_list:
+self.get_memberofindirect(entry_attrs)
+
+def get_memberindirect(self, group_entry):
+
+Get indirect members
+
+
+mo_filter = self.backend.make_filter({'memberof': group_entry.dn})
+filter = self.backend.combine_filters(
+('(member=*)', mo_filter), self.backend.MATCH_ALL)
+try:
+result, truncated = self.backend.find_entries(
+base_dn=self.api.env.basedn,
+filter=filter,
+attrs_list=['member'],
+size_limit=-1, # paged 

Re: [Freeipa-devel] [PATCH] 810 speed up indirect member processing

2015-04-09 Thread Petr Vobornik

On 04/08/2015 10:21 AM, Jan Cholasta wrote:

Hi,

Dne 31.3.2015 v 12:11 Petr Vobornik napsal(a):

the old implementation tried to get all entries which are member of
group. That means also user. User can't have any members therefore this
costly processing was unnecessary.

New implementation reduces the search only to entries which can have
entries.

Also page size was removed to avoid paging by small pages(default size:
100) which is very slow for many members.

https://fedorahosted.org/freeipa/ticket/4947

Useful to test with #809


1) To search for entries with members, you should search for entries
with the member attribute set ('(member=*)'), not for entries with some
arbitrary object class.


Replaced, new presence index added




2) I don't like how the search in get_memberindirect is limited to an
arbitrary hard-coded subtree. You should go through the object's
attribute_members to figure out which subtrees to search.



The subtree search was removed.



3) Since memberindirect and memberofindirect are not real attributes,
you must define their syntax in ipaldap before you cat set them using
.raw[], otherwise they will be decoded to wrong type.


Added.



4) The processing of memberof should be done even when memberofindirect
is not requested, otherwise its value will depend on whether
memberofindirect was requested or not.


True, but it's the same behavior as before. Could be changed in other patch.




5) I would prefer if all membership processing
(.convert_attribute_members() and .get_indirect_members()) was done in a
single LDAPObject method.


Now, as before, get_indirect_members is called before post callbacks and 
convert_attribute_members after. If it should be combined, it should be 
done separately.





Honza


--
Petr Vobornik
From 27dfa6d0e2a1815d496f47b4f10b5a6307f51fda Mon Sep 17 00:00:00 2001
From: Petr Vobornik pvobo...@redhat.com
Date: Tue, 31 Mar 2015 10:59:37 +0200
Subject: [PATCH] speed up indirect member processing

the old implementation tried to get all entries which are member of group.
That means also user. User can't have any members therefore this costly
processing was unnecessary.

New implementation reduces the search only to entries which have members.

Also page size was removed to avoid paging by small pages(default size: 100)
which is very slow for many members.

https://fedorahosted.org/freeipa/ticket/4947
---
 install/updates/20-indices.update |  2 +-
 ipalib/plugins/baseldap.py| 72 +++
 ipalib/plugins/host.py|  2 +-
 ipalib/plugins/role.py|  8 ++--
 ipapython/ipaldap.py  |  2 +
 ipaserver/plugins/ldap2.py| 90 ---
 6 files changed, 81 insertions(+), 95 deletions(-)

diff --git a/install/updates/20-indices.update b/install/updates/20-indices.update
index a8a432d9c28a7fb4ca74582e36d4c39fd98df2cf..a9ec9f9eb9bcc228dcbb7eba99879ce5a8251e80 100644
--- a/install/updates/20-indices.update
+++ b/install/updates/20-indices.update
@@ -27,7 +27,7 @@ default:nsSystemIndex: false
 only:nsIndexType: eq,pres,sub
 
 dn: cn=member,cn=index,cn=userRoot,cn=ldbm database,cn=plugins,cn=config
-only:nsIndexType: eq,sub
+only:nsIndexType: eq,pres,sub
 
 dn: cn=uniquemember,cn=index,cn=userRoot,cn=ldbm database,cn=plugins,cn=config
 only:nsIndexType: eq,sub
diff --git a/ipalib/plugins/baseldap.py b/ipalib/plugins/baseldap.py
index c9f98ed12d3a584597af9b0be08361bceca620e7..9c75bc048283546902a89825ba489d42b26f10fd 100644
--- a/ipalib/plugins/baseldap.py
+++ b/ipalib/plugins/baseldap.py
@@ -663,6 +663,61 @@ class LDAPObject(Object):
 new_attr.append(new_value)
 break
 
+def get_memberindirect(self, group_entry):
+
+Get indirect members
+
+
+mo_filter = self.backend.make_filter({'memberof': group_entry.dn})
+filter = self.backend.combine_filters(
+('(member=*)', mo_filter), self.backend.MATCH_ALL)
+try:
+result, truncated = self.backend.find_entries(
+base_dn=self.api.env.basedn,
+filter=filter,
+attrs_list=['member'],
+size_limit=-1, # paged search will get everything anyway
+paged_search=True)
+if truncated:
+raise errors.LimitsExceeded()
+except errors.NotFound:
+result = []
+
+indirect = set()
+for entry in result:
+indirect.update(entry.raw.get('member', []))
+indirect.difference_update(group_entry.raw.get('member', []))
+
+if indirect:
+group_entry.raw['memberindirect'] = list(indirect)
+
+def get_memberofindirect(self, entry):
+
+dn = entry.dn
+filter = self.backend.make_filter(
+{'member': dn, 'memberuser': dn, 'memberhost': dn})
+try:
+result, truncated = self.backend.find_entries(
+

Re: [Freeipa-devel] [PATCH] 810 speed up indirect member processing

2015-04-08 Thread Jan Cholasta

Hi,

Dne 31.3.2015 v 12:11 Petr Vobornik napsal(a):

the old implementation tried to get all entries which are member of
group. That means also user. User can't have any members therefore this
costly processing was unnecessary.

New implementation reduces the search only to entries which can have
entries.

Also page size was removed to avoid paging by small pages(default size:
100) which is very slow for many members.

https://fedorahosted.org/freeipa/ticket/4947

Useful to test with #809


1) To search for entries with members, you should search for entries 
with the member attribute set ('(member=*)'), not for entries with some 
arbitrary object class.



2) I don't like how the search in get_memberindirect is limited to an 
arbitrary hard-coded subtree. You should go through the object's 
attribute_members to figure out which subtrees to search.



3) Since memberindirect and memberofindirect are not real attributes, 
you must define their syntax in ipaldap before you cat set them using 
.raw[], otherwise they will be decoded to wrong type.



4) The processing of memberof should be done even when memberofindirect 
is not requested, otherwise its value will depend on whether 
memberofindirect was requested or not.



5) I would prefer if all membership processing 
(.convert_attribute_members() and .get_indirect_members()) was done in a 
single LDAPObject method.



Honza

--
Jan Cholasta

--
Manage your subscription for the Freeipa-devel mailing list:
https://www.redhat.com/mailman/listinfo/freeipa-devel
Contribute to FreeIPA: http://www.freeipa.org/page/Contribute/Code


[Freeipa-devel] [PATCH] 810 speed up indirect member processing

2015-03-31 Thread Petr Vobornik
the old implementation tried to get all entries which are member of 
group. That means also user. User can't have any members therefore this 
costly processing was unnecessary.


New implementation reduces the search only to entries which can have 
entries.


Also page size was removed to avoid paging by small pages(default size: 
100) which is very slow for many members.


https://fedorahosted.org/freeipa/ticket/4947

Useful to test with #809
--
Petr Vobornik
From 2d07532771a4a542cb220f87cdc7c1ce115014f6 Mon Sep 17 00:00:00 2001
From: Petr Vobornik pvobo...@redhat.com
Date: Tue, 31 Mar 2015 10:59:37 +0200
Subject: [PATCH] speed up indirect member processing

the old implementation tried to get all entries which are member of group.
That means also user. User can't have any members therefore this costly
processing was unnecessary.

New implementation reduces the search only to entries which can have entries.

Also page size was removed to avoid paging by small pages(default size: 100)
which is very slow for many members.

https://fedorahosted.org/freeipa/ticket/4947
---
 ipalib/plugins/baseldap.py   | 91 
 ipalib/plugins/group.py  |  1 +
 ipalib/plugins/host.py   |  2 +-
 ipalib/plugins/hostgroup.py  |  1 +
 ipalib/plugins/netgroup.py   |  1 +
 ipalib/plugins/permission.py |  1 +
 ipalib/plugins/role.py   |  8 ++--
 ipaserver/plugins/ldap2.py   | 90 ---
 8 files changed, 101 insertions(+), 94 deletions(-)

diff --git a/ipalib/plugins/baseldap.py b/ipalib/plugins/baseldap.py
index 42509d63de6078b01cc794a005a528d27a168f26..56f871ac309b562130f52abce11816d811f9c89c 100644
--- a/ipalib/plugins/baseldap.py
+++ b/ipalib/plugins/baseldap.py
@@ -538,6 +538,7 @@ class LDAPObject(Object):
 rdn_attribute = ''
 uuid_attribute = ''
 attribute_members = {}
+memberindirect_config = ('*', None)
 rdn_is_primary_key = False # Do we need RDN change to do a rename?
 password_attributes = []
 # Can bind as this entry (has userPassword or krbPrincipalKey)
@@ -663,6 +664,79 @@ class LDAPObject(Object):
 break
 del entry_attrs[attr]
 
+def get_memberindirect(self, group_entry):
+
+Get indirect members
+
+Other objects with memberindirect attribute should define
+`memberindirect_config`. This object class filter is used to limit the
+number of members returned to only the members which can contain other
+members.
+
+
+(member_oc, basedn) = self.memberindirect_config
+
+if not member_oc:
+self.log.error(
+('Missing `memberindirect_object_class` IPA object property.\n'
+ 'Skipping indirect member processing.'))
+return
+
+if not basedn:
+basedn = self.api.env.basedn
+
+filter = self.backend.make_filter(
+{'memberof': group_entry.dn, 'objectclass': member_oc},
+None, self.backend.MATCH_ALL
+)
+
+try:
+result, truncated = self.backend.find_entries(
+base_dn=basedn,
+filter=filter,
+attrs_list=['member'],
+size_limit=-1, # paged search will get everything anyway
+paged_search=True)
+if truncated:
+raise errors.LimitsExceeded()
+except errors.NotFound:
+result = []
+
+indirect = set()
+for entry in result:
+indirect.update(entry.raw.get('member', []))
+indirect.difference_update(group_entry.raw.get('member', []))
+
+if indirect:
+group_entry.raw['memberindirect'] = list(indirect)
+
+def get_memberofindirect(self, entry):
+
+dn = entry.dn
+filter = self.backend.make_filter(
+{'member': dn, 'memberuser': dn, 'memberhost': dn})
+try:
+result, truncated = self.backend.find_entries(
+base_dn=self.api.env.basedn,
+filter=filter,
+attrs_list=[''])
+if truncated:
+raise errors.LimitsExceeded()
+except errors.NotFound:
+result = []
+
+direct = set()
+indirect = set(entry.raw.get('memberof', []))
+for group_entry in result:
+dn = str(group_entry.dn)
+if dn in indirect:
+indirect.remove(dn)
+direct.add(dn)
+
+entry.raw['memberof'] = list(direct)
+if indirect:
+entry.raw['memberofindirect'] = list(indirect)
+
 def get_password_attributes(self, ldap, dn, entry_attrs):
 
 Search on the entry to determine if it has a password or
@@ -1106,6 +1180,12 @@ last, after all sets and adds.),
 )
 break
 
+def get_indirect_members(self, entry_attrs, attrs_list):
+if 'memberindirect' in