package org.opennaas.extensions.router.junos.actionssets.actions.chassis; import static com.google.common.base.Strings.nullToEmpty; import java.util.HashMap; import java.util.Map; 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.protocol.IProtocolSession; import org.opennaas.core.resources.protocol.ProtocolException; import org.opennaas.extensions.router.junos.actionssets.ActionConstants; import org.opennaas.extensions.router.junos.actionssets.actions.JunosAction; import org.opennaas.extensions.router.junos.commandsets.commands.CommandNetconfConstants.TargetConfiguration; import org.opennaas.extensions.router.junos.commandsets.commands.EditNetconfCommand; import org.opennaas.extensions.router.junos.commandsets.commands.GetNetconfCommand; import org.opennaas.extensions.router.junos.commandsets.commands.JunosCommand; import org.opennaas.extensions.router.model.ComputerSystem; import org.opennaas.extensions.router.model.LogicalPort; import org.opennaas.extensions.router.model.NetworkPort; public class SetTaggedEthernetEncapsulationAction extends JunosAction { private String getInterfaceTemplate = "/VM_files/getInterface.vm"; private String getSubInterfaceTemplate = "/VM_files/getSubInterface.vm"; public SetTaggedEthernetEncapsulationAction() { this.setActionID(ActionConstants.SET_TAGGEDETHERNET_ENCAPSULATION); this.protocolName = "netconf"; } @Override public void executeListCommand(ActionResponse actionResponse, IProtocolSession protocol) throws ActionException { try { Response getInterfaceResponse = getInterfaceFromCandidate((LogicalPort) params, protocol); actionResponse.addResponse(getInterfaceResponse); if (getInterfaceResponse.getStatus().equals(Response.Status.OK)) { // TODO Check params exists in the router. // checkInterfaceExists("", getInterfaceResponse); // Check params does not have subinterfaces without configured vlan-id checkNoSubInterfacesWithoutVlanId((LogicalPort) params, getInterfaceResponse); // set eth encapsulation EditNetconfCommand command = new EditNetconfCommand(getVelocityMessage()); command.initialize(); actionResponse.addResponse(sendCommandToProtocol(command, protocol)); } validateAction(actionResponse); } catch (Exception e) { throw new ActionException(this.actionID + ": " + e.getMessage(), e); } } @Override public void parseResponse(Object responseMessage, Object model) throws ActionException { // Nothing to parse by now. GetConfigurationAction will do it at the end of each queue execution } @Override public boolean checkParams(Object params) throws ActionException { if (!(params instanceof LogicalPort)) throw new ActionException("Invalid parameters type. A LogicalPort is expected"); if (((LogicalPort) params).getName() == null || ((LogicalPort) params).getName().isEmpty()) throw new ActionException("Invalid parameter. A LogicalPort must have a name"); // check tagged ethernet encapsulation is supported by given interface type if (isLoopbackInterface((LogicalPort) params)) { throw new ActionException("Tagged ethernet encapsulation in loopback interfaces is not supported."); } else if (isLogicalTunnelInterface((LogicalPort) params)) { if (isPhysicalInterface((LogicalPort) params)) { throw new ActionException("Tagged ethernet encapsulation cannot be applied to physical lt interfaces"); } } else if (isEthernetInterface((LogicalPort) params)) { if (isLogicalInterface((LogicalPort) params)) { throw new ActionException("Tagged ethernet encapsulation cannot be applied to logical eth interfaces"); } } else { throw new ActionException("Tagged ethernet encapsulation is not supported for given interface type"); } return true; } @Override public void prepareMessage() throws ActionException { checkParams(getParams()); setTemplateAccordingToParamsType((LogicalPort) params); String logicalRouterName = nullToEmpty(((ComputerSystem) modelToUpdate).getElementName()); Map<String, Object> extraParams = new HashMap<String, Object>(); extraParams.put("elementName", logicalRouterName); try { setVelocityMessage(prepareVelocityCommand(params, template, extraParams)); } catch (Exception e) { throw new ActionException(e); } } private void setTemplateAccordingToParamsType(LogicalPort params) throws ActionException { if (isLogicalTunnelInterface(params)) { setTemplate("/VM_files/setTaggedEthEncapsulationInLT.vm"); } else if (isEthernetInterface(params)) { setTemplate("/VM_files/setTaggedEthEncapsulationInETH.vm"); } else { throw new ActionException("Failed to determine Velocity template in Action " + getActionID()); } } private boolean isPhysicalInterface(LogicalPort iface) { return !isLogicalInterface(iface); } private boolean isLogicalInterface(LogicalPort iface) { return (iface instanceof NetworkPort); } private boolean isEthernetInterface(LogicalPort iface) { return isEthernetInterfaceName(iface.getName()); } private boolean isLogicalTunnelInterface(LogicalPort iface) { return isLogicalTunnelInterfaceName(iface.getName()); } private boolean isLoopbackInterface(LogicalPort iface) { return isLoopbackInterfaceName(iface.getName()); } private boolean isEthernetInterfaceName(String interfaceName) { return (interfaceName.startsWith("ge") || interfaceName.startsWith("fe")); } private boolean isLogicalTunnelInterfaceName(String interfaceName) { return (interfaceName.startsWith("lt")); } private boolean isLoopbackInterfaceName(String interfaceName) { return (interfaceName.startsWith("lo")); } private Response getInterfaceFromCandidate(LogicalPort iface, IProtocolSession protocol) throws ActionException, ProtocolException { String getInterfaceFilter = prepareGetInterfaceMessage(iface); JunosCommand getCommand = new GetNetconfCommand(getInterfaceFilter, TargetConfiguration.CANDIDATE); getCommand.initialize(); return sendCommandToProtocol(getCommand, protocol); } private String prepareGetInterfaceMessage(LogicalPort iface) throws ActionException { Map<String, Object> extraParams = new HashMap<String, Object>(); extraParams.put("elementName", nullToEmpty(((ComputerSystem) getModelToUpdate()).getElementName())); try { String templateToUse; if (isLogicalInterface(iface)) { templateToUse = getSubInterfaceTemplate; } else { templateToUse = getInterfaceTemplate; } return prepareVelocityCommand(iface, templateToUse, extraParams); } catch (Exception e) { throw new ActionException(e); } } private void checkInterfaceExists(String ifaceName, Response getInterfaceResponse) throws ActionException { // Check params is in current candidate configuration // FIXME it may not be in candidate but exist. Not all interfaces are in config // It should fail only if interface does not exists in the router! if (getInterfaceResponse.getInformation().equals("<configuration></configuration>")) { // an empty configuration means filter has failed throw new ActionException("Interface " + ifaceName + " not found in this router"); } } private void checkNoSubInterfacesWithoutVlanId(LogicalPort iface, Response getInterfaceResponse) throws ActionException { // there should be a vlan-id per unit int unitCount = occurrences(getInterfaceResponse.getInformation(), "<unit>"); int vlanCount = occurrences(getInterfaceResponse.getInformation(), "<vlan-id>"); int expectedVlanCount; if (isLogicalInterface(iface)) { // given interface unit will be present, but its vlanId may not expectedVlanCount = unitCount - 1; } else { expectedVlanCount = unitCount; } // vlanCount can be > expected, in the case isLogicalInterface(iface) and iface has a vlanId if (vlanCount < expectedVlanCount) { throw new ActionException("Interface has subinterfaces without vlanId. Please remove them before changing encapsulation."); } } private static int occurrences(String base, String toFind) { int count = 0; int index = 0; while (index < base.length() && index != -1) { index = base.indexOf(toFind, index); if (index != -1) { count++; index += toFind.length(); } } return count; } }