/* * Copyright 2015, Yahoo Inc. * Copyrights licensed under the Apache License. * See the accompanying LICENSE file for terms. */ package com.yahoo.dba.perf.myperf.snmp; import java.io.IOException; import java.math.BigDecimal; import java.util.ArrayList; import java.util.HashMap; import java.util.LinkedHashMap; import java.util.List; import java.util.Map; import java.util.logging.Logger; import org.snmp4j.CommunityTarget; import org.snmp4j.PDU; import org.snmp4j.ScopedPDU; import org.snmp4j.Snmp; import org.snmp4j.Target; import org.snmp4j.TransportMapping; 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.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.Address; import org.snmp4j.smi.GenericAddress; import org.snmp4j.smi.OID; import org.snmp4j.smi.OctetString; import org.snmp4j.smi.VariableBinding; import org.snmp4j.transport.DefaultUdpTransportMapping; import org.snmp4j.util.DefaultPDUFactory; import org.snmp4j.util.TableEvent; import org.snmp4j.util.TableUtils; import com.yahoo.dba.perf.myperf.common.SNMPSettings; /** * A simple SNMP client to poll a single MySQL server for OS performance metrics, such as CPU, memory, disk usage, etc. * This SNMP client uses snmp4j open source library. * @author xrao * */ public class SNMPClient { //common UC DAVIS oid public final static String memTotalSwap = ".1.3.6.1.4.1.2021.4.3.0"; public final static String memAvailSwap = ".1.3.6.1.4.1.2021.4.4.0"; public final static String memTotalReal = ".1.3.6.1.4.1.2021.4.5.0"; public final static String memAvailReal = ".1.3.6.1.4.1.2021.4.6.0"; public final static String memTotalSwapTXT = ".1.3.6.1.4.1.2021.4.7.0"; public final static String memTotalRealTXT = ".1.3.6.1.4.1.2021.4.9.0"; public final static String memTotalFree = ".1.3.6.1.4.1.2021.4.11.0"; public final static String memShared = ".1.3.6.1.4.1.2021.4.13.0"; public final static String memBuffer = ".1.3.6.1.4.1.2021.4.14.0"; public final static String memCached = ".1.3.6.1.4.1.2021.4.15.0"; public final static String memUsedSwapTXT = ".1.3.6.1.4.1.2021.4.16.0"; public final static String memUsedRealTXT = ".1.3.6.1.4.1.2021.4.17.0"; public final static String ssSwapIn = ".1.3.6.1.4.1.2021.11.3.0"; public final static String ssSwapOut = ".1.3.6.1.4.1.2021.11.4.0"; public final static String ssIOSent = ".1.3.6.1.4.1.2021.11.5.0"; public final static String ssIOReceive = ".1.3.6.1.4.1.2021.11.6.0"; public final static String ssSysInterrupts = ".1.3.6.1.4.1.2021.11.7.0"; public final static String ssSysContext = ".1.3.6.1.4.1.2021.11.8.0"; public final static String ssCpuUser = ".1.3.6.1.4.1.2021.11.9.0"; public final static String ssCpuSystem = ".1.3.6.1.4.1.2021.11.10.0"; public final static String ssCpuIdle = ".1.3.6.1.4.1.2021.11.11.0"; public final static String ssCpuRawUser = ".1.3.6.1.4.1.2021.11.50.0"; public final static String ssCpuRawNice = ".1.3.6.1.4.1.2021.11.51.0"; public final static String ssCpuRawSystem= ".1.3.6.1.4.1.2021.11.52.0"; public final static String ssCpuRawIdle = ".1.3.6.1.4.1.2021.11.53.0"; public final static String ssCpuRawWait = ".1.3.6.1.4.1.2021.11.54.0"; public final static String ssCpuRawKernel = ".1.3.6.1.4.1.2021.11.55.0"; public final static String ssCpuRawInterrupt = ".1.3.6.1.4.1.2021.11.56.0"; public final static String ssIORawSent = ".1.3.6.1.4.1.2021.11.57.0"; public final static String ssIORawReceived = ".1.3.6.1.4.1.2021.11.58.0"; public final static String ssRawInterrupts = ".1.3.6.1.4.1.2021.11.59.0"; public final static String ssRawContexts = ".1.3.6.1.4.1.2021.11.60.0"; public final static String ssCpuRawSoftIRQ = ".1.3.6.1.4.1.2021.11.61.0"; public final static String ssRawSwapIn = ".1.3.6.1.4.1.2021.11.62.0"; public final static String ssRawSwapOut = ".1.3.6.1.4.1.2021.11.63.0"; public final static String ssCpuRawSteal = ".1.3.6.1.4.1.2021.11.64.0"; public final static String ssCpuRawGuest = ".1.3.6.1.4.1.2021.11.65.0"; public final static String ssCpuRawGuestNice = ".1.3.6.1.4.1.2021.11.66.0"; public final static String laLoad1m = ".1.3.6.1.4.1.2021.10.1.3.1"; public final static String laLoad5m = ".1.3.6.1.4.1.2021.10.1.3.2"; public final static String laLoad15m = ".1.3.6.1.4.1.2021.10.1.3.3"; public final static String hrSystemUptime = ".1.3.6.1.2.1.25.1.1.0"; public final static String hrSystemNumUsers= ".1.3.6.1.2.1.25.1.5.0"; public final static String hrSystemProcesses = ".1.3.6.1.2.1.25.1.6.0"; public final static String tcpAttemptFails = ".1.3.6.1.2.1.6.7.0"; public final static String tcpCurrEstab = ".1.3.6.1.2.1.6.9.0"; //tcpCurrEstab public static OID[] COMMON_SYS_OIDS = null; public static final Map<String, String> OID_MAP = new LinkedHashMap<String, String>(); //Name to OID public static final Map<String, String> OID_NAME_MAP = new LinkedHashMap<String, String>(); //OID to Name private static Logger logger = Logger.getLogger(SNMPClient.class.getName()); Snmp snmp = null; String address = null; private String community; private String version; //v3 support private String username; private String password; private String authprotocol; private String privacypassphrase; private String privacyprotocol; private String context; static { OID_MAP.put("memTotalSwap",memTotalSwap); OID_MAP.put("memAvailSwap", memAvailSwap); OID_MAP.put("memTotalReal", memTotalReal); OID_MAP.put("memAvailReal", memAvailReal); OID_MAP.put("memTotalSwapTXT", memTotalSwapTXT); OID_MAP.put("memTotalRealTXT", memTotalRealTXT); OID_MAP.put("memTotalFree", memTotalFree); OID_MAP.put("memShared", memShared); OID_MAP.put("memBuffer", memBuffer); OID_MAP.put("memCached", memCached); OID_MAP.put("memUsedSwapTXT", memUsedSwapTXT); OID_MAP.put("memUsedRealTXT", memUsedRealTXT); OID_MAP.put("ssSwapIn", ssSwapIn); OID_MAP.put("ssSwapOut", ssSwapOut); OID_MAP.put("ssIOSent", ssIOSent); OID_MAP.put("ssIOReceive", ssIOReceive); OID_MAP.put("ssSysInterrupts",ssSysInterrupts); OID_MAP.put("ssSysContext", ssSysContext); OID_MAP.put("ssCpuUser", ssCpuUser); OID_MAP.put("ssCpuSystem", ssCpuSystem); OID_MAP.put("ssCpuIdle", ssCpuIdle); OID_MAP.put("ssCpuRawUser", ssCpuRawUser); OID_MAP.put("ssCpuRawNice", ssCpuRawNice); OID_MAP.put("ssCpuRawSystem",ssCpuRawSystem); OID_MAP.put("ssCpuRawIdle", ssCpuRawIdle); OID_MAP.put("ssCpuRawWait", ssCpuRawWait); OID_MAP.put("ssCpuRawKernel", ssCpuRawKernel); OID_MAP.put("ssCpuRawInterrupt",ssCpuRawInterrupt); OID_MAP.put("ssIORawSent", ssIORawSent); OID_MAP.put("ssIORawReceived" ,ssIORawReceived); OID_MAP.put("ssRawInterrupts", ssRawInterrupts); OID_MAP.put("ssRawContexts", ssRawContexts); OID_MAP.put("ssCpuRawSoftIRQ", ssCpuRawSoftIRQ); OID_MAP.put("ssRawSwapIn", ssRawSwapIn); OID_MAP.put("ssRawSwapOut", ssRawSwapOut); OID_MAP.put("ssCpuRawSteal", ssCpuRawSteal); OID_MAP.put("ssCpuRawGuest", ssCpuRawGuest); OID_MAP.put("ssCpuRawGuestNice", ssCpuRawGuestNice); OID_MAP.put("laLoad1m", laLoad1m); OID_MAP.put("laLoad5m", laLoad5m); OID_MAP.put("laLoad15m", laLoad15m); OID_MAP.put("hrSystemUptime",hrSystemUptime); OID_MAP.put("hrSystemNumUsers",hrSystemNumUsers); OID_MAP.put("hrSystemProcesses",hrSystemProcesses); OID_MAP.put("tcpAttemptFails",tcpAttemptFails); OID_MAP.put("tcpCurrEstab",tcpCurrEstab); COMMON_SYS_OIDS = new OID[OID_MAP.size()]; int oidIdx = 0; for(Map.Entry<String, String> e: OID_MAP.entrySet()) { OID_NAME_MAP.put(e.getValue(), e.getKey()); COMMON_SYS_OIDS[oidIdx] = new OID(e.getValue()); oidIdx ++; } }; public static class SNMPTriple { public String oid; public String name; public String value; public SNMPTriple(String oid, String name, String value) { this.oid = oid; this.name = name; this.value = value; } } /** * Constructor * @param host_name target host name. The final snmp address will in the form of udp:host_name/port, for example udp:127.0.0.1/161 */ public SNMPClient(String host_name) { address = "udp:"+host_name+"/161"; } /** * Retrieve common system SNMP data * @return * @throws IOException */ public Map<String, String> querySysData() throws IOException { logger.fine("Query snmp for "+address); Map<String, String> resMap = null; resMap = new java.util.LinkedHashMap<String, String>(); Map<OID, String> res = get(COMMON_SYS_OIDS); if(res!=null) { for(Map.Entry<OID, String> e: res.entrySet()) { if("noSuchObject".equalsIgnoreCase(e.getValue()))continue; resMap.put(OID_NAME_MAP.get("."+e.getKey().toString()), e.getValue()); } } return resMap; } /** * * @return * @throws IOException */ public List<SNMPTriple> querySysData3() throws IOException { logger.fine("Query snmp system data for "+address); List<SNMPTriple> snmpList = new ArrayList<SNMPTriple>(); Map<OID, String> res = get(COMMON_SYS_OIDS); if(res!=null) { for(Map.Entry<OID, String> e: res.entrySet()) { if("noSuchObject".equalsIgnoreCase(e.getValue()))continue; snmpList.add(new SNMPTriple(e.getKey().toString(), OID_NAME_MAP.get("."+e.getKey().toString()), e.getValue())); } } return snmpList; } /** * Start the Snmp session. If you forget the listen() method you will not * get any answers because the communication is asynchronous * and the listen() method listens for answers. * @throws IOException */ public void start() throws IOException { TransportMapping transport = new DefaultUdpTransportMapping(); snmp = new Snmp(transport); if("3".equals(this.version))//add v3 support { USM usm = new USM(SecurityProtocols.getInstance(), new OctetString(MPv3.createLocalEngineID()), 0); SecurityModels.getInstance().addSecurityModel(usm); } // Do not forget this line! transport.listen(); } public void stop() throws IOException { if(snmp!=null)snmp.close(); snmp = null; } /** * Method which takes a single OID and returns the response from the agent as a String. * @param oid * @return * @throws IOException */ public String getAsString(OID oid) throws IOException { ResponseEvent res = getEvent(new OID[] { oid }); if(res!=null) return res.getResponse().get(0).getVariable().toString(); return null; } private PDU createPDU() { if(!"3".equals(this.version)) return new PDU(); ScopedPDU pdu = new ScopedPDU(); if(this.context != null && !this.context.isEmpty()) pdu.setContextEngineID(new OctetString(this.context)); //if not set, will be SNMP engine id return pdu; } /** * This method is capable of handling multiple OIDs * @param oids * @return * @throws IOException */ public Map<OID, String> get(OID oids[]) throws IOException { PDU pdu = createPDU(); for (OID oid : oids) { pdu.add(new VariableBinding(oid)); } pdu.setType(PDU.GET); ResponseEvent event = snmp.send(pdu, getTarget(), null); if(event != null) { PDU pdu2 = event.getResponse(); VariableBinding[] binds = pdu2!=null?event.getResponse().toArray():null; if(binds!=null) { Map<OID, String> res = new LinkedHashMap<OID, String>(binds.length); for(VariableBinding b: binds) res.put(b.getOid(), b.getVariable().toString()); return res; }else return null; } throw new RuntimeException("GET timed out"); } public ResponseEvent getEvent(OID oids[]) throws IOException { PDU pdu = createPDU(); for (OID oid : oids) { pdu.add(new VariableBinding(oid)); } pdu.setType(PDU.GET); ResponseEvent event = snmp.send(pdu, getTarget(), null); if(event != null) { return event; } throw new RuntimeException("GET timed out"); } /** * This method returns a Target, which contains information about * where the data should be fetched and how. * @return */ private Target getTarget() { if("3".equals(this.version))return getTargetV3(); Address targetAddress = GenericAddress.parse(address); CommunityTarget target = new CommunityTarget(); //logger.info("snmp version "+this.version+", community: "+this.community); if(this.community == null || this.community.isEmpty()) target.setCommunity(new OctetString("public")); else target.setCommunity(new OctetString(this.community)); target.setAddress(targetAddress); target.setRetries(2); target.setTimeout(5000); target.setVersion(this.getVersionInt()); return target; } private Target getTargetV3() { //logger.info("Use SNMP v3, "+this.privacyprotocol +"="+this.password+", "+this.privacyprotocol+"="+this.privacypassphrase); OID authOID = AuthMD5.ID; if("SHA".equals(this.authprotocol)) authOID = AuthSHA.ID; OID privOID = PrivDES.ID; if(this.privacyprotocol == null || this.privacyprotocol.isEmpty()) privOID = null; UsmUser user = new UsmUser(new OctetString(this.username), authOID, new OctetString(this.password), //auth privOID, this.privacypassphrase!=null?new OctetString(this.privacypassphrase):null); //enc snmp.getUSM().addUser(new OctetString(this.username), user); Address targetAddress = GenericAddress.parse(address); UserTarget target = new UserTarget(); target.setAddress(targetAddress); target.setRetries(2); target.setTimeout(1500); target.setVersion(this.getVersionInt()); if(privOID != null) target.setSecurityLevel(SecurityLevel.AUTH_PRIV); else target.setSecurityLevel(SecurityLevel.AUTH_NOPRIV); target.setSecurityName(new OctetString(this.username)); return target; } public static final String DISK_TABLE_OID ="1.3.6.1.4.1.2021.13.15.1.1"; public static final String DISK_TABLE_DEVICE_OID ="1.3.6.1.4.1.2021.13.15.1.1.2"; public static final String[] DISK_TABLE_ENTRIES = {"", "diskIOIndex", "diskIODevice", "diskIONRead", "diskIONWritten", "diskIOReads", "diskIOWrites", "", "", "diskIOLA1", "diskIOLA5", "diskIOLA15", "diskIONReadX", "diskIONWrittenX"}; public List<SNMPTriple> getDiskData(String device) throws IOException { int index = this.getDiskIndex(device); if(index<0) { return new ArrayList<SNMPTriple>(); } logger.fine("Query disk stats for "+index); PDU pdu = createPDU(); for ( int i=1; i< DISK_TABLE_ENTRIES.length; i++) { if(DISK_TABLE_ENTRIES[i].length()==0)continue; pdu.add(new VariableBinding(new OID("."+DISK_TABLE_OID+"."+i+"."+index))); } pdu.setType(PDU.GET); Map<String, String> res = new HashMap<String, String>(13); ResponseEvent event = snmp.send(pdu, getTarget(), null); if(event != null) { VariableBinding[] binds = event.getResponse().toArray(); for(VariableBinding b: binds) res.put(b.getOid().toString(), b.getVariable().toString()); //logger.info(res.toString()); } List<SNMPTriple> resList = new ArrayList<SNMPTriple>(res.size()); for(int i=1;i<DISK_TABLE_ENTRIES.length; i++) { if(DISK_TABLE_ENTRIES[i].length()==0)continue; resList.add(new SNMPTriple("."+DISK_TABLE_OID+"."+i+"."+index, DISK_TABLE_ENTRIES[i], res.get(DISK_TABLE_OID+"."+i+"."+index))); } return resList; } public Map<String, List<SNMPTriple>> getMultiDiskData() throws IOException { Map<String, List<SNMPTriple>> resMap = new HashMap<String, List<SNMPTriple>>(); Map<Integer, String> indexes = this.getDiskIndexes(); if(indexes == null || indexes.size() == 0) return resMap; logger.fine("Query disk stats"); PDU pdu = createPDU(); int reqSize = 0; for(Map.Entry<Integer, String> entry: indexes.entrySet()) { for ( int i=1; i< DISK_TABLE_ENTRIES.length; i++) { if(DISK_TABLE_ENTRIES[i].length()==0)continue; reqSize++; pdu.add(new VariableBinding(new OID("."+DISK_TABLE_OID+"."+i+"."+entry.getKey()))); } } pdu.setType(PDU.GET); Map<String, String> res = new HashMap<String, String>(13); ResponseEvent event = snmp.send(pdu, getTarget(), null); if(event != null) { PDU resp = event.getResponse(); if(resp == null) { logger.info(this.address + ": Unexpected snmp response: "+event+", request size " + reqSize ); return resMap; } VariableBinding[] binds = resp.toArray(); for(VariableBinding b: binds) res.put(b.getOid().toString(), b.getVariable().toString()); //logger.info(res.toString()); } for(Map.Entry<Integer, String> entry: indexes.entrySet()) { List<SNMPTriple> resList = new ArrayList<SNMPTriple>(res.size()); for(int i=1;i<DISK_TABLE_ENTRIES.length; i++) { if(DISK_TABLE_ENTRIES[i].length()==0)continue; resList.add(new SNMPTriple("."+DISK_TABLE_OID+"."+i+"."+entry.getKey(), DISK_TABLE_ENTRIES[i], res.get(DISK_TABLE_OID+"."+i+"."+entry.getKey()))); } resMap.put(entry.getValue(), resList); } return resMap; } private int getDiskIndex(String device) throws IOException { TableUtils tUtils = new TableUtils(snmp, new DefaultPDUFactory()); logger.fine("Query "+this.address+" for disk data: "+device); @SuppressWarnings("unchecked") List<TableEvent> events = tUtils.getTable(getTarget(), new OID[]{new OID("."+DISK_TABLE_DEVICE_OID)}, null, null); for (TableEvent event : events) { if(event.isError()) { logger.warning(this.address + ": SNMP event error: "+event.getErrorMessage()); continue; //throw new RuntimeException(event.getErrorMessage()); } for(VariableBinding vb: event.getColumns()) { String key = vb.getOid().toString(); String value = vb.getVariable().toString(); if(value!=null && value.equals(device)) { logger.fine("Find device OID entry: "+key); int index = -1; String[] strs = key.split("\\."); try { index = Integer.parseInt(strs[strs.length-1]); }catch(Exception ex){} return index; } } } return -1; } private Map<Integer, String> getDiskIndexes() throws IOException { Map<Integer, String> diskIndexes = new HashMap<Integer, String>(); TableUtils tUtils = new TableUtils(snmp, new DefaultPDUFactory()); logger.fine("Query "+this.address+" for disk oids"); @SuppressWarnings("unchecked") List<TableEvent> events = tUtils.getTable(getTarget(), new OID[]{new OID("."+DISK_TABLE_DEVICE_OID)}, null, null); for (TableEvent event : events) { if(event.isError()) { logger.warning(this.address + ": SNMP event error: "+event.getErrorMessage()); continue; //throw new RuntimeException(event.getErrorMessage()); } for(VariableBinding vb: event.getColumns()) { String key = vb.getOid().toString(); String value = vb.getVariable().toString(); if(value == null || value.isEmpty() || value.startsWith("dm-"))continue;//ignore dm disk if(value.startsWith("ram") || value.startsWith("loop") )continue;//ignore dm disk char c = value.charAt(value.length()-1); if(c>='0' && c<='9' ) { if(value.startsWith("sd")) { if(value.length()>2) { char d = value.charAt(2); if(d>='a' && d<='z')continue; } } } logger.fine("Find device OID entry: "+key); int index = -1; String[] strs = key.split("\\."); try { index = Integer.parseInt(strs[strs.length-1]); diskIndexes.put(index, value); }catch(Exception ex){} } } return diskIndexes; } public static final String IF_TABLE_OID = "1.3.6.1.2.1.31.1.1.1"; public static final String IF_TABLE_DEVICE_OID = "1.3.6.1.2.1.31.1.1.1.1"; public static final String[] IF_TABLE_ENTRIES = {"", "ifName", "ifInMulticastPkts", "ifInBroadcastPkts", "ifOutMulticastPkts", "ifOutBroadcastPkts", "ifHCInOctets", "ifHCInUcastPkts", "ifHCInMulticastPkts", "ifHCInBroadcastPkts", "ifHCOutOctets", "ifHCOutUcastPkts", "ifHCOutMulticastPkts", "ifHCOutBroadcastPkts", "ifLinkUpDownTrapEnable", "ifHighSpeed", "ifPromiscuousMode", "ifConnectorPresent", "ifAlias", "ifCounterDiscontinuityTime"}; private Map<Integer, String> getNetIfIndexes(String device) throws IOException { Map<Integer, String> ifMaps = new HashMap<Integer, String> (); TableUtils tUtils = new TableUtils(snmp, new DefaultPDUFactory()); logger.fine("Query "+this.address+" for network interface, excluding lo"); @SuppressWarnings("unchecked") List<TableEvent> events = tUtils.getTable(getTarget(), new OID[]{new OID("."+IF_TABLE_DEVICE_OID)}, null, null); for (TableEvent event : events) { if(event.isError()) { logger.warning(this.address + ": SNMP event error: "+event.getErrorMessage()); continue; //throw new RuntimeException(event.getErrorMessage()); } for(VariableBinding vb: event.getColumns()) { String key = vb.getOid().toString(); String value = vb.getVariable().toString(); if(device!=null && !device.isEmpty() && !value.equalsIgnoreCase(device)) continue; if(value!=null && !value.equalsIgnoreCase("lo")) { logger.fine("Find device OID entry: "+key); int index = -1; String[] strs = key.split("\\."); try { index = Integer.parseInt(strs[strs.length-1]); ifMaps.put(index, value); }catch(Exception ex){} } } } return ifMaps; } public Map<String, List<SNMPTriple>> getNetIfData(String device) throws IOException { Map<Integer, String> ifMaps = new HashMap<Integer, String> (); Map<String, List<SNMPTriple>> resMap = new HashMap<String, List<SNMPTriple>>(); Map<String, String> res = new HashMap<String, String>(); TableUtils tUtils = new TableUtils(snmp, new DefaultPDUFactory()); logger.fine("Query "+this.address+" for network interface, excluding lo"); @SuppressWarnings("unchecked") List<TableEvent> events = tUtils.getTable(getTarget(), new OID[]{new OID("."+IF_TABLE_OID)}, null, null); for (TableEvent event : events) { if(event.isError()) { logger.warning(this.address + ": SNMP event error: "+event.getErrorMessage()+", already returned: "+ifMaps); continue; //throw new RuntimeException(event.getErrorMessage()); } for(VariableBinding vb: event.getColumns()) { String key = vb.getOid().toString(); String value = vb.getVariable().toString(); res.put(key, value); if(key.startsWith(IF_TABLE_DEVICE_OID+".")) { if(device!=null && !device.isEmpty() && !value.equalsIgnoreCase(device)) continue; if(value!=null && !value.equalsIgnoreCase("lo")) { logger.fine("Find device OID entry: "+key); int index = -1; String[] strs = key.split("\\."); try { index = Integer.parseInt(strs[strs.length-1]); ifMaps.put(index, value); }catch(Exception ex){} } } }//for var }//for event for(Map.Entry<Integer, String> entry: ifMaps.entrySet()) { int index = entry.getKey(); String ifName = entry.getValue(); //ignore the case with no incoming and no outgoing traffic if("0".equals(res.get(IF_TABLE_OID+".6."+index)) && "0".equals(res.get(IF_TABLE_OID+".10."+index)))continue; resMap.put(ifName, new ArrayList<SNMPTriple>(IF_TABLE_ENTRIES.length)); for(int i=1;i<IF_TABLE_ENTRIES.length; i++) { if(IF_TABLE_ENTRIES[i].length()==0)continue; resMap.get(ifName).add(new SNMPTriple("."+IF_TABLE_OID+"."+i+"."+index, IF_TABLE_ENTRIES[i], res.get(IF_TABLE_OID+"."+i+"."+index))); } } return resMap; } public Map<String, List<SNMPTriple>> getNetIfData3(String device) throws IOException { Map<String, List<SNMPTriple>> resMap = new HashMap<String, List<SNMPTriple>>(); Map<Integer, String> indexMap = this.getNetIfIndexes(device); if(indexMap == null || indexMap.size() ==0) { logger.warning("Cannot find network interfaces "); return resMap; } logger.fine("Query net if stats for network"); PDU pdu = createPDU(); for(Map.Entry<Integer, String> entry: indexMap.entrySet()) for ( int i=1; i< IF_TABLE_ENTRIES.length; i++) { if(IF_TABLE_ENTRIES[i].length()==0)continue; pdu.add(new VariableBinding(new OID("."+IF_TABLE_OID+"."+i+"."+entry.getKey()))); } pdu.setType(PDU.GET); Map<String, String> res = new HashMap<String, String>(IF_TABLE_ENTRIES.length*indexMap.size()); ResponseEvent event = snmp.send(pdu, getTarget(), null); if(event != null) { VariableBinding[] binds = event.getResponse().toArray(); for(VariableBinding b: binds) res.put(b.getOid().toString(), b.getVariable().toString()); //logger.info(res.toString()); } for(Map.Entry<Integer, String> entry: indexMap.entrySet()) { int index = entry.getKey(); String ifName = entry.getValue(); //ignore the case with no incoming and no outgoing traffic if("0".equals(res.get(IF_TABLE_OID+".6."+index)) && "0".equals(res.get(IF_TABLE_OID+".10."+index)))continue; resMap.put(ifName, new ArrayList<SNMPTriple>(IF_TABLE_ENTRIES.length)); for(int i=1;i<IF_TABLE_ENTRIES.length; i++) { if(IF_TABLE_ENTRIES[i].length()==0)continue; resMap.get(ifName).add(new SNMPTriple("."+IF_TABLE_OID+"."+i+"."+index, IF_TABLE_ENTRIES[i], res.get(IF_TABLE_OID+"."+i+"."+index))); } } return resMap; } public static final String STORAGE_TABLE_OID = "1.3.6.1.2.1.25.2.3.1"; public static final String STORAGE_TABLE_DEVICE_OID = "1.3.6.1.2.1.25.2.3.1.1"; public static final String[] STORAGE_TABLE_ENTRIES = {"", "hrStorageIndex", "hrStorageType", "hrStorageDescr", "hrStorageAllocationUnits", "hrStorageSize", "hrStorageUsed", "hrStorageAllocationFailures"}; public Map<String, List<SNMPTriple>> getStorageData(String device) throws IOException { List<SNMPTriple> resList = querySingleSNMPTableByOID("."+STORAGE_TABLE_OID); List<Integer> idxList = new ArrayList<Integer>(); Map<String, String> tmpMap = new HashMap<String, String>(); for(SNMPTriple e: resList) { tmpMap.put(e.oid, e.value); if(e.oid.startsWith(STORAGE_TABLE_DEVICE_OID)) { try { int idx = Integer.parseInt(e.oid.substring(STORAGE_TABLE_DEVICE_OID.length() + 1)); idxList.add(idx); }catch(Exception ex){} } } Map<String, List<SNMPTriple>> resMap = new HashMap<String, List<SNMPTriple>>(); for(int idx: idxList) { String name = tmpMap.get(STORAGE_TABLE_OID+"." + 3 +"." + idx); if(device != null && !name.equalsIgnoreCase(device))continue; List<SNMPTriple> entryList = new ArrayList<SNMPTriple>(); for(int i = 1; i<STORAGE_TABLE_ENTRIES.length; i++) { entryList.add(new SNMPTriple("."+STORAGE_TABLE_OID+"."+i+"."+idx, STORAGE_TABLE_ENTRIES[i], tmpMap.get(STORAGE_TABLE_OID+"."+i+"."+idx))); } resMap.put(name, entryList); } return resMap; } /** * For test SNMP purpose. Used to check if individual SNMP entry is supported * @param oid * @return * @throws IOException */ public List<SNMPTriple> querySingleSNMPEntryByOID(String oid) throws IOException { if(oid == null || oid.isEmpty())return null; if(!oid.startsWith("."))oid = "."+oid; List<SNMPTriple> snmpList = new ArrayList<SNMPTriple>(); Map<OID, String> res = get(new OID[]{new OID(oid)}); if(res!=null) { for(Map.Entry<OID, String> e: res.entrySet()) { //if("noSuchObject".equalsIgnoreCase(e.getValue()))continue; snmpList.add(new SNMPTriple(e.getKey().toString(), "", e.getValue())); } } return snmpList; } public List<SNMPTriple> querySingleSNMPTableByOID(String oid) throws IOException { if(oid == null || oid.isEmpty())return null; if(!oid.startsWith("."))oid = "."+oid; TableUtils tUtils = new TableUtils(snmp, new DefaultPDUFactory()); List<TableEvent> events = tUtils.getTable(getTarget(), new OID[]{new OID(oid)}, null, null); List<SNMPTriple> snmpList = new ArrayList<SNMPTriple>(); for (TableEvent event : events) { if(event.isError()) { logger.warning(this.address + ": SNMP event error: "+event.getErrorMessage()); continue; //throw new RuntimeException(event.getErrorMessage()); } for(VariableBinding vb: event.getColumns()) { String key = vb.getOid().toString(); String value = vb.getVariable().toString(); snmpList.add(new SNMPTriple(key, "", value)); } } return snmpList; } public static final String PROCESS_TABLE_OID = "1.3.6.1.2.1.25.4.2.1"; //hrSWRunTable //1.3.6.1.2.1.25.4.2.1.2. /** * Query index for given process name. Note the parameter only provides 128 characters, * so it could be difficult for us to differentiate each other if multi processes with same name exist. * So we will return this list and use the sum from all processes for our metrics * @param process * @return * @throws IOException */ private List<Integer> getProcessIndexes(String process) throws IOException { List<Integer> indexes = new ArrayList<Integer> (); if(process == null || process.isEmpty())return indexes; TableUtils tUtils = new TableUtils(snmp, new DefaultPDUFactory()); logger.fine("Query "+this.address+" for process " + process); @SuppressWarnings("unchecked") List<TableEvent> events = tUtils.getTable(getTarget(), new OID[]{new OID("."+PROCESS_TABLE_OID)}, null, null); for (TableEvent event : events) { if(event.isError()) { logger.warning(this.address + ": SNMP event error: "+event.getErrorMessage()); continue; //throw new RuntimeException(event.getErrorMessage()); } for(VariableBinding vb: event.getColumns()) { String key = vb.getOid().toString(); String value = vb.getVariable().toString(); if(process!=null && !process.isEmpty() && !value.equalsIgnoreCase(process)) continue; if(value!=null) { logger.fine("Find process OID entry: "+key); int index = -1; String[] strs = key.split("\\."); try { index = Integer.parseInt(strs[strs.length-1]); indexes.add(index); }catch(Exception ex){} } } } return indexes; } public static final String PROCESS_PERF_TABLE_OID = "1.3.6.1.2.1.25.5.1.1";//hrSWRunPerfTable public static final String[] PROCESS_PERF_TABLE_ENTRIES = {"", "hrSWRunPerfCPU", "hrSWRunPerfMem"}; public List<SNMPTriple> getProcessData(String processName) throws IOException { List<SNMPTriple> resList = new ArrayList<SNMPTriple>(); List<Integer> prIndexes = this.getProcessIndexes(processName); if(prIndexes == null || prIndexes.size() == 0) return resList; logger.fine("Query process stats"); PDU pdu = createPDU(); for(Integer idx: prIndexes) { for ( int i=1; i< PROCESS_PERF_TABLE_ENTRIES.length; i++) { if(PROCESS_PERF_TABLE_ENTRIES[i].length()==0)continue; pdu.add(new VariableBinding(new OID("."+PROCESS_PERF_TABLE_OID+"."+i+"."+idx))); //logger.info("Adding " + "."+PROCESS_PERF_TABLE_OID+"."+i+"."+idx); } } pdu.setType(PDU.GET); Map<String, String> res = new HashMap<String, String>(prIndexes.size()*2); ResponseEvent event = snmp.send(pdu, getTarget(), null); if(event != null) { VariableBinding[] binds = event.getResponse().toArray(); for(VariableBinding b: binds) { res.put(b.getOid().toString(), b.getVariable().toString()); //logger.info(b.getOid().toString() +", "+ b.getVariable().toString()); } } //logger.info("result: "+res); for(int i=1;i<PROCESS_PERF_TABLE_ENTRIES.length; i++) { if(PROCESS_PERF_TABLE_ENTRIES[i].length()==0)continue; BigDecimal data = new BigDecimal(0); for(Integer idx: prIndexes) { data = data.add(new BigDecimal(res.get(PROCESS_PERF_TABLE_OID+"."+i+"."+idx))); } resList.add(new SNMPTriple("", PROCESS_PERF_TABLE_ENTRIES[i], data.toString())); } return resList; } public Map<String, String> queryMysqld() throws IOException { logger.fine("Query mysqld for "+address); Map<String, String> resMap = null; resMap = new java.util.LinkedHashMap<String, String>(); List<SNMPTriple> res = this.getProcessData("mysqld"); if(res!=null) { for(SNMPTriple e: res) { if("noSuchObject".equalsIgnoreCase(e.value))continue; resMap.put(e.name, e.value); } } return resMap; } public String getCommunity() { return community; } public void setCommunity(String community) { this.community = community; } public String getVersion() { return version; } public void setVersion(String version) { this.version = version; } public int getVersionInt() { if("1".equals(this.version)) return SnmpConstants.version1; else if("3".equals(this.version)) return SnmpConstants.version3; else return SnmpConstants.version2c; } public void setSnmpSetting(SNMPSettings.SNMPSetting setting) { if(setting == null)return; this.setCommunity(setting.getCommunity()); this.setVersion(setting.getVersion()); if("3".equals(this.version)) { this.username = setting.getUsername(); this.password = setting.getPassword(); this.authprotocol = setting.getAuthProtocol(); this.privacypassphrase = setting.getPrivacyPassphrase(); this.privacyprotocol = setting.getPrivacyProtocol(); this.context = setting.getContext(); } } }