Community

Zenoss Newsletter
Views

Edit history

Edit: -1 of 1
Time: 2008-09-18 07:29:45
Note: /production/www/portal/public-website/community/manage_importObject

changed:
-
<h1>Scenario</h1>
An in-progress commentary on how to 'bake-in' support for, in this example, an AIX system.  Much of this text was taken from the forum in which an HPUX filesystem's information was gathered.
<p>
AIX and HPUX use vendor extensions to store MIB data, which the default Zenoss collectors don't understand.</p>
<p>Our Zenoss server name is zenoss1</p>


<h1>Overview of how to add support</h1>
<ul>
<li><a href="#add_mib">Add the platform-specific MIB</a> to make it easier to find items to collect SNMP information</li>
<li><a href="#add_device_group">Add a Device organizer for the platform</a> to create a tidy place to store platform-specific information.</li>
<li><a href="#create_zcollectors">Create zCollectorPlugins</a> (aka modelers) to gather information which doesn't change all that often (ie filesystem names)</li>
<li><a href="#create_perf_templates">Create Performance Templates</a> which will be used to gather current usage statistics (eg how full the filesystem is now)</li>
</ul>


<h1><a name="add_mib">Add the platform-specific MIB</a></h1>
<p>If you already have a nice MIB browser, skip this step as the Zenoss facilities are primitive.</p>
<p>Added AIX MIB which is stored in the/usr/lib/samples/snmp/aix.my MIB file with the command</p>
<pre>
     zenmib run $ZENHOME/share/mibs/site/aix.my</pre>
<p>
   Verify that the MIB is in the http://zenoss1:8080/zport/dmd/Mibs mangement page
</p>
<h1><a name="add_device_group">Add a Device organizer for the platform</a></h1>
<p>Add a device class for AIX in /Devices/Server/AIX. From the navigation bar at the left-hand side, go to the 'Classes' section and select 'Devices'.  Then click on Server, which shows you the 'Sub-Devices' screen.  From the 'Sub-Devices' menu, select 'Add New Organizer'.  Provide an id (ie AIX) and hit OK.
</p>

<h1><a name="create_zcollectors">Create zCollectorPlugins</a></h1>
<p>When you navigate to a particular host (ie Device) and then select 'Manage' -> 'Model Device, that runs all of the associated modelers (which are also called zCollectorPlugins).  What we need to do is copy and customize an existing modeler plugin from $ZENHOME/Products/DataCollector/plugins/zenoss/snmp and then add that plugin to our list of plugins that our platform's DeviceClass will use.</p>
<p>We'll start with creating a Filesystem modeler plugin.  We'll copy the HRFileSystemMap plugin and call our plugin AIXFileSystemMap.py.  Using the information in the MIB, we can find the place where it stores the list of filesystems.</p>

<h2>Verify the SNMP connectivity and OIDs</h2>
First, verify that your server's SNMP daemon is functional and that you have the correct SNMP version and credentials.  We'll assume that we're using SNMP version 1 and are using the 'public' community, and that your new host will allow connections from our Zenoss server.
<p>Run the snmpwalk command from the Zenoss monitoring server</p>
<pre>snmpwalk -v1 -c public myaixbox.example.com 1.3.6.1.4.1.2.6.191.1 | head
</pre>
<p>This produces a lot of output that we've truncated to save patience and space.</p>

