# Chapter 5

| # Building a Simple Module

> This chapter describes how to build a simple module. It covers the following topics:

- Required Components--page 31
- File Naming Conventions--page 32
- Parameters Specification--page 33
- Internationalizing Modules--page 37
- Data Model Specifications--page 40
- Simple Data Model Realization--page 54

## Required Components

- Module Parameters Specification--Specifying the parameters required by the module. Every module must specify a standard set of parameters and may specify additional parameters, depending on the requirements of the module..
- Data Model Creation--Identifying the components and properties required to model the managed entity. These components and properties are represented using managed object classes and managed properties, respectively, and are organized in tree hierarchy to reflect the hierarchical nature of managed entities.
- Data Model Realization--To realize the data model produced in the previous step, data acquisition mechanisms are integrated with the data models and the models are incorporated into the module framework so that it may be loaded into a Sun Management Center agent.

## File Naming Conventions

> Module definition files adhere to the following naming conventions:

>     <module><-subspec>-<descriptor>.<extension>

> where

> <module> is the module name.
> <subspec> is an optional qualifier for the module name.
> <descriptor> is one of a set of standard descriptors indicating the purpose of the file.
> <extension> is one of a set of standard file extensions indicating the file type.

> By convention, the <module> and <subspec> portions of the filename are common for all files associated with a specific module. This allows related module files to be easily grouped together while eliminating the chances of filename contention with the definition files of other modules.

> -d | Daemon file (Model Realization File)
> -m | Parameter file
> -models-d | Model file

### Standard Extensions

.x | File in module configuration file format

## Parameters Specification

> Module parameters used by Sun Management Center agents are specified in a parameter file. The parameter file specifies the parameters that are required by the module when it is loaded. The contents of this file are also used to provide a form to prompt the user for any required parameters.

> The format is as follows:

>     Format: <module><-subspec>-m.x
>     Example: solaris-example-m.x

| ### Creating a Parameter File

> To create a parameter file, do the following:

| 1. | Specify the mandatory parameters in the parameter file.

|  | Mandatory parameters are listed in the section, "Mandatory Parameters".

| 2. | Identify any additional parameters required by the module and add the appropriate entries to the parameter file.

|  | Additional required parameters are discussed in the section, "Additional Parameters", in Chapter 9.

> This section describes the format and the possible contents of parameter files. A Solaris example parameter file is also provided in the chapter.

### Mandatory Parameters

> The parameter file must always include the following lines:

>     [load default-m.x]
>     consoleHint:moduleParams(param) = module i18nModuleName
>     i18nModuleDesc version enterprise i18nModuleType
>     param:module = <agent filename>
>     param:moduleName = <name of module>
>     param:version = <version number>
>     param:console = <console filename>
>     param:moduleType = <module type>
>     param:enterprise = <module enterprise>
>     param:location = <symbolic oid>
>     param:oid = <numeric oid>
>     param:desc = <module description>

> where:

> The line [ load default-m.x ] loads the descriptions and edit access specifications for all mandatory module parameters. Any parameter definitions that are identical for all modules are placed in the `default-m.x` file, so that they do not have to be specified redundantly in each module parameter file individually. This makes it easy to add new common parameter definitions to all modules in the future, if required.

> consoleHint:moduleParams(param) lists the parameters that are displayed to Sun Management Center console users when the module is to be loaded.

> Additional parameters can be added to this list as required.

> <agent filename> must be the filename of the associated module. Agent file (<module><-subspec>-d.x) without the "-d.x" suffix. If the proper naming conventions are being followed, this is <module><-subspec> in all cases.

> <name of module> is a short string naming the module. This parameter can be used internally by the agent.

> <version number> is the version number of the module and is used internally by the agent. This must be the same as the version used as part of the module name (<module><-subspec>).

> <console filename> must be the same as <agent filename>.

> This field exists for historical reasons, and is not actively used in the Sun Management Center implementation.

> <moduleType> identifies the module category. This value determines where the module is placed in the Sun Management Center console when it is loaded.

> The <moduleType> field must be set to one of the following values:

>     hardware
>     operatingSystem
>     localApplication
>     remoteSystem
>     serverSupport

> > Note - serverSupport modules are not visible in the standard hierarchy view of the agent in the Sun Management Center console. More importantly, modules of this type do not contribute to the overall status of the agent. This module type must be used only for modules that are used internally by the agent. As a result, user must not be a able to load these modules (see the section entitled "Making a Module Not Loadable" for more information).

> <module enterprise> specifies the SNMP enterprise under which this module is loaded. This value must correspond to the enterprise specified in the <location> module parameter.

> <location> specifies the full symbolic OID (from .iso) where the module is to be loaded. The location string must not contain any "-" characters as indicated by RFC 1903.

> <oid> specifies the numeric OID described by the <location> parameter.

