Tivoli Directory Server – Performance monitoring with Zenoss

If you are trying to collect performance data from IBM’s Tivoli Directory Server, and you do not have Tivoli Directory Integrator installed, then you can still monitor some performance metrics with Zenoss.

The big Aha! moment for me was when I read that you can query some useful metrics with an LDAP client.

ldapsearch -h $LDAP_HOST -x -D "$LDAP_ADMIN_DN" -w $LDAP_ADMIN_PASSWORD -s base -b cn=monitor objectclass=*
# extended LDIF
# LDAPv3
# base <cn=monitor> with scope baseObject
# filter: objectclass=*
# requesting: ALL
version: IBM Tivoli Directory (SSL), 6.1
totalconnections: 50912
total_ssl_connections: 0
total_tls_connections: 0
currentconnections: 67
maxconnections: 1024
writewaiters: 0
readwaiters: 0
opsinitiated: 712582
livethreads: 1
opscompleted: 712581
entriessent: 620628
searchesrequested: 585265
searchescompleted: 585264
bindsrequested: 50917
bindscompleted: 50917
unbindsrequested: 50791

So we no longer need to use IBM’s SNMP listener therefore saving some time and maybe even some money. Zenoss allows you to run scripts and  so long as the script returns stuff in the right format Zenoss can graph them. Here’s how I did it.

1. The script

First we need a script to go get the data from TDS. As shown above, it is really only a simple LDAP search, but the output need to conform to the Nagios plugin standard. So here is my script. Feel free to use and improve upon it.


# Robert Hart https://robertjhart.wordpress.com/ July 2010
# Script to collect performance metrics from IBM Tivoli Directory Server 6.1
# For reference:
# http://community.zenoss.org/docs/DOC-4770
# http://nagiosplug.sourceforge.net/developer-guidelines.html#PLUGOUTPUT

# List of attributes to get.
# format: space seperated - attribute,UOM
ATTRIBUTES="bindsrequested,c currentconnections,"

# Stuff to tweak
LDAP_ADMIN_DN=<administrator distinguished name>
CMD="ldapsearch -h $LDAP_HOST -x -D "$LDAP_ADMIN_DN" -w $LDAP_ADMIN_PASSWORD -s base -b cn=monitor objectclass=*"
# if needed, set to a real file

# this parses the attribute value out of the ldpsearch output.
# usage: parse attribute,UOM
function parse
 echo "parsing $1" > $DEBUG
 ATT=`echo $1 | awk -F "," '{print$1}'`
 UOM=`echo $1 | awk -F "," '{print$2}'`
 KEY=`grep "^$ATT" $TMP_FILE | awk '{print $1}' | sed -e 's/://'`
 VALUE=`grep "^$ATT" $TMP_FILE | awk '{print $2}'`
 if [ -z $UOM ]

# Lets do some work

 echo "command ran" > $DEBUG
 exit 2

 if parse $ATTRIBUTE
 echo "parsed" > $DEBUG
 exit 1

echo "tds |$OUTPUT"
exit 0

Save this script as a file on the Zenoss server, make the zenoss user the owner and give it execute permissions.

You should be able to test the script and get a result:

$ ./zenoss-tds.sh ldap.example.org
tds |currentconnections=69;;;; bindsrequested=50880[c];;;;

2. Set up the template in Zenoss

First I created an device class because we have a couple of LDAP servers, and so devices inheriting from the device class is the more efficient way to do this.

I also set the LDAP monitor zProperties and bound the LDAP monitor template so we could graph LDAP response times too.

In the templates tab for the device class, I pulled down the menu in the Available Performance Templates section and selected “Add Template…”. Once you have given it a name, then you end up in a page where you can add a data source. In the Data Sources section pull down the menu and select “Add Datasource…”. Give it a name, and set the source to COMMAND. Make sure you set the parser to Nagios, and make sure you pass the device name to your command, eg. /opt/zenoss/scripts/zenoss-tds.sh ${devname}. Click Save, and then add DataPoints at the bottom.

When you create the DataPoints, remember to set the correct Type. Since most of the metrics in TDS zero themselves when you restart the server, then COUNTER is probably the most appropriate.

Once you have done that then you can go back to the template and add graph definitions. Then you can attach the appropriate data point to the graph.

3. See your Graph Loveliness

Lastly you need to bind your new template to the device class. You do that in the templates tab again. Remember to hold down the control key or you will deselect all the other templates in use here.

If you have not already done so, you can put a device in to that class and odel. You should start to see data for the metrics you are collecting.


Monitoring using zencommands

Nagios Plugin Output

And thanks to Dan for his help too.


Confiuraing Samba as a member Server in a Windows Domain

I found myself pulling this all together from various places. I actually did it a couple years back so somebody else may have put up a better howto by now.

The end result here will be a samba server on a Windows domain acting as a member server with all the ACL stuff, etc working.

This was developed on RHEL. I am sure it will work on CentOS with little to no modifications and Debian based distros will need to make some changes.

There are bound to be mistakes and omissions, If you see something wrong then let me know.

