org.nervousync.utils.SNMPUtils Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of utils-jdk11 Show documentation
Show all versions of utils-jdk11 Show documentation
Java utility collections, development by Nervousync Studio (NSYC)
/*
* Licensed to the Nervousync Studio (NSYC) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.nervousync.utils;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
import org.nervousync.commons.Globals;
import org.snmp4j.CommunityTarget;
import org.snmp4j.PDU;
import org.snmp4j.Snmp;
import org.snmp4j.Target;
import org.snmp4j.UserTarget;
import org.snmp4j.event.ResponseEvent;
import org.snmp4j.mp.MPv3;
import org.snmp4j.mp.SnmpConstants;
import org.snmp4j.security.AuthMD5;
import org.snmp4j.security.AuthSHA;
import org.snmp4j.security.Priv3DES;
import org.snmp4j.security.PrivDES;
import org.snmp4j.security.SecurityLevel;
import org.snmp4j.security.SecurityModels;
import org.snmp4j.security.SecurityProtocols;
import org.snmp4j.security.USM;
import org.snmp4j.security.UsmUser;
import org.snmp4j.smi.*;
import org.snmp4j.transport.DefaultTcpTransportMapping;
import org.snmp4j.transport.DefaultUdpTransportMapping;
import org.nervousync.beans.snmp.SNMPData;
import org.nervousync.beans.snmp.TargetHost;
import org.nervousync.commons.snmp.SNMPDataOperator;
import org.nervousync.enumerations.net.IPProtocol;
import org.nervousync.enumerations.snmp.SNMPVersion;
import org.nervousync.enumerations.snmp.auth.SNMPAuthProtocol;
import org.nervousync.exceptions.snmp.ProcessorConfigException;
/**
* SNMP utilities
* SNMP工具集
*
* @author Steven Wee [email protected]
* @version $Revision: 1.2.0 $ $Date: Oct 25, 2017 20:50:34 $
*/
public final class SNMPUtils {
/**
* Singleton instance
* 单一实例对象
*/
private static volatile SNMPUtils INSTANCE = null;
/**
* Logger instance
* 日志实例
*/
private static final LoggerUtils.Logger LOGGER = LoggerUtils.getLogger(SNMPUtils.class);
/**
* Prefix string of UDP protocol
* UDP协议前缀
*/
private static final String PROTOCOL_UDP = "udp:";
/**
* Prefix string of TCP protocol
* TCP协议前缀
*/
private static final String PROTOCOL_TCP = "tcp:";
/**
* Schedule process period time (Unit: milliseconds)
* 调度处理的间隔时间(单位:毫秒)
*/
private final long period;
/**
* Registered target host list
* 注册的目标主机列表
*/
private final List existsHosts;
/**
* Schedule processor
* 调度处理器
*/
private final ScheduledExecutorService scheduledExecutorService;
/**
* UDP agent
* UDP客户端
*/
private Snmp udpAgent;
/**
* TCP agent
* TCP客户端
*/
private Snmp tcpAgent;
/**
* Private constructor for SNMPUtils
* SNMP工具集的私有构造方法
*
* @param serverCount Maximum size of registered server list
* 允许注册目标主机的最大值
* @param period Schedule process period time (Unit: milliseconds)
* 调度处理的间隔时间(单位:毫秒)
*
* @throws IOException
* If an error occurs when generate agent
* 当创建客户端时出现异常
*/
private SNMPUtils(final int serverCount, final long period) throws IOException {
this.period = Math.max(period, 1000L);
this.existsHosts = new ArrayList<>(serverCount);
this.scheduledExecutorService = Executors.newScheduledThreadPool(serverCount);
this.udpAgent = new Snmp(new DefaultUdpTransportMapping());
this.udpAgent.listen();
this.tcpAgent = new Snmp(new DefaultTcpTransportMapping());
this.tcpAgent.listen();
}
/**
* Initialize SNMP Utilities
* 初始化SNMP工具集
*
* @param serverCount Maximum size of registered server list
* 允许注册目标主机的最大值
*
* @return Initialize result
* 初始化结果
*/
public static boolean initialize(final int serverCount) {
return SNMPUtils.initialize(serverCount, Globals.DEFAULT_VALUE_LONG);
}
/**
* Initialize SNMP Utilities
* 初始化SNMP工具集
*
* @param serverCount Maximum size of registered server list
* 允许注册目标主机的最大值
* @param period Schedule process period time (Unit: milliseconds)
* 调度处理的间隔时间(单位:毫秒)
*
* @return Initialize result
* 初始化结果
*/
public static boolean initialize(final int serverCount, final long period) {
if (SNMPUtils.INSTANCE != null) {
return Boolean.TRUE;
}
try {
synchronized (SNMPUtils.class) {
if (SNMPUtils.INSTANCE == null) {
SNMPUtils.INSTANCE = new SNMPUtils(serverCount, period);
}
}
return Boolean.TRUE;
} catch (IOException e) {
LOGGER.error("Init_SNMP_Error");
if (LOGGER.isDebugEnabled()) {
LOGGER.debug("Stack_Message_Error", e);
}
return Boolean.FALSE;
}
}
/**
* Static method for retrieve singleton instance of SNMP utilities
* 静态方法用于获取SNMP工具集单例实例对象
*
* @return Singleton instance
* 单例实例对象
*/
public static SNMPUtils getInstance() {
return SNMPUtils.INSTANCE;
}
/**
* Add monitor target host
* 添加要监控的目标主机
*
* @param identifiedKey Identify key of target host
* 目标主机的唯一标识字符串
* @param targetHost Target host instance
* 目标主机实例对象
* @param pduArray PDU instance array
* 协议数据单元实例对象数组
* @param snmpDataOperator SNMP data operator instance
* SNMP数据操作器实例对象
*
* @return Add result
* 添加结果
*/
public boolean addMonitor(final String identifiedKey, final TargetHost targetHost,
final SNMPDataOperator snmpDataOperator, final PDU... pduArray) {
if (this.existsHosts.contains(targetHost)) {
return Boolean.TRUE;
}
try {
this.existsHosts.add(targetHost);
this.scheduledExecutorService.scheduleAtFixedRate(
new SNMPProcessor(identifiedKey, targetHost, snmpDataOperator, pduArray),
0L, this.period, TimeUnit.MILLISECONDS);
return Boolean.TRUE;
} catch (ProcessorConfigException e) {
LOGGER.error("Add_Target_SNMP_Error");
if (LOGGER.isDebugEnabled()) {
LOGGER.debug("Stack_Message_Error", e);
}
return Boolean.FALSE;
}
}
/**
* Destroy agent and schedule processor
* 静态方法用于获取SNMP工具集单例实例对象
*
* @throws IOException
* If an error occurs when close agent
* 当关闭客户端时出现异常
*/
public static void destroy() throws IOException {
if (INSTANCE != null) {
INSTANCE.scheduledExecutorService.shutdownNow();
INSTANCE.tcpAgent.close();
INSTANCE.tcpAgent = null;
INSTANCE.udpAgent.close();
INSTANCE.udpAgent = null;
INSTANCE.existsHosts.clear();
INSTANCE = null;
}
}
/**
* Retrieve data from target host
* 从目标主机读取数据
*
* @param protocol IP Protocol
* IP协议
* @param target Target host instance
* 目标主机实例对象
* @param pdu PDU instance
* 协议数据单元实例对象
*
* @return Read data list
* 读取数据列表
*/
private List retrieveData(final IPProtocol protocol, final Target target, final PDU pdu) {
try {
ResponseEvent responseEvent;
switch (protocol) {
case TCP:
responseEvent = this.tcpAgent.send(pdu, target);
break;
case UDP:
responseEvent = this.udpAgent.send(pdu, target);
break;
default:
return new ArrayList<>();
}
if (responseEvent != null && responseEvent.getResponse() != null) {
PDU response = responseEvent.getResponse();
if (response.getErrorIndex() == PDU.noError
&& response.getErrorStatus() == PDU.noError) {
return response.getBindingList(new OID());
}
}
} catch (IOException e) {
LOGGER.error("Retrieve_Data_SNMP_Error");
if (LOGGER.isDebugEnabled()) {
LOGGER.debug("Stack_Message_Error", e);
}
}
return new ArrayList<>();
}
/**
* SNMP processor
* SNMP处理器线程
*
* @author Steven Wee [email protected]
* @version $Revision: 1.0.0 $ $Date: Oct 25, 2017 21:08:26 $
*/
private static final class SNMPProcessor implements Runnable {
/**
* Identify key of target host
* 目标主机的唯一标识字符串
*/
private final String identifiedKey;
/**
* IP Protocol
* IP协议
*/
private final IPProtocol protocol;
/**
* Target host instance
* 目标主机实例对象
*/
private final Target target;
/**
* PDU instance array
* 协议数据单元实例对象数组
*/
private final PDU[] pduArray;
/**
* SNMP data operator instance
* SNMP数据操作器实例对象
*/
private final SNMPDataOperator snmpDataOperator;
/**
* Private constructor for SNMPProcessor
* SNMP处理器线程的私有构造方法
*
* @param identifiedKey Identify key of target host
* 目标主机的唯一标识字符串
* @param targetHost Target host instance
* 目标主机实例对象
* @param pduArray PDU instance array
* 协议数据单元实例对象数组
* @param snmpDataOperator SNMP data operator instance
* SNMP数据操作器实例对象
*
* @throws ProcessorConfigException the processor config exception
*/
public SNMPProcessor(final String identifiedKey, final TargetHost targetHost,
final SNMPDataOperator snmpDataOperator, final PDU... pduArray)
throws ProcessorConfigException {
if (identifiedKey == null || targetHost == null || pduArray == null
|| pduArray.length == 0 || snmpDataOperator == null) {
throw new ProcessorConfigException(0x000000FF0001L, "Parameter_Invalid_Error");
}
this.identifiedKey = identifiedKey;
this.protocol = targetHost.getProtocol();
this.target = SNMPUtils.getInstance().generateTarget(targetHost);
this.pduArray = pduArray;
this.snmpDataOperator = snmpDataOperator;
}
/**
* (Non-Javadoc)
* @see Runnable#run()
*/
@Override
public void run() {
SNMPData snmpData = new SNMPData();
snmpData.setIdentifiedKey(this.identifiedKey);
Arrays.asList(this.pduArray).forEach(pdu ->
SNMPUtils.getInstance().retrieveData(this.protocol, this.target, pdu).forEach(snmpData::addData));
this.snmpDataOperator.operateData(snmpData);
}
}
/**
* Retrieve authenticate protocol OID instance
* SNMP处理器线程的私有构造方法
*
* @param snmpAuthProtocol SNMP Authentication Protocol
* SNMP身份验证协议
* @return OID instance
* OID实例对象
*/
private OID retrieveAuthProtocol(final SNMPAuthProtocol snmpAuthProtocol) {
switch (snmpAuthProtocol) {
case MD5:
return AuthMD5.ID;
case SHA:
return AuthSHA.ID;
}
return null;
}
/**
* Convert TargetHost instance to Target instance
* SNMP处理器线程的私有构造方法
*
* @param targetHost SNMP Target Host instance
* SNMP目标主机实例对象
*
* @return Converted Target instance
* 转换后的Target实例对象
*/
private Target generateTarget(final TargetHost targetHost) {
if (targetHost == null) {
return null;
}
String address = null;
switch (targetHost.getProtocol()) {
case TCP:
address = PROTOCOL_TCP + targetHost.getIpAddress() + "/" + targetHost.getPort();
break;
case UDP:
address = PROTOCOL_UDP + targetHost.getIpAddress() + "/" + targetHost.getPort();
break;
}
Target target;
if (SNMPVersion.VERSION3.equals(targetHost.getVersion())) {
USM usm = new USM(SecurityProtocols.getInstance(), new OctetString(MPv3.createLocalEngineID()), 0);
SecurityModels.getInstance().addSecurityModel(usm);
target = new UserTarget<>();
OctetString securityName = null;
OID authProtocol = null;
OctetString authPassword = null;
OID privProtocol = null;
OctetString privPassword = null;
switch (targetHost.getAuth()) {
case NOAUTH_NOPRIV:
target.setSecurityLevel(SecurityLevel.NOAUTH_NOPRIV);
securityName = new OctetString("noAuthUser");
break;
case AUTH_NOPRIV:
target.setSecurityLevel(SecurityLevel.AUTH_NOPRIV);
securityName = new OctetString("authUser");
authProtocol = retrieveAuthProtocol(targetHost.getAuthProtocol());
authPassword = new OctetString(targetHost.getAuthPassword());
break;
case AUTH_PRIV:
target.setSecurityLevel(SecurityLevel.AUTH_PRIV);
securityName = new OctetString("privUser");
authProtocol = retrieveAuthProtocol(targetHost.getAuthProtocol());
authPassword = new OctetString(targetHost.getAuthPassword());
switch (targetHost.getPrivProtocol()) {
case PrivDES:
privProtocol = PrivDES.ID;
break;
case Priv3DES:
privProtocol = Priv3DES.ID;
break;
}
privPassword = new OctetString(targetHost.getPrivPassword());
break;
}
if (securityName != null) {
target.setSecurityName(securityName);
UsmUser usmUser = new UsmUser(securityName, authProtocol, authPassword, privProtocol, privPassword);
switch (targetHost.getProtocol()) {
case TCP:
this.tcpAgent.getUSM().addUser(securityName, usmUser);
break;
case UDP:
this.udpAgent.getUSM().addUser(securityName, usmUser);
break;
}
}
} else {
target = new CommunityTarget<>();
((CommunityTarget)target).setCommunity(new OctetString(targetHost.getCommunity()));
}
target.setAddress(GenericAddress.parse(address));
target.setRetries(targetHost.getRetries());
target.setTimeout(targetHost.getTimeOut());
switch (targetHost.getVersion()) {
case VERSION1:
target.setVersion(SnmpConstants.version1);
break;
case VERSION2C:
target.setVersion(SnmpConstants.version2c);
break;
case VERSION3:
target.setVersion(SnmpConstants.version3);
break;
}
return target;
}
}