> <module description> is a verbose description of the module functionality. This parameter is used when exporting the module MIB during the creation of the module MIB text file.

> > Note - The i18n parameters relate to internationalization and are explained in the section, "Internationalizing Modules".

### Example Parameter File

> The Solaris example module does not require any additional parameters. The Parameter file for the Solaris Example module, `solaris-example-m.x`, is shown below.

>     #
>     # Parameter file for Solaris Example module
>     #
>     [ load default-m.x ]

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

>     param:module     = solaris-example
>     param:moduleName = Solaris Example
>     param:version    = 1.0
>     param:console    = solaris-example
>     param:moduleType = operatingSystem
>     param:enterprise = halcyon
>     param:location   =
>     .iso.org.dod.internet.private.enterprises.halcyon.
>     primealert.modules.solaris.example
>     param:oid        = 1.3.6.1.4.1.1242.1.2.90.1
>     param:desc       = This is an example module monitoring cpu, load,
>     and filesystem statistics.

>     param:i18nModuleName  = base.modules.solaris-example:moduleName
>     param:i18nModuleType  = base.modules.solaris-example:moduleType
>     param:i18nModuleDesc  = base.modules.solaris-example:moduleDesc
>     ?param:i18nModuleName?format = i18n
>     ?param:i18nModuleType?format = i18n
>     ?param:i18nModuleDesc?format = i18n

## Internationalizing Modules

> Internationalization, or l18n (an abbreviation for the term "internationalization" that also denotes the existence of 18 characters between "l" and "n"), is the process of enabling your code so that the programs can display localized text, such as text in French, Chinese, and other languages instead of displaying the English text for labels, errors, headings, titles and so forth.

> If no localized text is available, then the default English text is used. I18n of a program consists of defining the i18n keys and I18n text, and using the I18n key instead of a plain text while displaying the text. In Sun Management Center modules, there are some mandatory module parameters that should be internationalized. These are discussed in this section. For more details on this, refer to the Chapter 19.

### Mandatory Parameters for Internationalization in the Parameters File

> You can specify the I18n (international) keys for the module parameters in the parameters file. When displaying the module parameters in the console, the localized strings corresponding to the I18n key are used.

> The parameter file must also include the following lines:

>     param:i18nModuleName  = base.modules.<module><-subspec>:moduleName
>     param:i18nModuleType  = base.modules.<module><-subspec>:moduleType
>     param:i18nModuleDesc  = base.modules.<module><-subspec>:moduleDesc

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

> The mandatory lines are required to internationalize the default values of the moduleName, moduleType, and desc parameters. For user-defined parameters, refer to Chapter 6. These are the values that are displayed in the Sun Management Center console when a module is loaded. The following corresponding entries are required in the module properties file:

>     moduleName=<internationalized text>
>     moduleType=<internationalized text>
>     moduleDesc=<internationalized text>

> where <internationalized text> is the internationalized values for the module parameters. The properties file is discussed in the next section.

### Properties File

> Each module that requires internationalization must have a properties file. The name of this file must be:

>     <module><-subspec>[_<lang>].properties

> where

> <module> is the name of the module.
> <subspec> is an optional subspec for the module.
> <lang> is the locale representing the language of the internationalized text contained in this file. Not specifying the <lang> parameter in the file name indicates that the contents of the this file are to be used as the default when the current locale is not supported.

> The properties file contains key/value pairs for each part of the module to be internationalized. The format of the properties file is:

>     <key>=<value>

> where

> <key> is of the form <spec>[.<spec>....]. All <key>s in this file must be unique.
> <value> is the internationalized text.

> The corresponding properties file for the Solaris Example, for the English locale, would contain following internationalized text:

>     moduleName=Solaris Example
>     moduleType=Operating System
>     moduleDesc=This is an example module monitoring cpu, load, and
>     filesystem statistics.

#### Example Properties File

> For example, a fragment of the English Properties file for the Solaris Example module (`solaris-example.properties`) is:

>     #
>     # filesystem
>     #
>     filesystem=Filesystem Usage

>     #
>     # fileTable
>     #
>     filesystem.fileTable=Filesystem Usage Table

>     #
>     # fileEntry
>     #
>     filesystem.fileTable.fileEntry=Filesystem

>     filesystem.fileTable.fileEntry.mount=Mount Point
>     filesystem.fileTable.fileEntry.size=Total Size (KB)
>     filesystem.fileTable.fileEntry.avail=Available Space(KB)
>     filesystem.fileTable.fileEntry.pctUsed=Space Used (%)
>     filesystem.fileTable.fileEntry.pctRate=Rate (%/sec)

> The specification of a long <key> separated by dots (.) is for organizational purposes.

### Referencing Internationalized Text

> To reference internationalized text in the module, the following specification is used in the module definition files:

>     <type>:<qualifier> = base.module.<module><-subspec>:<key>

> where:

- <type> is the type of qualifier. This is typically consoleHint.
- <qualifier> is the part of the module that requires internationalization.
- <module> is the module name.
- <subspec> is the subspec of the module, which is optional.
- <key> is the same <key> that is used in the Properties File.

> For example, the internationalized text for the description of the mount point node in the Solaris Example module can be accessed using:

>     consoleHint:mediumDesc =
>     base.modules.solaris-example:filesytemtable.fileTable.
>     fileEntry.mount

## Data Model Specifications

> Data model creation defines the hierarchical structure of the managed object classes and managed properties required to model the entity to be managed.

| ### Creating a Data Model

> The steps involved in creating a data model are:

| 1. | Identify the components that comprise the entity to be managed.

|  | Refer to the section, ""Identifying Components and Properties of Managed Entity"," that identifies the properties that describe each of the components.

| 2. | Define the data model.

|  | Refer to the section, ""Defining the Data Model Structure"," that describes how to assign the structural primitive classes to the identified components and properties and organize them in a tree hierarchy to support status summarization.

| 3. | Add node descriptions.

|  | Refer to the section, ""Adding Node Descriptions"," that describes how to add descriptions to the managed object classes and managed properties.

### Identifying Components and Properties of Managed Entity

> In the data model, the physical and logical components are represented by managed object classes. The properties of the components are represented by managed properties.

> This action involves identifying each of the physical and logical components and properties of the managed entity that are to be included in the data model.

> > Note - The data model need not include every component and property of the managed entity. At the very least, it should 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 designer.

#### Solaris Example--Components and Properties

> For the Solaris Example module, the following logical components comprise the Solaris operating environment:

- CPU
- System
- File System

> > Note - The Solaris operating system contains many other logical components like swap, networking, processes, and so forth. However, to simplify the example, the components included in the model are limited to those listed above.

> The CPU component encompasses aspects related to CPU usage. The system component covers aspects related to the operating system in general. The file system component includes aspects related to mounted file systems.

> The next action is to determine what properties are required to describe each of the components. These properties are used to derive the health of each component, and collectively, summarize the health of the managed entity.

> CPU

> The CPU component can be characterized by the following properties:

- Percentage of time the CPU is idle
- Percentage of time the CPU is busy
- Percentage of CPU time spent on user processes
- Percentage of CPU time spent on system processes
- Average percentage of time the CPU is busy

> System

> The system component can be characterized by information about users logged into the system and the system load.

> User properties can include such things as:

- Current console user
- Number of users
- Number of sessions
- Primary user

> The system load can be described by the 1, 5, and 15 minute load averages.

> File System

> The file system component is composed of one or more mounted file systems. Each mounted file system is characterized by:

- Mount point
- Total size
- Available disk space
- Percentage of disk space used

### Defining the Data Model Structure

> The following sections describe how to define the data module structure. All examples are included at the end of this section.

#### Node Definition and Trees

> Because of the hierarchical nature of components of systems, the managed object classes and managed properties are organized in a tree hierarchy referred to as the data model structure. Managed object classes and managed properties are represented by branches and leaves, respectively. Branches and leaves in the tree structure are referred to as nodes.

> Note that the data model structure is an intermediate representation of the data model as it only contains the skeletal framework of the data model. The structural primitives and the basic object tree configurations are described in the following sections.

#### Structural Primitives

> Structural primitives specify characteristics required by nodes to define their place in the object tree hierarchy.

> Nodes can inherit from one of the following structural primitives:

- MANAGED-OBJECT
- MANAGED-PROPERTY
- MANAGED-PROPERTY-CLASS
- MANAGED-OBJECT-TABLE
- MANAGED-OBJECT-TABLE-ENTRY

> In module configuration file notation, nodes inherit from a primitive using the following syntax:

>     <node> = { [ use <PRIMITIVE1> <PRIMITIVE2> ] <body> }

>     where

> <node> is the node name. This name must be unique amongst its peer nodes.
> <PRIMITIVE> is a defined primitive that the node is inheriting from.
> <body> are entries for the node in module configuration file format

> MANAGED-OBJECT

>     <node> = { [ use MANAGED-OBJECT ] <body> }

> This primitive is used to identify managed object nodes that are branch nodes in the object tree. Branch nodes do not store data, instead they contain other branch or leaf nodes.

> MANAGED-PROPERTY

>     <node> = { [ use MANAGED-PROPERTY ] <body> }

> This primitive identifies managed property nodes that are leaf nodes in the object tree. These nodes store data associated with the property.

> MANAGED-PROPERTY-CLASS

>     <node> = { [ use MANAGED-PROPERTY-CLASS ] <managed properties> }

> This primitive is used to group related managed properties of a managed object together. Nodes that inherit from this primitive are branch nodes.

> Managed property classes are functionally identical to managed objects. The managed property class primitive has been created for convenience, to indicate more clearly that it is the properties that are being grouped.