Basic Steps

  • Set up kerberos
  • set up ldap
  • set up samba
  • set up nsswitch
  • join the domain
  • set up share
  • set file ACL’s

Packages Requied

  • openldap-clients
  • cyrus-sasl-gssapi
  • krb5-workstation
  • samba
  • acl


Setting this up enables a few things to be possible. In this instance it enables you to generate a keytab file. Then you can use SASL as the lauthentication method when doing LDAP queries against Active Directory. LAter we may talk about setting up PAM for loggin on to the server with your Windows username/password, or creating UPN’s for things like webservers.


  default = FILE:/var/log/krb5libs.log
  kdc = FILE:/var/log/krb5kdc.log
  admin_server = FILE:/var/log/kadmind.log

  default_realm = <YOUR.REALM>
  dns_lookup_realm = true
  dns_lookup_kdc = true
  forwardable = true
  proxiable = true

  <YOUR.REALM> = {
   kdc = <active.directory.server>
   admin_server = <active.directory.server>


This is so that you can get user and group information from active directory. I should point out that the users and groups that will be used for this must have POSIX attributes set up in the objects on the directory.


 base <search base of active directory?
 uri ldap://<active.directory.server>
 referrals no
 ldap_version 3
 bind_policy soft

# "getent passwd" will hang if this isn't set for AD
 sasl_secprops maxssf=0
 use_sasl on rootuse_sasl on
 pam_filter objectclass=user
 pam_password ad

If you want to restrict the search bases for various searches, add lines similar to these in ldap.con.

 nss_base_passwd <search base dn>
 nss_base_shadow <search base dn>
 nss_map_objectclass posixAccount user
 nss_map_objectclass shadowAccount user
 nss_map_objectclass posixGroup group
 nss_map_attribute username uid
 nss_map_attribute homeDirectory unixHomeDirectory


This file needs to be set up to get you on to the Domain and for keytab file creation. LAter, your share definition will go in here too.


   security = ads
    realm = <YOUR.REALM>
    password server =  <active.directory.server>
    username map = /etc/samba/smbusers
    use kerberos keytab = yes
    ldap ssl = yes
    encrypt passwords = true
    use spnego = yes
    obey pam restrictions = no
    invalid users = root


This tells the server which directories to search and in which order when looking for stuff like user or group information. In this situation, we are using LDAP to query AD.


 passwd:     files ldap
 shadow:     files ldap
 group:      files ldap ....
 hosts:      files dns wins

Join the domain

As root:

net -U <user> ads join createupn="HOST/<host>@<YOR.REALM>" createcomputer="<Active/Directory/server/account/container>"

For an explanation of the above commend (because it looks confusing). See this quote from the net man page:

[RPC|ADS] JOIN [TYPE] [-U username[%password]] [createupn=UPN] [createcomputer=OU] [options] Join a domain. If the account already exists on the server, and [TYPE] is MEMBER, the machine will attempt to join automatically. (Assuming that the machine has been created in server manager) Otherwise, a password will be prompted for, and a new account may be created.[TYPE] may be PDC, BDC or MEMBER to specify the type of server joining the domain.

[UPN] (ADS only) set the principalname attribute during the join. The default format is host/netbiosname@REALM.

[OU] (ADS only) Precreate the computer account in a specific OU. The OU string reads from top to bottom without RDNs, and is delimited by a ‘/’. Please note that ‘´ is used for escape by both the shell and ldap, so it may need to be doubled or quadrupled to pass through, and it is not used as a delimiter.

Next create the host keytab file:

net ads kytab create -U <username>

Start things up

chkconfig smb on
servic smb start

Winbind is optional in this configuration. If you do not use it make sure you do not include it for host name resolution in /etc/nsswitch,conf.

chkconfig winbind on
service winbind start


To test user and group resolution over ldap:

getent passwd <user>
getent group <group>

If things are working then you should see AD users and groups as will as local.

If you are using winbind:

wbinfo -u
wbinfo -g

These commands may be unreliable in large domains. Try a couple of times since it may take some time to download the databases.

If all this works, then you can use AD users and groups in file AC:’s

Using the Server

Set up a share


         comment =  some share
         path = /path/to/share
         browseable = yes
         writable = yes

Set the File permissions

We can use AD groups in posix ACL’s to control file and directory access. This allows us to do stuff like set up “default” acl’s that are inherited when a child object is created. Remember that in samba (unless told otherwise) rwx in linux = Full control on windows. That probably is not what a Windows power user expects. AFAIK you cannot yet implement “TAke Ownership” and the other Windows specific File permissions because they do not exiasst in Linux.

in a nutshell:

View ACL by: getfacl file Set using setfacl. One option is to pipe the output of getfacl to a file, edit the file and

setfacl -M < file Or you can use -m to modify the acl inline. Use -R to make the change recursively.


setfacl -R -m default:group::rx  /opt/directory
#generic group permission that is inherited by child. set recursively
setfacl -m user:rhart:rwx /opt/directory/file
#give full control to rhart for the specified file