技术开发 频道

从黑箱到企业:JMX 集成动手实践

        OpenNMS 集成动手实践

  现在准备将新的“CLICKMETER”服务集成进 OpenNMS。要做到这一点,将创建用于功能守护程序( capsd )的插件和用于轮询器守护程序( pollerd )的监控程序。

  用于 OpenNMS 发现的 ClickMeterPlugin

  在源码分发中提供了功能守护程序插件的代码,它在 org.opennms.netmgt.capsd.ClickMeterPlugin 类中。我们知道该插件必须实现 org.opennms.netmgt.capsd.Plugin 接口。清单 1 显示了从 AbstractPlugin 派生而来的这个类。这个 OpenNMS 所提供的抽象类提供了两个抽取参数的方法( getKeyedInteger() 和 getKeyedString() ),这两个参数对我们的编码会有帮助。

  清单 1. ClickMeterPlugin 管理类

1 public final class ClickMeterPlugin extends AbstractPlugin {
2     private static final String     PROTOCOL_NAME = "CLICKMETER";
3     private static final int    DEFAULT_PORT    = 8082;
4     private final static int    DEFAULT_RETRY   = 0;
5     private final static int    DEFAULT_TIMEOUT = 5000; // in milliseconds
6

  清单 2 中代码是 getProtocolName() 方法很普通的实现:

  清单 2. getProtocolName() 方法

1 public String getProtocolName() {
2      return PROTOCOL_NAME;
3      }
4

  清单 3 中的代码是 isProtocolSupported() 方法很简短的实现:

  清单 3. isProtocolSupported() 方法

1 public boolean isProtocolSupported(InetAddress address) {
2   return isClickMeter(address, DEFAULT_PORT, DEFAULT_RETRY, DEFAULT_TIMEOUT);
3   }
4

  在 isProtocolSupported() 方法的长版本中,我们处理传入的参数以用于构造访问远程 JMX 代理的 URL。一旦从这些参数中获得了 IP 和端口,则 isProtocolSupported() 调用 isClickMeter() 方法以确定该节点上的 ClickMeter 是否处于活动状态。清单 4 显示了 isClickMeter() 代码。注意:为 URL 而定义的两个常量对应于用于 ClickMeter incPanelValue 操作所需的 HTTP 协议适配器访问 URL。

  清单 4. isClickMeter() 方法

1 private final static String CLICK_METER_BEAN_LOCATOR_URL =
2 "/InvokeAction//MBean:name=ClickMeter/action=incPanelValue?
3    action=incPanelValue";
4       private final static String CLICK_METER_ID = "incPanelValue Successful";
5       private boolean isClickMeter(InetAddress host, int port,
6         int retries, int timeout) {
7           Category log = ThreadCategory.getInstance(getClass());
8           boolean foundClickMeter = false;
9           for (int attempts=0; attempts <= retries && !foundClickMeter;
10             attempts++)
11           {                  
12                   URL jmxLink = null;
13                   InputStream iStream = null;
14       try {
15                       String hostIP = host.getHostAddress();
16                       jmxLink = new URL("http", hostIP, port,
17                         CLICK_METER_BEAN_LOCATOR_URL);
18                       if (scanURL(jmxLink, CLICK_METER_ID, log)) {
19                             foundClickMeter = true;
20                             break;   // get out of the for loop
21                            }
22                      }
23           catch(IOException e) {
24                     log.info("ClickMeterPlugin: Error communicating
25                        with host " + host.getHostAddress(), e);
26                     foundClickMeter = false;
27               }
28           }
29           return foundClickMeter;
30     }
31

  清单 5 中所显示的 scanURL() 方法是一个助手方法,它可接受作为参数的 URL 和字符串。然后,访问这个 URL,并在产生的页面中搜索所指定的字符串。如果找到该字符串,则返回 true。否则,返回 false。在这里,在访问用于 ClickMeter 的 incPanelValue 操作的 URL 之后,查寻 incPanelValue Successful字符串。

  清单 5. scanURL() 方法

1 private boolean scanURL(URL inURL, String toSearch, Category log)    {
2                   InputStream iStream = null;
3       try {
4                      iStream = inURL.openStream();
5                      BufferedReader urlReader =
6                        new BufferedReader(new InputStreamReader(iStream));
7     
8                      String curLine = urlReader.readLine();
9                         do  {
10                                 if (curLine.indexOf(toSearch) != -1) {
11                                        return true;
12                                       }
13                            curLine = urlReader.readLine();
14                          } while (curLine != null);
15                     
16               }
17                  catch  (IOException e) {
18                               e.fillInStackTrace();
19                       log.debug("ClickMeterMonitor.poll:
20                         Error reading from URL:"
21                         + inURL, e);
22         
23                   }
24       finally {
25       try {
26                        if(iStream != null)
27                              iStream.close();
28                     }
29                     catch(IOException e) {
30                         e.fillInStackTrace();
31                         log.debug("ClickMeterMonitor.poll:
32                           Error closing stream to URL.", e);
33                     }
34                }
35 return false;
36    }
37 }
38

  集成该插件所需的第 2 步将编辑 /etc/capsd-configuration.xml 文件,并添加清单 6中所显示的 protocol-plugin 定义:

  清单 6. protocol-plugin 定义

1 <protocol-plugin
2       protocol="CLICKMETER"  
3       class-name="org.opennms.netmgt.capsd.ClickMeterPlugin"
4       scan="on" >
5         <property key="port" value="8082"/>
6         <property key="timeout" value="2000"/>
7         <property key="retry" value="1"/>
8     </protocol-plugin>
9

  您可能还希望编辑 discovery-configuration.xml 文件以限制 OpenNMS 扫描受管节点的 IP 范围。在清单 7 中,我们将其限制为两个节点,这样可以快速地找到 ClickMeter 应用程序:

  清单 7. 限制发现的范围

1 <include-range retries="2" timeout="3000">
2         <begin>192.168.23.75</begin>
3         <end>192.168.23.76</end>
4     </include-range>
5

  用于 OpenNMS 的 ClickMeterMonitor

  接下来,创建轮询器守护程序( pollerd )监控程序插件: org.opennms.netmgt.poller.ClickMeterMonitor 类。该类必须实现 org.opennms.netmgt.poller.ServiceMonitor 接口。OpenNMS 提供了一个基类( org.opennms.netmgt.poller.IPv4Monitor ),这个接口中的所有方法都有缺省实现。因为不需要任何特殊的初始化或资源释放,所以只需要覆盖 poll() 方法,如清单 8 所示:

  清单 8. poll() 方法

1 public int poll(NetworkInterface iface, Map parameters) {
2        if(iface.getType() != NetworkInterface.TYPE_IPV4)
3               throw new NetworkInterfaceNotSupportedException("Unsupported
4                     interface type, only TYPE_IPV4 currently supported");
5         Category log = ThreadCategory.getInstance(getClass());
6         int retry   =
7           getKeyedInteger(parameters, "retry", DEFAULT_RETRY);
8         int port    =
9           getKeyedInteger(parameters, "port", DEFAULT_PORT);
10         int timeout =
11           getKeyedInteger(parameters, "timeout", DEFAULT_TIMEOUT);
12         InetAddress ipv4Addr = (InetAddress)iface.getAddress();
13             String hostIP = ipv4Addr.getHostAddress();
14         if (log.isDebugEnabled())
15                log.debug("ClickMeterMonitor.poll: Polling interface: "
16                      + hostIP + " timeout: " + timeout + " retry: " + retry);
17         
18         int serviceStatus = ServiceMonitor.SERVICE_UNAVAILABLE;
19         for (int attempts=0; attempts <= retry && serviceStatus !=
20               ServiceMonitor.SERVICE_AVAILABLE; attempts++) {
21                   URL jmxLink = null;
22                   InputStream iStream = null;
23       try {
24                         jmxLink = new URL("http", hostIP, port,
25                                     CLICK_METER_BEAN_LOCATOR_URL);
26                         if (scanURL(jmxLink, CLICK_METER_ID, log)) {
27                             serviceStatus = ServiceMonitor.SERVICE_AVAILABLE;
28                             break;                             }
29                      }      
30             catch(IOException e) {
31                 e.fillInStackTrace();
32                 log.debug("ClickMeterMonitor.poll:
33                        IOException while polling address: "
34                        + ipv4Addr, e);
35             }
36     }  // of for
37        return serviceStatus;
38     }
39

  注意清单 8 中访问 ClickMeter MBean 的 scanURL() 助手方法的用法。

  在 /etc/poller-configuration.xml 文件中,必须添加一条 service 定义项。在清单 9 中,将指定轮询间隔时间为 10000 毫秒(或 10 秒):

  清单 9. 轮询器守护程序 service 定义

1 <service name="CLICKMETER" interval="10000"
2     user-defined="false" status="on">
3       <parameter key="timeout" value="3000"/>
4       <parameter key="port" value="8082"/>
5   </service>
6

  在同一个 poller-configuration.xml 文件中,我们还应该插入 monitor 定义,如清单 10 所示:

  清单 10.轮询器守护程序监控程序定义

1 <monitor service="CLICKMETER"  
2   class-name="org.opennms.netmgt.poller.ClickMeterMonitor" />
3
0
相关文章