CAMEL-5271 Implemented a SNMP Trap producer. TrapTest now validates both producer and consumer (for which the test previously was disabled)
Project: http://git-wip-us.apache.org/repos/asf/camel/repo Commit: http://git-wip-us.apache.org/repos/asf/camel/commit/8a7d71d5 Tree: http://git-wip-us.apache.org/repos/asf/camel/tree/8a7d71d5 Diff: http://git-wip-us.apache.org/repos/asf/camel/diff/8a7d71d5 Branch: refs/heads/camel-2.18.x Commit: 8a7d71d5dc9008c647b05afd6fc969e204c4b6c4 Parents: a40f381 Author: Sverker Abrahamsson <sver...@limetransit.com> Authored: Fri Feb 24 12:37:33 2017 +0100 Committer: Claus Ibsen <davscl...@apache.org> Committed: Fri Feb 24 13:38:14 2017 +0100 ---------------------------------------------------------------------- .../camel/component/snmp/SnmpEndpoint.java | 6 +- .../camel/component/snmp/SnmpTrapProducer.java | 133 +++++++++++++++++++ .../camel/component/snmp/TrapReceiveTest.java | 63 --------- .../apache/camel/component/snmp/TrapTest.java | 118 ++++++++++++++++ 4 files changed, 256 insertions(+), 64 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/camel/blob/8a7d71d5/components/camel-snmp/src/main/java/org/apache/camel/component/snmp/SnmpEndpoint.java ---------------------------------------------------------------------- diff --git a/components/camel-snmp/src/main/java/org/apache/camel/component/snmp/SnmpEndpoint.java b/components/camel-snmp/src/main/java/org/apache/camel/component/snmp/SnmpEndpoint.java index 005e635..82a5405 100644 --- a/components/camel-snmp/src/main/java/org/apache/camel/component/snmp/SnmpEndpoint.java +++ b/components/camel-snmp/src/main/java/org/apache/camel/component/snmp/SnmpEndpoint.java @@ -111,7 +111,11 @@ public class SnmpEndpoint extends DefaultPollingEndpoint { } public Producer createProducer() throws Exception { - return new SnmpProducer(this); + if (this.type == SnmpActionType.TRAP) { + return new SnmpTrapProducer(this); + } else { + return new SnmpProducer(this); + } } public boolean isSingleton() { http://git-wip-us.apache.org/repos/asf/camel/blob/8a7d71d5/components/camel-snmp/src/main/java/org/apache/camel/component/snmp/SnmpTrapProducer.java ---------------------------------------------------------------------- diff --git a/components/camel-snmp/src/main/java/org/apache/camel/component/snmp/SnmpTrapProducer.java b/components/camel-snmp/src/main/java/org/apache/camel/component/snmp/SnmpTrapProducer.java new file mode 100644 index 0000000..e72840f --- /dev/null +++ b/components/camel-snmp/src/main/java/org/apache/camel/component/snmp/SnmpTrapProducer.java @@ -0,0 +1,133 @@ +/** + * Licensed to the Apache Software Foundation (ASF) 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.apache.camel.component.snmp; + +import org.apache.camel.Exchange; +import org.apache.camel.impl.DefaultProducer; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.snmp4j.CommunityTarget; +import org.snmp4j.PDU; +import org.snmp4j.Snmp; +import org.snmp4j.TransportMapping; +import org.snmp4j.mp.MPv3; +import org.snmp4j.mp.SnmpConstants; +import org.snmp4j.security.SecurityModels; +import org.snmp4j.security.SecurityProtocols; +import org.snmp4j.security.USM; +import org.snmp4j.smi.Address; +import org.snmp4j.smi.GenericAddress; +import org.snmp4j.smi.Integer32; +import org.snmp4j.smi.OctetString; +import org.snmp4j.transport.DefaultTcpTransportMapping; +import org.snmp4j.transport.DefaultUdpTransportMapping; + +/** + * A snmp trap producer + */ +public class SnmpTrapProducer extends DefaultProducer { + + private static final Logger LOG = LoggerFactory.getLogger(SnmpTrapProducer.class); + + private SnmpEndpoint endpoint; + + private Address targetAddress; + private USM usm; + private CommunityTarget target; + public SnmpTrapProducer(SnmpEndpoint endpoint) { + super(endpoint); + this.endpoint = endpoint; + } + + @Override + protected void doStart() throws Exception { + super.doStart(); + + this.targetAddress = GenericAddress.parse(this.endpoint.getAddress()); + LOG.debug("targetAddress: {}", targetAddress); + + this.usm = new USM(SecurityProtocols.getInstance(), new OctetString(MPv3.createLocalEngineID()), 0); + SecurityModels.getInstance().addSecurityModel(this.usm); + + // setting up target + this.target = new CommunityTarget(); + this.target.setCommunity(new OctetString(endpoint.getSnmpCommunity())); + this.target.setAddress(this.targetAddress); + this.target.setRetries(this.endpoint.getRetries()); + this.target.setTimeout(this.endpoint.getTimeout()); + this.target.setVersion(this.endpoint.getSnmpVersion()); + + } + + @Override + protected void doStop() throws Exception { + super.doStop(); + + try { + SecurityModels.getInstance().removeSecurityModel(new Integer32(this.usm.getID())); + } finally { + this.targetAddress = null; + this.usm = null; + this.target = null; + } + } + + @Override + public void process(final Exchange exchange) throws Exception { + // load connection data only if the endpoint is enabled + Snmp snmp = null; + TransportMapping<? extends Address> transport = null; + + try { + LOG.debug("Starting SNMP Trap producer on {}", this.endpoint.getAddress()); + + // either tcp or udp + if ("tcp".equals(this.endpoint.getProtocol())) { + transport = new DefaultTcpTransportMapping(); + } else if ("udp".equals(this.endpoint.getProtocol())) { + transport = new DefaultUdpTransportMapping(); + } else { + throw new IllegalArgumentException("Unknown protocol: {} " + this.endpoint.getProtocol()); + } + + snmp = new Snmp(transport); + + LOG.debug("SnmpTrap: getting pdu from body"); + PDU trap = exchange.getIn().getBody(PDU.class); + + trap.setErrorIndex(0); + trap.setErrorStatus(0); + trap.setMaxRepetitions(0); + if (this.endpoint.getSnmpVersion() == SnmpConstants.version1) { + trap.setType(PDU.V1TRAP); + } else { + trap.setType(PDU.TRAP); + } + + LOG.debug("SnmpTrap: sending"); + snmp.send(trap, this.target); + LOG.debug("SnmpTrap: sent"); + } finally { + try { + transport.close(); + } catch (Exception e) { } + try { + snmp.close(); + } catch (Exception e) { } + } + } //end process +} \ No newline at end of file http://git-wip-us.apache.org/repos/asf/camel/blob/8a7d71d5/components/camel-snmp/src/test/java/org/apache/camel/component/snmp/TrapReceiveTest.java ---------------------------------------------------------------------- diff --git a/components/camel-snmp/src/test/java/org/apache/camel/component/snmp/TrapReceiveTest.java b/components/camel-snmp/src/test/java/org/apache/camel/component/snmp/TrapReceiveTest.java deleted file mode 100644 index e5c4862..0000000 --- a/components/camel-snmp/src/test/java/org/apache/camel/component/snmp/TrapReceiveTest.java +++ /dev/null @@ -1,63 +0,0 @@ -/** - * Licensed to the Apache Software Foundation (ASF) 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.apache.camel.component.snmp; - -import java.util.List; - -import org.apache.camel.Exchange; -import org.apache.camel.builder.RouteBuilder; -import org.apache.camel.component.mock.MockEndpoint; -import org.apache.camel.test.junit4.CamelTestSupport; -import org.junit.Ignore; -import org.junit.Test; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -public class TrapReceiveTest extends CamelTestSupport { - private static final Logger LOG = LoggerFactory.getLogger(TrapReceiveTest.class); - - // a disabled test... before enabling you must fill in a working IP, Port - // and maybe oids in the route below - @Ignore - @Test - public void testReceiveTraps() throws Exception { - MockEndpoint mock = getMockEndpoint("mock:result"); - mock.expectedMinimumMessageCount(1); - mock.assertIsSatisfied(); - List<Exchange> oids = mock.getExchanges(); - if (LOG.isInfoEnabled()) { - for (Exchange e : oids) { - LOG.info("TRAP: " + e.getIn().getBody(String.class)); - } - } - } - - @Test - public void testStartRoute() throws Exception { - // do nothing here , just make sure the camel route can started. - } - - protected RouteBuilder createRouteBuilder() { - return new RouteBuilder() { - public void configure() { - // START SNIPPET: e1 - from("snmp:0.0.0.0:1662?protocol=udp&type=TRAP").id("route1").transform(body().convertToString()).to("mock:result"); - // END SNIPPET: e1 - } - }; - } -} http://git-wip-us.apache.org/repos/asf/camel/blob/8a7d71d5/components/camel-snmp/src/test/java/org/apache/camel/component/snmp/TrapTest.java ---------------------------------------------------------------------- diff --git a/components/camel-snmp/src/test/java/org/apache/camel/component/snmp/TrapTest.java b/components/camel-snmp/src/test/java/org/apache/camel/component/snmp/TrapTest.java new file mode 100644 index 0000000..b688c35 --- /dev/null +++ b/components/camel-snmp/src/test/java/org/apache/camel/component/snmp/TrapTest.java @@ -0,0 +1,118 @@ +/** + * Licensed to the Apache Software Foundation (ASF) 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.apache.camel.component.snmp; + +import java.util.List; +import java.util.Vector; + +import org.apache.camel.Endpoint; +import org.apache.camel.Exchange; +import org.apache.camel.LoggingLevel; +import org.apache.camel.Producer; +import org.apache.camel.RoutesBuilder; +import org.apache.camel.builder.RouteBuilder; +import org.apache.camel.component.mock.MockEndpoint; +import org.apache.camel.test.junit4.CamelTestSupport; +import org.junit.Assert; +import org.junit.Test; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.snmp4j.PDU; +import org.snmp4j.mp.SnmpConstants; +import org.snmp4j.smi.OID; +import org.snmp4j.smi.OctetString; +import org.snmp4j.smi.TimeTicks; +import org.snmp4j.smi.Variable; +import org.snmp4j.smi.VariableBinding; + +/** + * This test covers both producing and consuming snmp traps + */ +public class TrapTest extends CamelTestSupport { + private static final Logger LOG = LoggerFactory.getLogger(TrapTest.class); + + @Test + public void testStartRoute() throws Exception { + // do nothing here , just make sure the camel route can started. + } + + @Test + public void testSendReceiveTraps() throws Exception { + // Create a trap PDU + PDU trap = new PDU(); + trap.setType(PDU.TRAP); + + OID oid = new OID("1.2.3.4.5"); + trap.add(new VariableBinding(SnmpConstants.snmpTrapOID, oid)); + trap.add(new VariableBinding(SnmpConstants.sysUpTime, new TimeTicks(5000))); // put your uptime here + trap.add(new VariableBinding(SnmpConstants.sysDescr, new OctetString("System Description"))); + + //Add Payload + Variable var = new OctetString("some string"); + trap.add(new VariableBinding(oid, var)); + + // Send it + LOG.info("Sending pdu " + trap); + Endpoint endpoint = context.getEndpoint("direct:snmptrap"); + Exchange exchange = endpoint.createExchange(); + exchange.getIn().setBody(trap); + Producer producer = endpoint.createProducer(); + producer.process(exchange); + + synchronized (this) { + Thread.sleep(1000); + } + + // If all goes right it should come here + MockEndpoint mock = getMockEndpoint("mock:result"); + mock.expectedMessageCount(1); + mock.assertIsSatisfied(); + List<Exchange> exchanges = mock.getExchanges(); + SnmpMessage msg = (SnmpMessage) exchanges.get(0).getIn(); + PDU receivedTrap = msg.getSnmpMessage(); + Assert.assertEquals(trap, receivedTrap); + if (LOG.isInfoEnabled()) { + LOG.info("Received SNMP TRAP:"); + Vector<? extends VariableBinding> variableBindings = receivedTrap.getVariableBindings(); + for (VariableBinding vb : variableBindings) { + LOG.info(" " + vb.toString()); + } + } + } + + /** + * RouteBuilders for the SNMP TRAP producer and consumer + */ + protected RoutesBuilder[] createRouteBuilders() { + return new RoutesBuilder[] { + new RouteBuilder() { + public void configure() { + from("direct:snmptrap") + .log(LoggingLevel.INFO, "Sending Trap pdu ${body}") + .to("snmp:127.0.0.1:1662?protocol=udp&type=TRAP&snmpVersion=" + SnmpConstants.version2c); + } + }, + new RouteBuilder() { + public void configure() { + from("snmp:0.0.0.0:1662?protocol=udp&type=TRAP&snmpVersion=" + SnmpConstants.version2c) + .id("SnmpTrapConsumer") + .to("mock:result"); + } + } + }; + } +}