OpenNMS擴展–基於JoeSNMP/MIB數據訪問實現

OpenNMS擴展基於JoeSNMP/MIB數據訪問實現

1.     MIB訪問流程及原理

JoeSNMPOpenNMS採用的SNMP API,已獨立成爲一個Open Source Framework,基於JoeSNMP可以對MIB網絡數據進行相應的操作。JoeSNMP封裝了多個對SNMP Get,Set等操作的處理。

l         Get:用於讀取設備MIB信息庫中實例對象的單個值,GetOID表示對象實例值,

l         Set:用於簡單的設置MIB中可讀寫的對象實例值。

MIB訪問的主流程圖如下:

 

1. MIB訪問的主流程圖

首先根據自變量接收一個要訪問的被管理對象主機名,並接收要查詢的對象標識符的簡略定義形式. 過程首先生成SNMP 報文,一旦報文生成,再把報文簡單反轉過來,發送出去.生成SNMP 報文後,建立代理地址,創建套接字連接,以便代理能將響應發回. 然後,SNMP 請求報文發給代理 ,等待一個響應的到來.因爲SNMP 是工作在UDP 之上的,所以在SNMP 應用實體間通信時,無需先建立連接,這樣雖降低了系統開銷,UDP 傳輸是不可靠的,爲此,網絡管理站採取了相應的超時和重發策略. 系統在發出請求報文之後,啓動超時計數器,等待響應的到來,並設置重發次數爲3. 3 次之後仍沒有收到響應,則關閉套接字,並返回一個接收失敗錯誤代碼. 反之,若確定收到一個響應,則調用一過程來把響應轉換成爲內部表示形式, 即對SNMP 報文進行譯碼. 再用已保存的Request-id與響應Request-id段進行比較,來驗證這個報文是否是剛纔發出的請求報文的響應. 若是,就調用另一個過程,把每段對象標識符的ASN.1表示形式轉換成自己的內部形式,並顯示其值

2.     Get-Request/Set-Request步驟

            實現SnmpHandler接口

寫一個SnmpSet, SnmpGet, implement SnmpHandler,實現處理SNMP的方法:snmpReceivedPdu, snmpTimeoutErrortsnmpInternalError. 如:SnmpGet.java

 

public class SnmpGet implements SnmpHandler {

     /**

     * The log4j category used to log debug messsages and statements.

     */

    private static final String LOG4J_CATEGORY = "SureTech.NMS";

    

     public void snmpInternalError(SnmpSession session, int err, SnmpSyntax pdu) {

              System.out.println("InternalError");

              value ="Internal Error";

              synchronized (session) {

                       session.notify();

              }

     }

 

     public void snmpReceivedPdu(SnmpSession session, int command, SnmpPduPacket pdu) {

              ThreadCategory.setPrefix(LOG4J_CATEGORY);

         Category log = ThreadCategory.getInstance();

              SnmpVarBind varBind = pdu.getVarBindAt(0);

              value = varBind.getValue().toString();

              if(log.isDebugEnabled()){

                       log.debug("Received value: " + varBind.getName() + "="

                                 + varBind.getValue());

              }

              synchronized (session) {

                       session.notify();

              }

     }

 

     public void snmpTimeoutError(SnmpSession session, SnmpSyntax pdu) {

              System.out.println("SnmpTimeout");

              value ="Snmp Timeout";

              synchronized (session) {

                       session.notify();

              }

     }

}

 

2.2創建SnmpPeer對象

創建一個SnmpPeer對象,需定義:

l         AgentIP地址

l         port (defaults to 161)

l         retries (defaults to 3)

l         timeout (defaults to .8 seconds)

如下在方法snmpGet方法中的紅色代碼片段:

/**

     * The value of snmpget command.

     */

     public String snmpGet(String host, String oid) throws SocketException,

                       UnknownHostException {

              InetAddress remote = InetAddress.getByName(host);

              SnmpPeer peer = new SnmpPeer(remote);

              peer.setPort(161);

              peer.setTimeout(5000);

              peer.setRetries(1); // it is actually number of tries

 

              SnmpParameters parms = peer.getParameters();

              parms.setVersion(SnmpSMI.SNMPV2);

              parms.setReadCommunity("public");

 

              final SnmpSession session = new SnmpSession(peer);

              session.setDefaultHandler(new SnmpGet());

 

              SnmpVarBind[] vblist = { new SnmpVarBind(oid) };

              SnmpPduRequest pdu = new SnmpPduRequest(

                                 oid.endsWith(".0") ? SnmpPduPacket.GET : SnmpPduPacket.GETNEXT,

                                 vblist);

              pdu.setRequestId(1);

 

              try {

                       synchronized (session) {

                                 session.send(pdu);

                                 session.wait();

                       }

 

              } catch (InterruptedException e) {

                       // do nothing

              } finally {

                       session.close();

              }

              return value;

     }

2.3創建SnmpParameters對象

創建一個SnmpPeer對象,需定義:

l         read community string (defaults to public)

l         write community string (defaults to null)

l         SNMP version to use (defaults to SNMPV1)

l         AsnEncoder to use (defaults to BER)

SnmpParameters parms = peer.getParameters();

parms.setVersion(SnmpSMI.SNMPV2);

parms.setReadCommunity("public");

2.4創建SnmpSession對象,發送PDU

SnmpPeer創建一個SnmpSession對象,這樣就創建一個“SnmpPortal”線程,此線程用來接受來自遠程Agent的響應,也可以創建一個Quene來處理所有的SNMP請求。

final SnmpSession session = new SnmpSession(peer);

              session.setDefaultHandler(new SnmpGet());

 

              SnmpVarBind[] vblist = { new SnmpVarBind(oid) };

              SnmpPduRequest pdu = new SnmpPduRequest(

                                 oid.endsWith(".0") ? SnmpPduPacket.GET : SnmpPduPacket.GETNEXT,

                                 vblist);

              pdu.setRequestId(1);

 

              try {

                       synchronized (session) {

                                 session.send(pdu);

                                 session.wait();

                       }

              } catch (InterruptedException e) {

                       // do nothing

              } finally {

                       session.close();

              }

 

l         通過調用session.send(pdu)發送PDU請求到遠程的Agent,開啓一個新的線程發送請求和處理重試或超時。

l         調用session.wait()進行線程等待。

l         SNMP session線程收到來自Agent的響應後會調用snmpTimeoutError方法,如果Agent沒有在超時時間內響應,SNMP session線程將調用snmpTimeoutError方法,如果是內部發生了問題,則調用snmpInternalError方法。

l         線程喚醒,並繼續處理。

2.5關閉Session

session.close();

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章