> MANAGED-OBJECT-TABLE

>     <node> = { [ use MANAGED-OBJECT-CLASS ] <body> }

> This branch primitive is used in conjunction with the MANAGED-OBJECT-TABLE-ENTRY primitive when constructing a table of managed properties. Each managed property in the table can store a vector of data instead of simple scalars. The object that uses this primitive must have a child who uses the MANAGED-OBJECT-TABLE-ENTRY primitive. The MANAGED-OBJECT-TABLE and MANAGED-OBJECT-TABLE-ENTRY nodes are included to support the SNMP MIB representation of tabular data.

> > Note - The Sun Management Center console retrieves data stored in a table using a single SNMP get request (maximum SNMP packet size is 64KB is -- this is due to the fact that SNMP uses UDP, which has such a limitation). If the table contains a large number of managed properties or a large number of rows, all the data cannot be retrieved by the Sun Management Center console in a single get request and the console reports an error. In such instances, the table must be made smaller or split into multiple tables for display in the Sun Management Center console.

> MANAGED-OBJECT-TABLE-ENTRY

>     <node> = { [ use MANAGED-OBJECT-TABLE-ENTRY ]

>     		index = <managed property name>

>     			descColumn = <managed property name>

>     <managed properties>

>     }

> This branch primitive is used in conjunction with the MANAGED-OBJECT-TABLE primitive when constructing a managed object with a table of managed properties. This primitive must be used by an object that is the child of a MANAGED-OBJECT-TABLE object. This object must contain one or more managed property objects that forms the columns of the table.

> To allow specific rows of the table to be referenced through SNMP, this object must specify an index qualifier that corresponds to one or more of its child managed properties that uniquely identify the row. This is the value that is used as part of the status messages. For example, if index is set to the table node containing mount point information and the /var file system is greater than 90% full, the status message is:`
> `

>     /var > 90%

> If more than one child node is specified as part of the index, the string used in the status message is a comma separated list of the indexes. For example, if index is set to the mount point and disk name nodes, the status string reads: `
> `

>     /var,/dev/dsk/c0t0d0s5 > 90%

> Optionally, this object can also specify descColumn to specify a child property value as a descriptive row name to be displayed on the Sun Management Center console for row status messages. If descColumn is specified to be a node containing the disk name, the status message is as follows regardless of the index setting:`
> `

>     /dev/dsk/c0t0d0s5 > 90%

#### Example Data Model File

> This section contains the following examples:

- Solaris Example--Model File
- Solaris Example--CPU Data Model Structure
- Solaris Example--Performance Data Model Structure
- Solaris Example--filesystems Data Model Structure

> Solaris Example--Model File

> The following code example lists the Solaris Example Model file, named `solaris-examples-models-d.x`. This example has two independent managed objects: CPU, and system .

> CODE EXAMPLE 5-1 Solaris Example--Model File

>     #
>     # Solaris Managed Object and Property Models
>     #
>     type = reference

>     #
>     # Cpu Managed Object
>     #
>     cpu = { [ use MANAGED-OBJECT ]

>         mediumDesc             = CPU Properties
>         consoleHint:mediumDesc = base.modules.solaris-example:cpu

>         idle = { [ use PERCENT MANAGED-PROPERTY ]
>             shortDesc       = Idle
>             mediumDesc      = CPU Idle Time
>             fullDesc        = Percentage of time the CPU is in the idle state
>             units           = %

>         }

>         busy = { [ use PERCENT MANAGED-PROPERTY ]
>             shortDesc       = Busy
>             mediumDesc      = CPU Busy Time
>             fullDesc        = Percentage of time the CPU is in the busy state
>             units           = %

>         }

>     }

>     #
>     # System Managed Object
>     #
>     system = { [ use MANAGED-OBJECT ]

>         mediumDesc             = System Information
>         consoleHint:mediumDesc = base.modules.solaris-example:system

>         userstats = { [ use MANAGED-PROPERTY-CLASS ]
>             mediumDesc             = User Statistics
>             consoleHint:mediumDesc = base.modules.solaris-example:system.userstats

>             consoleUser = { [ use STRING MANAGED-PROPERTY ]
>                 shortDesc       = User
>                 mediumDesc      = Console User
>                 fullDesc        = User currently logged in on the console

>                 consoleHint:mediumDesc = base.modules.\
>     solaris-example:system.userstats.consoleUser
>             }

>             numUsers = { [ use INT MANAGED-PROPERTY ]
>                 shortDesc       = #Users
>                 mediumDesc      = Number of Users
>                 fullDesc        = Number of unique users currently logged in

>                 consoleHint:mediumDesc = base.modules.\
>     solaris-example:system.userstats.numUsers
>             }

>         }

>         load = { [ use MANAGED-PROPERTY-CLASS ]
>             mediumDesc             = Load Average
>             consoleHint:mediumDesc = base.modules.solaris-example:system.load

>             one = { [ use FLOAT MANAGED-PROPERTY ]
>                 shortDesc       = 1min
>                 mediumDesc      = 1 Min Load Avg
>                 fullDesc        = The one minute load average

>                 consoleHint:mediumDesc = base.modules.solaris-example:system.load.one
>             }

>             five = { [ use FLOAT MANAGED-PROPERTY ]
>                 shortDesc       = 5min
>                 mediumDesc      = 5 Min Load Avg
>                 fullDesc        = The five minute load average

>                 consoleHint:mediumDesc = base.modules.\
>     solaris-example:system.load.five
>             }

>         }
>     }

