by Gary Childers

Contents:

Introduction

Virtually all organizations rely on some type of Directory Services as the basis of their network security system — whether Novell’s eDirectory, Microsoft’s Active Directory, LDAP directories, etc. In fact, a growing number of organizations have multiple directories or user databases, which are proprietary to their particular applications — different directories with the same user accounts, each with their own attributes and passwords that have to be managed.

Enter Novell Identity Manager. Identity Manager (IDM) is a tremendously powerful and flexible product to synchronize user accounts between a great number of different systems and directories, including Novell’s eDirectory, Microsoft’s Active Directory, LDAP directories, Linux/Unix servers, Lotus Notes, and many others.

Managing Identity Manager

Once you have the IDM product up and running, you’re always looking for ways to simplify and automate various maintenance tasks. This is particularly true when you have implemented IDM on the Linux platform, since Linux administrators tend to rely heavily upon using scripts to automate the day-to-day management tasks that are required. This ability to automate complex tasks with scripts is one of the strengths of the Linux operating system.

So let’s paint the scenario: administrators of Novell Identity Management (IDM) wish to be able to conveniently manage the IDM drivers running on Linux servers as part of the day-to-day administration of the Identity Management system. Novell provides iManager for Web-based remote administration, and also the dxcmd utility for local server console administration of IDM drivers.

The standard method for starting, stopping and checking the state of IDM drivers is to launch iManager on a workstation, login to a particular server, then select Identity Manager | Identity Manager Overview in the navigation pane, then select the desired Driver Set, and then finally select the particular IDM driver and click on the driver control button to Start, Stop, or Get Current Status for that driver.

This process can be slow or limiting, especially if you are at the Linux server console, and just want to quickly start, stop, or view the current state of your drivers. The dxcmd command-line utility can be used at the server console, but the interactive interface is a bit clunky. The real power in dxcmd is the ability for it to accept command parameters, and thus be included in scripting logic to perform the tasks which we want to do.

Solution Requirements

Let’s flesh out the requirements which we want our scripts to accomplish: IDM administrators wish to be able to use easy-to-remember console commands to manage the state of the IDM drivers, and also be able to script these same commands for use with automated processes, such as data backups. Thus the IDM administrators wish to have Linux scripts which will accomplish the following tasks:

  • display the status of IDM drivers
  • display the servers associated with an IDM driverset
  • start IDM drivers on a particular server
  • stop IDM drivers on a particular server
  • modify the startup option of an IDM driver
  • failover an IDM driver to an alternate server

Proposed Solution

To accomplish these objectives, I have developed a Linux bash script (named idmutil.sh) for use on Linux servers which have Novell Identity Manager installed. This script can be copied to at least one IDM server in the environment. A secondary script (named idmfailover.sh) uses the first script to perform the more complex driver failover operation.

The environment-specific variables, such as the eDirectory version, the LDAP search base, and the service account name and password, are contained in a configuration script (named idmutil.conf), which is called by the primary script to set all the necessary parameters that are particular to the eDirectory environment in which the scripts are implemented. This configuration script needs to be modified for every different environment.

Dependencies

The service account used in these scripts (in my implementation, IDMservice) should be created to allow IDM management with the least required privileges, for security reasons. The service account needs only to be made trustee of the DriverSet object in eDirectory, with compare, read and write attribute rights to the object.

By default, the eDirectory and Identity Management applications are installed and configured on Linux to run as the root user. These scripts are therefore designed to also run as the root user to manage the IDM drivers. In order to allow non-root users to use these scripts, include command aliases in the server’s ‘sudoers’ file, and run the scripts using sudo.

For more on being able to manage eDirectory as a non-root user, see the AppNote: Non-Root eDirectory Management. This goes into detail about using sudo to allow non-root users to run the specific commands and utilities on the Linux servers required to manage eDirectory.

Caveat Implementor

As with any proposed solution, I must not omit this standard “disclaimer”: Please note: command scripting (in general), whether in NetWare, Windows, or Linux can do wonders to automate and schedule repetitive tasks, but we must always be very careful. The wonderful thing about scripted tasks is that they perform commands exactly as we tell them to do, quickly and repeatedly. The terrible thing about scripted tasks is also that they perform commands exactly as we tell them to do (not particularly as we think that we are telling them to do), quickly and repeatedly.

Well-written scripts can do a world of good. Poorly-written (or poorly implemented) scripts can put you into a world of hurt. So always, always (and should I say “always”?) test your scripts (repeatedly) in a test lab (non-production) environment, and then carefully test them again in very limited fashion in a “pilot” environment, before full-scale production use. This is especially true for any script which you have “borrowed” from another environment.

