From b627f5012144768ce4348edc80652785635a5adc Mon Sep 17 00:00:00 2001 From: Rob Crittenden Date: Thu, 19 Mar 2009 15:44:19 -0400 Subject: Convert to use the new basegroup framework --- ipalib/plugins/netgroup.py | 272 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 272 insertions(+) create mode 100644 ipalib/plugins/netgroup.py (limited to 'ipalib/plugins') diff --git a/ipalib/plugins/netgroup.py b/ipalib/plugins/netgroup.py new file mode 100644 index 000000000..3ee23d6a5 --- /dev/null +++ b/ipalib/plugins/netgroup.py @@ -0,0 +1,272 @@ +# Authors: +# Rob Crittenden +# +# Copyright (C) 2009 Red Hat +# see file 'COPYING' for use and warranty information +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License as +# published by the Free Software Foundation; version 2 only +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +""" +Frontend plugins for netgroups. +""" + +from ipalib import api +from ipalib.plugins.basegroup import * +from ipalib import uuid + +display_attributes = ['cn','description','memberhost','externalhost','memberuser','member'] +container_netgroup = "cn=ng, cn=alt" +default_class = "ipaNISNetgroup" + +class netgroup(BaseGroup): + """ + netgroup object. + """ + container=container_netgroup + +api.register(netgroup) + + +class netgroup_add(basegroup_add): + 'Add a new netgroup.' + def execute(self, cn, **kw): + """ + Execute the netgroup-add operation. + + The dn should not be passed as a keyword argument as it is constructed + by this method. + + Returns the entry as it will be created in LDAP. + + :param cn: The name of the netgroup + :param kw: Keyword arguments for the other LDAP attributes. + """ + assert 'cn' not in kw + assert 'dn' not in kw + ldap = self.api.Backend.ldap + kw['cn'] = cn + kw['ipauniqueid'] = str(uuid.uuid1()) + kw['dn'] = "ipauniqueid=%s,%s,%s" % (kw['ipauniqueid'], container_netgroup, api.env.basedn) + if not kw.get('nisdomainname', False): + kw['nisdomainname'] = api.env.domain + + # some required objectclasses + kw['objectclass'] = ['top', 'ipaAssociation', 'ipaNISNetgroup'] + + return ldap.create(**kw) + +api.register(netgroup_add) + + +class netgroup_del(basegroup_del): + 'Delete an existing netgroup.' + container = container_netgroup + filter_class = default_class + +api.register(netgroup_del) + + +class netgroup_mod(basegroup_mod): + 'Edit an existing netgroup.' + container = container_netgroup + filter_class = default_class + +api.register(netgroup_mod) + + +class netgroup_find(basegroup_find): + 'Search the groups.' + container = container_netgroup + filter_class = default_class + +api.register(netgroup_find) + + +class netgroup_show(basegroup_show): + 'Examine an existing netgroup.' + default_attributes = display_attributes + container = container_netgroup + filter_class = default_class + +api.register(netgroup_show) + + +class netgroup_add_member(basegroup_add_member): + 'Add a member to a netgroup.' + default_attributes = display_attributes + container = container_netgroup + filter_class = default_class + takes_options = basegroup_add_member.takes_options + ( + List('hosts?', doc='comma-separated list of hosts to add'), + List('hostgroups?', doc='comma-separated list of host groups to add'), + List('netgroups?', doc='comma-separated list of netgroups to add'), + ) + + def _add_external(self, ldap, completed, members, cn): + failed = [] + kw = {"all": True} + netgroup = api.Command['netgroup_show'](cn, **kw) + external = netgroup.get('externalhost', []) + if not isinstance(external, list): + external = [external] + external_len = len(external) + for m in members: + if not m in external: + external.append(m) + completed+=1 + else: + failed.append(m) + if len(external) > external_len: + kw = {'externalhost': external} + ldap.update(netgroup['dn'], **kw) + + return completed, failed + + def execute(self, cn, **kw): + """ + Execute the group-add-member operation. + + Returns the updated group entry + + :param cn: The group name to add new members to. + :param kw: groups is a comma-separated list of groups to add + :param kw: users is a comma-separated list of users to add + :param kw: hostgroups is a comma-separated list of hostgroups to add + """ + assert self.container + ldap = self.api.Backend.ldap + dn = ldap.find_entry_dn("cn", cn, self.filter_class, self.container) + add_failed = [] + to_add = [] + completed = 0 + + # Hosts + members = kw.get('hosts', []) + (to_add, add_failed) = self._find_members(ldap, add_failed, members, "cn", "ipaHost") + + # If a host is not found we'll consider it an externalHost. It will + # be up to the user to handle typos + if add_failed: + (completed, add_failed) = self._add_external(ldap, completed, add_failed, cn) + + (completed, add_failed) = self._add_members(ldap, completed, to_add, add_failed, dn, "memberhost") + + # Hostgroups + members = kw.get('hostgroups', []) + (to_add, add_failed) = self._find_members(ldap, add_failed, members, "cn", "ipaHostGroup", self.api.env.container_hostgroup) + (completed, add_failed) = self._add_members(ldap, completed, to_add, add_failed, dn, "memberhost") + + # User + members = kw.get('users', []) + (to_add, add_failed) = self._find_members(ldap, add_failed, members, "uid", "posixAccount", self.api.env.container_user) + (completed, add_failed) = self._add_members(ldap, completed, to_add, add_failed, dn, "memberuser") + + # Groups + members = kw.get('groups', []) + (to_add, add_failed) = self._find_members(ldap, add_failed, members, "cn", "ipaUserGroup", self.api.env.container_group) + (completed, failed) = self._add_members(ldap, completed, to_add, add_failed, dn, "memberuser") + + # Netgroups + members = kw.get('netgroups', []) + (to_add, add_failed) = self._find_members(ldap, add_failed, members, "cn", self.filter_class, self.container) + (completed, add_failed) = self._add_members(ldap, completed, to_add, add_failed, dn, "member") + + return add_failed + +api.register(netgroup_add_member) + + +class netgroup_remove_member(basegroup_remove_member): + 'Remove a member from a netgroup.' + default_attributes = display_attributes + container = container_netgroup + filter_class = default_class + takes_options = basegroup_remove_member.takes_options + ( + List('hosts?', doc='comma-separated list of hosts to remove'), + List('hostgroups?', doc='comma-separated list of host groups to remove'), + List('netgroups?', doc='comma-separated list of netgroups to remove'), + ) + + def _remove_external(self, ldap, completed, members, cn): + failed = [] + kw = {"all": True} + netgroup = api.Command['netgroup_show'](cn, **kw) + external = netgroup.get('externalhost', []) + if not isinstance(external, list): + external = [external] + external_len = len(external) + for m in members: + try: + external.remove(m) + completed+=1 + except ValueError: + failed.append(m) + if len(external) < external_len: + kw = {'externalhost': external} + ldap.update(netgroup['dn'], **kw) + + return completed, failed + + def execute(self, cn, **kw): + """ + Execute the group-remove-member operation. + + Returns the updated group entry + + :param cn: The group name to remove new members to. + :param kw: groups is a comma-separated list of groups to remove + :param kw: users is a comma-separated list of users to remove + :param kw: hostgroups is a comma-separated list of hostgroups to remove + """ + assert self.container + ldap = self.api.Backend.ldap + dn = ldap.find_entry_dn("cn", cn, self.filter_class, self.container) + remove_failed = [] + to_remove = [] + completed = 0 + + # Hosts + members = kw.get('hosts', []) + (to_remove, remove_failed) = self._find_members(ldap, remove_failed, members, "cn", "ipaHost") + + # If a host is not found we'll consider it an externalHost. It will + # be up to the user to handle typos + if remove_failed: + (completed, remove_failed) = self._remove_external(ldap, completed, remove_failed, cn) + + (completed, remove_failed) = self._remove_members(ldap, completed, to_remove, remove_failed, dn, "memberhost") + + # Hostgroups + members = kw.get('hostgroups', []) + (to_remove, remove_failed) = self._find_members(ldap, remove_failed, members, "cn", "ipaHostGroup", self.api.env.container_hostgroup) + (completed, remove_failed) = self._remove_members(ldap, completed, to_remove, remove_failed, dn, "memberhost") + + # User + members = kw.get('users', []) + (to_remove, remove_failed) = self._find_members(ldap, remove_failed, members, "uid", "posixAccount", self.api.env.container_user) + (completed, remove_failed) = self._remove_members(ldap, completed, to_remove, remove_failed, dn, "memberuser") + + # Groups + members = kw.get('groups', []) + (to_remove, remove_failed) = self._find_members(ldap, remove_failed, members, "cn", "ipaUserGroup", self.api.env.container_group) + (completed, failed) = self._remove_members(ldap, completed, to_remove, remove_failed, dn, "memberuser") + + # Netgroups + members = kw.get('netgroups', []) + (to_remove, remove_failed) = self._find_members(ldap, remove_failed, members, "cn", self.filter_class, self.container) + (completed, remove_failed) = self._remove_members(ldap, completed, to_remove, remove_failed, dn, "member") + + return remove_failed + +api.register(netgroup_remove_member) -- cgit