>     # The solaris-example.properties file is shown below. This file also contains
>     # the module parameter internationalization key and strings.

>     #
>     # Module Parameters
>     #
>     moduleName=Solaris Example
>     moduleType=operatingSystem
>     moduleDesc=This is an example module monitoring cpu, load, and filesystem
>     statistics.

>     #
>     # Node Descriptions
>     #
>     cpu=CPU Properties

>     system=System Information

>     system.userstats=User Statistics
>     system.userstats.consoleUser=Console User
>     system.userstats.numUsers=Number of Users

>     system.load=Load Average
>     system.load.one=1 Min Load Avg
>     system.load.five=5 Min Load Avg

> Solaris Example--CPU Data Model Structure

> The managed properties of the managed object, CPU, are idle time, busy time, system time, user time, and busy average.

> FIGURE 5-1 Simple Managed Object

> The data model structure of the CPU is shown in module configuration file format:

> CODE EXAMPLE 5-2 Module Configuration File Format

>     cpu = { [ use MANAGED-OBJECT ]
>         idle = { [ use MANAGED-PROPERTY ] }
>         busy = { [ use MANAGED-PROPERTY ] }
>         system = { [ use MANAGED-PROPERTY ] }
>         user = { [ use MANAGED-PROPERTY ] }
>         average = { [ use MANAGED-PROPERTY ] }
>     }

> Solaris Example--Performance Data Model Structure

> The performance managed object contains a managed property, console user, plus the nested managed objects: CPU and load average, each of which contain their own managed properties.

> FIGURE 5-2 Performance Managed Object

> The following is a code example for the performance data model structure:

> CODE EXAMPLE 5-3 Performance Data Model Structure

>     performance = {[use MANAGED-OBJECT]
>         consoleUser = {[use MANAGED-PROPERTY]}
>         cpu = {[use MANAGED-OBJECT]
>             idle = {[use MANAGED-PROPERTY]}
>             busy = {[use MANAGED-PROPERTY]}
>             system = {[use MANAGED-PROPERTY]}
>             user = {[use MANAGED-PROPERTY]}
>             average = {[use MANAGED-PROPERTY]}
>         }
>         loadavg = {[use MANAGED-OBJECT]
>             one = {[use MANAGED-PROPERTY]}
>             five = {[use MANAGED-PROPERTY]}
>             fifteen = {[use MANAGED-PROPERTY]}
>        }
>     }

> > Note - CPU and loadavg can also be MANAGED-PROPERTY CLASS.

> Solaris Example--`filesystems` Data Model Structure

> In this example, the managed object is the file system component. The managed properties are the mount point, total size, KB available, and percent space used.

> The mount property is designated to be the index. This allows each file system to be referenced by their mount point names.

> FIGURE 5-3 Managed Object with Tabular Properties

> The data model structure of the file system component is shown in module configuration file notation:

> CODE EXAMPLE 5-4 File System Data Model Structure Code

>     filesystems = {[use MANAGED-OBJECT]
>       fileTable = {[use MANAGED-OBJECT-TABLE]
>          fileEntry = {[use MANAGED-OBJECT-TABLE-ENTRY]
>            index = mount
>            mount = {[use MANAGED-PROPERTY]}
>            size = {[use MANAGED-PROPERTY]}
>            avail = {[use MANAGED-PROPERTY]}
>            pctUsed = {[use MANAGED-PROPERTY]}
>         }
>       }
>     }

### Adding Data Types

> After creating the data model structure, data types must be assigned to the managed property nodes. Data primitives classes can be used to characterize the data and alarm types of the manage property nodes. These primitives are assigned to the managed property nodes using the same syntax as before.

>     <node> = { [ use <primitive> MANAGED-PROPERTY ] <body> }

> All managed properties must use a data type primitive. These primitives define the type of data stored in the property. Data type primitives can be optionally combined with an alarm type that characterizes the alarm checks performed on the property's data value.

> These data and alarm primitives have the following form:

>     <data type>[<alarm type>]

> where

> <data type> represents the type of data stored in the primitive
> <alarm type> optionally specifies the type of alarm checks to perform