Script Usage

So with that said, now to the script itself. The general syntax of the idmutil.sh script is:

idmutil.sh [ <action> ] [<driverCN>] [<host>] [<option>]

The script file itself is ‘idmutil.sh’, which in my implementations I have placed in the /opt/novell/eDirectory/scripts directory (create this directory) on the Linux servers which have both eDirectory and IDM installed.

Note: If a different directory than /opt/novell/eDirectory/scripts is used, then the value for the SCRIPTDIR variable (line 11) will need to be changed to reflect the script location.

I have incorporated some error messages into the script logic to assist the user with the proper syntax. For example, if the script command were entered with no parameters, it would yield these results:

sles-idm1:~ # idmutil
Usage: idmutil.sh [ <action> ] [ <driverCN> | all ] [ <host> ] [ <option> ]
Error: invalid action Valid Actions: start | stop | status | list | listhosts | getstate

So this tells us the valid options for the first script parameter: start, stop, status, list, listhosts and getstate (‘getstate’ is actually the same as ‘status’). This first (‘action’) parameter is always required.

Depending upon the action specified, there are some parameters that have default values. For example, the “list” action always defaults to “all” drivers, since it is assumed that you wish to list all drivers in the IDM driverset associated with the server. Similarly, if no “host” parameter is specified, it is assumed that the command will run against the local host or server.

Usage Examples

