summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--ipa_server/plugins/b_ldap.py9
-rw-r--r--ipa_server/servercore.py11
-rw-r--r--ipa_server/updates/automount.update35
-rw-r--r--ipalib/crud.py7
-rw-r--r--ipalib/plugins/f_automount.py472
5 files changed, 532 insertions, 2 deletions
diff --git a/ipa_server/plugins/b_ldap.py b/ipa_server/plugins/b_ldap.py
index e53afc125..c279ac706 100644
--- a/ipa_server/plugins/b_ldap.py
+++ b/ipa_server/plugins/b_ldap.py
@@ -139,6 +139,15 @@ class ldap(CrudBackend):
return entry.get('dn')
+ def get_base_entry(self, searchbase, searchfilter, attrs):
+ return servercore.get_base_entry(searchbase, searchfilter, attrs)
+
+ def get_sub_entry(self, searchbase, searchfilter, attrs):
+ return servercore.get_sub_entry(searchbase, searchfilter, attrs)
+
+ def get_one_entry(self, searchbase, searchfilter, attrs):
+ return servercore.get_one_entry(searchbase, searchfilter, attrs)
+
def get_ipa_config(self):
"""Return a dictionary of the IPA configuration"""
return servercore.get_ipa_config()
diff --git a/ipa_server/servercore.py b/ipa_server/servercore.py
index 052c386b8..5f13e8d40 100644
--- a/ipa_server/servercore.py
+++ b/ipa_server/servercore.py
@@ -104,13 +104,20 @@ def get_sub_entry (base, searchfilter, sattrs=None):
"""
return get_entry(base, ldap.SCOPE_SUBTREE, searchfilter, sattrs)
-def get_list (base, searchfilter, sattrs=None):
+def get_one_entry (base, searchfilter, sattrs=None):
+ """Get the children of an entry (with a scope of ONE).
+ Return as a list of dict of values.
+ Multi-valued fields are represented as lists.
+ """
+ return get_list(base, searchfilter, sattrs, ldap.SCOPE_ONELEVEL)
+
+def get_list (base, searchfilter, sattrs=None, scope=ldap.SCOPE_SUBTREE):
"""Gets a list of entries. Each is converted to a dict of values.
Multi-valued fields are represented as lists.
"""
entries = []
- entries = context.conn.getConn().getList(base, ldap.SCOPE_SUBTREE, searchfilter, sattrs)
+ entries = context.conn.getConn().getList(base, scope, searchfilter, sattrs)
return map(convert_entry, entries)
diff --git a/ipa_server/updates/automount.update b/ipa_server/updates/automount.update
new file mode 100644
index 000000000..25d45a092
--- /dev/null
+++ b/ipa_server/updates/automount.update
@@ -0,0 +1,35 @@
+#
+# An automount schema based on RFC 2307-bis.
+#
+# This schema defines new automount and automountMap objectclasses to represent
+# the automount maps and their entries.
+#
+dn: cn=schema
+add:attributeTypes:
+ ( 1.3.6.1.1.1.1.31 NAME 'automountMapName'
+ DESC 'automount Map Name'
+ EQUALITY caseExactIA5Match
+ SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 SINGLE-VALUE
+ X-ORIGIN 'RFC 2307bis' )
+add:attributeTypes:
+ ( 1.3.6.1.1.1.1.32 NAME 'automountKey'
+ DESC 'Automount Key value'
+ EQUALITY caseExactIA5Match
+ SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 SINGLE-VALUE
+ X-ORIGIN 'RFC 2307bis' )
+add:attributeTypes:
+ ( 1.3.6.1.1.1.1.33 NAME 'automountInformation'
+ DESC 'Automount information'
+ EQUALITY caseExactIA5Match
+ SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 SINGLE-VALUE
+ X-ORIGIN 'RFC 2307bis' )
+add:objectClasses:
+ ( 1.3.6.1.1.1.2.16 NAME 'automountMap'
+ DESC 'Automount Map information' SUP top
+ STRUCTURAL MUST automountMapName MAY description
+ X-ORIGIN 'RFC 2307bis' )
+add:objectClasses:
+ ( 1.3.6.1.1.1.2.17 NAME 'automount'
+ DESC 'Automount information' SUP top STRUCTURAL
+ MUST ( automountKey $ automountInformation ) MAY description
+ X-ORIGIN 'RFC 2307bis' )
diff --git a/ipalib/crud.py b/ipalib/crud.py
index 6194b3fa7..60c605dd9 100644
--- a/ipalib/crud.py
+++ b/ipalib/crud.py
@@ -46,6 +46,11 @@ class Del(frontend.Method):
def get_args(self):
yield self.obj.primary_key
+ def get_options(self):
+ for param in self.obj.params_minus_pk():
+ yield param
+ for option in self.takes_options:
+ yield option
class Mod(frontend.Method):
def get_args(self):
@@ -54,6 +59,8 @@ class Mod(frontend.Method):
def get_options(self):
for param in self.obj.params_minus_pk():
yield param.__clone__(required=False)
+ for option in self.takes_options:
+ yield option
class Find(frontend.Method):
diff --git a/ipalib/plugins/f_automount.py b/ipalib/plugins/f_automount.py
new file mode 100644
index 000000000..78e96ccdf
--- /dev/null
+++ b/ipalib/plugins/f_automount.py
@@ -0,0 +1,472 @@
+# Authors:
+# Rob Crittenden <rcritten@redhat.com>
+#
+# 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 automount.
+
+RFC 2707bis http://www.padl.com/~lukeh/rfc2307bis.txt
+"""
+
+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 ldap import explode_dn
+
+map_attributes = ['automountMapName', 'description', ]
+key_attributes = ['description', 'automountKey', 'automountInformation']
+
+def display_entry(entry):
+ # FIXME: for now delete dn here. In the future pass in the kw to
+ # output_for_cli()
+ attr = sorted(entry.keys())
+
+ for a in attr:
+ if a != 'dn':
+ print "%s: %s" % (a, entry[a])
+
+def make_automount_dn(mapname):
+ """
+ Construct automount dn from map name.
+ """
+ # FIXME, should this be in b_ldap?
+ # Experimenting to see what a plugin looks like for a 3rd party who can't
+ # modify the backend.
+ import ldap
+ return 'automountmapname=%s,%s,%s' % (
+ ldap.dn.escape_dn_chars(mapname),
+ api.env.container_accounts,
+ api.env.basedn,
+ )
+
+class automount(frontend.Object):
+ """
+ Automount object.
+ """
+ takes_params = (
+ Param('automountmapname',
+ cli_name='mapname',
+ primary_key=True,
+ doc='A group of related automount objects',
+ ),
+ )
+api.register(automount)
+
+
+class automount_addmap(crud.Add):
+ 'Add a new automount map.'
+ takes_options = (
+ Param('description?',
+ doc='A description of the automount map'),
+ )
+
+ def execute(self, mapname, **kw):
+ """
+ Execute the automount-addmap operation.
+
+ Returns the entry as it will be created in LDAP.
+
+ :param mapname: The map name being added.
+ :param kw: Keyword arguments for the other LDAP attributes.
+ """
+ assert 'automountmapname' not in kw
+ assert 'dn' not in kw
+ ldap = self.api.Backend.ldap
+ kw['automountmapname'] = mapname
+ kw['dn'] = make_automount_dn(mapname)
+
+ kw['objectClass'] = ['automountMap']
+
+ return ldap.create(**kw)
+ def output_for_cli(self, ret):
+ """
+ Output result of this command to command line interface.
+ """
+ if ret:
+ print "Automount map added"
+
+api.register(automount_addmap)
+
+
+class automount_addkey(crud.Add):
+ 'Add a new automount key.'
+ takes_options = (
+ Param('automountkey',
+ cli_name='key',
+ doc='An entry in an automount map'),
+ Param('automountinformation',
+ cli_name='info',
+ doc='Mount information for this key'),
+ Param('description?',
+ doc='A description of the mount'),
+ )
+
+ def execute(self, mapname, **kw):
+ """
+ Execute the automount-addkey operation.
+
+ Returns the entry as it will be created in LDAP.
+
+ :param mapname: The map name being added to.
+ :param kw: Keyword arguments for the other LDAP attributes.
+ """
+ assert 'automountmapname' not in kw
+ assert 'dn' not in kw
+ ldap = self.api.Backend.ldap
+ # use find_entry_dn instead of make_automap_dn so we can confirm that
+ # the map exists
+ map_dn = ldap.find_entry_dn("automountmapname", mapname, "automountmap")
+ kw['dn'] = "automountkey=%s,%s" % (kw['automountkey'], map_dn)
+
+ kw['objectClass'] = ['automount']
+
+ return ldap.create(**kw)
+ def output_for_cli(self, ret):
+ """
+ Output result of this command to command line interface.
+ """
+ if ret:
+ print "Automount key added"
+
+api.register(automount_addkey)
+
+
+class automount_delmap(crud.Del):
+ 'Delete an automount map.'
+ def execute(self, mapname, **kw):
+ """Delete an automount map. This will also remove all of the keys
+ associated with this map.
+
+ mapname is the automount map to remove
+
+ :param mapname: The map to be removed
+ :param kw: Not used.
+ """
+ ldap = self.api.Backend.ldap
+ dn = ldap.find_entry_dn("automountmapname", mapname, "automountmap")
+ keys = api.Command['automount_getkeys'](mapname)
+ if keys:
+ for k in keys:
+ ldap.delete(k.get('dn'))
+ return ldap.delete(dn)
+ def output_for_cli(self, ret):
+ """
+ Output result of this command to command line interface.
+ """
+ if ret:
+ print "Automount map and associated keys deleted"
+
+api.register(automount_delmap)
+
+
+class automount_delkey(crud.Del):
+ 'Delete an automount key.'
+ takes_options = (
+ Param('key',
+ doc='The automount key to remove'),
+ )
+ def execute(self, mapname, **kw):
+ """Delete an automount key.
+
+ key is the automount key to remove
+
+ :param mapname: The automount map containing the key to be removed
+ :param kw: "key" the key to be removed
+ """
+ ldap = self.api.Backend.ldap
+ dn = ldap.find_entry_dn("automountmapname", mapname, "automountmap")
+ keys = api.Command['automount_getkeys'](mapname)
+ keydn = None
+ keyname = kw.get('key').lower()
+ if keys:
+ for k in keys:
+ if k.get('automountkey').lower() == keyname:
+ keydn = k.get('dn')
+ break
+ if not keydn:
+ raise errors.NotFound
+ return ldap.delete(keydn)
+ def output_for_cli(self, ret):
+ """
+ Output result of this command to command line interface.
+ """
+ if ret:
+ print "Automount key deleted"
+
+api.register(automount_delkey)
+
+class automount_modmap(crud.Mod):
+ 'Edit an existing automount map.'
+ takes_options = (
+ Param('description?',
+ doc='A description of the automount map'),
+ )
+ def execute(self, mapname, **kw):
+ """
+ Execute the automount-modmap operation.
+
+ The dn should not be passed as a keyword argument as it is constructed
+ by this method.
+
+ Returns the entry
+
+ :param mapname: The map name to update.
+ :param kw: Keyword arguments for the other LDAP attributes.
+ """
+ assert 'automountmapname' not in kw
+ assert 'dn' not in kw
+ ldap = self.api.Backend.ldap
+ dn = ldap.find_entry_dn("automountmapname", mapname, "automountmap")
+ return ldap.update(dn, **kw)
+
+ def output_for_cli(self, ret):
+ """
+ Output result of this command to command line interface.
+ """
+ if ret:
+ print "Automount map updated"
+
+api.register(automount_modmap)
+
+
+class automount_modkey(crud.Mod):
+ 'Edit an existing automount key.'
+ takes_options = (
+ Param('automountkey',
+ cli_name='key',
+ doc='An entry in an automount map'),
+ Param('automountinformation?',
+ cli_name='info',
+ doc='Mount information for this key'),
+ Param('description?',
+ doc='A description of the automount map'),
+ )
+ def execute(self, mapname, **kw):
+ """
+ Execute the automount-modkey operation.
+
+ Returns the entry
+
+ :param mapname: The map name to update.
+ :param kw: Keyword arguments for the other LDAP attributes.
+ """
+ assert 'automountmapname' not in kw
+ assert 'dn' not in kw
+ keyname = kw.get('automountkey').lower()
+ del kw['automountkey']
+ ldap = self.api.Backend.ldap
+ dn = ldap.find_entry_dn("automountmapname", mapname, "automountmap")
+ keys = api.Command['automount_getkeys'](mapname)
+ keydn = None
+ if keys:
+ for k in keys:
+ if k.get('automountkey').lower() == keyname:
+ keydn = k.get('dn')
+ break
+ if not keydn:
+ raise errors.NotFound
+ return ldap.update(keydn, **kw)
+
+ def output_for_cli(self, ret):
+ """
+ Output result of this command to command line interface.
+ """
+ if ret:
+ print "Automount key updated"
+api.register(automount_modkey)
+
+
+class automount_findmap(crud.Find):
+ 'Search automount maps.'
+ takes_options = (
+ Param('all?', type=ipa_types.Bool(), doc='Retrieve all attributes'),
+ )
+ def execute(self, term, **kw):
+ ldap = self.api.Backend.ldap
+
+ search_fields = map_attributes
+
+ for s in search_fields:
+ kw[s] = term
+
+ kw['objectclass'] = 'automountMap'
+ if kw.get('all', False):
+ kw['attributes'] = ['*']
+ else:
+ kw['attributes'] = map_attributes
+ return ldap.search(**kw)
+ def output_for_cli(self, entries):
+ if not entries:
+ return
+ counter = entries[0]
+ entries = entries[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 e in entries:
+ display_entry(e)
+ print ""
+api.register(automount_findmap)
+
+
+class automount_findkey(crud.Find):
+ 'Search automount keys.'
+ takes_options = (
+ Param('all?', type=ipa_types.Bool(), doc='Retrieve all attributes'),
+ )
+ def execute(self, term, **kw):
+ ldap = self.api.Backend.ldap
+
+ search_fields = key_attributes
+
+ for s in search_fields:
+ kw[s] = term
+
+ kw['objectclass'] = 'automount'
+ if kw.get('all', False):
+ kw['attributes'] = ['*']
+ else:
+ kw['attributes'] = key_attributes
+ return ldap.search(**kw)
+ def output_for_cli(self, entries):
+ if not entries:
+ return
+ counter = entries[0]
+ entries = entries[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 e in entries:
+ display_entry(e)
+ print ""
+api.register(automount_findkey)
+
+
+class automount_showmap(crud.Get):
+ 'Examine an existing automount map.'
+ takes_options = (
+ Param('all?', type=ipa_types.Bool(), doc='Retrieve all attributes'),
+ )
+ def execute(self, mapname, **kw):
+ """
+ Execute the automount-showmap operation.
+
+ Returns the entry
+
+ :param mapname: The automount map to retrieve
+ :param kw: "all" set to True = return all attributes
+ """
+ ldap = self.api.Backend.ldap
+ dn = ldap.find_entry_dn("automountmapname", mapname, "automountmap")
+ # FIXME: should kw contain the list of attributes to display?
+ if kw.get('all', False):
+ return ldap.retrieve(dn)
+ else:
+ return ldap.retrieve(dn, map_attributes)
+ def output_for_cli(self, entry):
+ if entry:
+ display_entry(entry)
+
+api.register(automount_showmap)
+
+
+class automount_showkey(crud.Get):
+ 'Examine an existing automount key.'
+ takes_options = (
+ Param('key',
+ doc='The automount key to display'),
+ Param('all?', type=ipa_types.Bool(), doc='Retrieve all attributes'),
+ )
+ def execute(self, mapname, **kw):
+ """
+ Execute the automount-showkey operation.
+
+ Returns the entry
+
+ :param mapname: The mapname to examine
+ :param kw: "key" the key to retrieve
+ :param kw: "all" set to True = return all attributes
+ """
+ ldap = self.api.Backend.ldap
+ dn = ldap.find_entry_dn("automountmapname", mapname, "automountmap")
+ keys = api.Command['automount_getkeys'](mapname)
+ keyname = kw.get('key').lower()
+ keydn = None
+ if keys:
+ for k in keys:
+ if k.get('automountkey').lower() == keyname:
+ keydn = k.get('dn')
+ break
+ if not keydn:
+ raise errors.NotFound
+ # FIXME: should kw contain the list of attributes to display?
+ if kw.get('all', False):
+ return ldap.retrieve(keydn)
+ else:
+ return ldap.retrieve(keydn, key_attributes)
+ def output_for_cli(self, entry):
+ # The automount map name associated with this key is available only
+ # in the dn. Add it as an attribute to display instead.
+ if entry and not entry.get('automountmapname'):
+ elements = explode_dn(entry.get('dn').lower())
+ for e in elements:
+ (attr, value) = e.split('=',1)
+ if attr == 'automountmapname':
+ entry['automountmapname'] = value
+ display_entry(entry)
+
+api.register(automount_showkey)
+
+
+class automount_getkeys(frontend.Command):
+ 'Retrieve all keys for an automount map.'
+ takes_args = (
+ Param('automountmapname',
+ cli_name='mapname',
+ primary_key=True,
+ doc='A group of related automount objects',
+ ),
+ )
+ def execute(self, mapname, **kw):
+ """
+ Execute the automount-getkeys operation.
+
+ Return a list of all automount keys for this mapname
+
+ :param mapname: Retrieve all keys for this mapname
+ """
+ ldap = self.api.Backend.ldap
+ dn = ldap.find_entry_dn("automountmapname", mapname, "automountmap")
+ return ldap.get_one_entry(dn, 'objectclass=*', ['automountkey'])
+ def output_for_cli(self, keys):
+ if keys:
+ for k in keys:
+ print k.get('automountkey')
+
+api.register(automount_getkeys)