> > Note - Alarm types are optional and are discussed in the chapter on Chapter 7.

#### Available Data Types

> Data type primitives can be one of the following:

- STRING--general string type
- INT--`asn.1` integer type
- FLOAT --floating point value
- PERCENT--percentage
- COUNTER--`asn.1` counter type
- GAUGE--`asn.1` gauge type
- OID--`asn.1` OID type
- TIMETICKS--`asn.1` time tick type
- OCTETSTRING--`asn.1` octet string type
- IPADDRESS--`asn.1` IP address type
- UINT--`asn.1` unsigned integer type
- PHYSADDRESS--`asn.1` physical address type
- TESTANDINCR--`asn.1` test and increment type

> The TESTANDINCR is a primitive that has a special behavior. SNMP sets nodes using this primitive causing the agent to check the value that is being set against the current node value. If the values are the same, the current value is incremented by one. If the values do not match, the set will fail.

### Adding Node Descriptions

> One action in the creation of the data model is to add descriptions to the nodes.

> Three levels of description qualifiers can be defined for each node:

- shortDesc (optional)--typically a one word description of the node
- mediumDesc (mandatory)--a descriptive string about the node that must be unique within the scope of the module, less than 20 characters.
- fullDesc (optional)--a complete description of the node

> The mediumDesc value is used as part of the status message displayed on the console.

> A managed property can also have a unit qualifier. This qualifier specifies the units (if any) of the data value stored in that property and is used for display purposes only. Together, the mediumDesc and unit qualifiers are used as part of a template when generating status messages of the managed property that is displayed on the Sun Management Center console. The unit qualifier is also used to automatically specify the units for the vertical axis when graphing data values, for example,
> `units = sec`.

#### Node Type Based on Operational Behavior

> Each node must be assigned a type that defines its operational behavior:

>     type = <node type>

> One of the node types is `reference`.

> Reference nodes are objects that are loaded for use as a template in the model file. A node is specified as a reference node as follows:

>     type = reference

> The entry, type = reference, indicates that the managed object classes defined in this file are to be used only as a reference. These reference objects are typically loaded into a template area from which the active object tree, which will perform the management functions can inherit the model structure. The load into the template area is done through the agent file (<module><-subspec>-d.x) when the model is realized.

> The other node types are discussed in section, "Node Type Based on Operational Behavior."

## Simple Data Model Realization

> Creating a data model defines the layout of the data in your module. After doing this, you have to specify the methods by which the agent will acquire the values for this data layout. This process of specifying the methods is referred to as data acquisition (DAQ) or data model realization in the following sections and subsequent chapters.

> Data model realization is defined in the agent file. Additional files that can be created to support the agent file include filter file, procedure file, shell scripts, C libraries, and Tcl extension packages.

> The `agent` file <module><-subspec>`-d.x` is mandatory for a module:

>     <module><-subspec>-d.x

> Example:`
> `

>     solaris-example-d.x

> > Note - The data model realization file (`*-d.x`) is sometimes interchangeably called the agent file.

### Steps Involved in Data Model Realization

> The following sections describe the model realization process:

- Implementing Data Acquisition Mechanisms describes how to devise the means by which you can acquire the data values of the managed properties in the data model.
- Integrating Data Acquisition describes how to create the agent file that loads and inherits from the data models.
- Loading the DAQ Services describes how to add the DAQ mechanisms to the agent file so that the acquired data can be disseminated to the appropriate nodes.

### Mandatory Contents of Every Data Model Realization File

> The agent file is in module configuration file format, and must contain the following standard entries:

>     [ use MANAGED-MODULE ]
>     [ load <module><-subspec>-m.x ]
>     [ requires template <module><-subspec>-models-d ]

>     <managed object classes>

> The line [ use MANAGED-MODULE ] mandates the inheritance of the MANAGED-MODULE primitive at the root of the module. This primitive provides managed properties at the root of the module that reflect the status and availability of the entire module.

> The line [ load <module><-subspec>`-m.x` ] loads the parameter file entries into the root of the module. The entries can be referenced by other objects in the module.

> The line [ requires template <module><-subspec>`-models-d` ] loads the model file into the template area for use by the agent. Multiple entries can be specified if more than one model file is required.

> The line <`managed object classes`> represents the main body of the agent file. It consists of the managed object classes that use the data models loaded in the template area. The exact contents of this section will vary with each module.

### Implementing Data Acquisition Mechanisms

> The underlying logic to perform the data acquisition can be implemented in a number of different ways, including:

- UNIX programs and shell scripts
- Tcl/TOE code discussed in the Modules Appendix.
- C-code libraries and Tcl/TOE command extensions discussed in the Modules Appendix

> For more information about the Tcl programming language, refer to the Tcl and TK Toolkit manual.

#### UNIX Programs and Shell Scripts