Here are a few examples of the script usage to accomplish common tasks:

  • To list all drivers in the driverset on the local server:
    sles-idm1:~ # idmutil list all sles-idm1
    Listing drivers on sles-idm1 for DriverSet.MAIN ...
      EDIR2-EDIR1
      eDir2AD-RL
      Library
      BusLogic
      
      
    Note: as we just mentioned, the same results occur if we run “idmutil list” or “idmutil list all”, because of the default values which are used if none are specified.
  • To display the status of a single IDM driver:
    sles-idm1:~ # idmutil status edir1-edir2 sles-idm1
    Getting Status of drivers on sles-idm1 for DriverSet.MAIN ...
      edir1-edir2              : (2) Running      :  (2) Auto         on sles-idm1
      
      
    Note: if a hostname is not specified, the local host is assumed.
  • To display the status of all IDM drivers on another host:
    sles-idm1:~ # idmutil status all sles-idm2
    Getting Status of drivers on sles-idm2 for DriverSet.MAIN ...
      EDIR2-EDIR1              : (2) Running      :  (2) Auto         on sles-idm2
      eDir2AD-RL               : (2) Running      :  (2) Auto         on sles-idm2
      Library                  : (0) Stopped      :  (0) Disabled     on sles-idm2
      BusLogic                 : (0) Stopped      :  (0) Disabled     on sles-idm2
      
    
    Note: when “all” is used for the driverCN, the script will list information for all drivers
  • To display the servers associated with an IDM driverset:
    sles-idm1:~ # idmutil listhosts
    Listing Hosts for DriverSet.MAIN on sles-idm1 ...
    sles-idm1
    sles-idm3
    
    
    Note: the “listhosts” option does not take any further parameters.
  • To start an IDM driver on the local server:
    sles-idm1:~ # idmutil start edir1-edir2
    Starting drivers on sles-idm1 for DriverSet.MAIN ...
      edir1-edir2              : (0) Stopped      :  (2) Auto         on sles-idm1
     *Starting Driver edir1-edir2 on sles-idm1.  Please wait ...
      edir1-edir2              : (2) Running      :  (2) Auto         on sles-idm1
      
    
    Note: again, if a hostname is not specified, the local host is assumed. However, a driver CN is always required for ‘start’ and ‘stop’ operations.
  • To start an IDM driver on a remote server:
    sles-idm1:~ # idmutil start edir2-edir1 sles-idm2
    Starting drivers on sles-idm2 for DriverSet.MAIN ...
      edir2-edir1              : (0) Stopped      :  (2) Auto         on sles-idm2
     *Starting Driver edir2-edir1 on sles-idm2.  Please wait ...
      edir2-edir1              : (2) Running      :  (2) Auto         on sles-idm2
      
    
  • To stop an IDM driver on the local server:
    sles-idm1:~ # idmutil stop edir1-edir2
    Stopping drivers on sles-idm1 for DriverSet.MAIN ...
      edir1-edir2              : (2) Running      :  (2) Auto         on sles-idm1
     *Stopping Driver edir1-edir2 on sles-idm1.  Please wait ...
      edir1-edir2              : (0) Stopped      :  (2) Auto         on sles-idm1
      
    
  • To stop all IDM drivers on the local server:
    sles-idm1:~ # idmutil stop all
    Stopping drivers on sles-idm1 for DriverSet.MAIN ...
      EDIR1-EDIR2              : (2) Running      :  (2) Auto         on sles-idm1
     *Stopping Driver EDIR1-EDIR2 on sles-idm1.  Please wait ...
      EDIR1-EDIR2              : (0) Stopped      :  (2) Auto         on sles-idm1
      BusLogic1                : (2) Running      :  (2) Auto         on sles-idm1
     *Stopping Driver BusLogic1 on sles-idm1.  Please wait ...
      BusLogic1                : (0) Stopped      :  (2) Auto         on sles-idm1
      BusLogic2                : (2) Running      :  (2) Auto         on sles-idm1
     *Stopping Driver BusLogic2 on sles-idm1.  Please wait ...
      BusLogic2                : (0) Stopped      :  (2) Auto         on sles-idm1
    
    
    Note: The same action can be performed on a remote server, by adding the hostname.
  • To start all IDM drivers on a remote server:
    sles-idm2:~ # idmutil start all sles-idm1
    Starting drivers on sles-idm1 for DriverSet.MAIN ...
      EDIR1-EDIR2              : (0) Stopped      :  (2) Auto         on sles-idm1
     *Starting Driver EDIR1-EDIR2 on sles-idm1.  Please wait ...
      EDIR1-EDIR2              : (2) Running      :  (2) Auto         on sles-idm1
      BusLogic1                : (0) Stopped      :  (2) Auto         on sles-idm1
     *Starting Driver BusLogic1 on sles-idm1.  Please wait ...
      BusLogic1                : (2) Running      :  (2) Auto         on sles-idm1
      BusLogic2                : (0) Stopped      :  (2) Auto         on sles-idm1
     *Starting Driver BusLogic2 on sles-idm1.  Please wait ...
      BusLogic2                : (2) Running      :  (2) Auto         on sles-idm1
    
    
    Note: the IDM servers upon which the idmutil.sh script is run do not need to be in the same eDirectory trees, since the dxcmd utility, which it executes, is not tree-specific.
  • To modify the startup option of an IDM driver on a remote server:
    sles-idm2:~ # idmutil setstartoption edir1-edir2 sles-idm1 disabled
    Setting Start Option of drivers on sles-idm1 for DriverSet.MAIN ...
      edir1-edir2              : (2) Running      :  (2) Auto         on sles-idm1
      
      
    Note: by design, this command did not execute, since the driver is currently running. To disable the driver, we need to first stop the driver, as in:

    sles-idm2:~ # idmutil stop edir1-edir2 sles-idm1
    Stopping drivers on sles-idm1 for DriverSet.MAIN ...
      edir1-edir2              : (2) Running      :  (2) Auto         on sles-idm1
     *Stopping Driver edir1-edir2 on sles-idm1.  Please wait ...
      edir1-edir2              : (0) Stopped      :  (2) Auto         on sles-idm1
    sles-idm2:~ # idmutil setstartoption edir1-edir2 sles-idm1 disabled
    Setting Start Option of drivers on sles-idm1 for DriverSet.MAIN ...
      edir1-edir2              : (0) Stopped      :  (2) Auto         on sles-idm1
     *Setting Start Option of Driver edir1-edir2 on sles-idm1.  Please wait ...
      edir1-edir2              : (0) Stopped      :  (0) Disabled     on sles-idm1
      
      

    Note also that the only time the <option> parameter is used, is in conjunction with the “setstartoption” action parameter.

Using Symlinks and Aliases

No doubt you may have noticed that in all my examples I have run the command: “idmutil”, rather than the true name of the script, with the full path specified, as: “/opt/novell/eDirectory/scripts/idmutil.sh”. This is because I first created a symbolic link to the script file in /usr/bin (which by default is in the user’s path in most implementations of Linux). To create the symlink for the script, we merely have to execute this command:

ln -sf /opt/novell/eDirectory/scripts/idmutil.sh /usr/bin/idmutil

Remember, one of the requirements for this solution was to give IDM administrators easy-to-remember console commands to manage the state of the IDM drivers. Thus, to assist them with a simpler command syntax, I have also created a few aliases which merely call the idmutil.sh script with some pre-supplied parameters.

In Linux, we use aliases all the time. For example, we use “ll” as a shortcut for “ls -l” to list directory contents, an alias which saves us a mere three keystrokes. Similarly, we can use aliases to make our script syntax a bit easier to remember and execute.

