# Authors: # Pavel Zuna # # Copyright (C) 2010 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 """ Example plugins """ # Import the most important objects. # api is an object containing references to all plugins and useful classes. # errors is a module containing all IPA specific exceptions. from ipalib import api, errors # Command is the base class for command plugin. from ipalib import Command # Str is a subclass of Param, it is used to define string parameters for # command. We'll go through all other subclasses of Param supported by IPA # later in this file from ipalib import Str # output is a module containing the most common output patterns. # Command plugin do output validation based on these patterns. # You can define your own as we're going to show you later. from ipalib import output # We're going to create an example command plugin, that takes a name as its # only argument. Commands in IPA support input validation by defining # functions we're going to call 'validators'. This is an example of such # function: def validate_name(ugettext, name): """ Validate names for the exhelloworld command. Names starting with 'Y' (picked at random) are considered invalid. """ if name.startswith('Y'): raise errors.ValidationError( name='name', error='Names starting with \'Y\' are invalid!' ) # If the validator doesn't return anything (i.e. it returns None), # the parameter passes validation. class exhelloworld(Command): """ Example commnad: Hello world! """ # takes_args is an attribute of Command. It's a tuple containing # instances of Param (or its subclasses such as Str) that define # what position arguments are accepted by the command. takes_args = ( # The first argument of Param constructor is the name that will be # used to identify this parameter. It can be followed by validator # functions. The constructor can also take a bunch of keyword # arguments. Here we use default, to set the parameters default value # and autofill, that fills the default value if the parameter isn't # present. # Note the ? at the end of the parameter name. It makes the parameter # optional. Str('name?', validate_name, default=u'anonymous coward', autofill=True, ), ) # has_output is an attribute of Command, it is a tuple containing # output.Output instances that define its output pattern. # Commands in IPA return dicts with keys corresponding to items # in the has_output tuple. has_output = ( # output.summary is one of the basic patterns. # It's a string that should be filled with a user-friendly # decription of the action performed by the command. output.summary, ) # Every command needs to override the execute method. # This is where the command functionality should go. # It is always executed on the server-side, so don't rely # on client-side stuff in here! def execute(self, name): return dict(summary='Hello world, %s!' % name) # register the command, uncomment this line if you want to try it out api.register(exhelloworld) # Anyway, that was a pretty bad example of a command or, to be more precise, # a bad example of resource use. When a client executes a command locally, its # name and parameters are transfered to the server over XML-RPC. The command # execute method is then executed on the server and results are transfered # back to the client. The command does nothing, but create a string - a task # that could be easily done locally. This can be done by overriding the Command # forward method. It has the same signature as execute and is normally # responsible for transferring stuff to the server. # Most commands will, however, need to perfom tasks on the server. I didn't # want to start with forward and confuse the hell out of you. :) class exshowuser(Command): """ Example command: retrieve user entry from LDAP """ takes_args = ( Str('username'), ) takes_options = ( Str('nevim?'), ) has_output = ( output.Output('result', dict, 'user entry whithout DN'), ) def execute(self, username): ldap = self.api.Backend.ldap2 dn = ldap.make_dn_from_attr( 'uid', username, self.api.env.container_user ) (dn, entry_attrs) = ldap.get_entry(dn) return dict(result=entry_attrs, summary=dn) api.register(exshowuser)