> Much system data can be acquired using UNIX system commands like`vmstat, swap, iostat, netstat, ps`, and so forth. Existing custom programs and scripts can also be employed to gather data.

> Shell scripts can be employed to parse the raw results of the UNIX programs using such tools as `sed, grep, awk`, and so forth. When returning data to the agent from UNIX programs or scripts, each data element must be separated by newlines.

> The standard extension for the shell scripts is `.sh`, for example, `filename.sh`.

### Integrating Data Acquisition

> This action involves integrating DAQ capabilities with the intermediate agent file created previously. The objective of this step is to facilitate the refresh operation. The refresh operation consists of performing DAQ and disseminating the acquired data into the appropriate managed property nodes.

> The dissemination of a buffer of data into a tree of managed objects and managed properties is known as the data cascade. There are strict rules that govern the manner in which data can be cascaded in the tree. Data can be acquired one piece at a time and placed into managed properties, or larger amounts of information can be acquired in a single data acquisition operation and cascaded into several managed properties.

> The DAQ capabilities are integrated into the agent file by doing the following:

- Loading the DAQ services
- Specifying node types
- Specifying refresh parameters

### Loading the DAQ Services

> Typically, DAQ functionality and/or support services must be loaded or created by the agent to enable the DAQ mechanisms in the Sun Management Center agent. The possible types of DAQ services that can be loaded or created are listed below out of which only Bourne shell script is discussed here. The actual DAQ services that must be loaded or created depends on the DAQ mechanisms being employed.

- Bourne shell service
- Tcl shell service
- Tcl filters
- Tcl procedures
- Tcl command extension package

> For more information on Tcl shell service, filters, and procedures, refer to Chapter 6.

#### Bourne Shell Services

> If the DAQ was implemented using UNIX commands or shell scripts, the agent must create a Bourne shell service object to execute these commands. The Bourne shell service is essentially an object maintaining a pipe to one or more shell processes to which commands can be directed and the results returned asynchronously.

> The module configuration file specification for a Bourne shell service object is:

>     _services = { [ use SERVICE ]
>             sh = {
>                 command = "pipe://localhost//bin/sh;transport=shell"
>                 max = <max shells>
>             }
>         }

> where:

> <max shells> specifies the maximum number of shell subprocesses to spawn. This is typically set to 2. This value indicates the number of refresh commands that use the Bourne shell service that can be executed co-currently.
> For example, if <max shells> is set to 1, refresh commands can be queued waiting for previous commands to finish. Setting this value to a larger number increases the number of captive shells and resources used by the agent. `object _services.sh` can then be used by other objects for Bourne shell DAQ services.

### Node Type Based on Operational Behavior

> The following section discusses node types based on the operational behavior to be used in Model Realization File.

> Each node must be assigned a type that defines its operational behavior:

>     type = <node type>

> The possible node types are active, passive, derived, or reference.

> Passive and drived nodes are discussed in Chapter 6.

> Reference nodes are already discussed in this chapter. They are only used in the models file.

#### Active Nodes

> A node is specified to be active using the following specification:

>     type = active

> All data acquisition operations are initiated by an active node. An active node is a managed object or managed property that has refresh information associated with it.

> In general, active nodes specify a refresh service, refresh command, and a refresh interval. To acquire data, the refresh command is executed in the context of the refresh service at every refresh interval.

> Additional refresh parameters are available for filtering the data, specifying initialization behavior, and setting up internal refresh triggers.

> All active nodes must specify the following qualifiers:

>     refreshService = <service object>
>     refreshCommand = <command to run in the context of refreshService>
>     refreshInterval = <timex specification defining when to run the command>

> Other qualifiers that can be specified by active nodes are discussed in the next chapter.

### Mandatory RefreshQualifiers for Active Nodes

#### refreshService

> A refresh service is an object within the agent that can be used for data acquisition. A refresh service must be specified for active and derived nodes.

> Invoking a refresh command in the context of a refresh service activates typical refresh operations. A refresh command is a service-dependent command that defines the specific operation to perform. A refresh command is sent to the refresh service each time a refresh is triggered.

> Refresh services can be any object that supports the service interface. Typical, refresh services are objects that maintain pipes to shells (like Bourne shell or perl process). Other refresh services that can be specified by active nodes are discussed in the next chapter.

> The refreshService qualifier specifies the context in which the refreshCommand runs.

> Bourne Shell Service

>     refreshService = _services.sh

> Use this service when the refresh command is a UNIX command or shell script. To use this service, a Bourne shell service object (`like_services.sh`) must have been created at the root of this module as described in the Loading the DAQ Services section.

#### refreshCommand

> The refresh command must be specified for active and derived nodes.

>     refreshCommand = <command>

> The refresh command is a service-dependent command that defines the specific operation to perform. Conceptually, the refresh command is sent to the refresh service each time a refresh is triggered.

