# Appendix C

| # Module Building Tutorial

> This appendix provides a tutorial describing how to build a module.

> It covers the following topics:

- Module Example--page 589
- Steps to Create a Module--page 589

## Module Example

> An example module that monitors the size of a file is described here to illustrate the module construction process. The functionality of the module is simplified to demonstrate the creation of a simple module prototype. Enhanced versions of the module example are then described. The process of the module example is:

1. Monitor the size of the `/var/adm/wtmp` file using UNIX `ls` command.
2. Monitor file size using Tcl file command.
3. Parameterize filename so that any file can be monitored.
4. Add SNMP table management capabilities to monitor more than one file.

## Steps to Create a Module

> Creating a module consists of creating the definition files that describe the module and writing whatever code is required to perform the data acquisition and alarm checking.

> This process comprises:

- Naming the Module
- Creating a Data Model
- Realizing the Model
- Specifying Alarm Management Information

## `filesize` Module Version 1--Simple Prototype

> To simplify the implementation of the module, it is assumed that the module will always monitor the size of the system file `/var/adm/wtmp`.

### Naming the Module

> The first step is to name the module and create the parameter file for the module. By convention, the names of the definition files are based on the module name.

> The example module to monitor the size of the file `/var/adm/wtmp` can be called filesize. The associated parameter file then must be named `filesize-m.x` and contain the following entries:

> CODE EXAMPLE C-1 Example Parameter File (`filesize-m.x`)

>     [ load default-m.x ]

>     consoleHint:moduleParams(param) = module i18nModuleName \
>     i18nModuleDesc version enterprise i18nModuleType

>     param:module        = filesize
>     param:moduleName    = File Size Monitoring
>     param:version       = 1.0
>     param:console       = filesize
>     param:moduleType    = localApplication
>     param:enterprise    = halcyon
>     param:location = .iso.org.dod.internet.private.enterprises \
>     .halcyon.primealert.modules.filesize
>     param:oid           = 1.3.6.1.4.1.1242.1.2.91
>     param:desc          = An example module that monitors the size \
>     of /var/adm/wtmp.

>     param:i18nModuleName  = base.modules.filesize:moduleName
>     param:i18nModuleType  = base.modules.filesize:moduleType
>     param:i18nModuleDesc  = base.modules.filesize:moduleDesc

>     ?param:i18nModuleName?i18n = yes
>     ?param:i18nModuleType?i18n = yes
>     ?param:i18nModuleDesc?i18n = yes

### Creating a Data Model

> Creating the data model is the most important step in the module construction process. This step involves identifying the components and properties of the managed entity that are to be included in the data model. These components and properties then must be organized in a tree hierarchy. The data model is specified in a model file.

> > Note - The data model does not need to contain every component and property of the managed entity. It only needs to contain the information that is pertinent to the determination of the status of the entity. Additional information about the entity can be included at the discretion of the module developer.

> In the data model of the `wtmp` file, the managed object is simply the file. Managed properties of the file can include such items as its name, inode, size, last modification date, contents, and so forth. To simplify this example, the data model includes the file size as its only managed property. The size is represented by an INTHI primitive data type, which implies that its value is an integer and is capable of performing alarm checks against high limits.

> The relationship between the managed object and property is specified in the model file:

> CODE EXAMPLE C-2 Example Model File `(filesize-models-d.x)`

>     type = reference

>     file = { [ use MANAGED-OBJECT ]
>          mediumDesc             = File
>          consoleHint:mediumDesc = base.modules.filesize:file

>          size = { [ use MANAGED-PROPERTY INTHI ]
>               shortDesc  = size
>               mediumDesc = file size
>               fullDesc   = Size of file
>               units      = bytes

>               consoleHint:mediumDesc = base.modules.filesize:file.size
>               consoleHint:i18nunits  = base.modules.filesize:units.bytes
>          }
>     }

> The contents of the corresponding Properties File is shown below:

