package org.opennaas.itests.openflowforwarding.floodlight; /* * #%L * OpenNaaS :: iTests :: OpenflowForwarding :: Floodlight * %% * Copyright (C) 2007 - 2014 FundaciĆ³ Privada i2CAT, Internet i InnovaciĆ³ a Catalunya * %% * Licensed 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. * #L% */ import static org.ops4j.pax.exam.CoreOptions.options; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import javax.inject.Inject; import javax.ws.rs.HttpMethod; import javax.ws.rs.core.MediaType; import javax.xml.bind.JAXBException; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.eclipse.jetty.http.HttpStatus; 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.endpoints.WSEndpointListenerHandler; import org.opennaas.core.resources.IResource; import org.opennaas.core.resources.IResourceManager; import org.opennaas.core.resources.ResourceException; import org.opennaas.core.resources.capability.CapabilityException; import org.opennaas.core.resources.capability.ICapability; import org.opennaas.core.resources.descriptor.CapabilityDescriptor; 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.ProtocolException; import org.opennaas.extensions.openflowswitch.capability.offorwarding.IOpenflowForwardingCapability; import org.opennaas.extensions.openflowswitch.capability.offorwarding.OpenflowForwardingCapability; import org.opennaas.extensions.openflowswitch.driver.floodlight.offorwarding.actionssets.actions.CreateOFForwardingAction; import org.opennaas.extensions.openflowswitch.driver.floodlight.protocol.FloodlightProtocolSession; import org.opennaas.extensions.openflowswitch.model.FloodlightOFAction; import org.opennaas.extensions.openflowswitch.model.FloodlightOFFlow; import org.opennaas.extensions.openflowswitch.model.FloodlightOFMatch; import org.opennaas.extensions.openflowswitch.model.OFFlow; import org.opennaas.extensions.openflowswitch.model.OFFlowTable; import org.opennaas.extensions.openflowswitch.model.OpenflowSwitchModel; import org.opennaas.itests.helpers.InitializerTestHelper; import org.opennaas.itests.helpers.OpennaasExamOptions; import org.opennaas.itests.helpers.server.HTTPRequest; import org.opennaas.itests.helpers.server.HTTPResponse; import org.opennaas.itests.helpers.server.HTTPServerBehaviour; import org.opennaas.itests.helpers.server.MockHTTPServerTest; import org.ops4j.pax.exam.Configuration; import org.ops4j.pax.exam.Option; import org.ops4j.pax.exam.junit.PaxExam; import org.ops4j.pax.exam.spi.reactors.ExamReactorStrategy; import org.ops4j.pax.exam.spi.reactors.PerClass; import org.osgi.framework.BundleContext; @RunWith(PaxExam.class) @ExamReactorStrategy(PerClass.class) public class FloodlightDriverTest extends MockHTTPServerTest { @Inject protected IResourceManager resourceManager; @Inject protected IProtocolManager protocolManager; @Inject protected BundleContext context; private final static Log log = LogFactory.getLog(FloodlightDriverTest.class); private final static String SERVER_URL = "http://localhost:8080"; private final static String SERVLET_CONTEXT_URL = "/wm/staticflowentrypusher"; private final static String SWITCH_ID = "00:00:00:00:00:00:00:01"; private final static String FLOW_INGRESS_PORT = "1"; private final static String FLOW_OUTPUT_PORT = "2"; private final static String FLOW_PRIORITY = "32767"; private final static String OUTPUT_ACTION = CreateOFForwardingAction.FORWARDING_ACTION; private final static String GET_FLOWS_URL = SERVLET_CONTEXT_URL + "/list/" + SWITCH_ID + "/json"; private final static String ADD_FLOW_URL = SERVLET_CONTEXT_URL + "/json"; private final static String REMOVE_FLOW_URL = SERVLET_CONTEXT_URL + "/json"; private final static String FLOODLIGHT_ADD_FLOW_RESPONSE = "Entry pushed"; private final static String RESOURCE_INFO_NAME = "OpenflowSwitch"; private static final String ACTIONSET_NAME = "floodlight"; private static final String ACTIONSET_VERSION = "0.90"; private static final String MOCK_URI = "mock://user:pass@host.net:2212/mocksubsystem"; private static final String RESOURCE_TYPE = "openflowswitch"; private static final String PROTOCOL = FloodlightProtocolSession.FLOODLIGHT_PROTOCOL_TYPE; private static final String SWITCH_ID_NAME = FloodlightProtocolSession.SWITCHID_CONTEXT_PARAM_NAME; private IResource ofSwitchResource; private WSEndpointListenerHandler listenerHandler; private static final String WS_URI = "http://localhost:8888/opennaas/" + RESOURCE_TYPE + "/" + RESOURCE_INFO_NAME + "/" + OpenflowForwardingCapability.CAPABILITY_TYPE; private static final String WS_USERNAME = "admin"; private static final String WS_PASSWORD = "123456"; @Configuration public static Option[] configuration() { return options( OpennaasExamOptions.opennaasDistributionConfiguration(), OpennaasExamOptions.includeFeatures("opennaas-openflowswitch", "opennaas-openflowswitch-driver-floodlight", "itests-helpers"), OpennaasExamOptions.noConsole(), OpennaasExamOptions.doNotDelayShell(), OpennaasExamOptions.keepLogConfiguration(), // OpennaasExamOptions.openDebugSocket(), OpennaasExamOptions.keepRuntimeFolder()); } @Before public void initTestScenario() throws Exception { log.info("Creating initial scenario."); prepareBehaviours(); startServer(SERVLET_CONTEXT_URL); startResource(SERVER_URL, SWITCH_ID); log.info("Test initialized."); } @After public void shutDownTestScenario() throws Exception { log.info("Shutting down test scenario."); stopResource(); stopServer(); log.info("Test finished."); } /** * Test checks that, when creating a flow using the {@link IOpenflowForwardingCapability} with a successful result, it's set to model. * * @throws Exception */ @Test public void createRuleTest() throws Exception { IOpenflowForwardingCapability forwardingCapab = (IOpenflowForwardingCapability) getCapability(IOpenflowForwardingCapability.class); OFFlow forwardingRule = FloodlightTestHelper.sampleOFFlow("flow-mod-1", "32767", "1", "2"); forwardingCapab.createOpenflowForwardingRule(forwardingRule); OpenflowSwitchModel model = (OpenflowSwitchModel) ofSwitchResource.getModel(); Assert.assertNotNull(model); Assert.assertEquals(1, model.getOfTables().size()); OFFlowTable table = model.getOfTables().get(0); Assert.assertNotNull(table.getOfForwardingRules()); Assert.assertEquals(1, table.getOfForwardingRules().size()); OFFlow flow = table.getOfForwardingRules().get(0); Assert.assertNotNull(flow); Assert.assertNotNull("Flow should contain as id \"flow-mod-1\".", flow.getName()); Assert.assertEquals("Flow priority should be " + FLOW_PRIORITY, FLOW_PRIORITY, flow.getPriority()); Assert.assertEquals("Switch id should be " + SWITCH_ID, SWITCH_ID, model.getSwitchId()); Assert.assertNotNull("Flow should contain actions.", flow.getActions()); Assert.assertEquals("Flow should contain one action.", 1, flow.getActions().size()); FloodlightOFAction action = flow.getActions().get(0); Assert.assertEquals("The name of the action should be " + OUTPUT_ACTION, OUTPUT_ACTION, action.getType()); Assert.assertEquals("Output port should be " + FLOW_OUTPUT_PORT, FLOW_OUTPUT_PORT, action.getValue()); Assert.assertNotNull("Flow should contain match.", flow.getMatch()); FloodlightOFMatch match = flow.getMatch(); Assert.assertEquals("Ingress port should be " + FLOW_INGRESS_PORT, FLOW_INGRESS_PORT, match.getIngressPort()); } /** * Test createForwardingRule method through WS. Asserts that after sending a CreateForwardingRule request, the model of the switch contains the * expected forwarding rule. * * @throws CapabilityException */ @Test public void createRuleWithIPWS() throws CapabilityException { OFFlow forwardingRule = FloodlightTestHelper.sampleOFFlow("flow-mod-1", "32767", "1", "2"); forwardingRule.getMatch().setSrcIp("192.168.1.1"); forwardingRule.getMatch().setDstIp("192.168.1.2"); // forwardingRule.setSwitchId(SWITCH_ID); IOpenflowForwardingCapability forwardingClient = InitializerTestHelper.createRestClient(WS_URI, IOpenflowForwardingCapability.class, null, WS_USERNAME, WS_PASSWORD); forwardingClient.createOpenflowForwardingRule(forwardingRule); List<OFFlow> forwardingRules = forwardingClient.getOpenflowForwardingRulesAPI().getForwardingRules(); Assert.assertNotNull(forwardingRules); Assert.assertEquals(1, forwardingRules.size()); OFFlow readedForwardingRule = forwardingRules.get(0); Assert.assertEquals(forwardingRule, readedForwardingRule); } /** * * Floodlight driver needs to send a body message in the DELETE method because of the Floodlight API. Our Jetty server answers a HTTP 400 Bad * Request error if we include body in this method, so we can not test this functionality. * * @throws ResourceException */ @Ignore @Test public void createAndDeleteRuleTest() throws ResourceException { IOpenflowForwardingCapability forwardingCapab = (IOpenflowForwardingCapability) getCapability(IOpenflowForwardingCapability.class); OFFlow forwardingRule = FloodlightTestHelper.sampleOFFlow("flow-mod-1", "1", "1", "2"); forwardingCapab.createOpenflowForwardingRule(forwardingRule); OpenflowSwitchModel model = (OpenflowSwitchModel) ofSwitchResource.getModel(); OFFlowTable table = model.getOfTables().get(0); Assert.assertEquals(1, table.getOfForwardingRules().size()); FloodlightOFFlow flow = (FloodlightOFFlow) table.getOfForwardingRules().get(0); Assert.assertNotNull(flow); forwardingCapab.removeOpenflowForwardingRule(flow.getName()); Assert.assertEquals(0, table.getOfForwardingRules().size()); } @Override protected void prepareBehaviours() throws JAXBException, IOException { desiredBehaviours = new ArrayList<HTTPServerBehaviour>(); HTTPRequest reqCreateFlow = new HTTPRequest(ADD_FLOW_URL, HttpMethod.POST, MediaType.APPLICATION_JSON, readSampleFile("/addFlow.json"), new ArrayList<String>()); HTTPResponse resqCreateFlow = new HTTPResponse(HttpStatus.CREATED_201, MediaType.APPLICATION_JSON, FLOODLIGHT_ADD_FLOW_RESPONSE, ""); HTTPServerBehaviour behaviourCreateFlow = new HTTPServerBehaviour(reqCreateFlow, resqCreateFlow, false); desiredBehaviours.add(behaviourCreateFlow); HTTPRequest reqGetFlows = new HTTPRequest(GET_FLOWS_URL, HttpMethod.GET, MediaType.APPLICATION_JSON, "", new ArrayList<String>()); HTTPResponse respGetFlows = new HTTPResponse(HttpStatus.OK_200, MediaType.APPLICATION_JSON, readSampleFile("/getSwitchFlowsWithOneFlow.json"), ""); HTTPServerBehaviour behaviourgetFlows = new HTTPServerBehaviour(reqGetFlows, respGetFlows, true); desiredBehaviours.add(behaviourgetFlows); desiredBehaviours.add(behaviourgetFlows); HTTPRequest reqDelFlow = new HTTPRequest(REMOVE_FLOW_URL, HttpMethod.DELETE, MediaType.APPLICATION_JSON, "", new ArrayList<String>()); HTTPResponse respDelFlow = new HTTPResponse(HttpStatus.OK_200, MediaType.APPLICATION_JSON, "", ""); HTTPServerBehaviour behaviourDelFlows = new HTTPServerBehaviour(reqDelFlow, respDelFlow, true); desiredBehaviours.add(behaviourDelFlows); HTTPRequest reqCreateFlowIP = new HTTPRequest(ADD_FLOW_URL, HttpMethod.POST, MediaType.APPLICATION_JSON, readSampleFile("/addFlowWithIP.json"), new ArrayList<String>()); HTTPResponse resqCreateFlowIP = new HTTPResponse(HttpStatus.CREATED_201, MediaType.APPLICATION_JSON, FLOODLIGHT_ADD_FLOW_RESPONSE, ""); HTTPServerBehaviour behaviourCreateFlowIP = new HTTPServerBehaviour(reqCreateFlowIP, resqCreateFlowIP, false); desiredBehaviours.add(behaviourCreateFlowIP); // TODO add behaviour for next getter } private String readSampleFile(String url) throws IOException { String fileString = ""; BufferedReader br = new BufferedReader( new InputStreamReader(getClass().getResourceAsStream(url))); String line; while ((line = br.readLine()) != null) { fileString += line += "\n"; } br.close(); return fileString; } private void startResource(String serverURL, String switchId) throws ResourceException, ProtocolException, InterruptedException { List<CapabilityDescriptor> lCapabilityDescriptors = new ArrayList<CapabilityDescriptor>(); CapabilityDescriptor ofForwardingDescriptor = ResourceHelper.newCapabilityDescriptor(ACTIONSET_NAME, ACTIONSET_VERSION, OpenflowForwardingCapability.CAPABILITY_TYPE, MOCK_URI); lCapabilityDescriptors.add(ofForwardingDescriptor); // OFSwitch Resource Descriptor ResourceDescriptor resourceDescriptor = ResourceHelper.newResourceDescriptor(lCapabilityDescriptors, RESOURCE_TYPE, MOCK_URI, RESOURCE_INFO_NAME); ofSwitchResource = resourceManager.createResource(resourceDescriptor); Map<String, Object> sessionParameters = new HashMap<String, Object>(); sessionParameters.put(SWITCH_ID_NAME, switchId); // If not exists the protocol session manager, it's created and add the session context InitializerTestHelper.addSessionContextWithSessionParams(protocolManager, ofSwitchResource.getResourceIdentifier().getId(), serverURL, PROTOCOL, sessionParameters); // Start resource listenerHandler = new WSEndpointListenerHandler(); listenerHandler.registerWSEndpointListener(context, IOpenflowForwardingCapability.class); resourceManager.startResource(ofSwitchResource.getResourceIdentifier()); listenerHandler.waitForEndpointToBePublished(); } private void stopResource() throws ResourceException, InterruptedException { resourceManager.stopResource(ofSwitchResource.getResourceIdentifier()); listenerHandler.waitForEndpointToBeUnpublished(); resourceManager.removeResource(ofSwitchResource.getResourceIdentifier()); } private ICapability getCapability(Class<? extends ICapability> clazz) throws ResourceException { ICapability capab = ofSwitchResource.getCapabilityByInterface(clazz); Assert.assertNotNull(capab); return capab; } }