From 54f37503d2076b99b3b7479b19fec4fa17bc7c59 Mon Sep 17 00:00:00 2001 From: Rob Crittenden Date: Mon, 27 Oct 2008 12:24:17 -0400 Subject: Implement host groups --- ipalib/plugins/f_hostgroup.py | 328 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 328 insertions(+) create mode 100644 ipalib/plugins/f_hostgroup.py (limited to 'ipalib/plugins/f_hostgroup.py') diff --git a/ipalib/plugins/f_hostgroup.py b/ipalib/plugins/f_hostgroup.py new file mode 100644 index 00000000..27aea00c --- /dev/null +++ b/ipalib/plugins/f_hostgroup.py @@ -0,0 +1,328 @@ +# Authors: +# Rob Crittenden +# +# Copyright (C) 2008 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 groups of hosts +""" + +from ipalib import frontend +from ipalib import crud +from ipalib.frontend import Param +from ipalib import api +from ipalib import errors +from ipalib import ipa_types + +hostgroup_filter = "groupofnames)(!(objectclass=posixGroup)" + +class hostgroup(frontend.Object): + """ + Host Group object. + """ + takes_params = ( + Param('description', + doc='A description of this group', + ), + Param('cn', + cli_name='name', + primary_key=True, + normalize=lambda value: value.lower(), + ) + ) +api.register(hostgroup) + + +class hostgroup_add(crud.Add): + 'Add a new group of hosts.' + + def execute(self, cn, **kw): + """ + Execute the hostgroup-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. + + No need to explicitly set gidNumber. The dna_plugin will do this + for us if the value isn't provided by the caller. + + :param cn: The name of the host group being added. + :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['dn'] = ldap.make_hostgroup_dn(cn) + + # Get our configuration + #config = ldap.get_ipa_config() + + # some required objectclasses + # FIXME: get this out of config + kw['objectClass'] = ['groupofnames'] + + return ldap.create(**kw) + + def output_for_cli(self, ret): + """ + Output result of this command to command line interface. + """ + if ret: + print "Group added" + +api.register(hostgroup_add) + + +class hostgroup_del(crud.Del): + 'Delete an existing group of hosts.' + def execute(self, cn, **kw): + """ + Delete a group of hosts + + The memberOf plugin handles removing the group from any other + groups. + + :param cn: The name of the group being removed + :param kw: Unused + """ + ldap = self.api.Backend.ldap + dn = ldap.find_entry_dn("cn", cn, hostgroup_filter) + + return ldap.delete(dn) + + def output_for_cli(self, ret): + """ + Output result of this command to command line interface. + """ + if ret: + print "Group deleted" + +api.register(hostgroup_del) + + +class hostgroup_mod(crud.Mod): + 'Edit an existing group of hosts.' + def execute(self, cn, **kw): + """ + Execute the hostgroup-mod operation. + + The dn should not be passed as a keyword argument as it is constructed + by this method. + + Returns the entry + + :param cn: The name of the group to update. + :param kw: Keyword arguments for the other LDAP attributes. + """ + assert 'cn' not in kw + assert 'dn' not in kw + ldap = self.api.Backend.ldap + dn = ldap.find_entry_dn("cn", cn, hostgroup_filter) + return ldap.update(dn, **kw) + + def output_for_cli(self, ret): + """ + Output result of this command to command line interface. + """ + if ret: + print "Group updated" + +api.register(hostgroup_mod) + + +class hostgroup_find(crud.Find): + 'Search the groups of hosts.' + def execute(self, term, **kw): + ldap = self.api.Backend.ldap + + # Pull the list of searchable attributes out of the configuration. + config = ldap.get_ipa_config() + + # FIXME: for now use same search fields as user groups + search_fields_conf_str = config.get('ipagroupsearchfields') + search_fields = search_fields_conf_str.split(",") + + for s in search_fields: + kw[s] = term + + kw['objectclass'] = hostgroup_filter + return ldap.search(**kw) + + def output_for_cli(self, groups): + if not groups: + return + + counter = groups[0] + groups = groups[1:] + if counter == 0: + print "No entries found" + return + elif counter == -1: + print "These results are truncated." + print "Please refine your search and try again." + + for g in groups: + for a in g.keys(): + print "%s: %s" % (a, g[a]) + +api.register(hostgroup_find) + + +class hostgroup_show(crud.Get): + 'Examine an existing group of hosts.' + def execute(self, cn, **kw): + """ + Execute the hostgroup-show operation. + + The dn should not be passed as a keyword argument as it is constructed + by this method. + + Returns the entry + + :param cn: The group name to retrieve. + :param kw: Not used. + """ + ldap = self.api.Backend.ldap + # FIXME: this works for now but the plan is to add a new objectclass + # type. + dn = ldap.find_entry_dn("cn", cn, hostgroup_filter) + # FIXME: should kw contain the list of attributes to display? + return ldap.retrieve(dn) + + def output_for_cli(self, group): + if not group: + return + + for a in group.keys(): + print "%s: %s" % (a, group[a]) + +api.register(hostgroup_show) + + +class hostgroup_add_member(frontend.Command): + 'Add a member to a group.' + takes_args = ( + Param('group', primary_key=True), + ) + takes_options = ( + Param('groups?', doc='comma-separated list of groups to add'), + ) + def execute(self, cn, **kw): + """ + Execute the hostgroup-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 + """ + ldap = self.api.Backend.ldap + dn = ldap.find_entry_dn("cn", cn, hostgroup_filter) + add_failed = [] + to_add = [] + completed = 0 + + members = kw.get('groups', '').split(',') + for m in members: + if not m: continue + try: + member_dn = ldap.find_entry_dn("cn", m, hostgroup_filter) + to_add.append(member_dn) + except errors.NotFound: + add_failed.append(m) + continue + + for member_dn in to_add: + try: + ldap.add_member_to_group(member_dn, dn) + completed+=1 + except: + add_failed.append(member_dn) + + return add_failed + + def output_for_cli(self, add_failed): + """ + Output result of this command to command line interface. + """ + if add_failed: + print "These entries failed to add to the group:" + for a in add_failed: + print "\t'%s'" % a + else: + print "Group membership updated." + +api.register(hostgroup_add_member) + + +class hostgroup_remove_member(frontend.Command): + 'Remove a member from a group.' + takes_args = ( + Param('group', primary_key=True), + ) + takes_options = ( + Param('groups?', doc='comma-separated list of groups to remove'), + ) + def execute(self, cn, **kw): + """ + Execute the group-remove-member operation. + + Returns the members that could not be added + + :param cn: The group name to add new members to. + :param kw: groups is a comma-separated list of groups to remove + """ + ldap = self.api.Backend.ldap + dn = ldap.find_entry_dn("cn", cn, hostgroup_filter) + to_remove = [] + remove_failed = [] + completed = 0 + + members = kw.get('groups', '').split(',') + for m in members: + if not m: continue + try: + member_dn = ldap.find_entry_dn("cn", m, hostgroup_filter) + to_remove.append(member_dn) + except errors.NotFound: + remove_failed.append(m) + continue + + for member_dn in to_remove: + try: + ldap.remove_member_from_group(member_dn, dn) + completed+=1 + except: + remove_failed.append(member_dn) + + return remove_failed + + def output_for_cli(self, remove_failed): + """ + Output result of this command to command line interface. + """ + if remove_failed: + print "These entries failed to be removed from the group:" + for a in remove_failed: + print "\t'%s'" % a + else: + print "Group membership updated." + +api.register(hostgroup_remove_member) -- cgit From e825bc7ccbc787e65efa7171e9f19793bcd88615 Mon Sep 17 00:00:00 2001 From: Rob Crittenden Date: Tue, 4 Nov 2008 14:03:43 -0500 Subject: Revive the hostgroup_container and include add/remove hosts in hostgroups plugin --- ipalib/plugins/f_hostgroup.py | 28 ++++++++++++++++++++++++++-- 1 file changed, 26 insertions(+), 2 deletions(-) (limited to 'ipalib/plugins/f_hostgroup.py') diff --git a/ipalib/plugins/f_hostgroup.py b/ipalib/plugins/f_hostgroup.py index 27aea00c..8e4c3740 100644 --- a/ipalib/plugins/f_hostgroup.py +++ b/ipalib/plugins/f_hostgroup.py @@ -222,7 +222,8 @@ class hostgroup_add_member(frontend.Command): Param('group', primary_key=True), ) takes_options = ( - Param('groups?', doc='comma-separated list of groups to add'), + Param('groups?', doc='comma-separated list of host groups to add'), + Param('hosts?', doc='comma-separated list of hosts to add'), ) def execute(self, cn, **kw): """ @@ -231,7 +232,8 @@ class hostgroup_add_member(frontend.Command): 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: groups is a comma-separated list of host groups to add + :param kw: hosts is a comma-separated list of hosts to add """ ldap = self.api.Backend.ldap dn = ldap.find_entry_dn("cn", cn, hostgroup_filter) @@ -249,6 +251,16 @@ class hostgroup_add_member(frontend.Command): add_failed.append(m) continue + members = kw.get('hosts', '').split(',') + for m in members: + if not m: continue + try: + member_dn = ldap.find_entry_dn("cn", m, "ipaHost") + to_add.append(member_dn) + except errors.NotFound: + add_failed.append(m) + continue + for member_dn in to_add: try: ldap.add_member_to_group(member_dn, dn) @@ -278,6 +290,7 @@ class hostgroup_remove_member(frontend.Command): Param('group', primary_key=True), ) takes_options = ( + Param('hosts?', doc='comma-separated list of hosts to add'), Param('groups?', doc='comma-separated list of groups to remove'), ) def execute(self, cn, **kw): @@ -288,6 +301,7 @@ class hostgroup_remove_member(frontend.Command): :param cn: The group name to add new members to. :param kw: groups is a comma-separated list of groups to remove + :param kw: hosts is a comma-separated list of hosts to add """ ldap = self.api.Backend.ldap dn = ldap.find_entry_dn("cn", cn, hostgroup_filter) @@ -305,6 +319,16 @@ class hostgroup_remove_member(frontend.Command): remove_failed.append(m) continue + members = kw.get('hosts', '').split(',') + for m in members: + if not m: continue + try: + member_dn = ldap.find_entry_dn("cn", m, "ipaHost") + to_remove.append(member_dn) + except errors.NotFound: + remove_failed.append(m) + continue + for member_dn in to_remove: try: ldap.remove_member_from_group(member_dn, dn) -- cgit From fc8ac693726ec33b5c0924f9b8ff5d663705a5a3 Mon Sep 17 00:00:00 2001 From: Rob Crittenden Date: Fri, 5 Dec 2008 15:31:18 -0500 Subject: Port plugins to use the new output_for_cli() argument list Fix some errors uncovered by the nosetests --- ipalib/plugins/f_hostgroup.py | 21 +++++++++++++++++---- 1 file changed, 17 insertions(+), 4 deletions(-) (limited to 'ipalib/plugins/f_hostgroup.py') diff --git a/ipalib/plugins/f_hostgroup.py b/ipalib/plugins/f_hostgroup.py index 8e4c3740..6cbf4d51 100644 --- a/ipalib/plugins/f_hostgroup.py +++ b/ipalib/plugins/f_hostgroup.py @@ -30,6 +30,19 @@ from ipalib import ipa_types hostgroup_filter = "groupofnames)(!(objectclass=posixGroup)" +def get_members(members): + """ + Return a list of members. + + It is possible that the value passed in is None. + """ + if members: + members = members.split(',') + else: + members = [] + + return members + class hostgroup(frontend.Object): """ Host Group object. @@ -241,7 +254,7 @@ class hostgroup_add_member(frontend.Command): to_add = [] completed = 0 - members = kw.get('groups', '').split(',') + members = get_members(kw.get('groups', '')) for m in members: if not m: continue try: @@ -251,7 +264,7 @@ class hostgroup_add_member(frontend.Command): add_failed.append(m) continue - members = kw.get('hosts', '').split(',') + members = get_members(kw.get('hosts', '')) for m in members: if not m: continue try: @@ -309,7 +322,7 @@ class hostgroup_remove_member(frontend.Command): remove_failed = [] completed = 0 - members = kw.get('groups', '').split(',') + members = get_members(kw.get('groups', '')) for m in members: if not m: continue try: @@ -319,7 +332,7 @@ class hostgroup_remove_member(frontend.Command): remove_failed.append(m) continue - members = kw.get('hosts', '').split(',') + members = get_members(kw.get('hosts', '')) for m in members: if not m: continue try: -- cgit From af7b5645af001352aff626f46ec39031b2e9b10a Mon Sep 17 00:00:00 2001 From: Rob Crittenden Date: Wed, 10 Dec 2008 16:42:45 -0500 Subject: Convert to new output_for_cli() function --- ipalib/plugins/f_hostgroup.py | 64 ++++++++++++++++++------------------------- 1 file changed, 27 insertions(+), 37 deletions(-) (limited to 'ipalib/plugins/f_hostgroup.py') diff --git a/ipalib/plugins/f_hostgroup.py b/ipalib/plugins/f_hostgroup.py index 6cbf4d51..bde257f9 100644 --- a/ipalib/plugins/f_hostgroup.py +++ b/ipalib/plugins/f_hostgroup.py @@ -93,12 +93,11 @@ class hostgroup_add(crud.Add): return ldap.create(**kw) - def output_for_cli(self, ret): + def output_for_cli(self, textui, result, *args, **options): """ Output result of this command to command line interface. """ - if ret: - print "Group added" + textui.print_plain("Group added") api.register(hostgroup_add) @@ -120,12 +119,11 @@ class hostgroup_del(crud.Del): return ldap.delete(dn) - def output_for_cli(self, ret): + def output_for_cli(self, textui, result, *args, **options): """ Output result of this command to command line interface. """ - if ret: - print "Group deleted" + textui.print_plain("Group deleted") api.register(hostgroup_del) @@ -150,12 +148,11 @@ class hostgroup_mod(crud.Mod): dn = ldap.find_entry_dn("cn", cn, hostgroup_filter) return ldap.update(dn, **kw) - def output_for_cli(self, ret): + def output_for_cli(self, textui, result, *args, **options): """ Output result of this command to command line interface. """ - if ret: - print "Group updated" + texui.print_plain("Group updated") api.register(hostgroup_mod) @@ -178,22 +175,19 @@ class hostgroup_find(crud.Find): kw['objectclass'] = hostgroup_filter return ldap.search(**kw) - def output_for_cli(self, groups): - if not groups: - return - - counter = groups[0] - groups = groups[1:] + def output_for_cli(self, textui, result, *args, **options): + counter = result[0] + groups = result[1:] if counter == 0: - print "No entries found" + textui.print_plain("No entries found") return - elif counter == -1: - print "These results are truncated." - print "Please refine your search and try again." for g in groups: - for a in g.keys(): - print "%s: %s" % (a, g[a]) + textui.print_entry(g) + + if counter == -1: + textui.print_plain("These results are truncated.") + textui.print_plain("Please refine your search and try again.") api.register(hostgroup_find) @@ -219,12 +213,8 @@ class hostgroup_show(crud.Get): # FIXME: should kw contain the list of attributes to display? return ldap.retrieve(dn) - def output_for_cli(self, group): - if not group: - return - - for a in group.keys(): - print "%s: %s" % (a, group[a]) + def output_for_cli(self, textui, result, *args, **options): + textui.print_entry(result) api.register(hostgroup_show) @@ -283,16 +273,16 @@ class hostgroup_add_member(frontend.Command): return add_failed - def output_for_cli(self, add_failed): + def output_for_cli(self, textui, result, *args, **options): """ Output result of this command to command line interface. """ - if add_failed: - print "These entries failed to add to the group:" - for a in add_failed: + if result: + textui.print_plain("These entries failed to add to the group:") + for a in result: print "\t'%s'" % a else: - print "Group membership updated." + textui.print_entry("Group membership updated.") api.register(hostgroup_add_member) @@ -351,15 +341,15 @@ class hostgroup_remove_member(frontend.Command): return remove_failed - def output_for_cli(self, remove_failed): + def output_for_cli(self, textui, result, *args, **options): """ Output result of this command to command line interface. """ - if remove_failed: - print "These entries failed to be removed from the group:" - for a in remove_failed: + if result: + textui.print_plain("These entries failed to be removed from the group:") + for a in result: print "\t'%s'" % a else: - print "Group membership updated." + textui.print_plain("Group membership updated.") api.register(hostgroup_remove_member) -- cgit From 46bd3974af5ce312cb1dd3ca12e6184d78dc470e Mon Sep 17 00:00:00 2001 From: Rob Crittenden Date: Wed, 10 Dec 2008 16:45:07 -0500 Subject: Don't pass along the kw dictionary we were passed by XML-RPC. We generally want to just search indexed attributes. We get this list of attributes from the configuration, use it. --- ipalib/plugins/f_hostgroup.py | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) (limited to 'ipalib/plugins/f_hostgroup.py') diff --git a/ipalib/plugins/f_hostgroup.py b/ipalib/plugins/f_hostgroup.py index bde257f9..3e14b09a 100644 --- a/ipalib/plugins/f_hostgroup.py +++ b/ipalib/plugins/f_hostgroup.py @@ -169,11 +169,12 @@ class hostgroup_find(crud.Find): search_fields_conf_str = config.get('ipagroupsearchfields') search_fields = search_fields_conf_str.split(",") + search_kw = {} for s in search_fields: - kw[s] = term + search_kw[s] = term - kw['objectclass'] = hostgroup_filter - return ldap.search(**kw) + search_kw['objectclass'] = hostgroup_filter + return ldap.search(**search_kw) def output_for_cli(self, textui, result, *args, **options): counter = result[0] -- cgit From 64c072b7b3deb1800c242b365e277591f056093d Mon Sep 17 00:00:00 2001 From: Jason Gerard DeRose Date: Wed, 14 Jan 2009 22:10:09 -0700 Subject: Updated hostgroup plugins module to where it can at least be imported --- ipalib/plugins/f_hostgroup.py | 34 ++++++++++++++++------------------ 1 file changed, 16 insertions(+), 18 deletions(-) (limited to 'ipalib/plugins/f_hostgroup.py') diff --git a/ipalib/plugins/f_hostgroup.py b/ipalib/plugins/f_hostgroup.py index 3e14b09a..c365c918 100644 --- a/ipalib/plugins/f_hostgroup.py +++ b/ipalib/plugins/f_hostgroup.py @@ -21,12 +21,10 @@ Frontend plugins for groups of hosts """ -from ipalib import frontend -from ipalib import crud -from ipalib.frontend import Param -from ipalib import api -from ipalib import errors -from ipalib import ipa_types +from ipalib import api, crud, errors +from ipalib import Object, Command # Plugin base classes +from ipalib import Str # Parameter types + hostgroup_filter = "groupofnames)(!(objectclass=posixGroup)" @@ -43,18 +41,18 @@ def get_members(members): return members -class hostgroup(frontend.Object): +class hostgroup(Object): """ Host Group object. """ takes_params = ( - Param('description', + Str('description', doc='A description of this group', ), - Param('cn', + Str('cn', cli_name='name', primary_key=True, - normalize=lambda value: value.lower(), + normalizer=lambda value: value.lower(), ) ) api.register(hostgroup) @@ -220,14 +218,14 @@ class hostgroup_show(crud.Get): api.register(hostgroup_show) -class hostgroup_add_member(frontend.Command): +class hostgroup_add_member(Command): 'Add a member to a group.' takes_args = ( - Param('group', primary_key=True), + Str('group', primary_key=True), ) takes_options = ( - Param('groups?', doc='comma-separated list of host groups to add'), - Param('hosts?', doc='comma-separated list of hosts to add'), + Str('groups?', doc='comma-separated list of host groups to add'), + Str('hosts?', doc='comma-separated list of hosts to add'), ) def execute(self, cn, **kw): """ @@ -288,14 +286,14 @@ class hostgroup_add_member(frontend.Command): api.register(hostgroup_add_member) -class hostgroup_remove_member(frontend.Command): +class hostgroup_remove_member(Command): 'Remove a member from a group.' takes_args = ( - Param('group', primary_key=True), + Str('group', primary_key=True), ) takes_options = ( - Param('hosts?', doc='comma-separated list of hosts to add'), - Param('groups?', doc='comma-separated list of groups to remove'), + Str('hosts?', doc='comma-separated list of hosts to add'), + Str('groups?', doc='comma-separated list of groups to remove'), ) def execute(self, cn, **kw): """ -- cgit From 8154131ce1975c9e2109e408a0a25631ea797a8c Mon Sep 17 00:00:00 2001 From: Rob Crittenden Date: Fri, 16 Jan 2009 10:19:29 -0500 Subject: Use correct function for outputing a string --- ipalib/plugins/f_hostgroup.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'ipalib/plugins/f_hostgroup.py') diff --git a/ipalib/plugins/f_hostgroup.py b/ipalib/plugins/f_hostgroup.py index c365c918..706712c9 100644 --- a/ipalib/plugins/f_hostgroup.py +++ b/ipalib/plugins/f_hostgroup.py @@ -281,7 +281,7 @@ class hostgroup_add_member(Command): for a in result: print "\t'%s'" % a else: - textui.print_entry("Group membership updated.") + textui.print_plain("Group membership updated.") api.register(hostgroup_add_member) -- cgit