Once your MIBs are implemented as MBeans, your agent application needs an SNMP protocol adaptor in order to function as an SNMP agent. Since the SNMP adaptor is also an MBean, it can be created and started dynamically in your agent by a connected manager or through the HTML adaptor. In our simple Agent example, we will launch it through the code of the agent application.
public class Agent { static SnmpAdaptorServer snmpAdaptor = null; public static void main(String args[]) { MBeanServer server; ObjectName htmlObjName; ObjectName snmpObjName; ObjectName mibObjName; ObjectName trapGeneratorObjName; int htmlPort = 8082; int snmpPort = 8085; // non-standard [...] try { server = MBeanServerFactory.createMBeanServer(); String domain = server.getDefaultDomain(); // Create and start the HTML adaptor. // htmlObjName = new ObjectName( domain + ":class=HtmlAdaptorServer,protocol=html,port=" + htmlPort); HtmlAdaptorServer htmlAdaptor = new HtmlAdaptorServer(htmlPort); server.registerMBean(htmlAdaptor, htmlObjName); htmlAdaptor.start(); // Create and start the SNMP adaptor. // snmpObjName = new ObjectName(domain + ":class=SnmpAdaptorServer,protocol=snmp,port=" + snmpPort); snmpAdaptor = new SnmpAdaptorServer(snmpPort); server.registerMBean(snmpAdaptor, snmpObjName); snmpAdaptor.start(); // The rest of the code is specific to our SNMP agent // Send a coldStart SNMP Trap (use port = snmpPort+1) // Trap communities are defined in the ACL file // snmpAdaptor.setTrapPort(new Integer(snmpPort+1)); snmpAdaptor.sendV1Trap(0, 0, null); // Create the MIB-II (RFC 1213) and add it to the MBean server. // mibObjName = new ObjectName("snmp:class=RFC1213_MIB"); RFC1213_MIB mib2 = new RFC1213_MIB(); // The MBean will register all group and table entry MBeans // during its pre-registration server.registerMBean(mib2, mibObjName); // Bind the SNMP adaptor to the MIB mib2.setSnmpAdaptorName(snmpObjName); [...] } catch (Exception e) { e.printStackTrace(); } } // Needed to get a reference on the SNMP adaptor object static public SnmpAdaptorServer getSnmpAdaptor() { return snmpAdaptor; } } |
We launch the SNMP adaptor in the same way that we launch the HTML adaptor. First we create a meaningful object name for its MBean, then we instantiate the class with a constructor allowing us to specify a non-default port, we register the MBean with the MBean server, and we start the adaptor to make it active.
By default, the SNMP protocol adaptor uses the standard SNMP port 161. Since other applications may be using this port on a machine, our simple agent uses port 8085. When we connect to this agent our SNMP manager will need to specify this non-standard port number.
On certain platforms, applications also require super-user privileges to assign the default SNMP port 161. If your SNMP adaptor uses this port, its agent application will have to be launched with super-user privileges.
Our agent application creates and manages one MIB, our subset of MIB-II. To do so, it instantiates the corresponding RFC1213_MIB MBean that has been generated by the mibgen tool (see "MIB Development Process"). We give it a meaningful object name and then we register it in the MBean server.
The registration process lets the MBean instantiate and register other MBeans that represent the groups of the MIB and the entries of its tables. The set of all these MBeans at the end of registration make up the MBean representation of the MIB.
If you do not wish to expose a MIB through the MBean server, you do not have to register it. However, you still need to create all of its other constituent objects. The generated code provides the init method in the main MBean of the MIB. Calling this method will create all necessary MBean objects without registering them in the MBean server.
Because the SNMP data model relies on MIBs, only MBeans representing MIBs can be managed through SNMP. The main MBean of a MIB must be explicitly bound to the instance of the SNMP adaptor. The SNMP adaptor does not interact with any other MBeans, nor with the MBean server.
After a MIB is instantiated, you must set the SnmpAdaptorName attribute of its main MBean to bind it to the SNMP adaptor. You can either call its setSnmpAdaptorName method directly or, if the MIB's MBean was registered in the MBean server, another management application may set the attribute through the MBean's exposed interface. In this way, the SNMP adaptor will have a reference of all MIBs it must expose.
In the binding process, the SNMP adaptor obtains the root OID of the MIB. The adaptor uses this OID to determine which variables are implemented in the MIB's corresponding MBeans. In order for the SNMP adaptor to resolve a request on a given OID, the root OID of all bound MIBs must be distinct. This implies that no root OID may be equal to another or be a substring of another.
Even though the SNMP adaptor may be registered in the MBean server, the adaptor only makes MIBs visible to SNMP managers. Other MBeans in the agent cannot be accessed or even represented in the SNMP protocol. The SNMP manager is limited by its protocol: it cannot take full advantage of a Java Dynamic Management agent through the basic MIBs, and it does not have access to any other MBeans.
Once the MBean representing a MIB has been instantiated and bound to the SNMP adaptor, it is accessible through the SNMP adaptor. SNMP managers can send requests to operate on the contents of the MIB. The SNMP adaptor interprets the SNMP management requests, performs the operation on the corresponding MBean and returns the SNMP response to the manager. The SNMP protocol adaptor is compatible with SNMPv1 and SNMPv2 PDUs, with the exception of InformRequest which it doesn't handle.
The advantage of having an SNMP agent "inside" a Java Dynamic Management agent is that you can use the other communications protocols to interact with MIBs and manage the SNMP adaptor. Since both the registered MIBs and the adaptor are MBeans, they are exposed for management. In our simple agent, the MIB was registered, and you can view its MBeans in a web browser through the HTML protocol adaptor. Furthermore, the MIB implementations in the SNMP agent could be easily upgraded using the m-let loader service (see Chapter 6, The M-Let Class Loader).
If our agent included other connectors, management applications could connect to the agent and also manage the MIB and the SNMP adaptor. A non-SNMP manager could instantiate new MIB objects, bind them to the SNMP adaptor and operate on the exposed attributes and operations of the MIB.
Non-SNMP managers may operate on the variables of a MIB, getting and setting values regardless of any SNMP manager that might also be accessing them through the SNMP adaptor. The designer of the agent and management applications is responsible for all coherence issues when accessing MIBs concurrently through different protocols.
Non-SNMP managers can also control the SNMP agent through the MBean of the SNMP adaptor. Like the other communications MBeans, the port and other attributes can be modified when the SNMP adaptor is stopped. You can also get information about its state, and stop or restart it to control when it is on-line. These administrative attributes and operations are defined in the CommunicatorServerMBean interface.
The SNMP adaptor server also implements the SnmpAdaptorServerMBean interface to define its operating information. The Snmp group of MIB-II defines certain statistics variables that SNMP agents must expose. For example, the SNMP adaptor provides methods for getSnmpInPkts and getSnmpOutBadValues. Non-SNMP managers can read these variables as attributes of the SNMP adaptor MBean.
The SNMP adaptor also exposes other operating information that is unavailable to SNMP managers. For example, the ActiveClientCount and ServedClientCount read-only attributes report on SNMP manager connections to this agent. The read-write BufferSize attribute lets you change the size of the message buffer when the adaptor is stopped. The adaptor MBean also exposes operations for sending traps or implementing your own security (see "Message-Level Security").
After building the example as described in "MIB Development Process", launch the simple agent with the following command:
$ java -classpath classpath Agent |
You should see some initialization messages, including our notification listener giving information about the two table entries which are created. Then, you should see the agent sending out a trap every two seconds. Traps are covered in "Sending Traps", and we can ignore these messages. Access this agent's HTML adaptor by pointing a web browser to the following URL: http://localhost:8082/. Through the HTML adaptor, you can see the MBeans representing the MIB:
The class=RFC1213_MIB MBean in the snmp domain is the topmost MBean, it contains a name and information about the SNMP adaptor to which the MIB is bound
The RFC1213_MIB domain contains the MBeans for each group; these MBeans contain variables with values provided by our customizations
The ifTable domain contains the entries of the interface table
In any of these MBeans, you could write new values into the text fields of exposed attributes and click the "Apply" button. This will set the corresponding SNMP variable, and thereafter, SNMP managers will see the new value. This is an example of managing a MIB through a protocol other than SNMP.
For any SNMP agent application, you can turn on trace messages for the SNMP adaptor by specifying the -DINFO_ADAPTOR_SNMP property on the command line. The tracing mechanism is covered in the Java Dynamic Management Kit 4.0 Tools Reference guide and in the Javadoc API of the Trace class.
Type "Control-C" when you are done viewing the agent.