C H A P T E R  3

Getting Started With Netra CT Element Management Agent API

This chapter explains how to get started writing applications that interface with the Netra CT element management agent, using the Java Management Extensions (JMX) compatible Java API supported by the Netra CT management agent. The chapter consists of:


Before You Begin

You should become acquainted with the topology of the Netra CT server (see Chapter 2), and have some knowledge of Java programming, JMX specifications, and JDMK framework. For more information about JDMK refer to Java Dynamic Management Kit 4.2 Tutorial (806-6633), or go to http://java.sun.com/docs/books/tutorial/index.html.

Verify that you have the Solaris OS on your development system. In addition, you can download the required Netra CT patch packages from:

http://sunsolve.com 

These packages consist of:

TABLE 3-1 Solaris Packages for Netra CT Developer APIs

Package

Description

SUNW2jdrt

Java Runtime Java Dynamic Management Kit (JDMK) package

SUNWctmgx

Netra CT management agent package

SUNWctac

Alarm card firmware package that includes the Netra CT management agent


You will use these installed packages to work with this tutorial.


About Netra CT Element Management Agent API

The Netra CT server software package includes various modules and extensions (see Operating System Specifics), and the netract agent is one of these.

The netract agent, when appropriately invoked, provides configuration monitoring and fault monitoring. This enables you to investigate the installed system, and to determine whether the components are running smoothly.

Individual netract agents run on the alarm card, the host CPU board, and any satellite CPU board. A management application must be able to talk to the different agents and gather information about the system into a database.

Each netract agent notifies the management application of any changes, such as hardware or software configuration changes, and also detects faults when they occur.

The netract agent provides two different interfaces for the management applications, one is SNMP version 2C interface, the other is a JMX-compatible Java API called Netra CT management agent API. This chapter provides an introduction on how to write a management application using this Java API.

Netra CT Agent Security

For JMX/JDMK/RMI connectivity, the Netra CT agent provides security by authenticating the application connecting to it via the context of a valid username and password pair.

The username and password must be previously created in the Alarm Card database via Alarm Card CLI. An account on Alarm card consists of username, password and permission. For Netra CT agent, there are only two permissions: read-only and read-write. User account on Alarm Card must have ALL PRIVILEDGES ENABLED to have read-write permission. (See the Netra CT Server System Administration Guide for details on setting up user accounts.)

There is a security flag used to enable and disable the Security Feature. This flag is stored persistently and its default value is false. The security flag can be set to true or false via Alarm Card CLI command setmohsecurity. A reset of Alarm Card is required after changing the flag for the feature to take effect. (See the Netra CT Server System Administration Guide for information on the setmohsecurity and showmohsecurity CLI commands).

You can get the state of security flag with the Alarm Card CLI command showmohsecurity or with the API by using the NEMBean's getSecurityFlag method described in NEMBean.

If the flag is true, security is on. This means the application that connects to Netra CT agent must provide a valid username and password to be able to establish connection.

If the flag is false, security is off and no authentication is done. It does not matter whether an application provides username, password or not, it is always allowed to connect.

Sample code with Netra CT Security is shown CODE EXAMPLE 3-1.

CODE EXAMPLE 3-1 Sample code with Netra CT Security
...
// set up the authentication info
AuthClient.setAuthInfo(connectorClient, username, password);
// now connect to the agent...
connectorClient.connect();
... 


Creating Your Application

Creating an application to interface with and manage the configuration of the Netra CT server involves a series of steps. You must be able to:

1. Cut and paste the relevant code example into a text editor, make any necessary adjustments, and compile the code.

Make sure that SUNW2jdtk is installed before trying to compile Client.java. Refer to the Java Dynamic Management Kit 4.2 Tutorial for background information on Client.java.

2. To compile Client.java, issue the command /usr/j2se/bin/javac -classpath:

$ /usr/j2se/bin/javac -classpath \
/opt/SUNWjdmk/jdmk4.2/1.2/lib/jdmkrt.jar: \
/opt/SUNWnetract/mgmt2.0/lib/agent.jar Client.java

Compiling Client.java should produce the file Client.class. If you have difficulty, refer to the Java Tutorial example of running a simple client.

3. Before running Client.java, start the agent by issuing the command/opt/SUNWnetract/mgmt2.0/bin/ctmgx start

$ /opt/SUNWnetract/mgmt2.0/bin/ctmgx start

4. Use the following command to run Client.java:

