The Java interface to Solaris Bandwidth Manager is implemented as a set of management beans (m-beans) based on the Java Dynamic Management Kit framework.
Solaris Bandwidth Manager 1.6 includes the right to use the Runtime version of the Java Dynamic Management Kit to develop Solaris Bandwidth Manager applications only.
Solaris Bandwidth Manager includes Java management beans (m-beans) that provide programming interfaces to the following:
Configuration information
Directory information
Statistics and accounting
The Java APIs can each be accessed in one of two ways:
Using the Solaris Bandwidth Manager plug-ins that enable an agent to obtain m-beans from a local file.
In client mode
The Solaris Bandwidth Manager plug-ins allow the policy agent to obtain m-beans from a remote .jar file. Using the Java APIs in this way means that your applications are fully integrated into the policy agent and modify the way it works. This section contains an overview of the way in which the policy agent acts when m-beans are started and stopped, as well as a summary of the tasks that the developer must carry out to ensure that new m-beans operate correctly with the policy agent.
The example code in this section is contained in the /opt/SUNWconn/ba/html/examples directory.
The Solaris Bandwidth Manager policy agent carries out a number of tasks automatically. They are described below.
When intializing and starting an m-bean, the policy agent:
Loads the m-let text files contained in the /opt/SUNWconn/ba/html/beans/*.html directory.
Initializes the m-beans
The policy agent does so by loading the BeanName.zip and BeanName.class files and calling the initCmf() method. This:
Loads and starts the Solaris Bandwidth Manager configuration
Starts the m-beans
This is done using the performStart() method, which is defined in the com.sun.jaw.reference.agent.services.ActivatableIf interface and is part of the Java Dynamic Management Kit.
To stop an m-bean, the policy agent:
Calls the performStop() method, which is defined in the com.sun.jaw.reference.agent.services.ActivatableIf interface and is part of the Java Dynamic Management Kit.
Stops the Solaris Bandwidth Manager configuration.
Calls the deleteCmf() method to delete m-bean instances.
When writing an m-bean, you must:
Create an m-let text file.
The information on each m-bean is specified in a single instance of a tag, called the MLET tag. When an m-let text file is loaded, an instance of each m-bean specified in the file is created. For example, the m-let text file for the QDatabaseAccounting m-bean is contained in the file QDatabaseAccounting.html and looks like this:
<MLET CODE=com.sun.ba.beans.QDatabaseAccounting ARCHIVE="qdatabaseaccounting.jar, dbaccess.jar > <PARAM NAME=jdbcDriverName VALUE=com.sun.jdbc.SimpleText.SimpleTextDriver> <PARAM NAME=jdbcURLName VALUE=jdbc:SimpleText:/var/opt/SUNWconn/ba> </MLET>The attributes used in this example are:
The full Java class name of the m-bean
The files containing m-beans and other resources used by the QDataBaseAccounting m-bean. In this case the file qdatabaseaccounting.jar contains the required classes and dbaccess.jar contains the database driver.
A list of the parameters required by the QDataBaseAccounting m-bean. These will be passed as a modification list to the initCmf() method.
Implement the initCmf() method. The prototype of the initCmf() method must look like this:
. . . public void initCmf(Framework cmf, ObjectName name, boolean db, ModificationList list) . . .The ModificationList parameter is required in order to contain the list of parameters defined in the MLET tag.
You can also provide the bean and class names of the m-bean(s) to initialize:
.
.
.
ObjectName statsName = new ObjectName(cmf.getDomain(), beanName);
stats = (className) cmf.retrieveObject(statsName);
.
.
.
The initCmf() method in the QDatabaseAccounting.java file looks like this:
.
.
.
public void initCmf(Framework cmf, ObjectName name, boolean db,
ModificationList list)
throws InstanceNotFoundException, InstanceAlreadyExistException,
ServiceNotFoundException
{
this.cmf = cmf;
if (name == null) {
name = new ObjectName(cmf.getDomain(), getClass().getName());
}
if (db) {
cmf.addDBObject(this, name);
} else {
cmf.addObject(this, name);
}
this.name = name;
ObjectName statsName = new ObjectName(cmf.getDomain(), statsMOName);
stats = (QStatsInterface) cmf.retrieveObject(statsName);
String jdbcDriverName = null;
Enumeration enum = list.elements();
while (enum.hasMoreElements()) {
Modification modif = (Modification) enum.nextElement();
String property = modif.getProperty();
String value = (String) modif.getValue();
if (property.equalsIgnoreCase("jdbcDriverName")) {
jdbcDriverName = value;
} else if (property.equalsIgnoreCase("jdbcUrlName")) {
jdbcUrlName = value;
} else if (property.equalsIgnoreCase("jdbcUserName")) {
jdbcUserName = value;
} else if (property.equalsIgnoreCase("jdbcPassword")) {
jdbcPassword = value;
} else if (property.equalsIgnoreCase("jdbcTableName")) {
jdbcTableName = value;
}
}
try {
Class.forName(jdbcDriverName);
} catch (ClassNotFoundException e) {
throw new
ServiceNotFoundException("cannot load JDBC driver " + jdbcDriverName);
}
}
.
.
.
Make sure that the m-bean declaration implements the ActivatableIf interface:
.
.
.
public class QDatabaseAccounting implements QConstants, QFlowAccountingListene
r, ActivatableIf
{
.
.
.
This makes the performStart() and performStop() methods available.
Implement the performStart() method. In the case of the QDatabaseAccounting m-bean the performStart() method calls a method to start an event listener for flow accounting:
.
.
.
public void performStart()
{
if (!isActive()) {
try {
jdbcConnection = DriverManager.getConnection(jdbcUrlName, jdbcUserName,
jdbcPassword);
flowTable = new QFlowTable(jdbcConnection, jdbcTableName);
stats.addQFlowAccountingListener(this);
} catch (SQLException e) {
e.printStackTrace();
}
}
}
.
.
.
Implement the performStop() method. For the QDatabaseAccounting m-bean, the performStop() method looks like this:
.
.
.
public void performStop()
{
if (isActive()) {
stats.removeQFlowAccountingListener(this);
try {
jdbcConnection.commit();
jdbcConnection.close();
jdbcConnection = null;
flowTable = null;
} catch (SQLException e) {
e.printStackTrace();
}
}
}
.
.
.
Implement the isActive() method:
.
.
.
public boolean isActive()
{
return (jdbcConnection != null && flowTable != null);
}
.
.
.
Clients exist as separate processes, which act on the policy agent. For example, the configuration tool batool was implemented as a client.
When operating in client mode, applications connecting to the policy agent must specify a password at connect time in order to have write access.
First, you must import the necessary classes:
import com.sun.jaw.impl.adaptor.security.AuthInfo;
Then, when connecting to the policy agent, specify the password:
.
.
.
AdaptorMO adaptor = new AdaptorClient();
AuthInfo auth = new AuthInfo ("login", "password");
adaptor.connect (auth, host, portnumber, servicename.APT)
.
.
.
The login and password are the ones set when the Solaris Bandwidth Manager packages were installed. They are defined in the /etc/opt/SUNWconn/ba/agent.properties file.
You must also provide the name and class names of the c-beans to be retrieved:
.
.
.
ObjectName on = new ObjectName(domain, BeanName);
Vector v =adaptor.getObject (on, null);
if (v == null || v.size() ==0)
{
System.err.println("Unable to retrieve the Bandwidth Manager m-bean.");
System.err.println("Try stopping and restarting the policy agent";
System,exit(1);
}
className userDefinedVariable = (className) v.elementAt(0);
.
.
.
The configuration m-bean provides classes and methods for configuring Solaris Bandwidth Manager. The main methods provided are:
Table 2-1 Configuration M-bean Classes and Methods|
Class |
Method |
Description |
|---|---|---|
|
QDynamicConf |
addQClassListener() |
Registers a listener for receiving class events |
|
addQFilterListener() |
Registers a listener for receiving filter events |
|
|
performAddClass() |
Adds the specified class to the running configuration |
|
|
performAddFilterToClass() |
Adds a filter to the specified class |
|
|
performGetService() |
Returns the specified service |
|
|
performModifyClass() |
Changes the attributes of the specified class. It this is not possible, removes the class and re-creates it. |
|
|
performModifyFilter() |
Changes the attributes of the specified filter |
|
|
performRemoveClass() |
Removes specified class and its children from the running configuration |
|
|
performRemoveFilterFromClass() |
Removes the specified filter |
|
|
removeQClassListener() |
Removes listener for class events |
|
|
removeQFilterListener() |
Removes a listener for filter events |
|
|
setTimeout() |
Sets the timeout property and starts or restarts the garbage collection thread. |
To call the configuration m-bean, you require the following:
|
M-bean name |
QConstants.confMOName |
|
M-bean class name |
com.sun.ba.config.QDynamicConf |
|
C-bean class name |
com.sun.ba.mo.QDynamicConfMO |
The directory policy m-bean provides classes and methods for monitoring changes to directory information. The main classes and methods are:
Table 2-2 Directory M-bean Classes and Methods|
Class |
Method |
Description |
|---|---|---|
|
QDirMod |
toString() |
Returns a string representation of operation/value pairs |
|
getOpe() |
Returns the operation (ADD, MODIFY, or DELETE) |
|
|
getAttr() |
Returns the name of the attribute to which the operation applies |
|
|
QDirRep |
toString() |
Returns a string representation of the replication data sent by the directory server |
|
getDirOpe() |
Returns the operation (ADD, MODIFY, MODIFYDN, or DELETE) |
|
|
getDN() |
Returns the distinguished name (DN) of an entry |
|
|
getQDirMods() |
Returns the vector of modifications sent when the operation is a MODIFY |
|
|
getNewDN() |
Returns the new DN sent when the operation is a MODIFYDN |
|
|
getAttrs() |
Returns the list of attribute/value pairs sent when the operation is an ADD |
|
|
QDirEvent |
getTarget() |
Returns the replicated modification referred to in the event |
|
QDir |
addQDirListener() |
Registers a listener for receiving directory-related events |
|
removeQDirListener() |
Stops a listener receiving directory-related events |
|
|
QDirListener |
handleQDirEvent() |
Returns an event |
To call the directory m-bean, you require the following:
|
M-bean name |
QConstants.dirMOName |
|
M-bean class name |
com.sun.ba.ldap.QDir |
|
C-bean class name |
com.sun.ba.mo.QDirMO |
The statistics m-bean contains methods for collecting statistics. Some of these methods are implemented using native methods to call the C Statistics API. The main classes and methods are:
Table 2-3 Statistics M-bean Classes and Methods|
Class |
Method |
Description |
|---|---|---|
|
QStatsInterface |
addQFlowAccountingListener() |
Registers a listener for flow accounting events |
|
addQFlowAddedListener() |
Registers a listener for flow added events |
|
|
addQStatsResetListener() |
Registers a listener for statistics reset events |
|
|
performGetClassStats() |
Returns statistics for the specified class |
|
|
performGetFlowStats() |
Returns flow statistics for the specified class |
|
|
removeQFlowAccountingListener() |
Removes flow accounting events listener |
|
|
removeQFlowAddedListener() |
Removes listener for new flow events |
|
|
removeQStatsResetListener() |
Removes listener for statistics reset events |
|
|
QClassStats |
getBdrops() |
Returns the number of bytes dropped by this class |
|
getBorrows() |
Returns the number of packets sent using bandwidth borrowed from the parent class |
|
|
getClassName() |
Returns the distinguished name of the class |
|
|
getDrops() |
Returns the number of packets dropped by this class |
|
|
getLastSeen() |
Returns the time at which the last packet was sent |
|
|
getNumBytes() |
Returns the number of bytes sent through this class |
|
|
getNumPackets() |
Returns the number of packets sent through this class |
|
|
QFlow |
getClassName() |
Returns the distinguished name of the class this flow belongs to |
|
getFirstSeen() |
Returns the time at which the first packet was sent through this flow |
|
|
getLastSeen() |
Returns the time at which the last packet was sent through this flow |
|
|
getLocalIP() |
Returns the local IP address |
|
|
getLocalPort() |
Returns the local port number |
|
|
getNumBytes() |
Returns the number of bytes sent through this flow |
|
|
getNumPackets() |
Returns the number of packets sent through this flow |
|
|
getProtocol() |
Returns the IP protocol value |
|
|
getRemoteIP() |
Returns the remote IP address |
|
|
getRemotePort() |
Returns the remote port number |
|
|
getTosSent() |
Returns the Type of Service for this flow, after possible marking |
|
|
getURL() |
Returns the URL associated with this flow (null if not applicable) |
To call the statistics m-bean, you require the following:
|
M-bean name |
QConstants.statsMOName |
|
M-bean class name |
com.sun.ba.stats.QStatsInterface |
|
C-bean class name |
com.sun.ba.mo.QStatsInterfaceMO |