package org.opennaas.extensions.roadm.wonesys.actionsets.actions;
import java.util.Vector;
import org.opennaas.core.resources.action.Action;
import org.opennaas.core.resources.action.ActionException;
import org.opennaas.core.resources.action.ActionResponse;
import org.opennaas.core.resources.action.ActionResponse.STATUS;
import org.opennaas.core.resources.command.CommandException;
import org.opennaas.core.resources.command.Response;
import org.opennaas.core.resources.protocol.IProtocolSession;
import org.opennaas.core.resources.protocol.IProtocolSessionManager;
import org.opennaas.core.resources.protocol.ProtocolException;
import org.opennaas.extensions.roadm.wonesys.actionsets.ActionConstants;
import org.opennaas.extensions.roadm.wonesys.commandsets.commands.psroadm.SetChannel;
import org.opennaas.extensions.router.model.LogicalDevice;
import org.opennaas.extensions.router.model.opticalSwitch.FiberConnection;
import org.opennaas.extensions.router.model.opticalSwitch.WDMChannelPlan;
import org.opennaas.extensions.router.model.opticalSwitch.dwdm.WDMFCPort;
import org.opennaas.extensions.router.model.opticalSwitch.dwdm.proteus.ProteusOpticalSwitch;
public class RemoveConnectionAction extends Action {
public RemoveConnectionAction() {
super();
initialize();
}
protected void initialize() {
this.setActionID(ActionConstants.REMOVECONNECTION);
}
@Override
public boolean checkParams(Object arg0) throws ActionException {
if (!(params instanceof FiberConnection)) {
return false;
}
return true;
}
@Override
public ActionResponse execute(IProtocolSessionManager protocolSessionManager) throws ActionException {
ActionResponse actionResponse = new ActionResponse();
actionResponse.setActionID(this.actionID);
/* get protocol */
IProtocolSession protocol = null;
try {
protocol = protocolSessionManager.obtainSessionByProtocol("wonesys", false);
} catch (ProtocolException e) {
throw new ActionException(e);
}
/* check params */
if (!checkParams(params))
throw new ActionException("The Action " + getActionID() + " don't accept params");
/* load params */
FiberConnection connection = MakeConnectionAction.loadFiberConnectionFromRequest((FiberConnection) params,
(ProteusOpticalSwitch) this.modelToUpdate);
// check given connection exists
// return error if not
if (!connectionExists(connection, (ProteusOpticalSwitch) modelToUpdate)) {
return ActionResponse.errorResponse("Could not remove connection. There is no such connection in model");
} else {
connection = getFiberConnection(connection, (ProteusOpticalSwitch) this.modelToUpdate);
}
CardDescription[] cardsToDesconfigure = getConnectionsToRemove(connection);
/* remove cards */
ProteusOpticalSwitch switchModel = (ProteusOpticalSwitch) this.modelToUpdate;
for (CardDescription card : cardsToDesconfigure) {
if (!switchModel.getCard(card.getChassis(), card.getSlot()).isPassive()) {
/* read channel plan from the model */
WDMChannelPlan channelPlan = (WDMChannelPlan) switchModel.getCard(card.getChassis(), card.getSlot()).getChannelPlan();
int channelNum = channelPlan.getChannelNumberFromLambda(card.getLambda());
SetChannel channel = new SetChannel(card.getChassis(), card.getSlot(), channelNum, 0);
channel.initialize();
String response;
try {
response = (String) protocol.sendReceive(channel.message());
Response resp = channel.checkResponse(response);
validateResponse(resp);
actionResponse.addResponse(resp);
} catch (ProtocolException e) {
Vector<String> errors = new Vector<String>();
errors.add(e.getMessage());
Response.errorResponse((String) channel.message(), errors);
// TODO Specify workflow if we don't use
throw new ActionException(e);
}
}
}
/* updateModel */
removeConnectionInModel(connection, switchModel);
actionResponse.setStatus(STATUS.OK);
return actionResponse;
}
public static boolean connectionExists(FiberConnection connection, ProteusOpticalSwitch switchModel) {
return getFiberConnection(connection, switchModel) != null;
}
public static FiberConnection getFiberConnection(FiberConnection connection, ProteusOpticalSwitch switchModel) {
FiberConnection matchingConnection = null;
for (FiberConnection existentConnection : switchModel.getFiberConnections()) {
if ( // same cards
existentConnection.getSrcCard().getChasis() == connection.getSrcCard().getChasis() &&
existentConnection.getSrcCard().getModuleNumber() == connection.getSrcCard().getModuleNumber() &&
existentConnection.getDstCard().getChasis() == connection.getDstCard().getChasis() &&
existentConnection.getDstCard().getModuleNumber() == connection.getDstCard().getModuleNumber() &&
// same ports
existentConnection.getSrcPort().getPortNumber() == connection.getSrcPort().getPortNumber() &&
existentConnection.getDstPort().getPortNumber() == connection.getDstPort().getPortNumber() &&
// same channels
existentConnection.getSrcFiberChannel().getLambda() == connection.getSrcFiberChannel().getLambda() &&
existentConnection.getDstFiberChannel().getLambda() == connection.getDstFiberChannel().getLambda()) {
matchingConnection = existentConnection;
break;
}
}
return matchingConnection;
}
private void removeConnectionInModel(FiberConnection connection, ProteusOpticalSwitch switchModel) throws ActionException {
WDMFCPort srcSubPort = MakeConnectionAction.getSubportWithLambda(connection.getSrcPort(), connection.getSrcFiberChannel().getLambda());
WDMFCPort dstSubPort = MakeConnectionAction.getSubportWithLambda(connection.getDstPort(), connection.getDstFiberChannel().getLambda());
// remove chain of deviceConnections and subports
WDMFCPort subPort = srcSubPort;
// FIXME a malformed route may lead to an endless loop!!!
while (!subPort.equals(dstSubPort)) {
// there is a port connected to subPort using same lambda
WDMFCPort tmpSubPort = null;
for (LogicalDevice port : subPort.getOutgoingDeviceConnections()) {
if (port instanceof WDMFCPort) {
if (((WDMFCPort) port).getDWDMChannel().getLambda() == subPort.getDWDMChannel().getLambda()) {
tmpSubPort = (WDMFCPort) port;
break;
}
}
}
if (tmpSubPort == null)
throw new ActionException("");
// remove subport from parent port
subPort.getDevices().get(0).removePortOnDevice(subPort);
// remove connection between subports
subPort.removeDeviceConnection(tmpSubPort);
subPort = tmpSubPort;
}
// remove subport from parent port
dstSubPort.getDevices().get(0).removePortOnDevice(dstSubPort);
switchModel.getFiberConnections().remove(connection);
}
private CardDescription[] getConnectionsToRemove(FiberConnection connection) {
// TODO IT SHOULD BE IMPROVED TO CREATE PATHS AMONG DIFS. DEVICES TO REMOVE CONNECTIONS
CardDescription srcCardDescription = new CardDescription();
srcCardDescription.setChassis(connection.getSrcCard().getChasis());
srcCardDescription.setLambda(connection.getSrcFiberChannel().getLambda());
srcCardDescription.setSlot(connection.getSrcCard().getSlot());
srcCardDescription.setPortNum(connection.getSrcPort().getPortNumber());
CardDescription dstCardDescription = new CardDescription();
dstCardDescription.setChassis(connection.getDstCard().getChasis());
dstCardDescription.setLambda(connection.getDstFiberChannel().getLambda());
dstCardDescription.setSlot(connection.getDstCard().getSlot());
dstCardDescription.setPortNum(connection.getDstPort().getPortNumber());
CardDescription[] cards = { srcCardDescription, dstCardDescription };
return cards;
}
private void validateResponse(Response response) throws CommandException {
if (response.getStatus().equals(Response.Status.ERROR)) {
if (response.getErrors().size() > 0)
throw new CommandException(response.getErrors().get(0));
else
throw new CommandException("Command Failed");
}
}
public class CardDescription {
int chassis;
int slot;
double lambda;
int portNum;
public double getLambda() {
return lambda;
}
public void setLambda(double lambda) {
this.lambda = lambda;
}
public int getChassis() {
return chassis;
}
public void setChassis(int chassis) {
this.chassis = chassis;
}
public int getSlot() {
return slot;
}
public void setSlot(int slot) {
this.slot = slot;
}
public int getPortNum() {
return portNum;
}
public void setPortNum(int portNum) {
this.portNum = portNum;
}
}
}