ZenPacks can provide new classes of DataSources by subclassing ZenModel.RRDDataSource.RRDDataSource. If you include only one DataSource class per file, name the modules after the class the contain (ie MyDataSource.py contains the class MyDataSource), and place those modules in the ZenPack's datasources directory then they will automatically be discovered by Zenoss. If you wish to customized this behavior take a look at ZenPack.getDataSourceClasses(). See ZenPacks.zenoss.HttpMonitor and ZenPacks.zenoss.MySqlMonitor for examples of ZenPacks that provide custom DataSource classes.
When creating a custom DataSource class one of the first decisions you have to make is whether you want zencommand to process these DataSources for you or whether you will provide a custom collector daemon to process them. Zencommand is a very versatile mechanism for executing arbitrary commands either on the Zenoss server or on the device being monitored, processing performance data returned by the DataSource and generating events in Zenoss as appropriate. Zencommand expects the command it executes be compatible with the Nagios plug-in API. Specifically two aspects of that API are of most importance:
-
Return code
The command should exit with a return code of 0, 1, 2 or 3. These are described at http://nagiosplug.sourceforge.net/developer-guidelines.html#AEN78
-
Performance data
If the command returns performance data then that data can be pulled into Zenoss by creating DataPoints with the same names used in the command output. The output format is described at http://nagiosplug.sourceforge.net/developer-guidelines.html#AEN203
If you want zencommand to handle instances of your custom DataSource class then several methods in RRDDataSource are of particular insterest:
-
getDescription(self)
This returns a string describing the DataSource instance. This string is displayed next to the DataSource on the RRDTemplate view page.
-
useZenCommand(self)
The default implementation returns False. If you want to use zencommand then override this method and return True.
-
getCommand(self, context, cmd=None)
This returns the string that is the command for zencommand to execute. context is the device or component to be collected. If you need to evaluate TALES expressions in the command to replace things like ${dev/id} and so forth you can call the parent class's getCommand() and pass your command as the cmd argument. (cmd will not be passed into your method, it existis specifically for subclasses to pass their commands to the parent for TALES evaluation.)
-
checkCommandPrefix(self, context, cmd)
Zenoss will check the string you return from getCommand() to see if it is a relative or absolute path to a command. If the string starts with '/' or '$' then Zenoss assumes it is absolute. Otherwise the zProperty zCommandPath from the context is prepended to the cmd string. You can override checkCommandPrefix() if you wish to alter this behavior.
Make sure that your DataSource subclasses also subclass ZenPackPersistence and list it first among the parent classes. See the section on ZenPackPersistence.py for more details.