package org.opennaas.extensions.xifi.capability.e2e;
/*
* #%L
* OpenNaaS :: XIFI
* %%
* Copyright (C) 2007 - 2015 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 java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Properties;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.opennaas.core.resources.ActivatorException;
import org.opennaas.core.resources.IResource;
import org.opennaas.core.resources.IResourceManager;
import org.opennaas.core.resources.ResourceException;
import org.opennaas.core.resources.action.IAction;
import org.opennaas.core.resources.action.IActionSet;
import org.opennaas.core.resources.capability.AbstractCapability;
import org.opennaas.core.resources.capability.CapabilityException;
import org.opennaas.core.resources.configurationadmin.ConfigurationAdminUtil;
import org.opennaas.core.resources.descriptor.CapabilityDescriptor;
import org.opennaas.core.resources.descriptor.Information;
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.core.resources.protocol.ProtocolSessionContext;
import org.opennaas.extensions.abno.capability.linkprovisioning.ILinkProvisioningCapability;
import org.opennaas.extensions.abno.capability.linkprovisioning.LinkProvisioningCapability;
import org.opennaas.extensions.abno.capability.linkprovisioning.api.ProvisionLinkRequest;
import org.opennaas.extensions.abno.capability.linkprovisioning.protocol.ABNOProtocolSession;
import org.opennaas.extensions.abno.repository.ABNORepository;
import org.opennaas.extensions.openstack.capability.openstackadapter.IOpenstackAdapterCapability;
import org.opennaas.extensions.openstack.capability.openstackadapter.OpenstackAdaperCapability;
import org.opennaas.extensions.openstack.repository.OpenstackRepository;
import org.opennaas.extensions.protocols.http.HttpProtocolSession;
import org.opennaas.extensions.ryu.alarm.IAlarmObserver;
import org.opennaas.extensions.ryu.capability.monitoringmodule.IMonitoringModuleCapability;
import org.opennaas.extensions.ryu.capability.monitoringmodule.MonitoringModuleCapability;
import org.opennaas.extensions.xifi.Activator;
import org.opennaas.extensions.xifi.capability.e2e.api.ConnectEndsRequest;
import org.opennaas.extensions.xifi.capability.e2e.model.Region;
import org.opennaas.extensions.xifi.capability.e2e.model.XIFIConfiguration;
/**
* XIFI {@link IE2ECapability} implementation
*
* @author Julio Carlos Barrera
*
*/
public class E2ECapability extends AbstractCapability implements IE2ECapability {
private static final Log log = LogFactory.getLog(E2ECapability.class);
private String resourceId = "";
// configuration file and properties
private static final String XIFI_FILE = "xifi.regions";
private static final String ABNO_ENDPOINT = "abno.endpoint";
private static final String REGION = "region";
private static final String REGION_RYU = ".ryu";
private static final String REGION_RYU_SWITCH_DPID = REGION_RYU + ".switch";
private static final String REGION_OPENSTACK = ".openstack";
private static final String REGION_OPENSTACK_USER = REGION_OPENSTACK + ".user";
private static final String REGION_OPENSTACK_PWD = REGION_OPENSTACK + ".password";
private static final String REGION_OPENSTACK_TENANT = REGION_OPENSTACK + ".tenant";
private static final String REGION_AUTOBAHN_IFACE = ".autobahn.iface";
private XIFIConfiguration xifiConfiguration;
// resources
private IResource abno;
private Map<Region, IResource> ryuResourcesMap = new HashMap<Region, IResource>();
private Map<Region, IResource> openStackResourcesMap = new HashMap<Region, IResource>();
public E2ECapability(CapabilityDescriptor descriptor, String resourceId) {
super(descriptor);
this.resourceId = resourceId;
log.debug("Built new XIFI E2E Capability");
}
@Override
public void connectEnds(ConnectEndsRequest connectEndsRequest) throws CapabilityException {
// get configured regions from input parameters
Region srcRegion = getConfiguredRegionFromName(connectEndsRequest.getSourceRegion());
Region dstRegion = getConfiguredRegionFromName(connectEndsRequest.getDestinationRegion());
if (srcRegion == null || dstRegion == null) {
throw new CapabilityException("Source or destination region not found in configuration.");
}
// get source and destination MAC addresses and interfaces from OpenStack
IOpenstackAdapterCapability srcOpenStackCapability;
IOpenstackAdapterCapability dstOpenStackCapability;
try {
srcOpenStackCapability = (IOpenstackAdapterCapability) openStackResourcesMap.get(srcRegion).getCapabilityByInterface(
IOpenstackAdapterCapability.class);
dstOpenStackCapability = (IOpenstackAdapterCapability) openStackResourcesMap.get(dstRegion).getCapabilityByInterface(
IOpenstackAdapterCapability.class);
} catch (ResourceException e) {
throw new CapabilityException("Error getting IOpenstackAdapterCapability from resources.", e);
}
String srcPortId;
String dstPortId;
String srcMACAddress;
String dstMACAddress;
try {
String srcInstanceId = srcOpenStackCapability.getInstanceId(connectEndsRequest.getSourceInstance(), srcRegion.getOpenstackTenant());
String dstInstanceId = dstOpenStackCapability.getInstanceId(connectEndsRequest.getDestinationInstance(), dstRegion.getOpenstackTenant());
srcPortId = srcOpenStackCapability.getPortId(srcInstanceId, srcRegion.getOpenstackTenant());
dstPortId = dstOpenStackCapability.getPortId(dstInstanceId, dstRegion.getOpenstackTenant());
srcMACAddress = srcOpenStackCapability.getMACAddress(srcPortId, srcRegion.getOpenstackTenant());
dstMACAddress = dstOpenStackCapability.getMACAddress(dstPortId, dstRegion.getOpenstackTenant());
} catch (CapabilityException e) {
throw new CapabilityException("Error getting data form OpenStack instances.", e);
}
// call ABNO
ILinkProvisioningCapability linkProvisioningCapability;
try {
linkProvisioningCapability = (ILinkProvisioningCapability) abno.getCapabilityByInterface(ILinkProvisioningCapability.class);
} catch (ResourceException e) {
throw new CapabilityException("Error getting ILinkProvisioningCapability from ABNO resource.", e);
}
ProvisionLinkRequest request = new ProvisionLinkRequest(srcRegion.getName(), dstRegion.getName(), srcMACAddress, dstMACAddress, srcPortId,
dstPortId, ProvisionLinkRequest.Operation.WLAN_PATH_PROVISIONING, ProvisionLinkRequest.OperationType.XifiWF);
linkProvisioningCapability.provisionLink(request);
// register alarm (with callback)
IMonitoringModuleCapability srcMonitoringModuleCapability;
try {
srcMonitoringModuleCapability = (IMonitoringModuleCapability) ryuResourcesMap.get(srcRegion).getCapabilityByInterface(
IMonitoringModuleCapability.class);
} catch (ResourceException e) {
throw new CapabilityException("Error getting IMonitoringModuleCapability from source Ryu resource.", e);
}
AutoBAHNAlarmObserver alarmObserver = new AutoBAHNAlarmObserver(linkProvisioningCapability, request, srcRegion.getAutoBAHNInterface());
srcMonitoringModuleCapability.registerAlarmObservation(srcRegion.getRyuSwitchDPID(), srcPortId, connectEndsRequest.getBandwidthThreshold(),
alarmObserver);
}
private Region getConfiguredRegionFromName(String regionName) {
for (Region region : xifiConfiguration.getRegions()) {
if (region.getName().equals(regionName))
return region;
}
return null;
}
private class AutoBAHNAlarmObserver implements IAlarmObserver {
private ILinkProvisioningCapability linkProvisioningCapability;
private ProvisionLinkRequest originalRequest;
private String srcAutoBAHNInterface;
public AutoBAHNAlarmObserver(ILinkProvisioningCapability linkProvisioningCapability, ProvisionLinkRequest originalRequest,
String srcAutoBAHNInterface) {
this.linkProvisioningCapability = linkProvisioningCapability;
this.originalRequest = originalRequest;
this.srcAutoBAHNInterface = srcAutoBAHNInterface;
}
@Override
public void alarmReceived() {
log.info("Alarm received from Ryu Monitoring Module. Re-provsioning link with ABNO resource...");
// modify request with AUTOBHAN interface
originalRequest.setSrcInterface(srcAutoBAHNInterface);
try {
linkProvisioningCapability.provisionLink(originalRequest);
} catch (CapabilityException e) {
log.error("Error re-provisioning link with ABNO resource!", e);
return;
}
log.info("Link re-provsioned with ABNO resource.");
}
}
@Override
public void activate() throws CapabilityException {
registerService(Activator.getContext(), CAPABILITY_TYPE, getResourceType(), getResourceName(), E2ECapability.class.getName());
super.activate();
// read XIFI Configuration
try {
readAndCheckConfiguration();
} catch (Exception e) {
log.error("Error reading XIFI configuration.", e);
throw new CapabilityException(e);
}
log.info("XIFI configuration read:\n" + xifiConfiguration);
// initialize resources
try {
log.info("Initializing XIFI resources...");
initializeResources();
} catch (Exception e) {
log.error("Error initializing XIFI resources.", e);
throw new CapabilityException(e);
}
log.info("XIFI resources initilized.");
}
@Override
public void deactivate() throws CapabilityException {
unregisterService();
super.deactivate();
}
@Override
public String getCapabilityName() {
return CAPABILITY_TYPE;
}
@Override
public void queueAction(IAction action) throws CapabilityException {
throw new UnsupportedOperationException("Not Implemented. This capability is not using the queue.");
}
@Override
public IActionSet getActionSet() throws CapabilityException {
throw new UnsupportedOperationException("This capability does not contain actionset.");
}
private void initializeResources() throws ActivatorException, ResourceException, ProtocolException {
IResourceManager resourceManager = Activator.getResourceManagerService();
IProtocolManager protocolManager = Activator.getProtocolManagerService();
// ABNO resource
ResourceDescriptor resourceDescriptor = new ResourceDescriptor();
List<CapabilityDescriptor> capabilityDescriptors = new ArrayList<CapabilityDescriptor>();
capabilityDescriptors.add(ResourceHelper.newCapabilityDescriptor("internal", "1.0.0", LinkProvisioningCapability.CAPABILITY_TYPE, null));
resourceDescriptor.setCapabilityDescriptors(capabilityDescriptors);
Information information = new Information();
information.setType(ABNORepository.ABNO_RESOURCE_TYPE);
information.setName("abno1");
resourceDescriptor.setInformation(information);
abno = resourceManager.createResource(resourceDescriptor);
ProtocolSessionContext psc = new ProtocolSessionContext();
psc.addParameter(ProtocolSessionContext.AUTH_TYPE, "noauth");
psc.addParameter(ProtocolSessionContext.PROTOCOL, ABNOProtocolSession.ABNO_PROTOCOL_TYPE);
psc.addParameter(ProtocolSessionContext.PROTOCOL_URI, xifiConfiguration.getAbnoEndpoint());
protocolManager.getProtocolSessionManager(abno.getResourceIdentifier().getId()).registerContext(psc);
resourceManager.startResource(abno.getResourceIdentifier());
// Ryu and OpenStack per region
for (Region region : xifiConfiguration.getRegions()) {
// Ryu resource
resourceDescriptor = new ResourceDescriptor();
capabilityDescriptors = new ArrayList<CapabilityDescriptor>();
capabilityDescriptors.add(ResourceHelper.newCapabilityDescriptorWithoutActionset(MonitoringModuleCapability.CAPABILITY_TYPE));
resourceDescriptor.setCapabilityDescriptors(capabilityDescriptors);
information = new Information();
information.setType("ryu");
information.setName("ryu-" + region.getName());
resourceDescriptor.setInformation(information);
ryuResourcesMap.put(region, resourceManager.createResource(resourceDescriptor));
psc = new ProtocolSessionContext();
psc.addParameter(ProtocolSessionContext.AUTH_TYPE, "noauth");
psc.addParameter(ProtocolSessionContext.PROTOCOL, HttpProtocolSession.HTTP_PROTOCOL_TYPE);
psc.addParameter(ProtocolSessionContext.PROTOCOL_URI, region.getRyuEndpoint());
protocolManager.getProtocolSessionManager(ryuResourcesMap.get(region).getResourceIdentifier().getId()).registerContext(psc);
resourceManager.startResource(ryuResourcesMap.get(region).getResourceIdentifier());
// OpenStack resource
resourceDescriptor = new ResourceDescriptor();
capabilityDescriptors = new ArrayList<CapabilityDescriptor>();
capabilityDescriptors.add(ResourceHelper.newCapabilityDescriptorWithoutActionset(OpenstackAdaperCapability.CAPABILITY_TYPE));
resourceDescriptor.setCapabilityDescriptors(capabilityDescriptors);
information = new Information();
information.setType(OpenstackRepository.OPENSTACK_RESOURCE_TYPE);
information.setName(OpenstackRepository.OPENSTACK_RESOURCE_TYPE + "-" + region.getName());
resourceDescriptor.setInformation(information);
openStackResourcesMap.put(region, resourceManager.createResource(resourceDescriptor));
psc = new ProtocolSessionContext();
psc.addParameter(ProtocolSessionContext.AUTH_TYPE, "password");
psc.addParameter(ProtocolSessionContext.PROTOCOL, HttpProtocolSession.HTTP_PROTOCOL_TYPE);
psc.addParameter(ProtocolSessionContext.PROTOCOL_URI, region.getOpenstackEndpoint());
psc.addParameter(ProtocolSessionContext.USERNAME, region.getOpenstackUser());
psc.addParameter(ProtocolSessionContext.PASSWORD, region.getOpenstackPassword());
protocolManager.getProtocolSessionManager(openStackResourcesMap.get(region).getResourceIdentifier().getId()).registerContext(psc);
resourceManager.startResource(openStackResourcesMap.get(region).getResourceIdentifier());
}
}
private void readAndCheckConfiguration() throws Exception {
log.info("Reading XIFI configuration from file " + XIFI_FILE + "...");
xifiConfiguration = new XIFIConfiguration();
// get configuration file properties
ConfigurationAdminUtil configurationAdmin = new ConfigurationAdminUtil(Activator.getContext());
try {
Properties properties = ConfigurationAdminUtil.getProperties(Activator.getContext(), XIFI_FILE);
xifiConfiguration.setABNOEndpoint(configurationAdmin.getProperty(XIFI_FILE, ABNO_ENDPOINT));
for (Entry<Object, Object> entry : properties.entrySet()) {
String key = (String) entry.getKey();
log.trace("Analizing property: " + entry);
if (key.startsWith(REGION + ".") && key.lastIndexOf('.') == ((REGION + ".").length() - 1)) {
String regionName = (String) entry.getValue();
log.trace("Region found: " + regionName);
// create the Region
Region region = new Region();
region.setName(regionName);
String regionKey = key.substring((REGION + ".").length());
// fill fields
String ryuEndpoint = configurationAdmin.getProperty(XIFI_FILE, REGION + "." + regionKey + REGION_RYU);
region.setRyuEndpoint(ryuEndpoint);
String ryuSwitchDPID = configurationAdmin.getProperty(XIFI_FILE, REGION + "." + regionKey + REGION_RYU_SWITCH_DPID);
region.setRyuSwitchDPID(ryuSwitchDPID);
String openStackEndpoint = configurationAdmin.getProperty(XIFI_FILE, REGION + "." + regionKey + REGION_OPENSTACK);
region.setOpenstackEndpoint(openStackEndpoint);
String openStackUser = configurationAdmin.getProperty(XIFI_FILE, REGION + "." + regionKey + REGION_OPENSTACK_USER);
region.setOpenstackUser(openStackUser);
String openStackPassword = configurationAdmin.getProperty(XIFI_FILE, REGION + "." + regionKey + REGION_OPENSTACK_PWD);
region.setOpenstackPassword(openStackPassword);
String openStackTenant = configurationAdmin.getProperty(XIFI_FILE, REGION + "." + regionKey + REGION_OPENSTACK_TENANT);
region.setOpenstackTenant(openStackTenant);
String autobahnIface = configurationAdmin.getProperty(XIFI_FILE, REGION + "." + regionKey + REGION_AUTOBAHN_IFACE);
region.setAutoBAHNInterface(autobahnIface);
// add the region
xifiConfiguration.getRegions().add(region);
}
}
} catch (IOException e) {
log.error("Error getting configuration!");
throw e;
}
log.info("XIFI configuration read.");
// check configuration
log.info("Checking XIFI configuration...");
if (xifiConfiguration.getAbnoEndpoint() == null)
throw new Exception("ABNO Endpoint not set!");
for (Region region : xifiConfiguration.getRegions()) {
if (region.getName() == null)
throw new Exception("Region name not set!");
if (region.getRyuEndpoint() == null || region.getRyuSwitchDPID() == null)
throw new Exception("Ryu endpoint or switch DPID for region " + region.getName() + " not properly set!");
if (region.getOpenstackEndpoint() == null || region.getOpenstackUser() == null || region.getOpenstackPassword() == null || region
.getOpenstackTenant() == null)
throw new Exception("OpenStack endpoint for region " + region.getName() + " not properly set!");
}
log.info("XIFI configuration checked.");
}
}