For example, if an administrator wants to view the IDM driver status on the server by merely typing “idmstatus”, then I create an alias “idmstatus”, by executing this:

alias idmstatus='idmutil status'
Thus executing "idmstatus all" will really execute "idmutil status all", since the alias will be expanded out before the command execution, as in:
sles-idm1:~ # idmstatus
Getting Status of drivers on sles-idm1 for DriverSet.MAIN ...
  EDIR1-EDIR2              : (2) Running      :  (2) Auto         on sles-idm1
  BusLogic1                : (2) Running      :  (2) Auto         on sles-idm1
  BusLogic2                : (2) Running      :  (2) Auto         on sles-idm1
sles-idm1:~ # idmutil status all sles-idm1
Getting Status of drivers on sles-idm1 for DriverSet.MAIN ...
  EDIR1-EDIR2              : (2) Running      :  (2) Auto         on sles-idm1
  BusLogic1                : (2) Running      :  (2) Auto         on sles-idm1
  BusLogic2                : (2) Running      :  (2) Auto         on sles-idm1
  
  

Similarly, we can have an alias for listing, starting and stopping drivers by executing:

alias idmlist='idmutil list'
alias idmstart='idmutil start'
alias idmstop='idmutil stop'

An example of using these aliases to stop and start all IDM drivers on a server is:

sles-idm1:~ # idmstop all
Stopping drivers on sles-idm1 for DriverSet.MAIN ...
  EDIR1-EDIR2              : (2) Running      :  (2) Auto         on sles-idm1
 *Stopping Driver EDIR1-EDIR2 on sles-idm1.  Please wait ...
  EDIR1-EDIR2              : (0) Stopped      :  (2) Auto         on sles-idm1
  BusLogic1                : (2) Running      :  (2) Auto         on sles-idm1
 *Stopping Driver BusLogic1 on sles-idm1.  Please wait ...
  BusLogic1                : (0) Stopped      :  (2) Auto         on sles-idm1
  BusLogic2                : (2) Running      :  (2) Auto         on sles-idm1
 *Stopping Driver BusLogic2 on sles-idm1.  Please wait ...
  BusLogic2                : (0) Stopped      :  (2) Auto         on sles-idm1
sles-idm1:~ # idmstart all
Starting drivers on sles-idm1 for DriverSet.MAIN ...
  EDIR1-EDIR2              : (0) Stopped      :  (2) Auto         on sles-idm1
 *Starting Driver EDIR1-EDIR2 on sles-idm1.  Please wait ...
  EDIR1-EDIR2              : (2) Running      :  (2) Auto         on sles-idm1
  BusLogic1                : (0) Stopped      :  (2) Auto         on sles-idm1
 *Starting Driver BusLogic1 on sles-idm1.  Please wait ...
  BusLogic1                : (2) Running      :  (2) Auto         on sles-idm1
  BusLogic2                : (0) Stopped      :  (2) Auto         on sles-idm1
 *Starting Driver BusLogic2 on sles-idm1.  Please wait ...
  BusLogic2                : (2) Running      :  (2) Auto         on sles-idm1
  
  

Failing Drivers to Alternate Servers

Remember also that one of the requirements for this solution was to automate the fail-over of an IDM driver to an alternate server. Obviously, this first requires that we have already installed a secondary IDM server in the same eDirectory tree with the our primary IDM server, and extended the driverset to that server.

But then to accomplish the task of quickly failing over a driver or drivers to the second IDM server, another secondary script (idmfailover.sh) is utilized. The idmfailover.sh script is used to call the idmutil.sh script four times: first to stop the driver on the first server, to disable the driver on the first server, to enable the driver on the second server, and finally to start the driver on the second server.

The syntax for using the idmfailover.sh script is:

idmfailover <driverCN> <server1> <server2>

Here is an example:

VMSLES-1:~ # idmstatus
Getting Status of drivers on VMSLES-1 for DriverSet.MAIN ...
  BusLogic1                : (2) Running      :  (2) Auto         on VMSLES-1
  ACME-IDP2M               : (2) Running      :  (2) Auto         on VMSLES-1
VMSLES-1:~ # idmstatus all vmsles-3
Getting Status of drivers on vmsles-3 for DriverSet.MAIN ...
  BusLogic1                : (0) Stopped      :  (0) Disabled     on vmsles-3
  ACME-IDP2M               : (0) Stopped      :  (0) Disabled     on vmsles-3
