package com.sixsq.slipstream.module; /* * +=================================================================+ * SlipStream Server (WAR) * ===== * Copyright (C) 2013 SixSq Sarl (sixsq.com) * ===== * 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. * -=================================================================- */ import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map.Entry; import java.util.Set; import org.restlet.data.Form; import com.sixsq.slipstream.exceptions.NotFoundException; import com.sixsq.slipstream.exceptions.ValidationException; import com.sixsq.slipstream.persistence.DeploymentModule; import com.sixsq.slipstream.persistence.Module; import com.sixsq.slipstream.persistence.ModuleParameter; import com.sixsq.slipstream.persistence.Node; import com.sixsq.slipstream.persistence.NodeParameter; import com.sixsq.slipstream.persistence.RuntimeParameter; import com.sixsq.slipstream.persistence.User; /** * Unit test see * * @see DeploymentFormProcesorTest * */ public class DeploymentFormProcessor extends TargetContainerModuleFormProcessor { public DeploymentFormProcessor(User user) { super(user); } @Override public void parseForm() throws ValidationException, NotFoundException { super.parseForm(); parseNodeMapping(); setPostProcessingScript(); validate(); } private void parseNodeMapping() throws ValidationException { DeploymentModule module = castToModule(); module.getNodes().clear(); Set<String> formitems = getForm().getNames(); // will contain the mapping between nodeindex and mappings // (parameter mapping) HashMap<String, List<String>> nodeMappingList = new HashMap<String, List<String>>(); // will contain the mapping between nodeindex and node shortname HashMap<String, String> indexToNode = new HashMap<String, String>(); // items should be encoded as: // node--[nodeindex]--mappingstable--[mappingindex]--[value] // Or node--[index]--shortname // We start by extracting the node indices and the mappings for (String item : formitems.toArray(new String[0])) { if (item.startsWith("node--")) { String nodeindex = item.split("--")[1]; // get the nodeindex // Extract the node indexes if (item.endsWith("--shortname")) { String shortName = getForm().getFirstValue(item); indexToNode.put(nodeindex, shortName); List<String> mapping = nodeMappingList.get(nodeindex); if (mapping == null) { mapping = new ArrayList<String>(); } nodeMappingList.put(nodeindex, mapping); continue; } if (item.contains("--mappingtable--")) { List<String> mapping = nodeMappingList.get(nodeindex); if (mapping == null) { mapping = new ArrayList<String>(); } String mappingIndex = item.split("--")[3]; mapping.add(mappingIndex); nodeMappingList.put(nodeindex, mapping); } } } // Iterate over the local structure and extract the corresponding // data from the form for (Entry<String, List<String>> nodeentry : nodeMappingList.entrySet()) { String nodeindex = nodeentry.getKey(); String shortname = getForm().getFirstValue( "node--" + nodeindex + "--shortname"); if (shortname == null) { throw (new ValidationException("Missing node shortname")); } Node node = createNode(nodeindex, shortname); if (module.parametersContainKey(shortname)) { throw (new ValidationException( "Node short names must be unique. '" + shortname.replace("<", "<") + "' is already defined")); } for (String mappingindex : nodeentry.getValue()) { String input = getForm().getFirstValue( "node--" + nodeindex + "--mappingtable--" + mappingindex + "--input"); if (input == null) { throw (new ValidationException("Node " + node.getName() + " contains an empty input parameter")); } String output = getForm().getFirstValue( "node--" + nodeindex + "--mappingtable--" + mappingindex + "--output"); if (output == null) { throw (new ValidationException("Node " + node.getName() + " is missing a linked parameter for " + input)); } if (output.startsWith(shortname + RuntimeParameter.NODE_PROPERTY_SEPARATOR)) { throw (new ValidationException( "Output parameters cannot refer to their own node")); } node.setParameterMapping(new NodeParameter(input, output, "")); } setMultiplicity(getForm(), nodeindex, node); setCloudService(getForm(), nodeindex, node); setMaxProvisioningFailures(getForm(), nodeindex, node); module.setNode(node); } } private Node createNode(String nodeindex, String shortname) throws ValidationException { String imagelink = getForm().getFirstValue( "node--" + nodeindex + "--imagelink"); return new Node(shortname, imagelink); } private void setPostProcessingScript() throws ValidationException { Form form = getForm(); DeploymentModule module = castToModule(); Set<String> formitems = getForm().getNames(); // Look for the post-processing entry for (String item : formitems.toArray(new String[0])) { if (item.equals("post-processing")) { ModuleParameter parameter = new ModuleParameter(item, form.getFirstValue(item), "Post-Processing script"); module.setParameter(parameter); } } } private DeploymentModule castToModule() { return (DeploymentModule) getParametrized(); } private void setCloudService(Form form, String nodeindex, Node node) { String cloudServiceValue = form.getFirstValue("node--" + nodeindex + "--cloudservice--value", "default"); node.setCloudService(cloudServiceValue); } private void setMultiplicity(Form form, String nodeindex, Node node) throws ValidationException { String multiplicityValue = form.getFirstValue("node--" + nodeindex + "--multiplicity--value", "1"); node.setMultiplicity(parseMultiplicity(multiplicityValue)); } private int parseMultiplicity(String value) throws ValidationException { return parseIntegerValue(value, "multiplicity"); } private void setMaxProvisioningFailures(Form form, String nodeindex, Node node) throws ValidationException { String value = form.getFirstValue("node--" + nodeindex + "--max--provisioning--failures--value", "0"); node.setMaxProvisioningFailures(parseMaxProvisioningFailures(value)); } private int parseMaxProvisioningFailures(String value) throws ValidationException { return parseIntegerValue(value, "max provisioning failures"); } private int parseIntegerValue(String value, String fieldName) throws ValidationException { try { return Integer.parseInt(value); } catch (NumberFormatException e) { throw new ValidationException( "Field '" + fieldName + "' must be a valid integer, got: " + value); } } @Override protected Module getOrCreateParameterized(String name) throws ValidationException { Module loaded = load(name); return loaded == null ? new DeploymentModule(name) : loaded; } protected void validate() throws ValidationException { castToModule().validate(); } }