package org.opennaas.extensions.router.junos.actionssets.actions.linkaggregation;
/*
* #%L
* OpenNaaS :: Router :: Junos ActionSet
* %%
* 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.HashMap;
import java.util.List;
import java.util.Map;
import org.apache.commons.lang.StringUtils;
import org.opennaas.core.resources.action.ActionException;
import org.opennaas.core.resources.action.ActionResponse;
import org.opennaas.core.resources.command.Response;
import org.opennaas.core.resources.helpers.XmlHelper;
import org.opennaas.core.resources.protocol.IProtocolSession;
import org.opennaas.extensions.router.capability.linkaggregation.LinkAggregationActionSet;
import org.opennaas.extensions.router.junos.actionssets.actions.JunosAction;
import org.opennaas.extensions.router.junos.commandsets.commands.CommandNetconfConstants;
import org.opennaas.extensions.router.junos.commandsets.commands.EditNetconfCommand;
import org.opennaas.extensions.router.model.AggregatedLogicalPort;
import org.opennaas.extensions.router.model.ComputerSystem;
import org.opennaas.extensions.router.model.ManagedElement;
import org.opennaas.extensions.router.model.System;
import org.opennaas.extensions.router.model.utils.ModelHelper;
/**
* Implementation of LinkAggregationActionSet.REMOVE_AGGRETATED_INTERFACE for junos 10.04 devices.<br/>
*
* Removes an aggregated interface identified by given name.<br/>
*
* NOTICE: There must be an AggregatedLogicalPort with given name in the model. Otherwise, executing this action will fail. This requirement is
* related to the action implementation, not capability defined. There is need to retrieve the names of interfaces given aggregation includes, in
* order to remove an association in the junos configuration.
*
* @author Isart Canyameres Gimenez (i2cat)
*
*/
public class RemoveAggregatedInterfaceAction extends JunosAction {
/**
* The name of any aggregated interface in junos devices must start with this prefix
*/
public static final String JUNOS_AGGREGATED_INTERFACES_PREFIX = "ae";
private static final String DELETION_TEMPLATE = "/VM_files/deleteAggregatedInterface.vm";
private static final String REMOVE_FROM_AGGREGATED_TEMPLATE = "/VM_files/removeInterfaceFromAggregated.vm";
private static final String CONFIG_UNIT0_TEMPLATE = "/VM_files/configureUnitWithDescription.vm";
private AggregatedLogicalPort aggregator;
public RemoveAggregatedInterfaceAction() {
super();
setActionID(LinkAggregationActionSet.REMOVE_AGGREGATED_INTERFACE);
this.protocolName = "netconf";
}
@Override
public boolean checkParams(Object params) throws ActionException {
if (!(params instanceof String)) {
throw new ActionException("Invalid parameter in action " + actionID + ". Expected interface name.");
}
if (StringUtils.isEmpty((String) params))
throw new ActionException("Invalid parameter in action " + actionID + "." +
" Missing AggregatedLogicalPort name.");
return true;
}
@Override
public void prepareMessage() throws ActionException {
checkParams(params);
this.aggregator = retrieveAggregatedInterfaceFromModel((String) params);
// Nothing to prepare
// Messages are prepared in executeListCommand
}
@Override
public void executeListCommand(ActionResponse actionResponse, IProtocolSession protocol) throws ActionException {
actionResponse.addResponse(execRemovingEditCommand(prepareDeleteAggregatedInterfaceMessage(aggregator), protocol));
for (String interfaceName : aggregator.getInterfaces()) {
// remove ether-options 802.3ad
actionResponse.addResponse(execRemovingEditCommand(
prepareRemoveInterfaceFromAggregatedMessage(interfaceName, aggregator.getElementName()), protocol));
// configure unit 0 with description FREE, to make interface available in opennaas
actionResponse.addResponse(execEditCommand(prepareAddUnit0Message(interfaceName), protocol));
}
validateAction(actionResponse);
}
@Override
public void parseResponse(Object responseMessage, Object model) throws ActionException {
// nothing to parse
}
/**
* Creates an xml message that removes given aggregated interface (aggregator). <br/>
*
* @param aggregator
* @return
* @throws ActionException
*/
private String prepareDeleteAggregatedInterfaceMessage(AggregatedLogicalPort aggregator) throws ActionException {
try {
// FIXME passing unchecked values to junos (aggregator.getElementName()). May cause security issues.
String xml = XmlHelper.formatXML(prepareVelocityCommand(aggregator.getElementName(), DELETION_TEMPLATE, null));
return xml;
} catch (Exception e) {
throw new ActionException(e);
}
}
/**
* Creates an xml message that configures given interfaceName to be part of given aggregatedInterfaceName.<br/>
* This operation replaces the aggregatedInterfaceName interfaceName is part of, despite the fact that ifaceName may be part of another
* aggregatedInterface before sending these message.
*
* @param interfaceName
* @param aggregatedInterfaceName
* @return
* @throws ActionException
*/
private String prepareRemoveInterfaceFromAggregatedMessage(String interfaceName, String aggregatedInterfaceName) throws ActionException {
Map<String, Object> extraParams = prepareRemoveInterfaceFromAggregatedExtraParams(interfaceName, aggregatedInterfaceName);
try {
// FIXME passing unchecked values to junos (interfaceName and inside extraParams). May cause security issues.
String xml = XmlHelper.formatXML(prepareVelocityCommand(interfaceName, REMOVE_FROM_AGGREGATED_TEMPLATE, extraParams));
return xml;
} catch (Exception e) {
throw new ActionException(e);
}
}
/**
* Prepares extraParams for REMOVE_FROM_AGGREGATED_TEMPLATE. <br/>
*
* Sets following params: <br/>
* - String aggregatedIfaceName <br/>
* - boolean isLR <br/>
* - String lrName <br/>
* See the template for more information.
*
* @param interfaceName
* the interface to be de-aggregated
* @param aggregatedInterfaceName
* the interface to de-aggregate from
* @return extraParams required for REMOVE_FROM_AGGREGATED_TEMPLATE
*/
private Map<String, Object> prepareRemoveInterfaceFromAggregatedExtraParams(String interfaceName, String aggregatedInterfaceName) {
Map<String, Object> extraParams = prepareLRVelocityExtraParams();
extraParams.put("ifaceName", interfaceName);
extraParams.put("aggregatedIfaceName", aggregatedInterfaceName);
return extraParams;
}
private String prepareAddUnit0Message(String interfaceName) throws ActionException {
Map<String, Object> extraParams = prepareLRVelocityExtraParams();
extraParams.put("unitName", 0);
extraParams.put("description", "FREE");
try {
// FIXME passing unchecked values to junos (interfaceName inside extraParams). May cause security issues.
String xml = XmlHelper.formatXML(prepareVelocityCommand(interfaceName, CONFIG_UNIT0_TEMPLATE, extraParams));
return xml;
} catch (Exception e) {
throw new ActionException(e);
}
}
private Map<String, Object> prepareLRVelocityExtraParams() {
Map<String, Object> extraParams = new HashMap<String, Object>();
boolean isLR = isLogicalRouter((ComputerSystem) modelToUpdate);
extraParams.put("isLR", isLR);
if (isLR)
extraParams.put("lrName", getLogicalRouterName((ComputerSystem) modelToUpdate));
return extraParams;
}
private boolean isLogicalRouter(ComputerSystem system) {
if (system.getElementName() != null) {
return true;
}
return false;
}
private String getLogicalRouterName(ComputerSystem system) {
if (!isLogicalRouter(system))
return null;
return system.getElementName();
}
private Response execRemovingEditCommand(String netconfMsg, IProtocolSession protocol) throws ActionException {
try {
// when removing tags, none operation should be used as default
EditNetconfCommand command = new EditNetconfCommand(netconfMsg, CommandNetconfConstants.NONE_OPERATION);
command.initialize();
return sendCommandToProtocol(command, protocol);
} catch (Exception e) {
throw new ActionException(this.actionID + ": " + e.getMessage(), e);
}
}
private Response execEditCommand(String netconfMsg, IProtocolSession protocol) throws ActionException {
try {
EditNetconfCommand command = new EditNetconfCommand(netconfMsg);
command.initialize();
return sendCommandToProtocol(command, protocol);
} catch (Exception e) {
throw new ActionException(this.actionID + ": " + e.getMessage(), e);
}
}
private AggregatedLogicalPort retrieveAggregatedInterfaceFromModel(String aggregatedInterfaceName) throws ActionException {
List<AggregatedLogicalPort> allAggregated = ModelHelper.getAggregatedLogicalPorts((System) modelToUpdate);
ManagedElement desired = ModelHelper.getManagedElementByElementName(allAggregated, aggregatedInterfaceName);
if (desired == null)
throw new ActionException("Could not retrieve aggregatedInterface " + aggregatedInterfaceName + " from the model.");
return (AggregatedLogicalPort) desired;
}
}