> CODE EXAMPLE C-3 Example Properties File (`filesize.properties)`

>     moduleName=filesize
>     moduleType=localApplication
>     moduleDesc=An example module that monitors the size of \
>     /var/adm/wtmp.

>     file=File
>     file.size=file size

>     units.bytes=bytes

### Realizing the Model

> After the data model has been defined, it is realized by instantiating it in the context of a module and adding data acquisition mechanisms.

> For the example, the size of the `wtmp` file is computed by running the UNIX commands `ls -l /var/adm/wtmp | awk '{print $5}'` in a shell context. The execution of these commands is facilitated by the shell service (`_services.sh`), which provides a mechanism to run commands in a shell context.

> The commands `refreshService, refreshCommand`, and `refreshInterval,` are specified in the `wtmp` object to define the means and the frequency at which the datais acquired. The file object is set to an active node type to enable it, periodically, to acquire data. `
> `

> CODE EXAMPLE C-4 Example Agent File (`filesize-d.x`)

>     [ use MANAGED-MODULE ]
>     [ load filesize-m.x ]
>     [ requires template filesize-models-d ]
>     _services = { [ use SERVICE ]
>         #
>         # Standard Bourne Shell
>         #
>         sh = {
>             command = "pipe://localhost//bin/sh;transport=shell"
>             max             = 2
>         }
>     }
>     initInterval = 0
>     file = { [ use templates.filesize-models-d.file ]
>          type = active
>          refreshService = _services.sh
>          refreshCommand = ls -l /var/adm/wtmp | awk '{print $5}'
>          refreshInterval = 60
>     }
>     [ load filesize-d.def ]

### Specifying Alarm Management Information

> This step involves the specification of default alarm criteria and actions for managed properties. Alarm checks are performed every time the property value is computed. The alarm criteria that can be specified is dependent on the primitive data types used to represent the property.

> In the `filesize` example, the size property is an INTHI data type; consequently, high alarm limits can be specified.

> CODE EXAMPLE C-5 Example Alarm File (`filesize-d.def`)

>     file = {
>          size = {
>              alarmlimit:error-gt = 2000000
>              alarmlimit:warning-gt = 1500000
>          }
>     }

## `filesize` Module Version 2--Improving DAQ Mechanism

> Alternatively, the size can be computed more efficiently in C and integrated with the agent in the form of a Tcl package. The migration of functionality from scripts to C is described in the chapter of this document entitled "Binary Extensions and Packages".

> For the `filesize` module example, a Tcl command extension for obtaining file statistics already exists. The Tcl file command can be used to get the size of a file in bytes. The agent file is modified to use the Tcl file command in place of the UNIX ls command.

> > Note - The refreshService must also be set to _internal to facilitate the execution of the Tcl file command.

> Since the module MIB is modified in new version of the module, it is safe to release the new version of the module with the same module name and MIB location.

> CODE EXAMPLE C-6 Example Parameter File (`filesize-m.x`)

>     [ load default-m.x ]

>     consoleHint:moduleParams(param) = module i18nModuleName \
>     i18nModuleDesc version enterprise i18nModuleType

>     param:module        = filesize
>     param:moduleName    = File Size Monitoring
>     param:version       = 2.0
>     param:console       = filesize
>     param:moduleType    = localApplication
>     param:enterprise    = halcyon
>     param:location      = .iso.org.dod.internet.private.enterprises
>     \ .halcyon.primealert.modules.filesize
>     param:oid           = 1.3.6.1.4.1.1242.1.2.91
>     param:desc          = An example module that monitors the size \
>     of /var/adm/wtmp.

>     param:i18nModuleName  = base.modules.filesize:moduleName
>     param:i18nModuleType  = base.modules.filesize:moduleType
>     param:i18nModuleDesc  = base.modules.filesize:moduleDesc

>     ?param:i18nModuleName?i18n = yes
>     ?param:i18nModuleType?i18n = yes
>     ?param:i18nModuleDesc?i18n = yes

> CODE EXAMPLE C-7 Example Agent File (`filesize-d.x)`

>     [ use MANAGED-MODULE ]
>     [ load filesize-m.x ]
>     [ requires template filesize-models-d ]
>     initInterval = 0
>     file = { [ use templates.filesize-models-d.file ]
>         type = active
>         refreshService = _internal
>         refreshCommand = file size /var/adm/wtmp
>         refreshInterval = 60
>     }

>     [ load filesize-d.def ]

## `filesize` Module Version 3--Adding Parameters to File Name Specification

> This example illustrates how to allow any file to be monitored by the module. This enhancement will allow the module to have multiple instances in order to monitor multiple files.

> As in version 2 of the module, the new version does not modify module MIB, so the new version can be released with the same module name and location.

> Instance parameters must be added to parameter file to support the multiple instantiation of the module. In addition, entries for the file name parameter must be added so that the Sun Management Center console user is queried for this information when the module is loaded.

> CODE EXAMPLE C-8 Example Parameter File (`filesize-m.x`)

>     [ load default-m.x ]

>     consoleHint:moduleParams(param) = module i18nModuleName
>     i18nModuleDesc version enterprise i18nModuleType instance
>     instanceName i18nFilename

>     param:module        = filesize
>     param:moduleName    = File Size Monitoring
>     param:version       = 3.0
>     param:console       = filesize
>     param:moduleType    = localApplication
>     param:enterprise    = halcyon
>     param:location      =
>     .iso.org.dod.internet.private.enterprises.halcyon.primealert.mod
>     ules.filesize
>     param:oid           = 1.3.6.1.4.1.1242.1.2.91
>     param:desc          = An example module that monitors filesize

>     param:i18nModuleName  = base.modules.filesize:moduleName
>     param:i18nModuleType  = base.modules.filesize:moduleType
>     param:i18nModuleDesc  = base.modules.filesize:moduleDesc
>     ?param:i18nModuleName?i18n = yes
>     ?param:i18nModuleType?i18n = yes
>     ?param:i18nModuleDesc?i18n = yes

>     param:i18nFilename =
>     ?param:i18nFilename?description = base.modules.filesize:filename
>     ?param:i18nFilename?access      = rw

>     param:instance     =
>     param:instanceName =
>     ?param:instance?description = base.modules.default:instance
>     ?param:instance?reqd        = yes
>     ?param:instance?format      = instance
>     ?param:instanceName?description =
>     base.modules.default:description
>     ?param:instanceName?reqd        = yes

> The refresh command must be modified to reference the filename parameter instead of simply monitoring `/var/adm/wtmp`.

> CODE EXAMPLE C-9 Example Agent File (`filesize-d.x`)

>     [ use MANAGED-MODULE ]
>     [ load filesize-m.x ]
>     [ requires template filesize-models-d ]

>     consoleHint:mediumDesc = base.modules.filesize:moduleDetail

>     initInterval = 0

>     file = { [ use templates.filesize-models-d.file ]
>         type = active
>         refreshService = _internal
>         refreshCommand = file size %i18nFilename
>         refreshInterval = 60
>     }

>     [ load filesize-d.def ]

> The instance values must be internationalized.

> The corresponding changes to the properties file are:

> CODE EXAMPLE C-10 Example Properties File (`filesize.properties`)

>     moduleName=filesize
>     moduleType=localApplication
>     moduleDesc=An example module that monitors filesize

>     filename=File Name
>     moduleDetail=filesize [{0}]
>     file=File
>     file.size=file size
>     units.bytes=bytes

## `filesize` Module Version 4--Adding SNMP Table Management Capabilities

> The previous versions of this module were limited monitoring the size of a single file. To monitor the size of more than one file, the module needed to be loaded multiple times. Version four of the module can monitor one or more files in a single module instance. To do this, SNMP table management capabilities are added.

> In this version of the module, the module MIB must be changed. The most significant change is the introduction of a SNMP table to support the monitoring of multiple files. As a result, the new version of this module must be released with a new module name and MIB location.

### Module Name

> To distinguish this version of the module from previous versions, the module name has been modified. The subspec table is added to indicate that multiple files can be monitored, and the module name becomes filesize-table. This version of the module does not support multiple instantiation. However, this feature can be added in a similar manner as before. The associated parameter file is shown below. Differences between this version and previous versions are in bold.

> CODE EXAMPLE C-11 Example Parameter File (`filesize-table-m.x`)

>     [ load default-m.x ]

>     consoleHint:moduleParams(param) = module i18nModuleName \
>     i18nModuleDesc version enterprise i18nModuleType

>     param:module        = filesize-table
>     param:moduleName    = File Size Monitoring (Table)
>     param:version       = 1.0
>     param:console       = filesize-table
>     param:moduleType    = localApplication
>     param:enterprise    = halcyon
>     param:location      = .iso.org.dod.internet.private.enterprises\
>     .halcyon.primealert.modules.filesizetable
>     param:oid           = 1.3.6.1.4.1.1242.1.2.92
>     param:desc          = An example module that monitors the size \
>     of multiple files.

>     param:i18nModuleName  = base.modules.filesize-table:moduleName
>     param:i18nModuleType  = base.modules.filesize-table:moduleType
>     param:i18nModuleDesc  = base.modules.filesize-table:moduleDesc

>     ?param:i18nModuleName?i18n = yes
>     ?param:i18nModuleType?i18n = yes
>     ?param:i18nModuleDesc?i18n = yes

> Modifying the Model

> To support the monitoring of multiple files, the single managed property size must be made part of a SNMP table with other managed properties. The additional managed properties are:

- rowstatus - this node is required for SNMP management of tables
- instance - this node is used as the index for each row of the table
- name - the node is used to store the names of the files being monitored

> The complete model file is shown below.

> CODE EXAMPLE C-12 Example Model File (`filesize-table-models-d.x)`

>     type = reference
>     initInterval = 0
>     file = { [ use MANAGED-OBJECT ]
>          mediumDesc             = File
>          consoleHint:mediumDesc = base.modules.filesize-table:file
>          fileTable = { [ use MANAGED-OBJECT-TABLE ]
>              mediumDesc             = File Table
>              consoleHint:mediumDesc = base.modules.filesize-table:file.fileTable

>              fileEntry = { [ use MANAGED-OBJECT-TABLE-ENTRY ]
>                  mediumDesc             = File Entry
>                  consoleHint:mediumDesc = base.modules.filesize-
>     table.file.fileTable.fileEntry

>                  index = instance
>                  rowstatus = { [ use ROWSTATUS MANAGED-PROPERTY ]
>                      mediumDesc             = Row Status
>                      consoleHint:mediumDesc = base.modules.filesize\
>     -table:file.fileTable.fileEntry.rowstatus
>                      consoleHint:hidden     = true
>                  }
>                  instance = { [ use STRING MANAGED-PROPERTY ]
>                      mediumDesc             = File Instance
>                      consoleHint:mediumDesc = base.modules.filesize\
>     -table:file.fileTable.fileEntry.instance

>     name = { [ use STRING MANAGED-PROPERTY ]
>                      mediumDesc             = File Name
>                      consoleHint:mediumDesc = base.modules.filesize\
>     -table:file.fileTable.fileEntry.name
>                      required               = true
>                  }
>                  size = { [ use INTHI MANAGED-PROPERTY ]
>                       shortDesc  = size
>                       mediumDesc = file size
>                       fullDesc   = Size of file
>                       units      = bytes

>     consoleHint:mediumDesc = base.modules.filesize-\
>     table:file.fileTable.fileEntry.size
>      consoleHint:i18nunits  = base.modules.filesize-\
>     table:units.bytes
>     				}
>     			}
>     	}
>     }

### Realize the Modified Model

> The agent file for this version of the module contains a number of differences from the previous versions. These changes are:

- Adhoc commands are added to support the addition and removal of rows using the Sun Management Center console.
- A Procedure File which defines the refresh command as well as other procedures.
- `setrowActions` are defined for `createAndGo`, `createAndWait`, and `destroy` states. Both the `createAndGo` and `createAndWait` actions simply call a Tcl procedure that triggers a refresh and issues a SNMP trap when it is done. This trap allows the Sun Management Center console to refresh the data immediately. The `destroy` action calls a Tcl procedure `removeEntry` which is defined in the `Procedure` File.
- The `instance` node is given the operational type of derived. This is done so that data is not cascaded into it from the refresh command.

  CODE EXAMPLE C-13 Example Agent File (`filesize-table-d.x`)

      [ use MANAGED-MODULE ]
      [ load filesize-table-m.x ]
      [ requires template filesize-table-models-d ]

      _procedures = { [ use PROC ]
          [ source filesize-table-d.prc ]
      }
      initInterval = 0
      file = { [ use templates.filesize-table-models-d.file _procedures
      ]
           type            = active
           refreshService  = _internal
           refreshCommand  = getFileSizes
           refreshInterval = 300

           fileTable = {
               fileEntry = {

      	consoleHint:tableHeaderCommands = addrow
                   consoleHint:tableCommands = addrow unload

                   consoleHint:commandLabel(addrow) = \
      base.console.ConsoleGeneric:tableRow.addPopup
                   consoleHint:commandSpec(addrow) = launchUniqueDialog
      %windowID .templates.tools.rowadder objectUrl=snmp://
      %targetHost:%targetPort/mod/filesize-table/file/fileTable/
      fileEntry#%targetFragment

                   consoleHint:commandLabel(unload) =
      base.console.ConsoleGeneric:tableRow.deletePopup
                   consoleHint:commandSpec(unload) =
      requestTableRowOperation %windowID snmp://
      %targetHost:%targetPort/mod/filesize-table/file/fileTable/
      fileEntry/rowstatus#%targetFragment unload

                   rowstatus = {
                       setrowActions(createAndGo)   = refresh
                       setrowActions(createAndWait) = refresh
                       setrowActions(destroy)       = remove
             setrowService() = file

                       setrowCommand(refresh) = refreshValueAndTrap
             setrowCommand(remove)  = removeEntry %rowname
      			}
       instance = {
                       type = derived
                   }
      	name = {
                       access = rw
                   }

                   size = {
                       defaultvalue = 0
                   }
              }
          }
      }
      [ load filesize-table-d.def ]

> CODE EXAMPLE C-14 Example: Procedure File (`filesize-table-d.prc`)

>     #
>     # Tcl proc for refreshCommand
>     #
>     # This procedure gets the list of filenames in the table and
>     determines the size of each file (in bytes) using the Tcl file
>     command. A list of filename and file size is returned.
>     #
>     proc getFileSizes {} {
>         #
>         # initialize result
>         #
>         set result ""
>         #
>         # get list of all filenames
>         #
>         set files [ toe_send [ locate fileTable*name ] getValues ]

>         #
>         # loop through each file and determine file size
>         # append filename and filesize to result
>         #
>         foreach file $files {
>             set filesize [ file size $file ]
>             set result "$result $file $filesize"
>         }

>         return $result
>     }
>     #
>     # Tcl proc for removing a row
>     #
>     proc removeEntry { name } {
>         #
>         # clear any alarm status and editable parameters (limits,
>         # status command, and acks) associated with this row
>         #
>         set tableObject [ locate fileTable.fileEntry ]
>         if { $tableObject != "" } {
>     toe_send $tableObject cleanupRow $name CLEAR_PARMS
>         }
>         refreshValueAndTrap
>         return [ list "$name Entry Removed" ]
>     }

> CODE EXAMPLE C-15 Properties File (`filesize-table.properties)`

>     moduleName=File Size Monitoring (Table)
>     moduleType=localApplication
>     moduleDesc=An example module that monitors the size multiple
>     files.

>     file=File
>     file.fileTable=File Table
>     file.fileTable.fileEntry=File Entry

>     file.fileTable.fileEntry.rowstatus=Row Status
>     file.fileTable.fileEntry.instance=File Instance
>     file.fileTable.fileEntry.name=File Name
>     file.fileTable.fileEntry.size=File Size

>     units.bytes=bytes

### Alarm Management

> The alarm file is modified to take into account the new model that is used.

> CODE EXAMPLE C-16 Example Alarm File (`filesize-table-d.def`)

>     file = {
>          fileTable = {
>              fileEntry = {
>                  size = {
>                      alarmlimit:error-gt() = 2000000
>                      alarmlimit:warning-gt() = 1500000
>                  }
>              }
>          }
>     }

Copyright © 2000 Sun Microsystems, Inc. All Rights Reserved.