package org.opennaas.extensions.genericnetwork.capability.circuitprovisioning;
/*
* #%L
* OpenNaaS :: Generic Network
* %%
* 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 java.util.ArrayList;
import java.util.List;
import java.util.Map;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.opennaas.core.resources.ActivatorException;
import org.opennaas.core.resources.action.ActionException;
import org.opennaas.core.resources.action.ActionResponse;
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.descriptor.CapabilityDescriptor;
import org.opennaas.core.resources.descriptor.ResourceDescriptorConstants;
import org.opennaas.core.resources.protocol.IProtocolManager;
import org.opennaas.core.resources.protocol.IProtocolSessionManager;
import org.opennaas.core.resources.protocol.ProtocolException;
import org.opennaas.extensions.genericnetwork.Activator;
import org.opennaas.extensions.genericnetwork.capability.circuitprovisioning.api.CircuitsList;
import org.opennaas.extensions.genericnetwork.capability.circuitprovisioning.api.OldAndNewCircuits;
import org.opennaas.extensions.genericnetwork.capability.circuitprovisioning.api.helpers.CircuitProvisioningAPIHelper;
import org.opennaas.extensions.genericnetwork.exceptions.NotExistingCircuitException;
import org.opennaas.extensions.genericnetwork.model.GenericNetworkModel;
import org.opennaas.extensions.genericnetwork.model.circuit.Circuit;
import org.opennaas.extensions.genericnetwork.model.circuit.NetworkConnection;
/**
* Circuit Provisioning Capability implementation
*
* @author Julio Carlos Barrera
*
*/
public class CircuitProvisioningCapability extends AbstractCapability implements ICircuitProvisioningCapability {
public static final String CAPABILITY_TYPE = "circuitprovisioning";
private Log log = LogFactory.getLog(CircuitProvisioningCapability.class);
private String resourceId = "";
public CircuitProvisioningCapability(CapabilityDescriptor descriptor, String resourceId) {
super(descriptor);
this.resourceId = resourceId;
log.debug("Built new Circuit Provisioning Capability");
}
@Override
public String getCapabilityName() {
return CAPABILITY_TYPE;
}
@Override
public CircuitsList getCircuitsAPI() throws CapabilityException {
return CircuitProvisioningAPIHelper.listOfCircuits2CircuitList(getCircuits());
}
@Override
public List<Circuit> getCircuits() throws CapabilityException {
Map<String, Circuit> allocatedCircuitsMap = ((GenericNetworkModel) resource.getModel()).getAllocatedCircuits();
return new ArrayList<Circuit>(allocatedCircuitsMap.values());
}
@Override
public void replace(OldAndNewCircuits oldAndNewCircuits) throws CapabilityException {
replace(oldAndNewCircuits.getOldCircuits(), oldAndNewCircuits.getNewCircuits());
}
@Override
public void replace(List<Circuit> oldCircuits, List<Circuit> newCircuits) throws CapabilityException {
List<Circuit> toAllocate = new ArrayList<Circuit>(newCircuits.size());
List<String> toDeallocate = new ArrayList<String>(oldCircuits.size());
List<Circuit> commonCircuits = new ArrayList<Circuit>(oldCircuits.size());
// toAllocate contains all flows in newCircuits that are not in oldCircuits
// commonCircuits contains all flows that are both in oldCircuits and in newCircuits
for (Circuit newCircuit : newCircuits) {
if (!oldCircuits.contains(newCircuit)) {
toAllocate.add(newCircuit);
} else {
commonCircuits.add(newCircuit);
}
}
// toDeallocate contains all flows in oldCircuits that are not in newCircuits
// commonCircuits contains all flows that are both in oldCircuits and in newCircuits
for (Circuit oldCircuit : oldCircuits) {
if (!commonCircuits.contains(oldCircuit)) {
toDeallocate.add(oldCircuit.getCircuitId());
}
}
if (log.isDebugEnabled()) {
log.debug("Will deallocate circuits:");
for (String c : toDeallocate) {
log.debug(c);
}
log.debug("Will allocate circuits:");
for (Circuit c : toAllocate) {
log.debug(c.getCircuitId() + " with route " + c.getRoute().getId());
StringBuilder sb = new StringBuilder();
for (NetworkConnection x : c.getRoute().getNetworkConnections()) {
sb.append(x.getName());
sb.append(", ");
}
log.debug("Route details: " + sb.toString());
}
}
// HAVE TO DEALLOCATE BEFORE ALLOCATE
// if toDllocate and toDeallocate contain circuits with same id but with different from each others (i.e. because of re-routing)
// doing this in reverse order would mean deallocating the newly allocated circuit.
deallocateCircuits(toDeallocate);
allocateCircuits(toAllocate);
}
private void allocateCircuits(List<Circuit> circuits) throws CapabilityException {
// Allocate in reverse order.
// Reverse order is desired to ensure "circuits" are completely established when traffic starts to pass within them.
// This is so to minimize the amount of packet-in messages to treat.
for (int i = circuits.size() - 1; i >= 0; i--) {
allocate(circuits.get(i));
}
}
private void deallocateCircuits(List<String> circuitIds) throws CapabilityException {
// Deallocate in given order.
// Given order is desired to ensure "circuits" do not accept traffic when deallocation is taking place.
// This is so to minimize the amount of packet-in messages to treat.
for (String circuitId : circuitIds) {
deallocate(circuitId);
}
}
@Override
public void allocate(Circuit circuit) throws CapabilityException {
IAction action = createActionAndCheckParams(CircuitProvisioningActionSet.ALLOCATE_CIRCUIT, circuit);
ActionResponse response = executeAction(action);
if (!response.getStatus().equals(ActionResponse.STATUS.OK)) {
throw new ActionException(response.toString());
}
Map<String, Circuit> allocatedCircuitsMap = ((GenericNetworkModel) resource.getModel()).getAllocatedCircuits();
allocatedCircuitsMap.put(circuit.getCircuitId(), circuit);
}
@Override
public void deallocate(String circuitId) throws CapabilityException {
Map<String, Circuit> allocatedCircuitsMap = ((GenericNetworkModel) resource.getModel()).getAllocatedCircuits();
if (!allocatedCircuitsMap.containsKey(circuitId)) {
throw new NotExistingCircuitException("There is no such circuit with ID = " + circuitId);
}
Circuit circuitToRemove = allocatedCircuitsMap.get(circuitId);
IAction action = createActionAndCheckParams(CircuitProvisioningActionSet.DEALLOCATE_CIRCUIT, circuitToRemove);
ActionResponse response = executeAction(action);
if (!response.getStatus().equals(ActionResponse.STATUS.OK)) {
throw new ActionException(response.toString());
}
allocatedCircuitsMap.remove(circuitId);
}
@Override
public IActionSet getActionSet() throws CapabilityException {
String name = this.descriptor.getPropertyValue(ResourceDescriptorConstants.ACTION_NAME);
String version = this.descriptor.getPropertyValue(ResourceDescriptorConstants.ACTION_VERSION);
try {
return Activator.getActionSetService(CircuitProvisioningCapability.CAPABILITY_TYPE, name, version);
} catch (ActivatorException e) {
throw new CapabilityException(e);
}
}
@Override
public void activate() throws CapabilityException {
registerService(Activator.getContext(), CAPABILITY_TYPE, getResourceType(), getResourceName(),
CircuitProvisioningCapability.class.getName());
super.activate();
}
@Override
public void deactivate() throws CapabilityException {
unregisterService();
super.deactivate();
}
@Override
public void queueAction(IAction action) throws CapabilityException {
throw new UnsupportedOperationException("Not Implemented. This capability is not using the queue.");
}
private ActionResponse executeAction(IAction action) throws CapabilityException {
try {
IProtocolManager protocolManager = getProtocolManagerService();
IProtocolSessionManager protocolSessionManager = protocolManager.getProtocolSessionManager(this.resourceId);
ActionResponse response = action.execute(protocolSessionManager);
return response;
} catch (ProtocolException pe) {
log.error("Error getting protocol session - " + pe.getMessage());
throw new CapabilityException(pe);
} catch (ActivatorException ae) {
String errorMsg = "Error getting protocol manager - " + ae.getMessage();
log.error(errorMsg);
throw new CapabilityException(errorMsg, ae);
}
}
private IProtocolManager getProtocolManagerService() throws ActivatorException {
return Activator.getProtocolManagerService();
}
}