VMSLES-1:~ # idmfailover buslogic1 vmsles-1 vmsles-3
Stopping drivers on vmsles-1 for DriverSet.MAIN ...
  buslogic1                : (2) Running      :  (2) Auto         on vmsles-1
 *Stopping Driver buslogic1 on vmsles-1.  Please wait ...
  buslogic1                : (0) Stopped      :  (2) Auto         on vmsles-1
Setting Start Option of drivers on vmsles-1 for DriverSet.MAIN ...
  buslogic1                : (0) Stopped      :  (2) Auto         on vmsles-1
 *Setting Start Option of Driver buslogic1 on vmsles-1.  Please wait ...
  buslogic1                : (0) Stopped      :  (0) Disabled     on vmsles-1
Setting Start Option of drivers on vmsles-3 for DriverSet.MAIN ...
  buslogic1                : (0) Stopped      :  (0) Disabled     on vmsles-3
 *Setting Start Option of Driver buslogic1 on vmsles-3.  Please wait ...
  buslogic1                : (0) Stopped      :  (2) Auto         on vmsles-3
Starting drivers on vmsles-3 for DriverSet.MAIN ...
  buslogic1                : (0) Stopped      :  (2) Auto         on vmsles-3
 *Starting Driver buslogic1 on vmsles-3.  Please wait ...
  buslogic1                : (2) Running      :  (2) Auto         on vmsles-3
VMSLES-1:~ # idmstatus all vmsles-3
Getting Status of drivers on vmsles-3 for DriverSet.MAIN ...
  BusLogic1                : (2) Running      :  (2) Auto         on vmsles-3
  ACME-IDP2M               : (0) Stopped      :  (0) Disabled     on vmsles-3
VMSLES-1:~ # idmstatus
Getting Status of drivers on VMSLES-1 for DriverSet.MAIN ...
  BusLogic1                : (0) Stopped      :  (0) Disabled     on VMSLES-1
  ACME-IDP2M               : (2) Running      :  (2) Auto         on VMSLES-1
  
  

This example shows that the ‘BusLogic1′ driver was running on the vmsles-1 server, and we failed it over to the vmsles-3 server by executing: “idmfailover buslogic1 vmsles-1 vmsles-3″, and then verified that it is now running on the vmsles-3 server.

Note: be careful when using the “all” parameter (meaning to fail over all drivers), since it will do precisely just that. If you have drivers that are currently disabled (intentionally), they will be enabled and attempt to start by the idmfailover script.

And once again, you may notice that we utilized a symbolic link to reference the script. To create the symlink for the idmfailover.sh script, we merely have to execute this command:

ln -sf /opt/novell/eDirectory/scripts/idmfailover.sh /usr/bin/idmfailover

The automatic fail-over of IDM drivers may be required if administrators want to perform an operation such as a scheduled data backup of the server, or any other maintenance which would require stopping the drivers and starting them on an alternate server.

Scripts

And now for the actual scripts themselves. Below is the text of the scripts developed to accomplish the required tasks outlined above:

The main script, idmutil.sh:

#!/bin/bash
# idmutil.sh
# Script to start, stop, and list status of IDM drivers using dxcmd
# Author: Gary Childers, 02/09/2009	Version 1.3.1
# Usage: idmutil [ <action> ] [<driverCN>] [<host>] [<option>]

#----------------------------------------------------------------------------#
## Set initial required variables
SCRIPT=idmutil.sh
CONFFILE=ndsenvironment.conf
SCRIPTDIR=/opt/novell/eDirectory/scripts

## Set IDM server environment-specific variables from a separate config file
if [ -f $SCRIPTDIR/$CONFFILE ]; then 
  . $SCRIPTDIR/$CONFFILE
else
  echo "Configuration file $SCRIPTDIR/$CONFFILE missing!"
  exit 1
fi

## Required script variables
THISHOST=`/bin/hostname`
ACTION=$1
if [ "$ACTION" = "status" ]; then ACTION="getstate"; fi
DRVRCN=$2
if [ "$DRVRCN" = "" ]; then DRVRCN="all"; fi
DXMLHOST=$3
if [ "$DXMLHOST" = "" ]; then DXMLHOST="$THISHOST" ; fi
SETSTARTUP=$4
if [ "$ACTION" = "setstartoption" ]; then OPTOPTION=$SYNCOPTION; fi
ACTIONLIST="list listhosts start stop getstate getstartoption setstartoption"
OPTIONLIST="disabled manual auto"
DRVRSET=`echo $DRVRSETDN | sed s/"cn="//g | sed s/",ou="/"."/g |sed s/",o="/"."/g`
DELAY=3

