Solaris System Management Agent Developer's Guide

Chapter 2 Creating Modules

This chapter provides basic guidelines for creating System Management Agent modules. The chapter includes a process you can use to implement a MIB as a module in System Management Agent. Guidelines for naming components of your implementation to avoid conflicts are also included.

The following topics are discussed:

About Modules

The term module as used in this manual has two closely related meanings. Module refers generically to the “container” of the new pieces of management data that the developer needs to inform the agent about. In this sense, a module is an abstract concept.

However, an abstract module must be represented as a shared object file, which runs on a managed system. The shared object file, or the associated program, is often referred to as a module. Therefore, a module can be defined as a C program that works with the SMA to manage additional resources.

All modules communicate through the API library functions. The API functions are used whether the modules are compiled in the agent, or loaded dynamically, or running in a separate subagent.

Overview of Creating Modules

You can create modules for the System Management Agent to allow a specific application, device, system, or network to be managed through a management application. The System Management Agent includes and documents the functions that are required by a module. The functions are used to register a module with the agent, to handle requests for module data, and to perform other module tasks.

You are not required to code a module manually, although you can if you prefer. Refer to the http://www.net-snmp.org/ web site for information about writing a module manually. The process is outside the scope of this document.

The high-level process described in this manual for implementing a module is as follows:

  1. Define the MIB for the objects to be managed.

    To define a MIB, you must know what management data is associated with the system or entity to be managed. You must assign variable names to each discrete management item. You must also determine the attributes and ASN.1 data types. MIB definition is outside the scope of this manual. See Defining a MIB for more information about MIBs.

  2. Generate code templates for a module from the MIB.

    To generate code templates, you convert the MIB nodes into C source code files with the mib2c tool. The code templates include API functions for registering the data, and handling the requests for the data. See Generating Code Templates for more information.

  3. Modify the code templates to fill in the data collection and management portions of the module.

    To modify the code templates, you must determine how to implement much of the functionality of the agent. See Modifying Code Templates for more information.

  4. Compile the C files into a shared object file.

    You compile a module for the System Management Agent as you would compile any C shared object file.

  5. Decide on the deployment method and configuration of the module.

    You must determine whether to configure the module as a separate subagent, or to load the module dynamically into the SNMP agent. See Chapter 6, Deploying Modules for information about deployment.

Defining a MIB

MIB definition is one of the more time-consuming steps of creating a module. MIB syntax can be quite complicated, and is outside the scope of this document. Refer to Related Reading for suggestions of other sources of information about MIB syntax.


Tip –

The mib2c tool, used for converting MIBs to C code, includes error checking for MIB syntax. You can use mib2c to check your MIB syntax as you create your MIB, even before you are ready to convert the MIB.


You should consider using one of the standard MIBs that are included with the SMA as a model for creating your MIB. The /etc/sma/snmp/mibs directory contains all the standard MIBs supported by the SMA.

The following MIBs can be used as examples to emulate because the MIBs have been found to work well with mib2c:


Tip –

Pay particular attention to the name that is assigned for the MODULE-IDENTITY. This name should be equal to the MIB file name with the hyphens removed, and in mixed case. For example, SUN-SEA-EXTENSIONS-MIB.txt uses sunSeaExtensionsMIB for the MODULE-IDENTITY. A MIB file that does not use this format might not work with mib2c.


The file NET-SNMP-EXAMPLES-MIB.txt is also included in the /etc/sma/snmp/mibs directory, and might be helpful in explaining how to define a variety of MIB variable types.

MIB File Names

You must ensure unique names for your MIB files. All custom MIBs to be used with SMA are in the same namespace as the standard MIBs, even if you keep the custom MIBs in a separate directory. Most of the MIBs derived from RFCs have RFC numbers in their names to clearly identify the MIBs, and ensure unique names. Other MIBs follow naming conventions, which decrease the chances of duplicate names.

MIBs are usually named with the following conventions:

A sample name that uses these conventions is ACME-ROUTER-MIB.txt.

Setting MIB Environment Variables

