package org.opentosca.planbuilder.type.plugin.mosquittoconnectsto.bpel.handler; import java.io.IOException; import java.io.StringReader; import java.net.URL; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import javax.xml.parsers.DocumentBuilder; import javax.xml.parsers.DocumentBuilderFactory; import javax.xml.parsers.ParserConfigurationException; import org.opentosca.container.core.common.file.ResourceAccess; import org.opentosca.container.core.tosca.convention.Interfaces; import org.opentosca.planbuilder.core.bpel.context.BPELPlanContext; import org.opentosca.planbuilder.core.plugins.context.PropertyVariable; import org.opentosca.planbuilder.core.plugins.context.Variable; import org.opentosca.planbuilder.core.plugins.utils.PluginUtils; import org.opentosca.planbuilder.model.tosca.AbstractNodeTemplate; import org.opentosca.planbuilder.model.tosca.AbstractRelationshipTemplate; import org.opentosca.planbuilder.model.utils.ModelUtils; import org.opentosca.planbuilder.provphase.plugin.invoker.bpel.BPELInvokerPlugin; import org.opentosca.planbuilder.type.plugin.mosquittoconnectsto.core.handler.ConnectsToTypePluginHandler; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.w3c.dom.Document; import org.w3c.dom.Node; import org.xml.sax.InputSource; import org.xml.sax.SAXException; /** * Copyright 2016 IAAS University of Stuttgart <br> * <br> * * @author Kalman Kepes - [email protected] */ public class BPELConnectsToPluginHandler implements ConnectsToTypePluginHandler<BPELPlanContext> { private final static Logger LOG = LoggerFactory.getLogger(BPELConnectsToPluginHandler.class); private final BPELInvokerPlugin invokerPlugin = new BPELInvokerPlugin(); private final DocumentBuilderFactory docFactory; private final DocumentBuilder docBuilder; /** * Constructor * * @throws ParserConfigurationException is thrown when initializing the DOM Parsers fails */ public BPELConnectsToPluginHandler() throws ParserConfigurationException { this.docFactory = DocumentBuilderFactory.newInstance(); this.docFactory.setNamespaceAware(true); this.docBuilder = DocumentBuilderFactory.newInstance().newDocumentBuilder(); } @Override public boolean handle(final BPELPlanContext templateContext) { final AbstractRelationshipTemplate relationTemplate = templateContext.getRelationshipTemplate(); // fetch topic final Variable topicName = templateContext.getPropertyVariable(relationTemplate.getTarget(), "Name"); /* fetch ip of mosquitto */ Variable mosquittoVmIp = null; // find infrastructure nodes of mosquitto List<AbstractNodeTemplate> infrastructureNodes = new ArrayList<>(); ModelUtils.getInfrastructureNodes(relationTemplate.getTarget(), infrastructureNodes); ModelUtils.getNodesFromNodeToSink(relationTemplate.getTarget(), infrastructureNodes); for (final AbstractNodeTemplate infraNode : infrastructureNodes) { for (final String ipPropName : org.opentosca.container.core.tosca.convention.Utils.getSupportedVirtualMachineIPPropertyNames()) { // fetch mosquitto ip if (templateContext.getPropertyVariable(infraNode, ipPropName) != null) { mosquittoVmIp = templateContext.getPropertyVariable(infraNode, ipPropName); break; } } if (mosquittoVmIp != null) { break; } } /* fetch user, key, ip and ubuntuTemplateId of client stack */ PropertyVariable clientVmIp = null; PropertyVariable clientVmUser = null; PropertyVariable clientVmPass = null; String ubuntuTemplateId = null; infrastructureNodes = new ArrayList<>(); ModelUtils.getInfrastructureNodes(relationTemplate.getSource(), infrastructureNodes); for (final AbstractNodeTemplate infraNode : infrastructureNodes) { for (final String ipPropName : org.opentosca.container.core.tosca.convention.Utils.getSupportedVirtualMachineIPPropertyNames()) { if (templateContext.getPropertyVariable(infraNode, ipPropName) != null) { clientVmIp = templateContext.getPropertyVariable(infraNode, ipPropName); break; } } for (final String loginNameProp : org.opentosca.container.core.tosca.convention.Utils.getSupportedVirtualMachineLoginUserNamePropertyNames()) { if (templateContext.getPropertyVariable(infraNode, loginNameProp) != null) { ubuntuTemplateId = infraNode.getId(); clientVmUser = templateContext.getPropertyVariable(infraNode, loginNameProp); } } for (final String loginPwProp : org.opentosca.container.core.tosca.convention.Utils.getSupportedVirtualMachineLoginPasswordPropertyNames()) { if (templateContext.getPropertyVariable(infraNode, loginPwProp) != null) { ubuntuTemplateId = infraNode.getId(); clientVmPass = templateContext.getPropertyVariable(infraNode, loginPwProp); } } } /* create skript */ // the script itself final String bashCommand = "echo \"topicName = hostName\" > $(find ~ -maxdepth 1 -path \"*.csar\")/mosquitto_connections.txt;"; // add it as a var to the plan final Variable bashCommandVariable = templateContext.createGlobalStringVariable("addMosquittoConnection", bashCommand); // create bpel query which replaces topicName and hostName with real // values final String xpathQuery = "replace(replace($" + bashCommandVariable.getVariableName() + ",'topicName',$" + topicName.getVariableName() + "),'hostName',$" + mosquittoVmIp.getVariableName() + ")"; // create bpel assign with created query try { // create assign and append Node assignNode = loadAssignXpathQueryToStringVarFragmentAsNode("assignValuesToAddConnection" + System.currentTimeMillis(), xpathQuery, bashCommandVariable.getVariableName()); assignNode = templateContext.importNode(assignNode); templateContext.getProvisioningPhaseElement().appendChild(assignNode); } catch (final IOException e) { BPELConnectsToPluginHandler.LOG.error("Couldn't load fragment from file", e); return false; } catch (final SAXException e) { BPELConnectsToPluginHandler.LOG.error("Couldn't parse fragment to DOM", e); return false; } /* add logic to execute script on client machine */ final Map<String, Variable> runScriptRequestInputParams = new HashMap<>(); runScriptRequestInputParams.put("VMIP", clientVmIp); // these two are requested from the input message if they are not set if (!PluginUtils.isVariableValueEmpty(clientVmUser)) { runScriptRequestInputParams.put("VMUserName", clientVmUser); } else { runScriptRequestInputParams.put("VMUserName", null); } if (!PluginUtils.isVariableValueEmpty(clientVmPass)) { runScriptRequestInputParams.put("VMPrivateKey", clientVmPass); } else { runScriptRequestInputParams.put("VMPrivateKey", null); } runScriptRequestInputParams.put("Script", bashCommandVariable); this.invokerPlugin.handle(templateContext, ubuntuTemplateId, true, "runScript", Interfaces.OPENTOSCA_DECLARATIVE_INTERFACE_OPERATINGSYSTEM, runScriptRequestInputParams, new HashMap<String, Variable>(), templateContext.getProvisioningPhaseElement()); return true; } /** * Loads a BPEL Assign fragment which queries the csarEntrypath from the input message into String variable. * * @param assignName the name of the BPEL assign * @param csarEntryXpathQuery the csarEntryPoint XPath query * @param stringVarName the variable to load the queries results into * @return a DOM Node representing a BPEL assign element * @throws IOException is thrown when loading internal bpel fragments fails * @throws SAXException is thrown when parsing internal format into DOM fails */ public Node loadAssignXpathQueryToStringVarFragmentAsNode(final String assignName, final String xpath2Query, final String stringVarName) throws IOException, SAXException { final String templateString = loadAssignXpathQueryToStringVarFragmentAsString(assignName, xpath2Query, stringVarName); final InputSource is = new InputSource(); is.setCharacterStream(new StringReader(templateString)); final Document doc = this.docBuilder.parse(is); return doc.getFirstChild(); } /** * Loads a BPEL Assign fragment which queries the csarEntrypath from the input message into String variable. * * @param assignName the name of the BPEL assign * @param xpath2Query the csarEntryPoint XPath query * @param stringVarName the variable to load the queries results into * @return a String containing a BPEL Assign element * @throws IOException is thrown when reading the BPEL fragment form the resources fails */ public String loadAssignXpathQueryToStringVarFragmentAsString(final String assignName, final String xpath2Query, final String stringVarName) throws IOException { // <!-- {AssignName},{xpath2query}, {stringVarName} --> final URL url = getClass().getClassLoader() .getResource("mosquittoconnectsto-plugin/assignStringVarWithXpath2Query.xml"); String template = ResourceAccess.readResourceAsString(url); template = template.replace("{AssignName}", assignName); template = template.replace("{xpath2query}", xpath2Query); template = template.replace("{stringVarName}", stringVarName); return template; } }