## Set the location of utilities according to eDirectory version
if [ -f /usr/bin/dxcmd ]; then UTILDIR=/usr/bin; fi
if [ -f /opt/novell/eDirectory/bin/dxcmd ]; then UTILDIR=/opt/novell/eDirectory/bin; fi
if [ "$UTILDIR" = "" ]; then
  echo "Error: dxcmd utility not found"
  exit 1
fi
DXUTIL="$UTILDIR/dxcmd"
LDAPUTIL="$UTILDIR/ldapsearch"

## Set Error Messages
ERROR0="You must run this script as root."
ERROR1="invalid action"
ERROR4="invalid startup option"
USAGE="Usage: $SCRIPT [ <action> ] [<driverCN>] [<host>] [<option>]"
USAGE1="Valid Actions: start | stop | status | list | listhosts | getstate"
USAGE4="Valid Options: disabled | manual | auto"

## Notify root user dependency
if [ $(whoami) != "root" ]; then
  echo $ERROR0
  exit 1
fi

#----------------------------------------------------------------------------#
## Define functions

function LCASE()
{
  ## Function to translate strings to lowercase
  echo $1 | tr [:upper:] [:lower:]
}

function TESTLIST()
{
  ## Function to validate a parameter against a list
  ## Returns 1 if LOCALLIST contains LOCALOPTION, returns 0 otherwise
  LOCALOPTION=$1
  LOCALLIST=$2
  for LISTITEM in $LOCALLIST; do
    if [ "$(LCASE $LOCALOPTION)" = "$(LCASE $LISTITEM)" ]; then return 1; fi
  done
  return 0
}

function ECHOERROR()
{
  echo "$1 : $2"
  echo "$3"
  exit 1
}

function GETSTATE()
{
  ## Get the current state for the specified driver
  STATE=`$DXUTIL -s -host $DXMLHOST -user $IDMUSER -password $IDMPWD -getstate $DRVR.$DRVRSET`
  case $STATE in
    "0"		)  STATEDESC="Stopped"		;;
    "1"		)  STATEDESC="Starting"		;;
    "2"		)  STATEDESC="Running"		;;
    "3"		)  STATEDESC="Stopping"		;;
    "-601"	)  STATEDESC="No Such Entry"	;;
    *		)  STATEDESC="ERROR"		;;
  esac

  ## Get the current startup option for the specified driver
  STARTOPT=`$DXUTIL -s -host $DXMLHOST -user $IDMUSER -password $IDMPWD -getstartoption $DRVR.$DRVRSET`
  case $STARTOPT in
    "0"		)  STARTDESC="Disabled"		;;
    "1"		)  STARTDESC="Manual"		;;
    "2"		)  STARTDESC="Auto"		;;
    "-601"	)  STARTDESC="No Such Entry"	;;
    *		)  STARTDESC="ERROR"		;;
  esac

  ## Echo the results returned from getting State and Startup Option
  echo "  $(printf %-24.24s "$DRVR") : ($STATE) $(printf %-12s "$STATEDESC") :  ($STARTOPT) $(printf %-12s "$STARTDESC") on $DXMLHOST"
}

function TESTACTION()
{
  ## Test state and startup option
  case $ACTION in
    "start"	)	if [ $STATE = 2 ]	; then return 1; fi	;
			if [ $STARTOPT = 0 ]	; then return 1; fi	;;
    "stop"	)	if [ $STATE = 0 ]	; then return 1; fi	;;
    "setstartoption" )	if [ $STATE = 2 ]	; then return 1; fi	;;
  esac
  if [ $STATE  = "-601" ]			; then return 1; fi
  return 0
}

function DOACTION()
{
  ## Perform the specified action for the specified drivers
  echo " *$ACTDESC Driver $DRVR on $DXMLHOST.  Please wait ..."
  $DXUTIL -q -host $DXMLHOST -user $IDMUSER -password $IDMPWD -$ACTION $DRVR.$DRVRSET $SETSTARTUP $OPTOPTION
  sleep $DELAY
}

#----------------------------------------------------------------------------#

## Validate the provided arguments
## validate the action parameter
TESTLIST $ACTION "$ACTIONLIST"
if [ $? = "0" ]; then ECHOERROR $ACTION "$ERROR1" "$USAGE1"; fi