You should set the MIBS and MIBDIRS environment variables to ensure that the tools that use the MIBs can find and load your MIB file. Tools that use the MIBs include mib2c and all the snmp commands such as snmpget, snmpwalk, and snmpset.

Set the MIBS environment variable to include the MIB file that you are using. For example, to add a MIB called MYTESTMIB.txt to the list of MIBs, use one of the following commands:

In the csh or tcsh shells:


% setenv MIBS +MYTESTMIB

In the sh or bash shells:


# MIBS=+MYTESTMIB;export MIBS

These commands add your MIB to the list of default MIB modules that the agent supports.

The default search path for MIB files is /etc/sma/snmp/mibs. You can modify the MIB search path by setting the MIBDIRS variable. For example, to add the path /home/mydir/mibs to the MIB search path, type the following commands:

In the csh or tcsh shells:


% setenv MIBDIRS /home/mydir/mibs:/etc/sma/snmp/mibs
% setenv MIBS ALL

In the sh or bash shells:


# MIBDIRS=/home/mydir/mibs:/etc/sma/snmp/mibs
# export MIBDIRS
# MIBS=ALL;export MIBS

Setting MIBS to ALL ensures that mib2c finds all MIBs in the search location for MIB files. Both the MIB files to be loaded and the MIB file search location can also be configured in the snmp.conf file. See the snmp.conf(4)man page for more information.


Note –

You should avoid copying your MIBs into the /etc/sma/snmp/mibs directory. That directory should be reserved for the MIBs provided with SMA.


Generating Code Templates

You use the mib2c tool to generate C header files and implementation files from your MIB. You can use the generated C files as templates for your module. You can modify the templates appropriately for your purposes, and then use the templates to make your module. Before the file generation begins, mib2c tests your MIB node for syntax errors. Any errors are reported to standard output. You must fix any syntax errors before the code can be generated. This error-checking ability enables you to use mib2c as you create your MIB to ensure that the MIB syntax is correct.


Note –

Be sure to set your MIB environment variables as described in Setting MIB Environment Variables before you use mib2c.


The mib2c command must be run against nodes in the MIB, not on the entire MIB at once. You do not need to specify the MIB name, but the MIB file must be located in a directory on your MIB search path. On the mib2c command line, you must specify a configuration file and the name of one or more MIB nodes. The configuration file must matches the type of data in the MIB node. The command must use the following format:


mib2c -c configfile MIBnode [MIBnode2 MIBnode3 ...]

For example, if you have one node that is called scalarGroup in your MIB, you could use the following command to generate the code templates:


% mib2c -c mib2c.scalar.conf scalarGroup

The files scalarGroup.h and scalarGroup.c are generated.

If your MIB contains both scalar and table data, you should run mib2c separately on the MIB nodes for each type of data. You specify the appropriate configuration file for each type of data.

The following table lists the mib2c configuration files. The table describes the purpose of each configuration file, to help you decide which configuration file to use for your data.

Table 2–1 Configuration Files for Use With mib2c Tool

mib2c Configuration File

Purpose 

mib2c.scalar.conf

For scalar data, including integers and non-integers. This configuration file causes mib2c to generate handlers for the scalar objects in the specified MIB node. Internal structural definitions, table objects, and notifications in the MIB are ignored.

mib2c.int_watch.conf

For scalar integers only. When you use this configuration file, mib2c generates code to map integer type scalar MIB objects to C variables. GET or SET requests on MIB objects subsequently have the effect of getting and setting the corresponding C variables in the module automatically. This feature might be useful if you want to watch, or monitor, the values of certain objects.

mib2c.iterate.conf

For tables of data that are not kept in the agent's memory. The tables are located externally, and the tables need to be searched to find the correct row. When you use this configuration file, mib2c generates a pair of routines that can iterate through the table. The routines can be used to select the appropriate row for any given request. The row is then passed to the single table handler routine. This routine handles the rest of the processing for all of the column objects, for both GET and SET requests.

mib2c.create-dataset.conf

For tables of data that are kept in the agent's memory. The table does not need to be searched to find the correct row. This configuration file causes mib2c to generate a single handler routine for each table. Most of the processing is handled internally within the agent, so this handler routine is only needed if particular column objects require special processing.

