Mercurial > stress-tester
changeset 1123:9517e4cb9bd7
SnmpService in progress
author | Devel 2 |
---|---|
date | Fri, 05 Jun 2020 09:41:41 +0200 |
parents | b33418b1f310 |
children | 83c771436e55 |
files | stress-tester/pom.xml stress-tester/src/main/java/com/passus/st/snmp/SnmpOIDInfo.java stress-tester/src/main/java/com/passus/st/snmp/SnmpService.java stress-tester/src/main/java/com/passus/st/snmp/SnmpTargetSettings.java stress-tester/src/main/java/com/passus/st/snmp/SnmpUtils.java stress-tester/src/main/java/com/passus/st/snmp/SystemMetric.java |
diffstat | 6 files changed, 553 insertions(+), 0 deletions(-) [+] |
line wrap: on
line diff
--- a/stress-tester/pom.xml Wed Jun 03 13:30:11 2020 +0200 +++ b/stress-tester/pom.xml Fri Jun 05 09:41:41 2020 +0200 @@ -187,6 +187,12 @@ </dependency> <dependency> + <groupId>org.snmp4j</groupId> + <artifactId>snmp4j</artifactId> + <version>2.8.4</version> + </dependency> + + <dependency> <groupId>org.testng</groupId> <artifactId>testng</artifactId> <version>6.9.10</version>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/stress-tester/src/main/java/com/passus/st/snmp/SnmpOIDInfo.java Fri Jun 05 09:41:41 2020 +0200 @@ -0,0 +1,101 @@ +package com.passus.st.snmp; + +import org.snmp4j.smi.OID; + +import java.util.Collections; +import java.util.HashSet; +import java.util.Objects; +import java.util.Set; + +public final class SnmpOIDInfo { + + public static final SnmpOIDInfo OID_CPU_LOAD_1M = new SnmpOIDInfo(".1.3.6.1.4.1.2021.10.1.3.1", "cpuLoad1M"); + public static final SnmpOIDInfo OID_CPU_LOAD_5M = new SnmpOIDInfo(".1.3.6.1.4.1.2021.10.1.3.2", "cpuLoad5M"); + public static final SnmpOIDInfo OID_CPU_LOAD_15M = new SnmpOIDInfo(".1.3.6.1.4.1.2021.10.1.3.3", "cpuLoad15M"); + public static final SnmpOIDInfo OID_CPU_USER = new SnmpOIDInfo(".1.3.6.1.4.1.2021.11.9.0", "cpuUser"); + public static final SnmpOIDInfo OID_CPU_IDLE = new SnmpOIDInfo(".1.3.6.1.4.1.2021.11.11.0", "cpuIdle"); + public static final SnmpOIDInfo OID_RAM_FREE = new SnmpOIDInfo(".1.3.6.1.4.1.2021.4.6.0", "ramFree"); + public static final SnmpOIDInfo OID_RAM_TOTAL = new SnmpOIDInfo(".1.3.6.1.4.1.2021.4.5.0", "ramTotal"); + public static final SnmpOIDInfo OID_SWAP_FREE = new SnmpOIDInfo(".1.3.6.1.4.1.2021.4.4.0", "swapFree"); + public static final SnmpOIDInfo OID_SWAP_TOTAL = new SnmpOIDInfo(".1.3.6.1.4.1.2021.4.3.0", "swapTotal"); + + public static final Set<SnmpOIDInfo> OIDS; + + static { + Set<SnmpOIDInfo> oidsTmp = new HashSet<>(); + oidsTmp.add(OID_CPU_LOAD_1M); + oidsTmp.add(OID_CPU_LOAD_5M); + oidsTmp.add(OID_CPU_LOAD_15M); + oidsTmp.add(OID_CPU_USER); + oidsTmp.add(OID_CPU_IDLE); + oidsTmp.add(OID_RAM_FREE); + oidsTmp.add(OID_RAM_TOTAL); + oidsTmp.add(OID_SWAP_FREE); + oidsTmp.add(OID_SWAP_TOTAL); + OIDS = Collections.unmodifiableSet(oidsTmp); + } + + private final OID oid; + + private final String name; + + public SnmpOIDInfo(String oid, String name) { + this(new OID(oid), name); + } + + public SnmpOIDInfo(OID oid, String name) { + this.oid = oid; + this.name = name; + } + + public OID oid() { + return oid; + } + + public String name() { + return name; + } + + @Override + public int hashCode() { + return Objects.hash(oid); + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + + SnmpOIDInfo that = (SnmpOIDInfo) o; + return Objects.equals(oid, that.oid); + } + + @Override + public String toString() { + return "SnmpOIDInfo{" + + "oid=" + oid + + ", name='" + name + '\'' + + '}'; + } + + public static Set<OID> getAllOIDs() { + Set<OID> out = new HashSet<>(OIDS.size()); + OIDS.forEach(o -> out.add(o.oid)); + return out; + } + + public static SnmpOIDInfo findByOID(String oid) { + return findByOID(new OID(oid)); + } + + public static SnmpOIDInfo findByOID(OID oid) { + for (SnmpOIDInfo info : OIDS) { + if (info.oid.equals(oid)) { + return info; + } + } + + return null; + } + +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/stress-tester/src/main/java/com/passus/st/snmp/SnmpService.java Fri Jun 05 09:41:41 2020 +0200 @@ -0,0 +1,254 @@ +package com.passus.st.snmp; + +import com.passus.commons.Assert; +import com.passus.commons.service.Service; +import com.passus.commons.service.ServiceException; +import com.passus.commons.time.DefaultScheduledTimerService; +import com.passus.commons.time.ScheduledTimerService; +import com.passus.st.Log4jConfigurationFactory; +import com.passus.st.metric.MetricSource; +import com.passus.st.metric.MetricsContainer; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; +import org.snmp4j.*; +import org.snmp4j.event.ResponseEvent; +import org.snmp4j.mp.SnmpConstants; +import org.snmp4j.smi.*; +import org.snmp4j.transport.DefaultUdpTransportMapping; + +import java.io.IOException; +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; +import java.util.Set; + +public class SnmpService implements Service, MetricSource { + + private static final Logger LOGGER = LogManager.getLogger(SnmpService.class); + + private Snmp snmp; + + private volatile boolean started; + + private final List<SnmpTarget> targets = new ArrayList<>(); + + private ScheduledTimerService scheduledTimerService; + + private long interval = 30_000; + + private Set<OID> oids = SnmpOIDInfo.getAllOIDs(); + + public long getInterval() { + return interval; + } + + public void setInterval(long interval) { + Assert.greaterThanZero(interval, "interval"); + this.interval = interval; + } + + public void addTarget(SnmpTargetSettings settings) { + Assert.notNull(settings, "settings"); + SnmpTarget snmpTarget = new SnmpTarget(settings); + targets.add(snmpTarget); + } + + @Override + public boolean isStarted() { + return started; + } + + @Override + public void start() { + if (started) { + return; + } + + try { + TransportMapping transport = new DefaultUdpTransportMapping(); + transport.listen(); + snmp = new Snmp(transport); + + targets.forEach(t -> { + if (!t.init) { + t.init(); + } + }); + + scheduledTimerService = new DefaultScheduledTimerService("SnmpService.Scheduler", interval, this::sendAll); + scheduledTimerService.start(); + started = true; + } catch (IOException e) { + throw new ServiceException("Unable to start service. " + e.getMessage(), e); + } + } + + @Override + public void stop() { + if (!started) { + return; + } + + scheduledTimerService.stop(); + + try { + snmp.close(); + } catch (IOException ignore) { + + } + + started = false; + } + + @Override + public boolean isCollectMetrics() { + return true; + } + + @Override + public void setCollectMetrics(boolean collectMetrics) { + + } + + @Override + public void writeMetrics(MetricsContainer container) { + targets.forEach(t -> { + synchronized (t.metric) { + container.update(t.metric); + t.metric.reset(); + } + }); + } + + private void sendAll() { + targets.forEach(t -> send(t, oids)); + } + + private void updateMetric(List<? extends VariableBinding> vars, SystemMetric metric) { + synchronized (metric) { + for (VariableBinding varBind : vars) { + SnmpOIDInfo oidInfo = SnmpOIDInfo.findByOID(varBind.getOid()); + if (oidInfo != null) { + Variable var = varBind.getVariable(); + switch (oidInfo.name()) { + case "cpuLoad1M": { + float value = Float.parseFloat(var.toString()); + metric.updateLoad1M(value); + break; + } + case "cpuLoad5M": { + float value = Float.parseFloat(var.toString()); + metric.updateLoad5M(value); + break; + } + case "cpuLoad15M": { + float value = Float.parseFloat(var.toString()); + metric.updateLoad15M(value); + break; + } + case "cpuUser": { + metric.updateCpuUser(var.toInt()); + break; + } + case "cpuIdle": { + metric.updateCpuIdle(var.toInt()); + break; + } + case "ramFree": { + metric.updateRamFree(var.toLong()); + break; + } + case "ramTotal": { + metric.updateRamTotal(var.toLong()); + break; + } + case "swapFree": { + metric.updateSwapFree(var.toLong()); + break; + } + case "swapTotal": { + metric.updateSwapTotal(var.toLong()); + break; + } + } + } + } + } + } + + private void send(SnmpTarget target, Collection<OID> oids) { + if (LOGGER.isDebugEnabled()) { + LOGGER.debug("[{}] SNMP sending request.", target.target.getAddress()); + } + + PDU pdu = new PDU(); + for (OID oid : oids) { + pdu.add(new VariableBinding(oid)); + } + + try { + ResponseEvent event = snmp.get(pdu, target.target); + if (event == null) { + LOGGER.warn("[{}] SNMP request timeout.", target.target.getAddress()); + } else { + PDU respPdu = event.getResponse(); + if (respPdu == null) { + LOGGER.warn("[{}] SNMP request error. Response PDU is null.", target.target.getAddress()); + } else if (respPdu.getErrorStatus() == PDU.noError) { + List<? extends VariableBinding> vars = respPdu.getVariableBindings(); + updateMetric(vars, target.metric); + if (LOGGER.isDebugEnabled()) { + LOGGER.debug("[{}] Metric updated. {}", target.target.getAddress(), target.metric); + } + } else { + LOGGER.warn("[{}] SNMP request error. Index: {}, Status: {}, Text: {}.", target.target.getAddress(), + respPdu.getErrorIndex(), respPdu.getErrorIndex(), respPdu.getErrorStatusText()); + } + } + } catch (Exception e) { + LOGGER.warn("[{}] SNMP sending error. {}", target.target.getAddress(), e.getMessage(), e); + } + } + + private Target createTargetV2(SnmpTargetSettings settings) { + Address targetAddress = new UdpAddress(settings.getAddress()); + if (targetAddress == null) { + throw new IllegalArgumentException("Invalid address '" + settings.getAddress() + "'."); + } + + CommunityTarget target = new CommunityTarget(); + target.setCommunity(new OctetString(settings.getCommunity())); + target.setAddress(targetAddress); + target.setRetries(settings.getRetries()); + target.setTimeout(settings.getTimeout()); + target.setVersion(SnmpConstants.version2c); + return target; + } + + private class SnmpTarget { + + private final SnmpTargetSettings settings; + + private Target target; + + private SystemMetric metric; + + private boolean init; + + private SnmpTarget(SnmpTargetSettings settings) { + this.settings = settings; + } + + private void init() { + target = createTargetV2(settings); + metric = new SystemMetric(SystemMetric.DEFAULT_NAME + "." + target.getAddress()); + init = true; + } + + @Override + public String toString() { + return target.getAddress().toString(); + } + } + +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/stress-tester/src/main/java/com/passus/st/snmp/SnmpTargetSettings.java Fri Jun 05 09:41:41 2020 +0200 @@ -0,0 +1,52 @@ +package com.passus.st.snmp; + +import com.passus.commons.Assert; + +import static com.passus.st.snmp.SnmpUtils.*; + +public final class SnmpTargetSettings { + + private String address = DEFAULT_ADDRESS; + + private long timeout = DEFAULT_TIMEOUT; + + private int retries = DEFAULT_RETRIES; + + private String community = DEFAULT_COMMUNITY; + + public String getAddress() { + return address; + } + + public void setAddress(String address) { + Assert.notNull(address, "address"); + this.address = address; + } + + public long getTimeout() { + return timeout; + } + + public void setTimeout(long timeout) { + Assert.greaterThanZero(timeout, "timeout"); + this.timeout = timeout; + } + + public int getRetries() { + return retries; + } + + public void setRetries(int retries) { + Assert.greaterThanZero(retries, "retries"); + this.retries = retries; + } + + public String getCommunity() { + return community; + } + + public void setCommunity(String community) { + Assert.notNull(community, "community"); + this.community = community; + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/stress-tester/src/main/java/com/passus/st/snmp/SnmpUtils.java Fri Jun 05 09:41:41 2020 +0200 @@ -0,0 +1,12 @@ +package com.passus.st.snmp; + +public final class SnmpUtils { + + public static final String DEFAULT_ADDRESS = "localhost"; + public static final long DEFAULT_TIMEOUT = 1500; + public static final int DEFAULT_RETRIES = 1; + public static final String DEFAULT_COMMUNITY = "passus"; + + private SnmpUtils() { + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/stress-tester/src/main/java/com/passus/st/snmp/SystemMetric.java Fri Jun 05 09:41:41 2020 +0200 @@ -0,0 +1,128 @@ +package com.passus.st.snmp; + +import com.passus.commons.metric.Metric; +import com.passus.st.client.GenericMetric; +import org.apache.commons.lang3.mutable.MutableFloat; +import org.apache.commons.lang3.mutable.MutableInt; +import org.apache.commons.lang3.mutable.MutableLong; + +public class SystemMetric extends GenericMetric { + + public static final String DEFAULT_NAME = "system"; + + private MutableFloat cpuLoad1M = new MutableFloat(); + + private MutableFloat cpuLoad5M = new MutableFloat(); + + private MutableFloat cpuLoad15M = new MutableFloat(); + + private MutableInt cpuUser = new MutableInt(); + + private MutableInt cpuIdle = new MutableInt(); + + private MutableLong ramFree = new MutableLong(); + + private MutableLong ramTotal = new MutableLong(); + + private MutableLong swapFree = new MutableLong(); + + private MutableLong swapTotal = new MutableLong(); + + public SystemMetric() { + super(DEFAULT_NAME); + } + + public SystemMetric(String name) { + super(name); + attrs.put("cpuLoad1M", cpuLoad1M); + attrs.put("cpuLoad5M", cpuLoad5M); + attrs.put("cpuLoad15M", cpuLoad15M); + attrs.put("cpuUser", cpuUser); + attrs.put("cpuIdle", cpuIdle); + attrs.put("ramFree", ramFree); + attrs.put("ramTotal", ramTotal); + attrs.put("swapFree", swapFree); + attrs.put("swapTotal", swapTotal); + } + + public void updateLoad1M(float value) { + max(cpuLoad1M, value); + } + + public void updateLoad5M(float value) { + max(cpuLoad5M, value); + } + + public void updateLoad15M(float value) { + max(cpuLoad15M, value); + } + + public void updateCpuUser(int value) { + max(cpuUser, value); + } + + public void updateCpuIdle(int value) { + max(cpuIdle, value); + } + + public void updateRamFree(long value) { + max(ramFree, value); + } + + public void updateRamTotal(long value) { + max(ramTotal, value); + } + + public void updateSwapFree(long value) { + max(swapFree, value); + } + + public void updateSwapTotal(long value) { + max(swapTotal, value); + } + + @Override + public void update(Metric metric) { + SystemMetric sm = (SystemMetric) metric; + cpuLoad1M = Metric.max(cpuLoad1M, sm.cpuLoad1M); + cpuLoad5M = Metric.max(cpuLoad5M, sm.cpuLoad5M); + cpuLoad15M = Metric.max(cpuLoad15M, sm.cpuLoad15M); + cpuUser = Metric.max(cpuUser, sm.cpuUser); + cpuIdle = Metric.max(cpuIdle, sm.cpuIdle); + ramFree = Metric.max(ramFree, sm.ramFree); + ramTotal = Metric.max(ramTotal, sm.ramTotal); + swapFree = Metric.max(swapFree, sm.swapFree); + swapTotal = Metric.max(swapTotal, sm.swapTotal); + } + + @Override + public void reset() { + cpuLoad1M.setValue(0); + cpuLoad5M.setValue(0); + cpuLoad15M.setValue(0); + cpuUser.setValue(0); + cpuIdle.setValue(0); + ramFree.setValue(0); + ramTotal.setValue(0); + swapFree.setValue(0); + swapTotal.setValue(0); + } + + private static void max(MutableFloat val1, float val2) { + if (val1.floatValue() < val2) { + val1.setValue(val2); + } + } + + private static void max(MutableInt val1, int val2) { + if (val1.intValue() < val2) { + val1.setValue(val2); + } + } + + private static void max(MutableLong val1, long val2) { + if (val1.longValue() < val2) { + val1.setValue(val2); + } + } +}