> The refresh command must be appropriate for the specified refresh service. Depending on the refresh service specified, the refresh command can be such things as the following will be discussed in a later chapter:

- UNIX commands and scripts
- Tcl commands and procedures

> All module parameters and parameters defined in the value slice can be referenced by the refreshCommand. This information can be referenced using %<parameter> as part of the refreshCommand. For example refreshCommand = myCommand %moduleName will pass in the moduleName module parameter to the command myCommand.

> The exit status of UNIX commands and scripts are not used by the agent. Instead the agent interprets any data return on stderr as a data acquisition error. If this happens, the active node automatically goes into an indeterminate alarm state, indicating that the node failed to update. In addition, no data cascades into the agent regardless if any data was returned on `stdout`.

> The number of elements and the type of data returned by the refresh command is dictated by the number and type of nodes into which the data is cascaded. Generally, data cascade is the dissemination of data collected by an active node into passive nodes. The exception is when a leaf node is active and collects data for itself.

> If the refresh command returns less than the required number of elements for a complete data cascade, an error message is generated by the agent. However, the data cascade still occurs. All available data is used by the nodes at the beginning of the cascade. Nodes towards the end of the data cascade will not receive any data. If the refresh command returns more than the required number of elements, the additional data elements are ignored.

> A DAQ error can also be encountered if there is a mismatch between the type of data being cascaded into a node and the node's data type. Again, the data cascade continues until the node where the data type mismatch occurs. Note that empty strings are valid data values for nodes whose data type is STRING.

#### refreshInterval

> The refresh interval specifies the time specification that the refresh command is executed.

>     refreshInterval = <timex specification>

> The refresh interval must be specified for active and optionally for derived nodes. If no refreshInterval is specified for an active node, it is treated by the agent as an on-demand refresh node, that is, the data values are refreshed whenever the data is requested as opposed to being computed periodically or on initialization only.

> > Note - Alarm rules or checks are not supported for on-demand nodes. If an on-demand node is detected to have an alarm rule or check during module load, the agent aborts immediately.

> If the refresh interval is not specified, the refresh command is executed whenever the data is requested through SNMP.

> If the refresh interval is set to 0, the refresh command is executed only on initialization. The refresh command is not executed when the data is requested through SNMP. Refer to the Appendix, "Time Expression Specifications," for more information. For more information on refreshQualifiers, refer to Chapter 6.

### Example of a Simple Module

> Refer to the examples, `helloworld01` through `helloworld03` in the Sun Management Center Sun Management Center Developer Environment Manual installed on your system. The online versions of these examples are in the following location once you install the developer environment:

>     /opt/SUNWsymon/sdk/examples/modules

> This section contains the following examples:

- Example Data Model Realization File
- The solaris-example-console-user-d.sh File

> Example Data Model Realization File

> The following code example lists the Solaris Example Model Realization File.

> CODE EXAMPLE 5-5 Solaris Example Model Realization File

>     [ use MANAGED-MODULE ]
>     [ requires template solaris-example-models-d ]

>     #
>     # Load Module Parameters
>     #
>     [ load solaris-example-m.x ]

>     #
>     # Define services required by this module
>     #
>     _services = { [ use SERVICE ]
>         #
>         # Standard Bourne Shell
>         #
>         sh = {
>             command = "pipe://localhost//bin/sh;transport=shell"
>             max     = 2
>         }
>     }

>     #
>     # Cpu Information
>     #
>     cpu = { [ use templates.solaris-example-models-d.cpu ]

>         idle = {
>             type            = active
>             refreshService  = _services
>             refreshCommand  = echo 10
>             refreshInterval     = 60
>         }

>         busy = {
>             type            = active
>             refreshService  = _services
>             refreshCommand  = echo 20
>             refreshInterval     = 60
>         }
>     }

>     #
>     # System User and Load Information
>     #
>     system = { [ use templates.solaris-example-models-d.system ]
>         userstats = {
>             consoleUser = {
>                 type            = active
>                 refreshService  = _services.sh
>                 refreshCommand  = solaris-example-console-user-d.sh
>                 refreshInterval     = 60
>             }
>             numUsers = {
>                 type            = active
>                 refreshService  = _services.sh
>                 refreshCommand  = echo 10
>                 refreshInterval     = 60
>             }
>         }

>         load = {
>     one = {
>                 type = active
>                 refreshService  = _services.sh
>                 refreshCommand  = echo 10.2
>                 refreshInterval     = 60
>     }
>     five = {
>                 type = active
>                 refreshService  = _services.sh
>                 refreshCommand  = echo 10.2
>                 refreshInterval     = 60
>             }
>         }
>     }

> The `solaris-example-console-user-d.sh` File

> The `solaris-example-console-user-d.sh` file is shown below:

> CODE EXAMPLE 5-6 The `solaris-example-console-user-d.sh` File

>     #!/bin/sh
>     echo "I am a console user (from Sh)"

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