mib2c.array-user.conf

For tables of data that are kept in the agent's memory. The data can be sorted by the table index. This configuration file causes mib2c to generate a series of separate routines to handle different aspects of processing the request. As with the mib2c.create-dataset.conf file, much of the processing is handled internally in the agent. Many of the generated routines can be deleted if the relevant objects do not need special processing.

mib2c.column_defines.conf

To create a header file that contains a #define for each column number in a MIB table.

mib2c.column_enums.conf

To create a header file that contains a #define for each enum of common values used by the columns in a MIB table.

The mib2c(1M) man page includes more details about using the mib2c tool. You should also see Chapter 3, Data Modeling for more examples of using mib2c.

Modifying Code Templates

The code templates that are generated by mib2c include code that registers the OIDs for the MIB data and handles the requests for the data. The init_module routine in the mibnode.c template provides the basic code for data retrieval. You must modify the templates to provide the data collection and data management, or instrumentation, of your module. See init_module Routine for information about modifying the initialization routine.

The following table shows where to find more information about how to do various types of data collection.

Table 2–2 Data Collection Documentation

Type of data 

Reference 

Scalar objects 

Scalar Objects

Simple tables 

Simple Tables

General tables 

General Tables

Long running 

Chapter 8, Long–Running Data Collection

Configuring the Module

Configuration of the module depends partly on the module. You can provide automatic configuration as part of the installation process for your module. Alternatively, you can provide the steps and suggestions as part of the end user documentation. If you want users to be able to set configuration parameters for your module, you can store configuration parameters in a configuration file. The parameters can then be retrieved by the module whenever the module starts. See Chapter 4, Storing Module Data for information.

For any module, you must decide whether to run the module as a subagent or a dynamically loading module. See Chapter 6, Deploying Modules for more information.

Delivering the Module

When the module code is complete, you must decide how to deliver the module. If you are creating a module that must be distributed and then be installed, you should use the operating system's native software delivery model. For the Solaris operating system, you should use packages as described in the Application Packaging Developer’s Guide.

Namespace Issues

This section explains the naming conventions for the System Management Agent. The conventions are required to enable all developers to avoid namespace collisions.

Avoiding Namespace Collisions

Namespace is a term used to indicate the complete set of possible names that can exist together in a certain “space.” Namespaces exist in the computer world and in the real world. For example, the names of people in a group, such as the passenger list in an aircraft, forms a namespace. In the computer world, a namespace might be a list of file names in a directory, or the function names in a source code file.

A namespace usually requires names to be unique, to ease the addressing of an individual entity. In the real world, the names of entities in a namespace might not always be unique. For example, there might be two aircraft passengers with the same name. In such situations, an attribute other than the name of the entities of the namespace must be used. For example, the seat numbers might form the namespace of the passengers on the aircraft.

The namespaces in the computing world mandate that uniqueness is ensured. For example, you must have unique names for all the files in a directory or functions that are part of the same program.

Namespace collision occurs if parts of the namespace delivered by different people have the same names. For example, two vendors might come up with the same library name and install in the same directory. A recent trend is to make the directory name part of the namespace, to ensure different directories for different vendors or different products. Even if the file names are the same, the file names are in different directories.

For the SMA developer, several areas are susceptible to namespace collisions. The following sections discuss naming conventions that you must follow to greatly reduce the possibility of having naming issues.

Module Names

The module name should be based closely on the name of the MIB that is implemented by the module. MIB name guidelines are discussed in MIB File Names.

Use the following guidelines to name your module, beginning with the name of the MIB file:

For example, if your MIB name is ACME-ROUTER-MIB.txt, you should name the module acmerouter. When you compile, the shared object that results is acmerouter.so.

Library Names

You must ensure unique names for your custom libraries because all libraries to be used with SMA are delivered into a single lib namespace. You should observe the following guidelines in naming your libraries:

For example, assume that your MIB name is ACME-ROUTER-MIB.txt. Your module name is acmerouter. The associated library should be named libacmerouter.so. The .so extension is added when you compile.