package org.opennaas.itests.roadm.protocol.wonesys; import static java.util.concurrent.TimeUnit.MILLISECONDS; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertTrue; import static org.openengsb.labs.paxexam.karaf.options.KarafDistributionOption.keepRuntimeFolder; import static org.opennaas.itests.helpers.OpennaasExamOptions.includeFeatures; import static org.opennaas.itests.helpers.OpennaasExamOptions.noConsole; import static org.opennaas.itests.helpers.OpennaasExamOptions.opennaasDistributionConfiguration; import static org.ops4j.pax.exam.CoreOptions.options; import java.io.IOException; import java.util.ArrayList; import java.util.List; import java.util.Properties; import java.util.concurrent.CountDownLatch; import javax.inject.Inject; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.junit.After; import org.junit.Assert; import org.junit.Before; import org.junit.Ignore; import org.junit.Test; import org.junit.runner.RunWith; import org.opennaas.core.events.EventFilter; import org.opennaas.core.events.IEventManager; import org.opennaas.core.resources.IResourceManager; import org.opennaas.core.resources.ResourceException; import org.opennaas.core.resources.command.CommandException; import org.opennaas.core.resources.command.Response; import org.opennaas.core.resources.descriptor.ResourceDescriptor; import org.opennaas.core.resources.helpers.ResourceHelper; import org.opennaas.core.resources.protocol.IProtocolManager; import org.opennaas.core.resources.protocol.IProtocolSession; import org.opennaas.core.resources.protocol.IProtocolSessionManager; import org.opennaas.core.resources.protocol.ProtocolException; import org.opennaas.core.resources.protocol.ProtocolSessionContext; import org.opennaas.extensions.roadm.wonesys.commandsets.WonesysCommand; import org.opennaas.extensions.roadm.wonesys.commandsets.WonesysResponse; import org.opennaas.extensions.roadm.wonesys.commandsets.commands.GetInventoryCommand; import org.opennaas.extensions.roadm.wonesys.commandsets.commands.psroadm.GetChannels; import org.opennaas.extensions.roadm.wonesys.protocols.WonesysProtocolSessionFactory; import org.opennaas.extensions.roadm.wonesys.protocols.alarms.IWonesysAlarmConfigurator; import org.opennaas.extensions.roadm.wonesys.protocols.alarms.WonesysAlarm; import org.opennaas.extensions.roadm.wonesys.protocols.alarms.WonesysAlarmEvent; import org.opennaas.extensions.roadm.wonesys.protocols.alarms.WonesysAlarmEventFilter; import org.opennaas.extensions.roadm.wonesys.transports.ITransport; import org.opennaas.extensions.roadm.wonesys.transports.ITransportListener; import org.opennaas.extensions.roadm.wonesys.transports.WonesysTransport; import org.opennaas.extensions.roadm.wonesys.transports.WonesysTransportException; import org.opennaas.extensions.roadm.wonesys.transports.rawsocket.RawSocketTransport; import org.ops4j.pax.exam.Option; import org.ops4j.pax.exam.junit.Configuration; import org.ops4j.pax.exam.junit.JUnit4TestRunner; import org.ops4j.pax.exam.util.Filter; import org.osgi.framework.BundleContext; import org.osgi.service.blueprint.container.BlueprintContainer; import org.osgi.service.event.Event; import org.osgi.service.event.EventHandler; import uk.co.westhawk.snmp.pdu.OneTrapPduv2; import uk.co.westhawk.snmp.stack.AsnInteger; import uk.co.westhawk.snmp.stack.AsnObject; import uk.co.westhawk.snmp.stack.AsnObjectId; import uk.co.westhawk.snmp.stack.AsnOctets; import uk.co.westhawk.snmp.stack.AsnUnsInteger; import uk.co.westhawk.snmp.stack.PduException; import uk.co.westhawk.snmp.stack.SnmpContext; import uk.co.westhawk.snmp.stack.SnmpContextv2c; import uk.co.westhawk.snmp.stack.TrapPduv2; import uk.co.westhawk.snmp.stack.varbind; @RunWith(JUnit4TestRunner.class) public class WonesysProtocolTest implements EventHandler, ITransportListener { private static Log log = LogFactory.getLog(WonesysProtocolTest.class); private String alarmsPort = "32162"; // SNMP traps port (162). if different, // 162 needs to be redirected to this port private String resourceName = "Proteus-Pedrosa"; private String resourceId; private String hostIpAddress = "10.10.80.11"; private String hostPort = "27773"; // in order to receive traps. private long alarmWaittime = 5 * 1000; // 5sec private final CountDownLatch alarmReceived = new CountDownLatch(1); boolean eventReceived = false; String receivedMessage; // Required services @Inject private BundleContext bundleContext; @Inject private IProtocolManager protocolManager; @Inject private IResourceManager resourceManager; @Inject @Filter(value = "(osgi.blueprint.container.symbolicname=org.opennaas.extensions.roadm.protocols.wonesys)", timeout = 20000) BlueprintContainer wonesysProtocolService; @Inject private IEventManager eventManager; @Inject private IWonesysAlarmConfigurator alarmConfig; @Configuration public static Option[] configuration() { return options(opennaasDistributionConfiguration(), includeFeatures("opennaas-luminis", "opennaas-roadm-proteus"), noConsole(), keepRuntimeFolder()); } @Before public void createResource() throws ResourceException { ResourceDescriptor resourceDescriptor = ResourceHelper.newResourceDescriptorProteus("roadm"); resourceDescriptor.getInformation().setName(resourceName); resourceId = resourceManager.createResource(resourceDescriptor).getResourceIdentifier().getId(); } @After public void removeResource() throws ResourceException { resourceManager.destroyAllResources(); } // FIXME Uncomment to test transport works ok // @Test // uses real connection @Ignore public void sendReceiveTest() { ProtocolSessionContext sessionContext = newWonesysProtocolSessionContext(hostIpAddress, hostPort); try { ITransport transport = new WonesysTransport(sessionContext); int regNum = registerAsListener(transport); eventReceived = false; transport.connect(); String message = "5910ffffffffff01ffffffff0000b700"; // get inv command transport.sendAsync(message); log.debug("Message sent: " + message); Thread.sleep(5000); Assert.assertTrue(eventReceived); log.debug("Message received: " + receivedMessage); Assert.assertTrue(receivedMessage.startsWith("5910ffffffffff01ffffffff")); unregisterAsListener(regNum); transport.disconnect(); } catch (ProtocolException e) { Assert.fail(e.getLocalizedMessage()); } catch (Exception e) { Assert.fail(e.getLocalizedMessage()); } } // FIXME Uncomment to test transport works ok @Test // uses real connection @Ignore public void sendAsyncTest() { ProtocolSessionContext sessionContext = newWonesysProtocolSessionContext(hostIpAddress, hostPort); try { WonesysTransport transport = new WonesysTransport(sessionContext); transport.connect(); String message = "5910ffffffffff01ffffffff0000b700"; // get inv command transport.sendAsync(message); // if socket is not connected will throw an exception // TODO check message reached device transport.disconnect(); } catch (ProtocolException e) { Assert.fail(e.getLocalizedMessage()); } catch (WonesysTransportException e) { Assert.fail(e.getLocalizedMessage()); } } /** * 0. Obtain services <br> * 1. Use WonesysAlarmActivator to configure and activate alarms <br> * 2. Create a WonesysAlarmEventFilter <br> * 3. Use eventManager to register an EventHandler (this), using created filter <br> * 4. Trigger an alarm <br> * 5. Wait for alarm reception <br> * 6. Receive the alarm and checks <br> * 7. Unregister Handlers and disable alarms <br> * * @throws PduException * * @throws CommandException * @throws ProtocolException * * @throws Exception */ @Test public void testAlarms() throws IOException { // set up Properties alarmProperties = new Properties(); alarmProperties.setProperty(IWonesysAlarmConfigurator.ALARM_PORT_PROPERTY_NAME, alarmsPort); alarmProperties.setProperty(IWonesysAlarmConfigurator.ALARM_WAITTIME_PROPERTY_NAME, Long.valueOf(alarmWaittime).toString()); alarmConfig.configureAlarms(alarmProperties); alarmConfig.enableAlarms(); EventFilter filter = new WonesysAlarmEventFilter(); int serviceID = eventManager.registerEventHandler(this, filter); // test TrapPduv2 pdu = null; try { pdu = triggerAlarm(); try { log.info("Waiting for an alarm..."); alarmReceived.await(alarmWaittime * 3, MILLISECONDS); } catch (InterruptedException e) { log.warn("Interrupted!"); } assertEquals(0, alarmReceived.getCount()); } finally { // clean up if (pdu != null) pdu.getContext().destroy(); eventManager.unregisterHandler(serviceID); alarmConfig.disableAlarms(); } } @Test public void testSendMultipleMessages() throws ProtocolException { // loadBundles(); sendMultipleMessages(1); sendMultipleMessages(5); } @Test public void sendCommandTest() throws ProtocolException, CommandException { // loadBundles(); /* Wait for the activation of all the bundles */ // IntegrationTestsHelper.waitForAllBundlesActive(bundleContext); ProtocolSessionContext sessionContext = createWonesysProtocolSessionContext(hostIpAddress, hostPort); sessionContext.addParameter("protocol.mock", "true"); try { // get WonesysProtocolSession using ProtocolSessionManager IProtocolSession protocolSession = getProtocolSession(resourceId, sessionContext); if (protocolSession == null) throw new ProtocolException("Could not get a valid ProtocolSession"); // create command WonesysCommand command = new GetInventoryCommand(); command.initialize(); // send command & receive response Object rawResponse = protocolSession.sendReceive(command.message()); WonesysResponse response = (WonesysResponse) command.checkResponse(rawResponse); assertNotNull(response); // assure response is correct log.info("Received response " + response.getWonesysResponseMessage().toString()); if (response.getStatus() == Response.Status.OK) { log.info("Response is OK"); } else if (response.getStatus() == Response.Status.ERROR) { log.info("Response is ERROR"); assertTrue(response.getErrors().size() > 0); for (String error : response.getErrors()) log.info(error); } List<int[]> model = new ArrayList<int[]>(); // command.parseResponse(response, model); String responseData = response.getInformation(); int resultLength = 4 * 2; int resultsCount = responseData.length() / resultLength; String[] results = new String[resultsCount]; log.info("Node has " + resultsCount + " cards"); for (int i = 0; i < resultsCount; i++) { results[i] = responseData.substring(i * resultLength, (i + 1) * resultLength); String schasis = results[i].substring(0, 2); String sslot = results[i].substring(2, 4); String stype = results[i].substring(4, 6); String ssubtype = results[i].substring(6, 8); int chasis = Integer.parseInt(schasis, 16); int slot = Integer.parseInt(sslot, 16); int type = Integer.parseInt(stype, 16); int subtype = Integer.parseInt(ssubtype, 16); log.info("Chasis:" + chasis + " Slot:" + slot + " Type:" + type + " SubType:" + subtype); model.add(new int[] { chasis, slot, type, subtype }); } for (int[] card : model) { if (card[2] == 11 && (card[3] == 1 || card[3] == 3)) { command = new GetChannels(card[0], card[1]); command.initialize(); rawResponse = protocolSession.sendReceive(command.message()); response = (WonesysResponse) command.checkResponse(rawResponse); // assure response is correct log.info("Received response " + response.getWonesysResponseMessage().toString()); if (response.getStatus() == Response.Status.OK) { log.info("Response is OK"); } else if (response.getStatus() == Response.Status.ERROR) { log.info("Response is ERROR"); assertTrue(response.getErrors().size() > 0); for (String error : response.getErrors()) log.info(error); } log.info(response.getInformation()); } } } catch (ProtocolException e) { Assert.fail(e.getMessage()); } catch (CommandException e) { Assert.fail(e.getMessage()); } } /** * Called when the alarm is received */ @Override public void handleEvent(Event event) { assertNotNull(event); assertTrue(event instanceof WonesysAlarmEvent); WonesysAlarmEvent wevent = (WonesysAlarmEvent) event; WonesysAlarm a = wevent.getAlarm(); assertNotNull(a); log.info("Alarm received: " + a.toString()); alarmReceived.countDown(); } private TrapPduv2 triggerAlarm() throws IOException { TrapPduv2 pdu = createSNMPTrap(); sendSNMPTrap(pdu); return pdu; // try { // // Send setChannel command to trigger an alarm // IProtocolSession protocolSession = getProtocolSession(resourceId, createWonesysProtocolSessionContext(hostIpAddress, hostPort)); // // WonesysCommand command = new SetChannel(); // command.initialize(); // // // send command & receive response // Object rawResponse = protocolSession.sendReceive(command.message()); // WonesysResponse response = (WonesysResponse) command.checkResponse(rawResponse); // assertNotNull(response); // assertTrue(response.getStatus().equals(Response.Status.OK)); // } catch (ProtocolException e) { // log.error("Could not trigger alarm. Command sending failed", e); // throw e; // } catch (CommandException e) { // log.error("Could not trigger alarm. Command failed", e); // throw e; // } } /** * Simulates an alarm has been received. * * @throws IOException * @throws PduException */ private void sendSNMPTrap(TrapPduv2 pdu) throws IOException { try { log.info("Sending Pdu"); pdu.send(); } catch (PduException e) { log.error("PDUException", e); pdu.getContext().destroy(); throw new IOException(e); } } private TrapPduv2 createSNMPTrap() throws IOException { SnmpContext snmpContext = new SnmpContextv2c("127.0.0.1", Integer.parseInt(alarmsPort)); // should send from a different port snmpContext.setCommunity("publica"); TrapPduv2 pdu = new OneTrapPduv2(snmpContext); AsnObjectId varbindID; AsnObject varbindValue; // pdu.setIpAddress(new byte[] { 127, 0, 0, 1 }); // pdu.setEnterprise("1.3.6.1.4.1.9"); // pdu.setGenericTrap(SnmpConstants.SNMP_TRAP_ENTERPRISESPECIFIC); // pdu.setSpecificTrap(0); // pdu.setTimeTicks(20646400); varbindID = new AsnObjectId("1.3.6.1.2.1.1.3.0"); varbindValue = new AsnUnsInteger(20646400); pdu.addOid(new varbind(varbindID, varbindValue)); varbindID = new AsnObjectId("1.3.6.1.6.3.1.1.4.1.0"); varbindValue = new AsnObjectId("1.3.6.1.4.1.18223.9.8.2.2"); pdu.addOid(new varbind(varbindID, varbindValue)); varbindID = new AsnObjectId("1.3.6.1.4.1.18223.9.8.2.3"); varbindValue = new AsnInteger(0); pdu.addOid(new varbind(varbindID, varbindValue)); varbindID = new AsnObjectId("1.3.6.1.4.1.18223.9.8.2.4"); varbindValue = new AsnInteger(4); pdu.addOid(new varbind(varbindID, varbindValue)); varbindID = new AsnObjectId("1.3.6.1.4.1.18223.9.8.2.5"); varbindValue = new AsnOctets("0B"); pdu.addOid(new varbind(varbindID, varbindValue)); varbindID = new AsnObjectId("1.3.6.1.4.1.18223.9.8.2.6"); varbindValue = new AsnOctets("586376724c617365724f6666"); pdu.addOid(new varbind(varbindID, varbindValue)); varbindID = new AsnObjectId("1.3.6.1.4.1.18223.9.8.2.7"); varbindValue = new AsnOctets("5472616E73636569766572204C61736572206F6666"); pdu.addOid(new varbind(varbindID, varbindValue)); varbindID = new AsnObjectId("1.3.6.1.4.1.18223.9.8.2.8"); varbindValue = new AsnInteger(0); pdu.addOid(new varbind(varbindID, varbindValue)); varbindID = new AsnObjectId("1.3.6.1.4.1.18223.9.8.2.9"); varbindValue = new AsnOctets("0B0001"); pdu.addOid(new varbind(varbindID, varbindValue)); return pdu; } private void sendMultipleMessages(int numMessagesToSend) throws ProtocolException { ProtocolSessionContext protocolSessionContext1 = createWonesysProtocolSessionContext( hostIpAddress, hostPort); // use mock transport protocolSessionContext1.addParameter("protocol.mock", "true"); String sessionId1 = "1"; Object command = createGetCommand(); WonesysProtocolSessionFactory factory = new WonesysProtocolSessionFactory(); try { IProtocolSession protocolSession = factory.createProtocolSession( sessionId1, protocolSessionContext1); protocolSession.connect(); for (int i = 0; i < numMessagesToSend; i++) { log.info("Sending message... " + command); Object response = protocolSession.sendReceive(command); log.info("Received response: " + (String) response); assertNotNull(response); assertFalse(response.equals("")); } protocolSession.disconnect(); } catch (ProtocolException e) { log.info("Failed to send message!", e); throw e; } } private ProtocolSessionContext createWonesysProtocolSessionContext(String ip, String port) { ProtocolSessionContext protocolSessionContext = new ProtocolSessionContext(); protocolSessionContext.addParameter(ProtocolSessionContext.PROTOCOL, "wonesys"); protocolSessionContext.addParameter(ProtocolSessionContext.PROTOCOL_URI, "wonesys://" + ip + ":" + port); return protocolSessionContext; } private IProtocolSession getProtocolSession(String resourceId, ProtocolSessionContext sessionContext) throws ProtocolException { // IProtocolManager protocolManager = getOsgiService(IProtocolManager.class, 5000); if (protocolManager == null) return null; IProtocolSessionManager protocolSessionManager = protocolManager.getProtocolSessionManager(resourceId); return protocolSessionManager.obtainSession(sessionContext, true); } private Object createGetCommand() { // getInventory command String cmd = "5910ffffffffff01ffffffff0000"; String xor = getXOR(cmd); cmd += xor + "00"; return cmd; } private String getXOR(String cmd) { int xor = Integer.parseInt(cmd.substring(0, 2), 16) ^ Integer.parseInt(cmd.substring(2, 4), 16); for (int i = 4; i <= cmd.length() - 2; i++) { xor = xor ^ Integer.parseInt(cmd.substring(i, i + 2), 16); i++; } String hxor = Integer.toHexString(xor); if (hxor.length() < 2) { hxor = "0" + hxor; } return hxor; } private ProtocolSessionContext newWonesysProtocolSessionContext(String ip, String port) { ProtocolSessionContext protocolSessionContext = new ProtocolSessionContext(); protocolSessionContext.addParameter(ProtocolSessionContext.PROTOCOL, "wonesys"); protocolSessionContext.addParameter(ProtocolSessionContext.PROTOCOL, "password"); protocolSessionContext.addParameter(ProtocolSessionContext.PROTOCOL_URI, "wonesys://" + ip + ":" + port); return protocolSessionContext; } private int registerAsListener(ITransport transport) { // register as a transport listener // this will receive all events from its wonesysTransport String topic = RawSocketTransport.ALL_EVENTS_TOPIC; Properties properties = new Properties(); properties.setProperty(RawSocketTransport.TRANSPORT_ID_PROPERTY_NAME, transport.getTransportID()); EventFilter filter = new EventFilter(new String[] { topic }, properties); return eventManager.registerEventHandler(this, filter); } private void unregisterAsListener(int regNum) { eventManager.unregisterHandler(regNum); } }