$ /usr/j2se/bin/java -classpath \
.:/opt/SUNWjdmk/jdmk4.2/1.2/lib/jdmkrt.jar: \
/opt/SUNWnetract/mgmt2.0/lib/agent.jar Client

The following sections point out various features of the Netra CT element management API.

Purpose of the Application

First, a management application needs to know how the system is configured. The simplest example sets up an agent describing the hardware containment hierarchy. From the root of this tree, the management tree can be developed to show, for example, how many fans there are, which cards are in which slots and so on. Developing code that begins this action is the purpose of Determining the System Configuration Hierarchy.

Listening for Notifications deals with developing a way of monitoring notifications such as power on and power off to a particular slot or device.

Managing Alarms covers alarm management: how to handle the receiving and transmitting of system alarms such as CPU over-temperature alarm.

Software Monitoring shows how to get a list of running software services and daemons, so they can be registered to receive notice of events.

Determining the System Configuration Hierarchy

In this section you develop a client to print out the object names of the MBeans representing the system. A complete description of Mbeans, together with examples, can be found in the JDMK documentation.

1. Ensure you have the appropriate software installed on the development system for the application you intend to develop.

Refer to the Netra CT Server System Administration Guide if you need help in installing the appropriate software.

2. Go to: /opt/SUNWnetract/mgmt2.0/docs/api to find the documentation that identifies the pieces you need to communicate with the netract agent.

See the API documentation for:

For JDMK documentation, go to: /opt/SUNWjdmk/jdmk4.2/1.2/docs. For an introduction to JDMK, go to //docs.sun.com, and search for the Java Dynamic Management Kit 4.2 Tutorial.

See the API documentation for:

Communicating to the Netra CT Agent

This simple demonstration lets you connect a client with an instance of netract agent, beginning in CODE EXAMPLE 3-2. This example represents part one of a three-part example. A detailed explanation follows.

CODE EXAMPLE 3-2 Creating a Client to Communicate With the Netra CT Agent (Part 1)

import java.util.Iterator;
import java.util.Set;
import javax.management.ObjectName;
import com.sun.ctmgx.moh.MohNames;
import com.sun.jdmk.ServiceName;
import com.sun.jdmk.comm.RmiConnectorAddress;
import com.sun.jdmk.comm.RmiConnectorClient;
 
public class Client {
 
    private RmiConnectorClient connectorClient;
    private RmiConnectorAddress connectorAddress;
    
    public Client() {
        connectorClient = new RmiConnectorClient();
        connectorAddress = new RmiConnectorAddress();
    }
 