## Set the description for the specified action
case $ACTION in
  "list"		)  ACTDESC="Listing";		DRVRCN="all"	;;
  "listhosts"		)  ACTDESC="Listing Hosts";	DRVRCN="all"	;;
  "start"		)  ACTDESC="Starting"				;;
  "stop"		)  ACTDESC="Stopping"				;;
  "getstate"		)  ACTDESC="Getting Status of"			;;
  "getstartoption"	)  ACTDESC="Getting Start Option of"		;;
  "setstartoption"	)  ACTDESC="Setting Start Option of"		;;
  *			)  ACTDESC="INVALID ACTION"			;;
esac

## Validate the host parameter
ERROR3a="Server $DXMLHOST: is not a valid IDM host"
USAGE3a="Valid Hosts: $HOSTLIST"
TESTLIST $DXMLHOST "$HOSTLIST"	
if [ $? = "0" ]; then ECHOERROR $DXMLHOST "$ERROR3a" "$USAGE3a"; fi

## Validate the startoption parameter
if [ "$1" = "setstartoption" ]; then
  TESTLIST $SETSTARTUP "$OPTIONLIST"
  if [ $? = "0" ]; then ECHOERROR $SETSTARTUP "$ERROR4" "$USAGE4"; fi
fi

## Find Servers associated with the DriverSet using LDAP search
DXMLHOSTS=`$LDAPUTIL -h $DXMLHOST -p 389 -x -D $LDAPUSER -w $IDMPWD -s base -b $DRVRSETDN DirXML-ServerList | grep DirXML-ServerList:  | cut -d" " -f2 | cut -d"=" -f2 | cut -d"," -f1`

## Find Drivers contained in the DriverSet using LDAP search
DXMLDRVRS=`$LDAPUTIL -h $DXMLHOST -p 389 -x -D $LDAPUSER -w $IDMPWD -s one -b $DRVRSETDN dn | grep dn: | cut -d" " -f2 | cut -d"=" -f2 | cut -d"," -f1`

## List Servers associated with the DriverSet
if [ $ACTION = "listhosts" ]; then
  echo "$ACTDESC for $DRVRSET on $DXMLHOST ..." 
  for HOST in $DXMLHOSTS; do echo $HOST; done
  exit 0
fi

## Validate if the IDM driverset is associated with the specified server 
ERROR3b="Server $DXMLHOST is not associated with $DRVRSET"
USAGE3b="Valid Hosts: $DXMLHOSTS"
TESTLIST $DXMLHOST "$DXMLHOSTS"
if [ $? = "0" ]; then ECHOERROR $DXMLHOST "$ERROR3b" "$USAGE3b"; fi

## Validate if the driver is in the IDM driverset
ERROR2="is not a valid driver in $DRVRSET on $DXMLHOST"
USAGE2="Valid Drivers: $DXMLDRVRS"
if [ "$DRVRCN" != "all" ]; then
  TESTLIST $DRVRCN "$DXMLDRVRS"
  if [ $? = "0" ]; then ECHOERROR $DRVRCN "$ERROR2" "$USAGE2"; fi
fi

## Show status of the IDM drivers, and conditionally perform the action
if [ "$ACTION" = "list" -o "$DRVRCN" = "all" ]
  then DRVRLIST=$DXMLDRVRS
  else DRVRLIST=$DRVRCN
fi
echo "$ACTDESC drivers on $DXMLHOST for $DRVRSET ..."
for DRVR in $DRVRLIST; do
  if [ "$ACTION" = "list" ]; then
    echo $DRVR
  else
    GETSTATE {}
    if [ "$ACTION" = "start" -o  "$ACTION" = "stop" -o  "$ACTION" = "setstartoption" ]; then
      TESTACTION {}
      if [ $? != 1 ]; then
        DOACTION {}
        GETSTATE {}
      fi
    fi
  fi
done

exit 0

The configuration script, idmutil.conf :

#!/bin/bash
# idmutil.conf
# Set environment-specific variables for the idmutil.sh script

## Environment-specific variables
LDAPUSER="cn=IDMservice,o=MAIN"
IDMUSER="IDMservice.MAIN"
IDMPWD="n0v3ll"
DRVRSETDN="cn=DriverSet,o=MAIN"
LDAPBASE="o=MAIN"
SYNCOPTION=noresync
HOSTLIST="vmsles-1 vmsles-2 vmsles-3 vmsles-4"

Obviously, these parameters are specific to the environment in which the scripts are to be deployed. The IDMservice account password is stored in clear text, which is why we setup an account with the least required privileges. The file should also be restricted to be readable only by the root user.

The script to failover IDM drivers to alternate servers, idmfailover.sh:

#!/bin/bash
# idmfailover.sh
# Script to failover IDM drivers to another server using idmutil script
# Author: Gary Childers	2009-02-09	Version 1.2
# Usage: idmfailover <driverCN> <server1> <server2>

