diff options
author | Ana Krivokapic <akrivoka@redhat.com> | 2013-09-19 14:01:58 +0200 |
---|---|---|
committer | Martin Kosek <mkosek@redhat.com> | 2013-11-15 12:46:06 +0100 |
commit | d97386de5b68c90c53362dda54b126fdc97e00b6 (patch) | |
tree | ddd3927c48e16a54613f07b132476c2eca122fda /ipalib/plugins | |
parent | eaaf7ed0f20b81ce10e1e36ce36c673445a83f2b (diff) | |
download | freeipa-d97386de5b68c90c53362dda54b126fdc97e00b6.tar.gz freeipa-d97386de5b68c90c53362dda54b126fdc97e00b6.tar.xz freeipa-d97386de5b68c90c53362dda54b126fdc97e00b6.zip |
Add automember rebuild command
Add a new command to IPA CLI: ipa automember-rebuild
The command integrates the automember rebuild membership task functionality
into IPA CLI. It makes it possible to rebuild automember membership for
groups/hostgroups.
Design: http://www.freeipa.org/page/V3/Automember_rebuild_membership
https://fedorahosted.org/freeipa/ticket/3752
Diffstat (limited to 'ipalib/plugins')
-rw-r--r-- | ipalib/plugins/automember.py | 143 |
1 files changed, 133 insertions, 10 deletions
diff --git a/ipalib/plugins/automember.py b/ipalib/plugins/automember.py index 4f563f119..fc696cc62 100644 --- a/ipalib/plugins/automember.py +++ b/ipalib/plugins/automember.py @@ -16,13 +16,11 @@ # # You should have received a copy of the GNU General Public License # along with this program. If not, see <http://www.gnu.org/licenses/>. - -from ipalib import api, errors -from ipalib import Str, StrEnum +import uuid +import ldap as _ldap +from ipalib import api, errors, Str, StrEnum, _, ngettext from ipalib.plugins.baseldap import * -from ipalib import _, ngettext from ipalib.request import context -import ldap as _ldap from ipapython.dn import DN __doc__ = _(""" @@ -43,6 +41,8 @@ A default group or hostgroup could be specified for entries that do not match any rule. In case of user entries this group will be a fallback group because all users are by default members of group specified in IPA config. +The automember-rebuild command can be used to retroactively run automember rules +against existing entries, thus rebuilding their membership. EXAMPLES: @@ -107,6 +107,18 @@ EXAMPLES: Delete an automember rule: ipa automember-del --type=hostgroup webservers ipa automember-del --type=group devel + + Rebuild membership for all users: + ipa automember-rebuild --type=group + + Rebuild membership for all hosts: + ipa automember-rebuild --type=hostgroup + + Rebuild membership for specified users: + ipa automember-rebuild --users=tuser1 --users=tuser2 + + Rebuild membership for specified hosts: + ipa automember-rebuild --hosts=web1.example.com --hosts=web2.example.com """) # Options used by Condition Add and Remove. @@ -184,14 +196,17 @@ class automember(LDAPObject): ), ) - def dn_exists(self, grouptype, groupname, *keys): + def dn_exists(self, otype, oname): ldap = self.api.Backend.ldap2 - dn = self.api.Object[grouptype].get_dn(groupname) + dn = self.api.Object[otype].get_dn(oname) try: - (gdn, entry_attrs) = ldap.get_entry(dn, []) + entry = ldap.get_entry(dn, []) except errors.NotFound: - raise errors.NotFound(reason=_(u'Group: %s not found!') % groupname) - return gdn + raise errors.NotFound( + reason=_(u'%(otype)s "%(oname)s" not found') % + dict(otype=otype, oname=oname) + ) + return entry.dn def get_dn(self, *keys, **options): if self.parent_object: @@ -587,3 +602,111 @@ class automember_default_group_show(LDAPRetrieve): return result api.register(automember_default_group_show) + + +class automember_rebuild(Command): + __doc__ = _('Rebuild auto membership.') + # TODO: Add a --dry-run option: + # https://fedorahosted.org/freeipa/ticket/3936 + takes_options = ( + group_type[0].clone( + required=False, + label=_('Rebuild membership for all members of a grouping') + ), + Str( + 'users*', + label=_('Users'), + doc=_('Rebuild membership for specified users'), + ), + Str( + 'hosts*', + label=_('Hosts'), + doc=_('Rebuild membership for specified hosts'), + ), + ) + has_output = output.standard_value + msg_summary = _('Automember rebuild membership task completed') + + def validate(self, **kw): + """ + Validation rules: + - at least one of 'type', 'users', 'hosts' is required + - 'users' and 'hosts' cannot be combined together + - if 'users' and 'type' are specified, 'type' must be 'group' + - if 'hosts' and 'type' are specified, 'type' must be 'hostgroup' + """ + super(automember_rebuild, self).validate(**kw) + users, hosts, gtype = kw.get('users'), kw.get('hosts'), kw.get('type') + + if not (gtype or users or hosts): + raise errors.MutuallyExclusiveError( + reason=_('at least one of options: type, users, hosts must be ' + 'specified') + ) + + if users and hosts: + raise errors.MutuallyExclusiveError( + reason=_("users and hosts cannot both be set") + ) + if gtype == 'group' and hosts: + raise errors.MutuallyExclusiveError( + reason=_("hosts cannot be set when type is 'group'") + ) + if gtype == 'hostgroup' and users: + raise errors.MutuallyExclusiveError( + reason=_("users cannot be set when type is 'hostgroup'") + ) + + def execute(self, *keys, **options): + ldap = self.api.Backend.ldap2 + cn = str(uuid.uuid4()) + + gtype = options.get('type') + if not gtype: + gtype = 'group' if options.get('users') else 'hostgroup' + + types = { + 'group': ( + 'user', + 'users', + DN(api.env.container_user, api.env.basedn) + ), + 'hostgroup': ( + 'host', + 'hosts', + DN(api.env.container_host, api.env.basedn) + ), + } + + obj_name, opt_name, basedn = types[gtype] + obj = self.api.Object[obj_name] + + names = options.get(opt_name) + if names: + for name in names: + obj.get_dn_if_exists(name) + search_filter = ldap.make_filter_from_attr( + obj.primary_key.name, + names, + rules=ldap.MATCH_ANY + ) + else: + search_filter = '(%s=*)' % obj.primary_key.name + + entry = ldap.make_entry( + DN( + ('cn', cn), + ('cn', 'automember rebuild membership'), + ('cn', 'tasks'), + ('cn', 'config'), + ), + objectclass=['top', 'extensibleObject'], + cn=[cn], + basedn=[basedn], + filter=[search_filter], + scope=['sub'] + ) + ldap.add_entry(entry) + return dict(result=True, value=u'') + +api.register(automember_rebuild) |