package org.opennaas.itests.ofertie.ncl;
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 static org.ops4j.pax.exam.CoreOptions.systemTimeout;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.inject.Inject;
import junit.framework.Assert;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.opennaas.core.resources.IResource;
import org.opennaas.core.resources.IResourceManager;
import org.opennaas.core.resources.ResourceException;
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.IProtocolSessionManager;
import org.opennaas.core.resources.protocol.ProtocolException;
import org.opennaas.core.resources.protocol.ProtocolSessionContext;
import org.opennaas.extensions.ofertie.ncl.provisioner.api.INCLProvisioner;
import org.opennaas.extensions.ofertie.ncl.provisioner.api.model.Flow;
import org.opennaas.extensions.ofertie.ncl.provisioner.api.model.FlowRequest;
import org.opennaas.extensions.ofertie.ncl.provisioner.api.model.QoSRequirements;
import org.opennaas.extensions.openflowswitch.capability.IOpenflowForwardingCapability;
import org.opennaas.extensions.openflowswitch.capability.OpenflowForwardingCapability;
import org.opennaas.extensions.openflowswitch.driver.floodlight.protocol.FloodlightProtocolSession;
import org.opennaas.extensions.openflowswitch.driver.floodlight.protocol.client.IFloodlightStaticFlowPusherClient;
import org.opennaas.extensions.openflowswitch.driver.floodlight.protocol.client.mockup.FloodlightMockClientFactory;
import org.opennaas.extensions.openflowswitch.model.FloodlightOFFlow;
import org.opennaas.extensions.sdnnetwork.capability.ofprovision.IOFProvisioningNetworkCapability;
import org.opennaas.extensions.sdnnetwork.capability.ofprovision.OFProvisioningNetworkCapability;
import org.opennaas.extensions.sdnnetwork.model.NetworkConnection;
import org.opennaas.extensions.sdnnetwork.model.SDNNetworkOFFlow;
import org.opennaas.itests.helpers.InitializerTestHelper;
import org.ops4j.pax.exam.Option;
import org.ops4j.pax.exam.junit.Configuration;
import org.ops4j.pax.exam.junit.ExamReactorStrategy;
import org.ops4j.pax.exam.junit.JUnit4TestRunner;
import org.ops4j.pax.exam.spi.reactors.EagerSingleStagedReactorFactory;
import org.ops4j.pax.exam.util.Filter;
import org.osgi.service.blueprint.container.BlueprintContainer;
/**
*
* @author Adrian Rosello (i2cat)
* @author Isart Canyameres Gimenez (i2cat)
*
*/
@RunWith(JUnit4TestRunner.class)
@ExamReactorStrategy(EagerSingleStagedReactorFactory.class)
public class NCLProvisionerTest {
private IResource switch3;
private IResource switch4;
private IResource switch5;
private IResource switch6;
private IResource switch7;
private IResource switch8;
private IResource sdnNetResource;
private FlowRequest flowRequest;
private Map<String, IResource> switches;
private static final String SWITCH_3_NAME = "s3";
private static final String SWITCH_4_NAME = "s4";
private static final String SWITCH_5_NAME = "s5";
private static final String SWITCH_6_NAME = "s6";
private static final String SWITCH_7_NAME = "s7";
private static final String SWITCH_8_NAME = "s8";
private static final String SWITCH_3_ID = "00:00:00:00:00:00:00:03";
private static final String SWITCH_4_ID = "00:00:00:00:00:00:00:04";
private static final String SWITCH_5_ID = "00:00:00:00:00:00:00:05";
private static final String SWITCH_6_ID = "00:00:00:00:00:00:00:06";
private static final String SWITCH_7_ID = "00:00:00:00:00:00:00:07";
private static final String SWITCH_8_ID = "00:00:00:00:00:00:00:08";
private static final String FLOODLIGHT_ACTIONSET_NAME = "floodlight";
private static final String FLOODLIGHT_ACTIONSET_VERSION = "0.90";
private static final String FLOODLIGHT_PROTOCOL = FloodlightProtocolSession.FLOODLIGHT_PROTOCOL_TYPE;
private static final String OFSWITCH_RESOURCE_TYPE = "openflowswitch";
private static final String SWITCH_ID_NAME = FloodlightProtocolSession.SWITCHID_CONTEXT_PARAM_NAME;
private static final String CAPABILITY_URI = "mock://user:pass@host.net:2212/mocksubsystem";
private static final String RESOURCE_URI = "mock://user:pass@host.net:2212/mocksubsystem";
private static final String PROTOCOL_URI = "http://dev.ofertie.i2cat.net:8080";
private static final String SDN_ACTIONSET_NAME = "internal";
private static final String SDN_ACTIONSET_VERSION = "1.0.0";
private static final String SDN_RESOURCE_NAME = "sdnNetwork";
private static final String SDNNETWORK_RESOURCE_TYPE = "sdnnetwork";
/* FLOW REQUEST PARAMS */
private static final String SRC_IP_ADDRESS = "192.168.2.10";
private static final String DST_IP_ADDRESS = "192.168.2.11";
private static final int SRC_PORT = 0;
private static final int DST_PORT = 1;
private static final int TOS = 0;
private static final int SRC_VLAN_ID = 22;
private static final int DST_VLAN_ID = 22;
private static final int QOS_MIN_DELAY = 5;
private static final int QOS_MAX_DELAY = 10;
private static final int QOS_MIN_JITTER = 2;
private static final int QOS_MAX_JITTER = 4;
private static final int QOS_MIN_BANDWIDTH = 100;
private static final int QOS_MAX_BANDWIDTH = 1000;
private static final int QOS_MIN_PACKET_LOSS = 0;
private static final int QOS_MAX_PACKET_LOSS = 1;
private static final String WS_URI = "http://localhost:8888/opennaas/ofertie/ncl";
private static final String WS_USERNAME = "admin";
private static final String WS_PASSWORD = "123456";
/**
* Make sure blueprint for specified bundle has finished its initialization
*/
@SuppressWarnings("unused")
@Inject
@Filter(value = "(osgi.blueprint.container.symbolicname=org.opennaas.extensions.openflowswitch)", timeout = 50000)
private BlueprintContainer switchBlueprintContainer;
@SuppressWarnings("unused")
@Inject
@Filter(value = "(osgi.blueprint.container.symbolicname=org.opennaas.extensions.openflowswitch.driver.floodlight)", timeout = 50000)
private BlueprintContainer floodlightDriverBundleContainer;
@SuppressWarnings("unused")
@Inject
@Filter(value = "(osgi.blueprint.container.symbolicname=org.opennaas.extensions.sdnnetwork)", timeout = 50000)
private BlueprintContainer sdnNetworkBlueprintContainer;
@SuppressWarnings("unused")
@Inject
@Filter(value = "(osgi.blueprint.container.symbolicname=org.opennaas.extensions.ofertie.ncl)", timeout = 50000)
private BlueprintContainer nclBlueprintContainer;
@Inject
private IProtocolManager protocolManager;
@Inject
private IResourceManager resourceManager;
@Inject
private INCLProvisioner provisioner;
@Configuration
public static Option[] configuration() {
return options(
opennaasDistributionConfiguration(),
includeFeatures("opennaas-openflow-switch", "opennaas-openflow-switch-driver-floodlight", "opennaas-sdn-network",
"opennaas-ofertie-ncl", "itests-helpers"),
systemTimeout(1000 * 60 * 10),
noConsole(),
keepRuntimeFolder());
}
@Before
public void createResources() throws Exception {
createSwitches();
createSDNNetwork();
flowRequest = generateSampleFlowRequest();
}
@After
public void deleteResources() throws Exception {
resourceManager.destroyAllResources();
}
@Test
public void test() throws Exception {
testAllocateDeallocate(provisioner);
}
@Test
public void wsTest() throws Exception {
INCLProvisioner provisionerClient = InitializerTestHelper.createRestClient(WS_URI, INCLProvisioner.class, null, WS_USERNAME, WS_PASSWORD);
testAllocateDeallocate(provisionerClient);
}
public void testAllocateDeallocate(INCLProvisioner provisioner) throws Exception {
String flowId = provisioner.allocateFlow(flowRequest);
Collection<Flow> flows = provisioner.readAllocatedFlows();
Flow allocatedFlow = null;
for (Flow flow : flows) {
if (flow.getId().equals(flowId)) {
allocatedFlow = flow;
break;
}
}
Assert.assertNotNull("readAllocatedFlows() must contain allocated flow", allocatedFlow);
// Get flows in SDN network
IOFProvisioningNetworkCapability sdnCapab = (IOFProvisioningNetworkCapability) sdnNetResource
.getCapabilityByInterface(IOFProvisioningNetworkCapability.class);
Collection<SDNNetworkOFFlow> netFlows = sdnCapab.getAllocatedFlows();
// Get allocated flow in SDN network
SDNNetworkOFFlow netFlow = null;
for (SDNNetworkOFFlow flow : netFlows) {
if (flow.getName().equals(flowId)) {
netFlow = flow;
break;
}
}
Assert.assertNotNull("sdn network has flow with correct flowId", netFlow);
// Get flows in switches
for (NetworkConnection connection : netFlow.getRoute().getNetworkConnections()) {
if (connection.getSource().getDeviceId().equals(connection.getDestination().getDeviceId())) {
IResource switchResource = getSwitchResourceFromName(connection.getSource().getDeviceId());
IOpenflowForwardingCapability s3capab = (IOpenflowForwardingCapability) switchResource
.getCapabilityByInterface(IOpenflowForwardingCapability.class);
List<FloodlightOFFlow> switchFlows = s3capab.getOpenflowForwardingRules();
FloodlightOFFlow switchFlow = null;
for (FloodlightOFFlow flow : switchFlows) {
if (flow.getName().equals(connection.getId())) {
switchFlow = flow;
break;
}
}
Assert.assertNotNull("switch has flow with flowId equals to connectionId", switchFlow);
}
}
provisioner.deallocateFlow(flowId);
flows = provisioner.readAllocatedFlows();
Flow deallocatedFlow = null;
for (Flow flow : flows) {
if (flow.getId().equals(flowId)) {
deallocatedFlow = flow;
break;
}
}
Assert.assertNull("readAllocatedFlows() must not contain deallocated flow", deallocatedFlow);
// Get flows in SDN network
netFlows = sdnCapab.getAllocatedFlows();
// Get allocated flow in SDN network
SDNNetworkOFFlow deallocatedNetFlow = null;
for (SDNNetworkOFFlow flow : netFlows) {
if (flow.getName().equals(flowId)) {
deallocatedNetFlow = flow;
break;
}
}
Assert.assertNull("sdn network has no flow with deallocated flowId", deallocatedNetFlow);
// Get flows in switches
for (NetworkConnection connection : netFlow.getRoute().getNetworkConnections()) {
if (connection.getSource().getDeviceId().equals(connection.getDestination().getDeviceId())) {
IResource switchResource = getSwitchResourceFromName(connection.getSource().getDeviceId());
IOpenflowForwardingCapability s3capab = (IOpenflowForwardingCapability) switchResource
.getCapabilityByInterface(IOpenflowForwardingCapability.class);
List<FloodlightOFFlow> switchFlows = s3capab.getOpenflowForwardingRules();
FloodlightOFFlow switchFlow = null;
for (FloodlightOFFlow flow : switchFlows) {
if (flow.getName().equals(connection.getId())) {
switchFlow = flow;
break;
}
}
Assert.assertNull("switch has no flow with deallocated flow connections Ids", switchFlow);
}
}
}
private IResource getSwitchResourceFromName(String deviceName) {
return switches.get(deviceName);
}
private FlowRequest generateSampleFlowRequest() {
FlowRequest myRequest = new FlowRequest();
QoSRequirements myQoSRequirements = new QoSRequirements();
myRequest.setRequestId(String.valueOf(TOS));
myRequest.setSourceIPAddress(SRC_IP_ADDRESS);
myRequest.setDestinationIPAddress(DST_IP_ADDRESS);
myRequest.setSourcePort(SRC_PORT);
myRequest.setDestinationPort(DST_PORT);
myRequest.setTos(TOS);
myRequest.setSourceVlanId(SRC_VLAN_ID);
myRequest.setDestinationVlanId(DST_VLAN_ID);
myQoSRequirements.setMinDelay(QOS_MIN_DELAY);
myQoSRequirements.setMaxDelay(QOS_MAX_DELAY);
myQoSRequirements.setMinJitter(QOS_MIN_JITTER);
myQoSRequirements.setMaxJitter(QOS_MAX_JITTER);
myQoSRequirements.setMinBandwidth(QOS_MIN_BANDWIDTH);
myQoSRequirements.setMaxBandwidth(QOS_MAX_BANDWIDTH);
myQoSRequirements.setMinPacketLoss(QOS_MIN_PACKET_LOSS);
myQoSRequirements.setMaxPacketLoss(QOS_MAX_PACKET_LOSS);
myRequest.setQoSRequirements(myQoSRequirements);
return myRequest;
}
private void createSwitches() throws ResourceException, ProtocolException {
switches = new HashMap<String, IResource>();
switches.put(SWITCH_3_NAME, createSwitch(switch3, SWITCH_3_ID, SWITCH_3_NAME));
switches.put(SWITCH_4_NAME, createSwitch(switch4, SWITCH_4_ID, SWITCH_4_NAME));
switches.put(SWITCH_5_NAME, createSwitch(switch5, SWITCH_5_ID, SWITCH_5_NAME));
switches.put(SWITCH_6_NAME, createSwitch(switch6, SWITCH_6_ID, SWITCH_6_NAME));
switches.put(SWITCH_7_NAME, createSwitch(switch7, SWITCH_7_ID, SWITCH_7_NAME));
switches.put(SWITCH_8_NAME, createSwitch(switch8, SWITCH_8_ID, SWITCH_8_NAME));
}
private void createSDNNetwork() throws ResourceException {
List<CapabilityDescriptor> lCapabilityDescriptors = new ArrayList<CapabilityDescriptor>();
CapabilityDescriptor provisionCapab = ResourceHelper.newCapabilityDescriptor(SDN_ACTIONSET_NAME,
SDN_ACTIONSET_VERSION, OFProvisioningNetworkCapability.CAPABILITY_TYPE, CAPABILITY_URI);
lCapabilityDescriptors.add(provisionCapab);
ResourceDescriptor resourceDescriptor = ResourceHelper.newResourceDescriptor(lCapabilityDescriptors, SDNNETWORK_RESOURCE_TYPE,
RESOURCE_URI, SDN_RESOURCE_NAME);
sdnNetResource = resourceManager.createResource(resourceDescriptor);
resourceManager.startResource(sdnNetResource.getResourceIdentifier());
}
private IResource createSwitch(IResource switchResource, String switchId, String switchName) throws ResourceException, ProtocolException {
List<CapabilityDescriptor> lCapabilityDescriptors = new ArrayList<CapabilityDescriptor>();
CapabilityDescriptor ofForwardingDescriptor = ResourceHelper.newCapabilityDescriptor(FLOODLIGHT_ACTIONSET_NAME,
FLOODLIGHT_ACTIONSET_VERSION, OpenflowForwardingCapability.CAPABILITY_TYPE, CAPABILITY_URI);
lCapabilityDescriptors.add(ofForwardingDescriptor);
lCapabilityDescriptors.add(ofForwardingDescriptor);
// OFSwitch Resource Descriptor
ResourceDescriptor resourceDescriptor = ResourceHelper.newResourceDescriptor(lCapabilityDescriptors, OFSWITCH_RESOURCE_TYPE,
RESOURCE_URI, switchName);
switchResource = resourceManager.createResource(resourceDescriptor);
Map<String, Object> sessionParameters = new HashMap<String, Object>();
sessionParameters.put(SWITCH_ID_NAME, switchId);
sessionParameters.put(ProtocolSessionContext.AUTH_TYPE, "noauth");
// If not exists the protocol session manager, it's created and add the session context
InitializerTestHelper.addSessionContextWithSessionParams(protocolManager, switchResource.getResourceIdentifier().getId(), PROTOCOL_URI,
FLOODLIGHT_PROTOCOL, sessionParameters);
// Start resource
resourceManager.startResource(switchResource.getResourceIdentifier());
// COMMENT THIS LINE BELOW TO LAUNCH THE TEST IN THE REAL ENVIRONMENT
// BE SURE TO HAVE PROTOCOL_URI POINTING TO YOUR FLOODLIGHT CONTROLLER
prepareClientForSwitch(switchResource);
return switchResource;
}
/**
* Overrides IFloodlightStaticFlowPusherClient in floodlight protocol session, with a FloodlightMockClient.
*
* @param switchResource
* @throws ProtocolException
*/
private void prepareClientForSwitch(IResource switchResource) throws ProtocolException {
IProtocolSessionManager sessionManager = protocolManager.getProtocolSessionManager(switchResource.getResourceIdentifier().getId());
FloodlightProtocolSession session = (FloodlightProtocolSession) sessionManager.obtainSessionByProtocol(
FloodlightProtocolSession.FLOODLIGHT_PROTOCOL_TYPE, false);
session.setClientFactory(new FloodlightMockClientFactory());
IFloodlightStaticFlowPusherClient client = session.getClientFactory().createClient(session.getSessionContext());
session.setFloodlightClient(client);
}
}