## Test the provided parameters
USAGE="Usage: idmfailover <driverCN> <server1> <server2>"
if [ "$1" = "" -o "$2" = "" -o "$3" = "" ]; then
  echo "invalid parameters"
  echo $USAGE
  exit 1
fi

## Set required variables
IDMUTIL1=/opt/novell/eDirectory/scripts/idmutil.sh
DRIVER=$1
SERVER1=$2
SERVER2=$3

## Stop the driver on the first server
$IDMUTIL1 stop $DRIVER $SERVER1

## Set the start option to disabled on the first server
$IDMUTIL1 setstartoption $DRIVER $SERVER1 disabled

## Set the start option to auto on the second server
$IDMUTIL1 setstartoption $DRIVER $SERVER2 auto

## Start the driver on the second server
$IDMUTIL1 start $DRIVER $SERVER2

exit 0

Summary

Just to recap this suggested solution for scripted management of IDM drivers on Linux:

  • Deploy the scripts in /opt/novell/eDirectory/scripts (create the directory)
  • Create a service account with appropriate eDirectory rights to the IDM DriverSet
  • Modify the idmutil.conf file to accommodate the desired eDirectory environment
  • Create symlinks and aliases to the script files for ease-of-use

This solution allows IDM administrators to more easily manage IDM drivers from the Linux console, and to more easily script IDM commands for automated processes, such as data backups. If you choose to adapt these scripts for your environment, be sure (I say again) to test them thoroughly before deployment on production servers. Happy scripting!

0 votes, average: 0.00 out of 50 votes, average: 0.00 out of 50 votes, average: 0.00 out of 50 votes, average: 0.00 out of 50 votes, average: 0.00 out of 5 (0 votes, average: 0.00 out of 5)
You need to be a registered member to rate this post.
Loading...Loading...
Categories: Uncategorized

Disclaimer: As with everything else at NetIQ Cool Solutions, this content is definitely not supported by NetIQ, so Customer Support will not be able to help you if it has any adverse effect on your environment.  It just worked for at least one person, and perhaps it will be useful for you too.  Be sure to test in a non-production environment.

Leave a Reply

7 Comments

  • dgersic says:

    Section 1.2 of the docs, “Securing Directory Access” might be good to review if you are on IDM 3.6 or newer. You can lock down the security required on your IDMservice account even further.

  • bwillhite says:

    I have a single server IDM test environment, SLES 10, IDM 3.6 eDir 8.8, when I run the idmutil script I receive an error stating ‘Server idm-srv: is not a valid IDM host’.

    I can run dxcmd and ldapsearch successfully and I have double-checked the idmutil.conf and it seems correct. I can also connect via LDAP on port 389.

    What am I missing?

    Thanks

    • gchilders says:

      Hi, sorry for the delay in responding.

      Looking at the script, I see where your error is coming from. I included a servername checking routine, to limit the number of servers to check:
      ## Validate the host parameter
      ERROR3a=”Server $DXMLHOST: is not a valid IDM host”
      USAGE3a=”Valid Hosts: $HOSTLIST”
      TESTLIST $DXMLHOST “$HOSTLIST”
      if [ $? = “0” ]; then ECHOERROR $DXMLHOST “$ERROR3a” “$USAGE3a”; fi

      I did this because all of the eDirectory servers in the tree were not IDM servers.

      But I can see that there is a line missing from the published idmutil.conf file:

      HOSTLIST=”vmsles-1 vmsles-2 vmsles-3 vmsles-4″ ## example ##

      The ‘TESTLIST’ function merely tests a supplied parameter against a list of values. If you add the HOSTLIST variable with valid IDM server names in your idmutil.conf file, that should eradicate the error.

  • ukrause says:

    This give some very nice option for Admins to easily observe their environment. Execllent done. Thx.

  • mbristow says:

    This makes life much easier!

  • mbristow says:

    FYI… I wasn’t able to get these scripts to work with IDM 3.0.1, and it think it is due to the “-s” switch that gets used with DXCMD. DXCMD version 1.0 that comes with IDM 3.0.1 does not support “-s”.

  • mchavezn says:

    Hello, hopping you can see my message, until now the functions exposed by idmutil works great, but now days a sentinel monitor started using this utility at the same time that a cron use, causing unexpected results(shutdown other drivers, misconfiguration. etc), this script was done in order to be invoked at the same time by others scripts? Thank you in advance.

By: gchilders
Feb 25, 2009
3:10 pm
Reads:
3,558
Score:
Unrated