<pre>
SNMPv2-SMI::enterprises.2.6.191.1.1.1.0 = INTEGER: 5
SNMPv2-SMI::enterprises.2.6.191.1.1.2.0 = ""
SNMPv2-SMI::enterprises.2.6.191.1.1.3.0 = INTEGER: 2
SNMPv2-SMI::enterprises.2.6.191.1.1.4.0 = Gauge32: 0
SNMPv2-SMI::enterprises.2.6.191.1.1.5.0 = INTEGER: 0
SNMPv2-SMI::enterprises.2.6.191.1.1.6.0 = INTEGER: 2
SNMPv2-SMI::enterprises.2.6.191.1.1.7.0 = STRING: "The current used percentage 93 of the file system /mnt  has gon"
SNMPv2-SMI::enterprises.2.6.191.1.1.9.0 = INTEGER: 0
SNMPv2-SMI::enterprises.2.6.191.1.1.10.0 = INTEGER: 0
SNMPv2-SMI::enterprises.2.6.191.1.1.11.0 = INTEGER: 0
</pre>
<p>If you don't see output like the above, nothing else will work.  Find the issue and fix it.</p>
<h3>Frequently Found Hiccups</h3>
Here's a list of some common reasons why snmpwalk may not return any data:
<ul>
<li>The SNMP daemon on the remote system is not running</li>
<li>The SNMP daemon on the remote system has different security credentials than what you're using (ie version 1 vs version 2c, wrong community name)</li>
<li>The SNMP daemon on the remote system only allows connections from certain IP addresses or IP address ranges and the Zenoss server doesn't meet that criteria.</li>
<li>The SNMP daemon on the remote system only allows queries to certain portions of certain MIBs, and you have specified something not allowed by that policy.</li>
<li>The firewall(s) between the Zenoss server and the remote system do not allow UDP or SNMP traffic.</li>
<li>The firewall on the Zenoss server does not allow UDP or SNMP traffic outbound or inbound.</li>
<li>The firewall on the remote system does not allow UDP or SNMP traffic outbound or inbound.</li>
</ul>
<p>As a first sanity check, try the snmpwalk command on the remote host. For example:</p>
<pre>snmpwalk -v1 -c public localhost 1.3.6.1.4.1.2.6.191.1 | head
</pre>