    public static void main(String[] args) {
        Client client = new Client();
        try {
            client.printContainmentTree();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
 

CODE EXAMPLE 3-2 instantiates the RmiConnectorClient and RmiConnectorAddress.

The demonstration continues in CODE EXAMPLE 3-3.

Finding the Root Object Name

CODE EXAMPLE 3-3 continues from the previous example. The code example connects to the client and prints the ContainmentTree by getting the ObjectName of the root MBean in the containment hierarchy.

Each MohNames instance comes up with ObjectNames instances that are accessible via public static fields defined in MohNames. This includes the ContainmentTreeMBean instance, which provides a mechanism for the user to traverse the containment hierarchy representing the Netra CT system.

CODE EXAMPLE 3-3 Getting the Root MBean Object Name (Part 2)

  public void printContainmentTree() throws Exception {
        connectorClient.connect(connectorAddress);
 
        Object[] params = new Object[0];
        String[] signature = new String[0];
        ObjectName rootName =
            (ObjectName)connectorClient.invoke(MohNames.MOH_CONTAINMENT_TREE,
                                               "getRoot", params, signature);
        printSubTree(rootName);
 
        connectorClient.disconnect();
    }
 

This demonstration returns the object name of the instance of NEMBean. NEMBean is the name of the network element MBean representing the system as a whole, in other words, the root of the tree.

Now that you have identified the ObjectName of the root of the MOH_CONTAINMENT_TREE you are ready to traverse the tree and find out what other elements are in the tree.

Traversing the Containment Hierarchy From a Node

Continuing the demonstration from the previous example, in CODE EXAMPLE 3-4 you traverse the MOH_CONTAINMENT_TREE from a node, and can get a list of all the nodes on the tree using getChildren.

CODE EXAMPLE 3-4 Traversing the Containment Hierarchy From a Node (Part 3)

    private void printSubTree(ObjectName nodeName) throws Exception {
        System.out.println(nodeName);
 
        Object[] params = {nodeName};
        String[] signature = {"javax.management.ObjectName"};
 
        Set children =
            (Set)connectorClient.invoke(MohNames.MOH_CONTAINMENT_TREE,
                                        "getChildren", params, signature);
 
        for (Iterator itr = children.iterator(); itr.hasNext();) {
            printSubTree((ObjectName)itr.next());
        }
    }
}
 

Here, the nodeName is the ObjectName of the MBean where the search should start from. The line beginning Set children gets the children of the specified MBean in the containment hierarchy.

Once you have established the hierarchy of the existing system, your application must receive notification when changes to the system occur. This is the subject of the following section.

Listening for Notifications

This series of examples assumes you continue from the previous three-part example. Return to /opt/SUNWnetract/mgmt2.0/docs/api to find documentation.

In the JDMK framework, look at:

In MOH documentation you need to look at: com.sun.ctmgx.moh.MohNames and com.sun.ctmgx.moh.Moh.EFDMBean.

Registering a Notification Listener With EFDMBean Instance

This example continues from the previous examples and shows you how to register a NotificationListener using a NotificationFilter.You begin by adding a NotificationListener that catches communications from the RmiConnectorClient.

CODE EXAMPLE 3-5 RMI Example of Listening for MOH Notifications

Registering a NotificationListener with a NotificationFilter
 
      try {
            // accessing MohNames for MOH_DEFAULT_EFD
            //
            connectorClient.addNotificationListener(MohNames.MOH_DEFAULT_EFD,\
                                                         aListener, aFilter, null);
       }
            catch (com.sun.jdmk.comm.CommunicationException ce) {                                       
            try {
                 connectorClient.setMode(RmiConnectorClient.PULL_MODE);
                 connectorClient.addNotificationListener\
                    (MohNames.MOH_DEFAULT_EFD,aListener, aFilter, null);
            }
            catch (Exception e) {
            }
       }
 

CODE EXAMPLE 3-5 establishes that MohNames can access MOH_DEFAULT_EFD. The EFDMBean exposes the remote management interface of an event forwarding discriminator managed object.

The netract agent of the Netra CT alarm card does not support the PUSH_MODE, so the above code will work for any of the netract agent instances (those on the host, satellite, and alarm card) in a Netra CT drawer.

Managing Alarms

Before you begin this segment of code example, you should refer back to: /opt/SUNWnetract/mgmt2.0/docs/api

Look at the MOH documentation for:

Registering a Notification Listener With an Alarm Notification Filter

In this section you identify the kinds of alarms the script listens for when events occur. You can specify the level of action; this example listens for critical or major alarms. AlarmNotification represents an alarm notification emitted by an MBean.

CODE EXAMPLE 3-6 Registering a NotificationListener With an AlarmNotificationFilter

AlarmNotificationFilter aFilter = new AlarmNotificationFilter();
 
// interested in all types of alarms
//
aFilter.enableAllAlarmTypes();
 
// interested in only CRITICAL and MAJOR alarms
//
aFilter.enableSeverity(AlarmSeverity.CRITICAL);
aFilter.enableSeverity(AlarmSeverity.MAJOR);
 
try {
                connectorClient.addNotificationListener(MohNames.MOH_DEFAULT_EFD,\
                                                         aListener, aFilter, null)
            }
 catch (com.sun.jdmk.comm.CommunicationException ce) {                                       
            connectorClient.setMode(RmiConnectorClient.PULL_MODE);
                connectorClient.addNotificationListener(MohNames.MOH_DEFAULT_EFD,\
                                                         aListener, aFilter, null)
            }
            catch (Exception e) {
            }   
 

CODE EXAMPLE 3-6 follows the form of the previous example in setting the RmiConnectorClient to PULL_MODE. The alarm filter is set to enableAllAlarmTypes, then refined to enable only AlarmSeverity.CRITICAL and AlarmSeverity.MAJOR.

Using the Default Alarm Severity Profile

Each netract agent instance comes up with a default instance of AlarmSeverityProfile which can be accessed by its object name, MohNames.MOH_DEFAULT_ASP. The MBean instances that might generate AlarmNotifications will have this default alarm severity profile associated with them. The user can associate a new profile to any of those MBeans at any time.

CODE EXAMPLE 3-7 Using the Default Alarm Severity Profile

// Get the alarm severity association of the default profile
//
Object[] allObjs = null;
Object obj = null;
Java.util.Set mySet = null;
Java.util.Map myMap = null;
        try {
            myMap = (Map)connectorClient.invoke(MohNames.MOH_DEFAULT_ASP,\ 
                      "getAlarmSeverityList", null,null);
            
            mySet = (Set)myMap.keySet();
            allObjs = mySet.toArray();
        } catch(Exception e) {
            e.printStackTrace();
        }
        
        AlarmType aType = null;
        AlarmSeverity aSeverity = null;
  
        for (int i = 0; i < mySet.size();i++) {
            try {
                // aType and aSeverity is the association in this 
                // default profile
                aType = (AlarmType)allObjs[i];
                aSeverity = (AlarmSeverity)myMap.get(aType);
                    
                // setting the severity of high temp alarm to critical
                //
                if (aType.equals(AlarmType.HIGH_TEMPERATURE)) {
                    Object[] params = new Object[2];
                    String[] signature = new String[2];
                    params[0] = aType;
                    params[1] = AlarmSeverity.CRITICAL;
                    signature[0] = "com.sun.ctmgx.moh.AlarmType";
                    signature[1] = "com.sun.ctmgx.moh.AlarmSeverity";
                    connectorClient.invoke(MohNames.MOH_DEFAULT_ASP, \
                          "setAlarmSeverity", params, signature);
 
 
            } catch(Exception e) {
                e.printStackTrace();
            }
        }
 

In CODE EXAMPLE 3-7, the severity level of HIGH.TEMPERATURE AlarmType in the default alarm severity profile has been set to CRITICAL. The following example shows how to create your own alarm severity profile instances.

Creating Your Own Alarm Severity Profile

You can create your own alarm severity profile by following CODE EXAMPLE 3-8.

CODE EXAMPLE 3-8 Creating an Alarm Severity Profile

try {
    // You need to provide the class name to instantiate an MBean,
    // for AlarmSeverityProfileMBean
    // the class name string is defined by the constant MohNames.CLASS_NAME_ASP
    //
            ObjectName profileName = new ObjectName("NetraCT:name=\
                  AlarmSeverityProfile,id=2");
            connectorClient.createMBean(MohNames.CLASS_NAME_ASP, profileName,\
                  null,null);
 
   // To make the profile usable, you need to provide the alarm type and severity 
   // associations
   // 
            Object[] params = new Object[2];
            String[] signature = new String[2];
            signature[0] = "com.sun.ctmgx.moh.AlarmType";
            signature[1] = "com.sun.ctmgx.moh.AlarmSeverity";
 
            // For high temperature alarm
            //            
            params[0] = AlarmType.HIGH_TEMPERATURE; 
            params[1] = AlarmSeverity.CRITICAL; 
            connectorClient.invoke(profileName, \
                   "setAlarmSeverity", params, signature);
 
            // For high memory utilization alarm
            //
            params[0] = AlarmType.HIGH_MEMORY_UTILIZATION; 
            params[1] = AlarmSeverity.MAJOR; 
            connectorClient.invoke(profileName,\ 
                   "setAlarmSeverity", params, signature);
 
          // For fan failure alarm (NetraCT agent does not support this alarm 
          // currently
          //
            params[0] = AlarmType.FAN_FAILURE; 
            params[1] = AlarmSeverity.MINOR; 
            connectorClient.invoke(profileName,\ 
                   "setAlarmSeverity", params, signature); 
 
          // For fuse failure alarm (NetraCT agent does not support this alarm
          // currently
          //
            params[0] = AlarmType.FUSE_FAILURE; 
            params[1] = AlarmSeverity.WARNING; 
            connectorClient.invoke(profileName,\ 
                   "setAlarmSeverity", params, signature);
            
        } catch (Exception e) {
            e.printStackTrace();
        }
 

CODE EXAMPLE 3-8 assigns alarm notifications for high memory usage, fan failure, and fuse failure, although the current netract agent does not support alarm notifications for fuse failure. The code example is included here for demonstration purposes.

Assigning a New Alarm Severity Profile

CODE EXAMPLE 3-9 shows how to assign a new alarm severity profile to an MBean which can generate AlarmNotifications.

CODE EXAMPLE 3-9 Assigning a New Alarm Severity Profile

try {
            Object[] params = new Object[1];
            String[] signature = new String[1];
            
            signature[0] = "javax.management.ObjectName";
            
            // pass the object name of the newly created AlarmSeverityProfileMBean 
         // instance
         //
            params[0] = profileName;
            
            // sensorObjectName is the object name of lets say a temperature sensor
         // MBean instance
         // 
            connectorClient.invoke(sensorObjectName,\ 
                "setAlarmSeverityProfilePointer", params, signature);
 
        } catch (Exception e) {
               e.printStackTrace();
        }
 

The new alarm severity profile can be reserved to replace the default profile when required.

Configuring the Agent to Drive Alarm Card Alarm Outputs

The system configuration hierarchy indicates the physical alarm port which corresponds to a termination point, as shown in Hardware Resource Hierarchy Showing Managed Object Classes and subsequent views. The alarm port termination point supports five alarm interfaces: three for output, two for input. In general, when an alarm occurs, the corresponding output alarm pin is driven high based on the alarm severity.

The output alarm pins (alarm0, alarm1, alarm2) are statically mapped into severities of critical, major, and minor respectively.

For example, assume that HIGH_TEMPERATURE is assigned as critical, and HIGH_MEMORY_UTILIZATION is assigned as minor. When a high temperature occurs, alarm0 is driven high to indicate a critical alarm. When a HIGH_MEMORY_UTILIZATION occurs, alarm2 is driven high to indicate a minor alarm.

TABLE 3-2 Example of Alarm Output Mapping

alarm0

alarm1

alarm2

critical

major

minor

HIGH_TEMPERATURE

 

HIGH_MEMORY_UTILIZATION


In JMX, an alarm is defined as a notification with a severity associated with it. These alarms are assigned as NetworkInterfaceMBeans, each of which represent a network interface object in the system. Refer to NetworkInterfaceMBean.

You can configure an alarm card agent to drive output alarms from the alarm card on the Netra CT server using MOH as described in the following section.


procedure icon  To Set Up and Use Alarm Features

The following steps show how to configure an agent from the alarm card to correspond with the mapping in TABLE 3-2.

1. Register a notification listener with an AlarmNotificationFilter.

Use the examples beginning Registering a Notification Listener With an Alarm Notification Filter, and modify the default to listen for critical or major alarms. Return to the start of this chapter for help in getting an ObjectName.

2. Develop an AlarmSeverityProfile based on the default profile.

An AlarmSeverityProfile (ASP) contains multiple entries, and can be assigned to several alarm-generating objects. Some entries in the profile might not be used by an object, because that object might not be generating that specific kind of alarm. The default instance of AlarmSeverityProfile can be accessed by its object name, MohNames.MOH_DEFAULT_ASP.

3. Assign the AlarmSeverityProfile to the corresponding objects.

In CODE EXAMPLE 3-10 extracted from Using the Default Alarm Severity Profile, the severity level of HIGH.TEMPERATURE AlarmType in the default ASP has been set to CRITICAL corresponding with alarm0.

CODE EXAMPLE 3-10 Extract of Using the Default Alarm Severity Profile

// Get the alarm severity association of the default profile
//
<snip>
 ..... 
                // setting the severity of high temp alarm to critical
                //
                if (aType.equals(AlarmType.HIGH_TEMPERATURE)) {
                    Object[] params = new Object[2];
                    String[] signature = new String[2];
                    params[0] = aType;
                    params[1] = AlarmSeverity.CRITICAL;
                    signature[0] = "com.sun.ctmgx.moh.AlarmType";
                    signature[1] = "com.sun.ctmgx.moh.AlarmSeverity";
                    connectorClient.invoke(MohNames.MOH_DEFAULT_ASP, \
                          "setAlarmSeverity", params, signature);
.....
<unsnip>
 

Any number of objects are capable of generating an alarm. If you assign this profile to a particular object, whenever a hardware failure of that object occurs, the netract agent refers to the profile and responds as you have specified.

CODE EXAMPLE 3-11 creates your own alarm severity profile instances based on these examples. In this case, the sensorObjectName is the object name of a temperature sensor MBean instance.

CODE EXAMPLE 3-11 Extract of Assigning a New Alarm Severity Profile

try {
            Object[] params = new Object[1];
            String[] signature = new String[1];
            
            signature[0] = "javax.management.ObjectName";
            
            // pass the object name of the newly created AlarmSeverityProfileMBean 
         // instance
         //
            params[0] = profileName;
            
            // sensorObjectName is the object name of lets say a temperature sensor
         // MBean instance
         // 
            connectorClient.invoke(sensorObjectName,\ 
                "setAlarmSeverityProfilePointer", params, signature);
 
        } catch (Exception e) {
               e.printStackTrace();
        }
 

The new alarm severity profile replaces the default profile when required.

You can create several alarm severity profiles, each specifying a different response. One might designate fan failure as critical, another might designate high temperature as major. You then assign the appropriate profile to the object.

Clearing Alarms

Alarms are cleared automatically when each alarm relay is driven low. OperationalState will accordingly be shown to be enabled, disabled or unknown.

Software Monitoring

The following code examples help monitor software events. The series begins in CODE EXAMPLE 3-12 with establishing the printService to print system status reports, then gathers the list of software services and their associated daemons.

CODE EXAMPLE 3-12 Software Monitor Test (Part 1)

private void printService(ObjectName objName) {
    try {
        String name = (String)connectorClient.getAttribute(objName,"Name");
        String status = (String)connectorClient.getAttribute(objName,"Status");
        Integer polling_interval =\
           (Integer)connectorClient.getAttribute(objName,"PollingInterval");
        System.out.println("Name: " + name);
        System.out.println("Status: " + status);
        System.out.println("Polling Interval: " + polling_interval);
        }catch(Exception e) {
        e.printStackTrace();
        }
    }
 
         private void printDaemon(ObjectName objName) {
    try {
        String name = (String)connectorClient.getAttribute(objName,"Name");
        String status = (String)connectorClient.getAttribute(objName,"State");
        Integer retry = (Integer)connectorClient.getAttribute(objName,\
           "CurrentRetryCount");
        Integer maxretry = (Integer)connectorClient.getAttribute(objName,\
           "MaxRetryCount");
 
        System.out.println("name: " + name);
        System.out.println("state: " + status);
        System.out.println("retry: " + retry);
        System.out.println("maxretry: " + maxretry);
        }catch(Exception e) {e.printStackTrace();}
    }  
 
    // This method traverses through the hierarchy of software monitor and 
    // prints out all the software services and the daemons.
    private void test() {
        Object[] allObjs = null;
        Set swServiceList = null;
        ObjectName myObjName = null;
        try {
    // Get the list of all software services */
        swServiceList =(Set)connectorClient.invoke\
           (MohNames.MOH_SOFTWARE_MONITOR,"getSoftwareServiceList",null,null);
        allObjs = swServiceList.toArray();
 

CODE EXAMPLE 3-12 builds on previous examples to establish the status of connectorClient, and examine the hierarchy of the swServiceList in order to find existing services and running daemons.

The following segment of code collects the attributes of each software service so that the service can be registered to receive event notification.

CODE EXAMPLE 3-13 Traversing the Software Service List (Part 2)

     //Traverse through the software service list and print out the attributes 
    //of each software service
    for (int i = 0; i < swServiceList.size();i++) {
        myObjName = (ObjectName)allObjs[i];
        System.out.println("service : "+ ((ObjectName)allObjs[i]).toString());
        printService(myObjName);
        // Register the software service to receive the event notifications
        connectorClient.addNotificationListener(myObjName,this,null,null);
 

CODE EXAMPLE 3-13 traverses swServiceList and adds NotificationListener to the connectorClient.

The final code segment gets the list of daemons that support the service, and prints out the daemon attributes for event notification.

CODE EXAMPLE 3-14 Getting the List of Service Daemons (Part 3)

        // For each service, get the list of daemons that support the service
        ObjectName[] daemonList =\ 
           (ObjectName[])connectorClient.getAttribute(myObjName,"DaemonList");
        if (daemonList != null && daemonList.length > 0){
            System.out.print("Daemon List:  ");
            Integer retry = null;
            Integer maxretry = null;
            // For each daemon, print out all attributes of the daemon.
            for (int k= 0;k < daemonList.length;k++) {
                printDaemon(daemonList[k]);
                // register the daemon to receive the event notifications
                connectorClient.addNotificationListener\ 
                   (daemonList[k],this,null,null);
            }
        }
    }
    }catch(Exception e) {throw new UncheckedException(e);}
    }
 

CODE EXAMPLE 3-14 establishes a DaemonList for each service and prints out the attributes of each daemon. Finally, the code registers these daemons to receive notice of events with addNotificationListener.

For further information, look at /opt/SUNWnetract/mgmt2.0/docs/api which details all the MOH interfaces and classes that are provided for the Netra CT system software.