<h2>Testing the plugin</h2>
<p>To test your new modeler plugin, add it to the list of zCollector plugins.  From within the newly-created 'AIX' DeviceClass, click on 'More' --> 'Collector Plugins' to (crossing my fingers) select the appropriate plugin, which should be in the list of items to add.  Failing that, modify the 'zCollectorPlugins' zProperty either through Zenoss or through the Zope back-end.  (To get to the Zope back end, add '/manage' to your Zenoss server's URL.  eg http://zenoss1:8080/zport/dmd/manage)</p>

<a href="plugin_modeler_filesystem">Code for the AIXFileSystemMap modeler plugin</a>

<p>You can test your new plugin by using zenmodeler from the command-line.</p>
<pre>
zenmodeler run -d myaixbox.example.com -v 10
</pre>
<p>For testing purposes, you may want to add this and only this zCollector plugin to one particular host and make it the only plugin.  Any syntax errors or exceptions will be visible so that you can hopefully debug them.</p>
<p>Once you're satisfied that everything is working correctly, verify everything by running the 'Manage' -> 'Model Device' command and then examining the OS tab.  If everything is correct, you'll see your list of filesystems in the Filesystems area, but with 'unknown' for everything except the total size of the filesystems.  The actual usage numbers of the filesystem is collected by a different mechanism -- a performance template.</p>
<p>Keep in mind that a zCollector plugin is run infrequently (eg once a day or once a week, depending on your settings), while a performance template is run every five or ten minutes.</p>

<h1><a href="#create_perf_templates">Create Performance Templates</a></h1>
A performance template gathers the current statistics of items such as the amount of space used in a filesystem.  The data can be collected using either a script or an SNMP command.  For our Filesystem data, we must create a new performance template called 'Filesystem' (this is a special name) that has a Datasource called 'usedBlocks' (another special name).</p>
<p>To create our new performance template, go to the AIX DeviceClass organizer and select 'More' -> 'All Templates'.  This will take you to a screen which shows you the performance templates.  From the menu, select 'Add Tempate...' and provide with an id of 'Filesystem' (yes, there should already be one there, but from the /Devices/Server path).</p>
<p>Click on the newly created performance tempate and add in a nice description.  Then, click in the 'Data Sources' menu and select 'Add DataSource...' to create the special 'usedBlocks' datasource.  If your operating system's MIB provides a 'usedBlocks' (or something named like that) value, then select a type of SNMP.  Otherwise, you need to create a script to take the total size of the filesystem (ie 'totalBlocks') and subtract the 'freeBlocks' value.  Unfortunately, AIX only provides 'freeBlocks', so we need to create a command.</p>
<p>
<a href="#appendix_plugin_code">Code for the plugin</a>
</p>
<h2>Create a Graph</h2>
From the DevlceClass (ie /Devices/Server/AIX), click on the Templates tab.  Click on the template and go to the 'Graph Definitions' sub-menu.    From that sub-menu, choose 'Add a Graph'.  You will be prompted for the  name of your new graph.  Add the datapoints of interest to create a graph and then click on the 'save' button at the bottom of the screen.   Note that if you're interested in doing something more complicated than just adding datapoints, you'll need to start browsing the <a href="http://oss.oetiker.ch/rrdtool">RRDtool site</a>.

<h1><a name="appendix">Appendices</a></h1>
<h2><a name="appendix_plugin_code">Plugin code</a></h2>
<pre>
__doc__="""AIXFileSystemMap

This modeler determines the filesystems on the device and updates appropriately.
It is up to the performance template that must be named 'Filesystems' to collect
the actual performance data (eg free/available blocks).
"""

import re

from Products.ZenUtils.Utils import unsigned
from CollectorPlugin import SnmpPlugin, GetTableMap
from DataMaps import ObjectMap

class AIXFileSystemMap(SnmpPlugin):

    maptype = "FileSystemMap"
    compname = "os"
    relname = "filesystems"
    modname = "Products.ZenModel.FileSystem"
    deviceProperties =  \
      SnmpPlugin.deviceProperties + ('zFileSystemMapIgnoreNames',)

    #
    # These column names are for the aixFsTable from the
    #  /usr/samples/snmpd/aixmib.my MIB file located on your AIX hosts.
    # (It's in the bos.net.tcp.adt fileset.)
    #
    columns = {
         '.1': 'snmpindex', # aixFsIndex
         '.2': 'storageDevice', # aixFsName
         '.3': 'mount', # aixFsMountPoint
         '.4': 'type', # aixFsType
         '.5': 'totalBlocks', # aixFsSize - a value in MB

#
# Comment out the following entries to reduce the amount
# of stuff that we need to send.  They are listed here
# for reference and completeness.
#
#         '.6': 'aixFsFree',
#         '.7': 'aixFsNumINodes',
#         '.8': 'aixFsUsedInodes',
#         '.9': 'aixFsStatus',
#         '.10': 'aixFsExecution',
#         '.11': 'aixFsResultMsg',
         }

    snmpGetTableMaps = (
        GetTableMap('aixFsTable', '.1.3.6.1.4.1.2.6.191.6.2.1', columns),
    )

    #
    # This table is included for reference
    #
    aixFsType = {
         1: 'jfs',
         2: 'jfs2',
         3: 'cdrfs',
         4: 'procfs',
         5: 'cachefs',
         6: 'autofs',
         7: 'afs',
         8: 'dfs',
         9: 'nfs',
         10: 'nfs3',
         11: 'other',
    }

    def process(self, device, results, log):
        """Gather data from the standard AIX snmpd + friends"""

        log.info('processing %s for device %s', self.name(), device.id)
        getdata, tabledata = results

        #
        # Gather the data using SNMP and just exit if there's an SNMP
        # issue.  If we don't, the filesystem table in Zenoss will get
        # wiped out.  Ouch!
        #
        fstable = tabledata.get( "aixFsTable" )
        if not fstable:
            log.warn('No SNMP response from %s for the %s plugin', device.id, self.name() )
            return

        skipfsnames = getattr(device, 'zFileSystemMapIgnoreNames', None)
        maps = []
        rm = self.relMap()
        for fs in fstable.values():
            if not fs.has_key("totalBlocks"):
               continue # Ignore blank entries

            if not self.checkColumns(fs, self.columns, log):
               continue

            #log.info( "Found %s", fs['mount'] )
            #
            # Ensure that we only check on local disk
            # NB: it may make sense to report on AFS/DFS volumes....
            #
            fstype = self.aixFsType.get( fs['type'], None)
            if fstype not in ( 'jfs', 'jfs2' ):
               continue

            if fs['totalBlocks'] > 0 and (not skipfsnames or not re.search(skipfsnames,fs['mount'])):
                om = self.objectMap(fs)

                #
                # The internal id that Zenoss uses can be used in URLs, while
                # Unix filesystem names cannot.  Map to an URL-safe name.
                #
                om.id = self.prepId(om.mount)

                #
                # Map our MIB data to what Zenoss expects
                #
                om.blockSize = 1024**2; # ie MB

                rm.append(om)
        maps.append(rm)

        #
        # As a final sanity check, see if we found anything.  If we
        # didn't find anything, that's probably an error so just return.
        #
        if len(maps) == 0:
           log.warn( "No filesystems found by %s for %s", self.name(), device.id)
           return

        return maps
</pre>