Java tutorial
/* * Copyright (c) 2013 Technische Universitat Wien (TUW), Distributed Systems Group. http://dsg.tuwien.ac.at * * This work was partially supported by the European Commission in terms of the CELAR FP7 project (FP7-ICT-2011-8 #317790), http://www.celarcloud.eu/ * * 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. */ package at.ac.tuwien.dsg.cloud.salsa.engine.smartdeployment.main; import at.ac.tuwien.dsg.cloud.salsa.common.cloudservice.model.enums.SalsaEntityType; import at.ac.tuwien.dsg.cloud.salsa.common.interfaces.SalsaException; import at.ac.tuwien.dsg.cloud.salsa.engine.smartdeployment.QUELLE.QuelleService; import at.ac.tuwien.dsg.cloud.salsa.engine.smartdeployment.QUELLE.RecommendationSummaries; import at.ac.tuwien.dsg.cloud.salsa.engine.smartdeployment.SALSA.ToscaEnricherSALSA; import at.ac.tuwien.dsg.cloud.salsa.engine.utils.EngineLogger; import at.ac.tuwien.dsg.cloud.salsa.engine.utils.SalsaConfiguration; import at.ac.tuwien.dsg.cloud.salsa.tosca.extension.SalsaMappingProperties; import at.ac.tuwien.dsg.cloud.salsa.engine.dataprocessing.ToscaStructureQuery; import at.ac.tuwien.dsg.cloud.salsa.engine.dataprocessing.ToscaXmlProcess; import at.ac.tuwien.dsg.mela.common.monitoringConcepts.Metric; import at.ac.tuwien.dsg.mela.common.monitoringConcepts.MetricValue; import at.ac.tuwien.dsg.mela.common.monitoringConcepts.MonitoredElement; import at.ac.tuwien.dsg.mela.common.requirements.Condition; import at.ac.tuwien.dsg.mela.common.requirements.Requirement; import at.ac.tuwien.dsg.mela.common.requirements.Requirements; import at.ac.tuwien.dsg.quelle.cloudServicesModel.requirements.MultiLevelRequirements; import at.ac.tuwien.dsg.quelle.cloudServicesModel.requirements.Strategy; import at.ac.tuwien.dsg.quelle.cloudServicesModel.requirements.StrategyCategory; import generated.oasis.tosca.TArtifactTemplate; import generated.oasis.tosca.TDefinitions; import generated.oasis.tosca.TDeploymentArtifact; import generated.oasis.tosca.TEntityTemplate; import generated.oasis.tosca.TNodeTemplate; import generated.oasis.tosca.TPolicy; import generated.oasis.tosca.TServiceTemplate; import generated.oasis.tosca.TTopologyTemplate; import java.io.File; import java.io.IOException; import java.io.InputStream; import java.net.URL; import java.util.ArrayList; import java.util.Arrays; import java.util.HashMap; import java.util.LinkedList; import java.util.List; import java.util.Map; import java.util.UUID; import java.util.logging.Level; import java.util.logging.Logger; import javax.ws.rs.Consumes; import javax.ws.rs.DefaultValue; import javax.ws.rs.GET; import javax.ws.rs.POST; import javax.ws.rs.Path; import javax.ws.rs.PathParam; import javax.ws.rs.Produces; import javax.ws.rs.QueryParam; import javax.ws.rs.core.MediaType; import javax.ws.rs.core.Response; import javax.xml.bind.JAXBContext; import javax.xml.bind.JAXBException; import javax.xml.bind.Marshaller; import javax.xml.bind.Unmarshaller; import org.antlr.v4.runtime.ANTLRInputStream; import org.antlr.v4.runtime.CharStream; import org.antlr.v4.runtime.CommonTokenStream; import org.antlr.v4.runtime.tree.ParseTreeWalker; import org.apache.commons.io.FileUtils; import org.apache.commons.lang.StringUtils; import org.eclipse.camf.carl.antlr4.CARLLexer; import org.eclipse.camf.carl.antlr4.CARLParser; import org.eclipse.camf.carl.antlr4.CARLParser.RequirementsContext; import org.eclipse.camf.carl.antlr4.CARLProgramListener; import org.eclipse.camf.carl.model.CPURequirement; import org.eclipse.camf.carl.model.DiskRequirement; import org.eclipse.camf.carl.model.IRequirement; import org.eclipse.camf.carl.model.MemoryRequirement; import org.eclipse.camf.carl.model.NetworkRequirement; import org.eclipse.camf.carl.model.OSRequirement; import org.eclipse.camf.carl.model.RangeAttribute; import org.eclipse.camf.carl.model.RequirementCategory; import org.eclipse.camf.carl.model.SoftwareRequirement; import org.eclipse.camf.carl.model.SystemRequirement; import org.springframework.stereotype.Service; /** * * @author Duc-Hung Le */ @Service @Path("/smart") public class SmartDeploymentService { String origineExt = ".original"; String enrichedExt = ".enriched"; String requirementExt = ".requirements"; public enum EnrichFunctions { QuelleCloudServiceRecommendation, SalsaInfoCompletion } @POST @Path("/tosca/{serviceName}") @Consumes(MediaType.APPLICATION_XML) public boolean submitTosca(String toscaXML, @PathParam("serviceName") String serviceName, @DefaultValue("true") @QueryParam("overwrite") boolean overwrite) { String saveAs = SalsaConfiguration.getToscaTemplateStorage() + File.separator + serviceName + origineExt; if (new File(saveAs).exists() && overwrite == false) { EngineLogger.logger.debug("Do not overwrite file : " + saveAs); return false; } try { TDefinitions def = ToscaXmlProcess.readToscaXML(toscaXML); ToscaXmlProcess.writeToscaDefinitionToFile(def, saveAs); } catch (JAXBException e) { EngineLogger.logger.error("Fail to pass the TOSCA !", e); } catch (IOException ex) { EngineLogger.logger.error("Cannot write the TOSCA to disk !", ex); } EngineLogger.logger.debug("Saved/Updated cloud description in : " + saveAs); return true; } @POST @Path("/requirement/{serviceName}") @Consumes(MediaType.APPLICATION_XML) public void submitQuelleRequirementForService(MultiLevelRequirements requirements, @PathParam("serviceName") String serviceName) { String saveAs = SalsaConfiguration.getToscaTemplateStorage() + File.separator + serviceName + requirementExt; JAXBContext jaxbContext; try { jaxbContext = JAXBContext.newInstance(MultiLevelRequirements.class); Marshaller jaxbMarshaller = jaxbContext.createMarshaller(); jaxbMarshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true); jaxbMarshaller.marshal(requirements, new File(saveAs)); } catch (JAXBException ex) { EngineLogger.logger.error("Cannot marshall the multilevel requirements that you submitted !"); ex.printStackTrace(); } } @GET @Path("/salsaTosca/enrich/{serviceName}") @Consumes(MediaType.APPLICATION_XML) public String enrichSalsaTosca(@PathParam("serviceName") String serviceName, @QueryParam("f") String[] listOfFunctionality) { List<String> list = Arrays.asList(listOfFunctionality); String file = SalsaConfiguration.getToscaTemplateStorage() + "/" + serviceName + this.enrichedExt; if (!(new File(file).exists())) { try { FileUtils.copyFile( new File( SalsaConfiguration.getToscaTemplateStorage() + "/" + serviceName + this.origineExt), new File(file)); } catch (IOException ex) { EngineLogger.logger.error("The original Tosca is not found to copy. Cannot enrich.", ex); } } if (list.contains(EnrichFunctions.SalsaInfoCompletion.toString())) { EngineLogger.logger.debug("Start to enrich by using: SalsaComponentCompletement"); try { TDefinitions def = ToscaXmlProcess.readToscaFile(file); ToscaEnricherSALSA salsaEnricher = new ToscaEnricherSALSA(def); salsaEnricher.enrichHighLevelTosca(); ToscaXmlProcess.writeToscaDefinitionToFile(def, file); } catch (JAXBException | IOException | SalsaException ex) { EngineLogger.logger.error("Error when reading TOSCA to enrich.", ex); } } if (list.contains(EnrichFunctions.QuelleCloudServiceRecommendation.toString())) { EngineLogger.logger.debug("Start to enrich by using: QuelleCloudServiceRecommendation"); QuelleService quelleService = new QuelleService(); // load requirements MultiLevelRequirements reqs = loadQuelleRequirement(serviceName); RecommendationSummaries sums = quelleService.getRecommendationSummary(reqs); EngineLogger.logger.debug("recommendation sums: " + sums.toXML()); // now load the service description try { TDefinitions def = ToscaXmlProcess.readToscaFile(file); updateSalsaDescriptionWithQuelleResult(def, sums); EngineLogger.logger.debug("Writing down Quelle enriched file"); ToscaXmlProcess.writeToscaDefinitionToFile(def, file); EngineLogger.logger.debug("Writing down Quelle enriched file done"); } catch (JAXBException | IOException ex) { EngineLogger.logger.error("Error when enriching TOSCA.", ex); } } try { return FileUtils.readFileToString(new File(file)); } catch (IOException ex) { EngineLogger.logger.error("Cannot read the enriched file. Big problem !", ex); return null; } } @POST @Path("/CAMFTosca/enrich/CSAR/{serviceName}") @Consumes(MediaType.APPLICATION_OCTET_STREAM) @Produces(MediaType.TEXT_PLAIN) public String enrich_CAMF_CSAR(byte[] fileBytes, @PathParam("serviceName") String serviceName) { SalsaConfiguration.getArtifactStorage(); // retrieve the CSAR String csarTmp = SalsaConfiguration.getToscaTemplateStorage() + "/" + serviceName + ".csar"; try { FileUtils.writeByteArrayToFile(new File(csarTmp), fileBytes); return enrich_CAMF_CSAR_Process(csarTmp, serviceName); } catch (IOException ex) { EngineLogger.logger.error("Fail to get byteArray of CSAR file to save to {}", csarTmp, ex); return null; } } // This is the MAIN class which received a CSAR and return a enriched CSAR @POST @Path("/CAMFTosca/enrich/CSAR/{serviceName}") @Consumes(MediaType.TEXT_PLAIN) @Produces(MediaType.TEXT_PLAIN) public String enrich_CAMF_CSAR(String csarURL, @PathParam("serviceName") String serviceName) { SalsaConfiguration.getArtifactStorage(); // download the CSAR String csarTmp = SalsaConfiguration.getToscaTemplateStorage() + "/" + serviceName + ".csar"; try { FileUtils.copyURLToFile(new URL(csarURL), new File(csarTmp)); return enrich_CAMF_CSAR_Process(csarTmp, serviceName); } catch (IOException ex) { EngineLogger.logger.error("Fail to download CSAR file at URL: {} and save to {}", csarURL, csarTmp, ex); return null; } } private String enrich_CAMF_CSAR_Process(String csarTmp, String serviceName) { String extractedFolder = csarTmp + ".extracted"; String toscaFile = extractedFolder + "/Definitions/Application.tosca"; String scriptDir = extractedFolder + "/Scripts/"; try { // extract CSAR CSARParser.extractCsar(new File(csarTmp), extractedFolder); // enrich with QUELLE for String toscaXML = FileUtils.readFileToString(new File(toscaFile)); EngineLogger.logger.debug("Read tosca string done. 100 first characters: {}", toscaXML); EngineLogger.logger.debug("Now trying to enrich with QUELLE...."); //enrichCAMFToscaWithQuelle(toscaXML, serviceName, new String[]{EnrichFunctions.QuelleCloudServiceRecommendation.toString(), EnrichFunctions.SalsaInfoCompletion.toString()}); SmartDeploymentService sds = new SmartDeploymentService(); String result = sds.enrichCAMFToscaWithQuelle(toscaXML, serviceName, new String[] { EnrichFunctions.QuelleCloudServiceRecommendation.toString() }); EngineLogger.logger.debug("After enrich with QUELLE, the result is: {}", result); // write back to right place FileUtils.writeStringToFile(new File(toscaFile), result); // read software requirement in TOSCA for each node, put in a map + artifact // a map between node ID and full requirement in Tag Map<String, String> allRequirements = new HashMap<>(); TDefinitions def = ToscaXmlProcess.readToscaFile(toscaFile); for (TNodeTemplate node : ToscaStructureQuery.getNodeTemplateList(def)) { EngineLogger.logger.debug("Checking node: {}", node.getId()); String policiesStr = new String(); if (node.getPolicies() != null) { EngineLogger.logger.debug("Found policies of node: " + node.getId() + "/" + node.getName()); List<TPolicy> policies = node.getPolicies().getPolicy(); for (TPolicy p : policies) { if (p.getPolicyType().getLocalPart().equals("Requirement") && p.getPolicyType().getPrefix().equals("SmartDeployment")) { if (p.getName().startsWith("CONSTRAINT")) { // TODO: parse SYBL policies } else { policiesStr += p.getName().trim(); if (!p.getName().trim().endsWith(";")) { policiesStr += ";"; EngineLogger.logger.debug("polociesStr = {}", policiesStr); } } } } } EngineLogger.logger.debug("Collected policies for node {} is : {}", node.getId(), policiesStr); allRequirements.put(node.getId(), policiesStr); } EngineLogger.logger.debug("In total, we got following requirements: " + allRequirements.toString()); // Load dependency graph knowledge base String dependencyDataFile = SmartDeploymentService.class.getResource("/data/salsa.dependencygraph.xml") .getFile(); SalsaStackDependenciesGraph depGraph = SalsaStackDependenciesGraph .fromXML(FileUtils.readFileToString(new File(dependencyDataFile))); // ENRICH SCRIPT // extract all the requirement, put into the hashmap for (Map.Entry<String, String> entry : allRequirements.entrySet()) { EngineLogger.logger.debug("Analyzing node: {}. Full policies string is: *** {} ***", entry.getKey(), entry.getValue()); // extract CARL Strings CharStream stream = new ANTLRInputStream(entry.getValue()); CARLLexer lexer = new CARLLexer(stream); CommonTokenStream tokens = new CommonTokenStream(lexer); CARLParser parser = new CARLParser(tokens); RequirementsContext requirementsContext = parser.requirements(); ParseTreeWalker walker = new ParseTreeWalker(); // create standard walker CARLProgramListener extractor = new CARLProgramListener(parser); walker.walk(extractor, requirementsContext); // initiate walk of tree with listener org.eclipse.camf.carl.model.Requirements requirements = extractor.getRequirements(); HashMap<String, String> allReqsOfNode = new HashMap<>(); ArrayList<String> checkList = new ArrayList<>(); // os=Ubuntu; os:ver=12.04; sw=jre:1.7 ==> os=Ubuntu, // here flat all the requirement of the node for (IRequirement req : requirements.getRequirements()) { EngineLogger.logger.debug("Irequirement: " + req.toString()); if (req.getCategory().equals(RequirementCategory.SOFTWARE)) { SoftwareRequirement swr = (SoftwareRequirement) req; allReqsOfNode.put("sw", removeQuote(swr.getName())); allReqsOfNode.put(removeQuote(swr.getName()) + ":ver", swr.getVersion().getVersion()); checkList.add(swr.getName()); } else { if (req.getCategory().equals(RequirementCategory.OPERATING_SYSTEM)) { // the system part is generated by quelle OSRequirement osReq = (OSRequirement) req; if (osReq.getName() != null) { allReqsOfNode.put("os", removeQuote(osReq.getName())); } if (osReq.getVersion() != null) { allReqsOfNode.put("os:ver", osReq.getVersion().getVersion()); } } } } // find all the deploymet script of all "sw" requirements LinkedList<String> listOfScripts = new LinkedList<>(); EngineLogger.logger.debug("The node {} will be enriched based-on the requirements: {}", entry.getKey(), checkList.toString()); for (String swReq : checkList) { EngineLogger.logger.debug("Searching deployment script for software req: {}", swReq); SalsaStackDependenciesGraph theNode = depGraph.findNodeByName(swReq); EngineLogger.logger.debug("Node found: {}", theNode.getName()); EngineLogger.logger.debug("All requirements: {}", allReqsOfNode.toString()); LinkedList<String> tmp = theNode.searchDeploymentScriptTemplate(allReqsOfNode); if (tmp != null) { listOfScripts.addAll(tmp); } } EngineLogger.logger.debug(listOfScripts.toString()); // create a script to solve all dependencies first String nodeID = entry.getKey(); String theDependencyScript = "#!/bin/bash \n\n######## Generated by the Decision Module to solve the software dependencies ######## \n\n"; for (String appendScript : listOfScripts) { String theAppend = SmartDeploymentService.class.getResource("/scriptRepo/" + appendScript) .getFile(); String stringToAppend = FileUtils.readFileToString(new File(theAppend)); theDependencyScript += stringToAppend + "\n"; } theDependencyScript += "######## End of generated script ########"; String tmpScriptFile = scriptDir + "/" + nodeID + ".salsatmp"; // read original script, remove the #!/bin/bash if having String originalScriptFile = null; TNodeTemplate node = ToscaStructureQuery.getNodetemplateById(nodeID, def); EngineLogger.logger.debug("Getting artifact template of node: {}", node.getId()); for (TDeploymentArtifact art : node.getDeploymentArtifacts().getDeploymentArtifact()) { EngineLogger.logger.debug("Checking art.Name: {}, type: {}", art.getName(), art.getArtifactType().getLocalPart()); if (art.getArtifactType().getLocalPart().equals("ScriptArtifactPropertiesType")) { String artTemplateID = art.getArtifactRef().getLocalPart(); TArtifactTemplate artTemplate = ToscaStructureQuery.getArtifactTemplateById(artTemplateID, def); if (artTemplate != null) { originalScriptFile = artTemplate.getArtifactReferences().getArtifactReference().get(0) .getReference(); originalScriptFile = extractedFolder + "/" + originalScriptFile; } } } if (originalScriptFile != null) { String originalScript = FileUtils.readFileToString(new File(originalScriptFile)); originalScript = originalScript.replace("#!/bin/bash", ""); originalScript = originalScript.replace("#!/bin/sh", ""); theDependencyScript += originalScript; FileUtils.writeStringToFile(new File(tmpScriptFile), theDependencyScript); EngineLogger.logger.debug("originalScript: {}, moveto: {}", originalScriptFile, originalScriptFile + ".original"); FileUtils.moveFile(FileUtils.getFile(originalScriptFile), FileUtils.getFile(originalScriptFile + ".original")); FileUtils.moveFile(FileUtils.getFile(tmpScriptFile), FileUtils.getFile(originalScriptFile)); } else { // TODO: there is no original script, just add new template, add tmpScript into that } } // end for each node in allRequirements analysis // repack the CSAR FileUtils.deleteQuietly(FileUtils.getFile(csarTmp)); File directory = new File(extractedFolder); File[] fList = directory.listFiles(); //CSARParser.buildCSAR(fList, csarTmp); String builtCSAR = SalsaConfiguration.getToscaTemplateStorage() + "/" + serviceName + ".csar"; CSARParser.buildCSAR(extractedFolder, builtCSAR); } catch (IOException ex) { EngineLogger.logger.error("Error when enriching CSAR: " + csarTmp, ex); return "Error"; } catch (JAXBException ex) { EngineLogger.logger.error("Cannot parse the Tosca definition in CSAR file: " + toscaFile, ex); return "Error"; } // return the link to the CSAR String csarURLReturn = SalsaConfiguration.getSalsaCenterEndpoint() + "/rest/smart/CAMFTosca/enrich/CSAR/" + serviceName; EngineLogger.logger.info("Enrich CSAR done. URL to download is: {}", csarURLReturn); return csarURLReturn; } @GET @Path("/CAMFTosca/enrich/CSAR/{serviceName}") @Produces(MediaType.APPLICATION_OCTET_STREAM) public Response get_enriched_CSAR(@PathParam("serviceName") String serviceName) { EngineLogger.logger.debug("GETTING A CSAR !!!!!!!!!!!!!"); String fileName = SalsaConfiguration.getToscaTemplateStorage() + "/" + serviceName + ".csar"; EngineLogger.logger.debug("Read and return the CSAR file: {}. ServiceName is: {}", fileName, serviceName); File file = new File(fileName); return Response.ok(file, MediaType.APPLICATION_OCTET_STREAM) .header("Content-Disposition", "attachment; filename=\"" + file.getName() + "\"") //optional .build(); } private String removeQuote(String quoteString) { return quoteString.replace("\"", "").trim(); } @GET @Path("/CAMFTosca/enrich/quelle/{serviceName}") @Consumes(MediaType.APPLICATION_XML) public String enrichCAMFToscaWithQuelle(@PathParam("serviceName") String serviceName, @QueryParam("f") String[] listOfFunctionality) { List<String> list = Arrays.asList(listOfFunctionality); String file = SalsaConfiguration.getToscaTemplateStorage() + "/" + serviceName + this.enrichedExt; if (!(new File(file).exists())) { try { FileUtils.copyFile( new File( SalsaConfiguration.getToscaTemplateStorage() + "/" + serviceName + this.origineExt), new File(file)); } catch (IOException ex) { EngineLogger.logger.error("The original Tosca is not found to copy. Cannot enrich.", ex); } } if (list.contains(EnrichFunctions.SalsaInfoCompletion.toString())) { // TODO: develop this } if (list.contains(EnrichFunctions.QuelleCloudServiceRecommendation.toString())) { EngineLogger.logger.debug("Start to enrich by using: QuelleCloudServiceRecommendation"); QuelleService quelleService = new QuelleService(); try { TDefinitions def = ToscaXmlProcess.readToscaFile(file); MultiLevelRequirements reqs = generateQuelleRequirementFromCAMFTosca(def); RecommendationSummaries sums = quelleService.getRecommendationSummary(reqs); // load requirements EngineLogger.logger.debug("recommendation sums: " + sums.toXML()); updateCAMFDescriptionWithQuelleResult(def, sums); EngineLogger.logger.debug("Writing down Quelle enriched file"); JAXBContext jaxbContext = JAXBContext.newInstance(TDefinitions.class, CAMFElasticityProperty.class); Marshaller jaxbMarshaller = jaxbContext.createMarshaller(); jaxbMarshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true); jaxbMarshaller.marshal(def, new File(file)); EngineLogger.logger.debug("Writing down Quelle enriched file done"); } catch (JAXBException | IOException ex) { EngineLogger.logger.error("Failure in enriching CAMF TOSCA.", ex); } } try { return FileUtils.readFileToString(new File(file)); } catch (IOException ex) { EngineLogger.logger.error("Cannot read the enriched file. Big problem !", ex); return null; } } @POST @Path("/CAMFTosca/enrich/quelle/{serviceName}") @Consumes(MediaType.APPLICATION_XML) public String enrichCAMFToscaWithQuelle(String toscaXML, @PathParam("serviceName") String serviceName, @QueryParam("f") String[] listOfFunctionality) { SmartDeploymentService sds = new SmartDeploymentService(); sds.submitTosca(toscaXML, serviceName, true); return enrichCAMFToscaWithQuelle(serviceName, listOfFunctionality); } private MultiLevelRequirements loadQuelleRequirement(String serviceName) { String saveAs = SalsaConfiguration.getToscaTemplateStorage() + File.separator + serviceName + requirementExt; JAXBContext jaxbContext; try { jaxbContext = JAXBContext.newInstance(MultiLevelRequirements.class); Unmarshaller jaxbUnmarshaller = jaxbContext.createUnmarshaller(); MultiLevelRequirements reqs = (MultiLevelRequirements) jaxbUnmarshaller.unmarshal(new File(saveAs)); return reqs; } catch (JAXBException ex) { EngineLogger.logger.error("Cannot marshall the multilevel requirements that you submitted !", ex); return null; } } private void updateSalsaDescriptionWithQuelleResult(TDefinitions def, RecommendationSummaries resume) { EngineLogger.logger.debug("Starting update Salsa description with QUELLE recommendation"); List<TNodeTemplate> nodes = ToscaStructureQuery .getNodeTemplatesOfTypeList(SalsaEntityType.SOFTWARE.getEntityTypeString(), def); for (TNodeTemplate node : nodes) { EngineLogger.logger.debug("Checking node: " + node.getId()); String infrastructureRequirement = node.getId() + ".IaaS"; EngineLogger.logger.debug("The requirement name is: " + infrastructureRequirement); TNodeTemplate osNode = ToscaStructureQuery.getNodeTemplate_ofOSType_ThatHost(node, def); if (osNode != null) { EngineLogger.logger.debug("The OS node that hosts node " + node.getId() + " is " + osNode.getId()); SalsaMappingProperties oldProps = (SalsaMappingProperties) osNode.getProperties().getAny(); if (oldProps == null) { oldProps = new SalsaMappingProperties(); } if (resume.requirementExisted(infrastructureRequirement)) { SalsaMappingProperties props = new SalsaMappingProperties(); props.put(SalsaEntityType.OPERATING_SYSTEM.getEntityTypeString(), "provider", resume.getFirstRecommendationOfRequirement(infrastructureRequirement).getProvider()); String des = resume.getFirstRecommendationOfRequirement(infrastructureRequirement) .getDescription() + " "; des = des.substring(0, des.indexOf(" ")).trim(); props.put(SalsaEntityType.OPERATING_SYSTEM.getEntityTypeString(), "instanceType", des); if (props.get(SalsaEntityType.OPERATING_SYSTEM.getEntityTypeString(), "provider").equals( oldProps.get(SalsaEntityType.OPERATING_SYSTEM.getEntityTypeString(), "provider"))) { props.put(SalsaEntityType.OPERATING_SYSTEM.getEntityTypeString(), "baseImage", oldProps.get(SalsaEntityType.OPERATING_SYSTEM.getEntityTypeString(), "baseImage")); } props.put(SalsaEntityType.OPERATING_SYSTEM.getEntityTypeString(), "packages", oldProps.get(SalsaEntityType.OPERATING_SYSTEM.getEntityTypeString(), "packages")); osNode.getProperties().setAny(props); } } } } private void updateOSNodeConfig(TTopologyTemplate topo) { List<TEntityTemplate> entities = topo.getNodeTemplateOrRelationshipTemplate(); boolean found = false; for (TEntityTemplate enti : entities) { if (enti.getType().getLocalPart().equals(SalsaEntityType.OPERATING_SYSTEM.getEntityTypeString())) { TNodeTemplate node = (TNodeTemplate) enti; SalsaMappingProperties maps; if (node.getProperties() == null) { maps = new SalsaMappingProperties(); } else { maps = (SalsaMappingProperties) node.getProperties().getAny(); if (maps == null) { maps = new SalsaMappingProperties(); } found = false; for (SalsaMappingProperties.SalsaMappingProperty imap : maps.getProperties()) { if (imap.getType().equals(SalsaEntityType.OPERATING_SYSTEM.getEntityTypeString())) { found = true; } } if (found) { continue; } } if (!found) { System.out.println("Start write out some configuration for node: " + enti.getId()); // can put some optimization processing here, now get the default values InputStream input = ToscaEnricherSALSA.class .getResourceAsStream("/cloudconfig.default.properties"); java.util.Properties prop = new java.util.Properties(); try { prop.load(input); } catch (IOException e) { EngineLogger.logger.error("Couldn't find the default cloud configuration file."); return; } String provider = prop.getProperty("provider"); String instanceType = prop.getProperty("instanceType"); String baseImage = prop.getProperty("baseImage"); String packages = ""; System.out.println( "Write the configuration: " + provider + ", " + instanceType + ", " + baseImage); Map<String, String> map = new HashMap<>(); map.put("provider", provider); map.put("instanceType", instanceType); map.put("baseImage", baseImage); map.put("packages", packages); maps.put(SalsaEntityType.OPERATING_SYSTEM.getEntityTypeString(), map); EngineLogger.logger.debug("Map of properties is created"); node.getProperties().setAny(maps); node.setMinInstances(1); node.setMaxInstances("unbounded"); EngineLogger.logger.debug("Done adding configuration"); } //if !found } } } // generate requirement and save public MultiLevelRequirements generateQuelleRequirementFromCAMFTosca(TDefinitions def) { // get all Node policy String serviceName = ToscaStructureQuery.getServiceTemplateList(def).get(0).getName(); MultiLevelRequirements serviceReq = new MultiLevelRequirements( MonitoredElement.MonitoredElementLevel.SERVICE); serviceReq.setName(serviceName); // get Strategy TServiceTemplate st = ToscaStructureQuery.getServiceTemplateList(def).get(0); Strategy newStra = new Strategy(); newStra.setStrategyCategory(StrategyCategory.OVERALL_REQUIREMENTS); serviceReq.addStrategy(newStra); newStra.setStrategyCategory(StrategyCategory.MINIMUM_COST); serviceReq.addStrategy(newStra); newStra.setStrategyCategory(StrategyCategory.MINIMUM_RESOURCES); serviceReq.addStrategy(newStra); // add requirement MultiLevelRequirements topoReq = new MultiLevelRequirements( MonitoredElement.MonitoredElementLevel.SERVICE_TOPOLOGY); topoReq.setName(serviceName + "topo"); serviceReq.addMultiLevelRequirements(topoReq); // GET ALL NODE's POLICIES List<TNodeTemplate> nodeTemplates = ToscaStructureQuery.getNodeTemplateList(def); for (TNodeTemplate node : nodeTemplates) { if (node.getPolicies() != null) { EngineLogger.logger.debug("Found policies of node: " + node.getId()); List<TPolicy> policies = node.getPolicies().getPolicy(); MultiLevelRequirements suReq = new MultiLevelRequirements( MonitoredElement.MonitoredElementLevel.SERVICE_UNIT); suReq.setName(node.getName()); topoReq.addMultiLevelRequirements(suReq); Requirements reqs = new Requirements(); reqs.setName(node.getName() + ".IaaS"); suReq.addRequirements(reqs); for (TPolicy p : policies) { EngineLogger.logger.debug("Analyzing policy name: {}, type:{} ", p.getName(), p.getPolicyType().toString()); if (p.getPolicyType().getLocalPart().equals("Requirement") && p.getPolicyType().getPrefix().equals("SmartDeployment")) { String theReq = p.getName(); EngineLogger.logger.debug("Parsing the requirement: " + theReq); // E>G> CONSTRAINT Memory&gt;2048 String keyword = theReq.split(" ", 2)[0].trim(); EngineLogger.logger.debug("The first word: {}", keyword); if (keyword.equals("CONSTRAINT")) { EngineLogger.logger.debug("Parsing SYBL constraint: {}" + theReq); Requirement req = syblPolicyToQuelleRequirement(theReq, node, p); topoReq.addRequirement(req); reqs.addRequirement(req); } else { EngineLogger.logger.debug("Parsing CAMF constraint: {}" + theReq); List<Requirement> req = CAMFPolicyToQuelleRequirement(theReq, node, p); for (Requirement r : req) { EngineLogger.logger.debug("Adding requirement {}", r.toString()); topoReq.addRequirement(r); reqs.addRequirement(r); } } } } } // end node.getPolicies() != null } // end For // try to save it, useless but ya JAXBContext jaxbContext; try { String saveReq = SalsaConfiguration.getToscaTemplateStorage() + File.separator + serviceName + requirementExt; EngineLogger.logger.debug("Requirement is generated, trying to save to: " + saveReq); jaxbContext = JAXBContext.newInstance(MultiLevelRequirements.class); Marshaller jaxbMarshaller = jaxbContext.createMarshaller(); jaxbMarshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true); jaxbMarshaller.marshal(serviceReq, new File(saveReq)); } catch (JAXBException ex) { Logger.getLogger(SmartDeploymentService.class.getName()).log(Level.SEVERE, null, ex); } return serviceReq; } private Requirement syblPolicyToQuelleRequirement(String theReq, TNodeTemplate node, TPolicy p) { String constraint = theReq.split(" ", 2)[1].trim(); String metric = constraint.split("&", 2)[0].trim(); String operation = constraint.substring(constraint.indexOf("&") + 1, constraint.lastIndexOf(";")); String value = constraint.substring(constraint.lastIndexOf(";") + 1); EngineLogger.logger.debug("Parsing SYBL directive: Node:" + node.getId() + "/" + node.getName()); EngineLogger.logger.debug("Parsing SYBL directive: - Policy:" + p.getName()); EngineLogger.logger.debug("Parsing SYBL directive: - Keyword:" + constraint); EngineLogger.logger.debug("Parsing SYBL directive: - metric:" + metric); EngineLogger.logger.debug("Parsing SYBL directive: - operation:" + operation); EngineLogger.logger.debug("Parsing SYBL directive: - value:" + value); Condition.Type type; switch (operation) { case "lt": type = Condition.Type.LESS_THAN; break; case "le": type = Condition.Type.LESS_EQUAL; break; case "gt": type = Condition.Type.GREATER_THAN; break; case "ge": type = Condition.Type.GREATER_EQUAL; break; case "eq": type = Condition.Type.EQUAL; break; default: type = Condition.Type.EQUAL; break; } Requirement req = new Requirement(node.getName() + "_req_" + metric); req.addTargetServiceID(node.getName()); MetricValue mValue = new MetricValue(value); if (StringUtils.isNumeric(value)) { mValue.setValueType(MetricValue.ValueType.NUMERIC); int numberValue = Integer.parseInt(value); mValue = new MetricValue(numberValue); } req.addCondition(new Condition(type, new Metric(metric), mValue)); req.setMetric(new Metric(metric)); req.setId(UUID.randomUUID().toString()); return req; } private List<Requirement> CAMFPolicyToQuelleRequirement(String theReq, TNodeTemplate node, TPolicy p) { List<Requirement> listReq = new ArrayList<>(); // extract CARL Strings CharStream stream = new ANTLRInputStream(theReq); CARLLexer lexer = new CARLLexer(stream); CommonTokenStream tokens = new CommonTokenStream(lexer); CARLParser parser = new CARLParser(tokens); RequirementsContext requirementsContext = parser.requirements(); ParseTreeWalker walker = new ParseTreeWalker(); // create standard walker CARLProgramListener extractor = new CARLProgramListener(parser); walker.walk(extractor, requirementsContext); // initiate walk of tree with listener org.eclipse.camf.carl.model.Requirements requirements = extractor.getRequirements(); HashMap<String, String> allReqsOfNode = new HashMap<>(); // os=Ubuntu; os:ver=12.04; sw=jre:1.7 ==> os=Ubuntu, // here flat all the requirement of the node for (IRequirement req : requirements.getRequirements()) { EngineLogger.logger.debug("Irequirement: " + req.toString()); // QUELLE only cares about system requirements if (req.getCategory().equals(RequirementCategory.SYSTEM)) { SystemRequirement sys = (SystemRequirement) req; RangeAttribute range = sys.getRange(); String metric; if (sys instanceof CPURequirement) { metric = "VCPU"; } else if (sys instanceof DiskRequirement) { metric = "StorageDisks"; } else if (sys instanceof MemoryRequirement) { metric = "Memory"; } else if (sys instanceof NetworkRequirement) { metric = "NetworkPerformance"; } else { metric = "unknown"; } EngineLogger.logger.debug("Parsing CAMF, mapping to metric: {}", metric); Condition.Type type; if (range != null) { int fromRance = range.from(); int toRange = range.to(); EngineLogger.logger.debug("We are parsing a range value: [{} --> {}]", fromRance, toRange); Requirement quellReq = new Requirement(node.getName() + "_req_" + metric); quellReq.addTargetServiceID(node.getId()); EngineLogger.logger.debug("Before setting metric. Metric: " + quellReq.getMetric()); quellReq.setMetric(new Metric(metric)); EngineLogger.logger.debug("After setting metric. Metric: " + quellReq.getMetric()); quellReq.addCondition( new Condition(Condition.Type.GREATER_EQUAL, null, new MetricValue(fromRance))); quellReq.addCondition(new Condition(Condition.Type.LESS_EQUAL, null, new MetricValue(toRange))); listReq.add(quellReq); } else { EngineLogger.logger.debug("We are parsing equal, there is no range value !"); switch (sys.getOperator()) { case "lt": type = Condition.Type.LESS_THAN; break; case "le": type = Condition.Type.LESS_EQUAL; break; case "gt": type = Condition.Type.GREATER_THAN; break; case "ge": type = Condition.Type.GREATER_EQUAL; break; case "eq": type = Condition.Type.EQUAL; break; default: type = Condition.Type.EQUAL; break; } Requirement quellReq = new Requirement(node.getName() + "_req_" + metric); quellReq.addTargetServiceID(node.getId()); EngineLogger.logger.debug("Before setting metric. Metric: " + quellReq.getMetric()); quellReq.setMetric(new Metric(metric)); EngineLogger.logger.debug("Before setting metric. Metric: " + quellReq.getMetric()); quellReq.addCondition(new Condition(type, null, new MetricValue(sys.getValue()))); listReq.add(quellReq); } } } return listReq; } private void updateCAMFDescriptionWithQuelleResult(TDefinitions def, RecommendationSummaries resume) { EngineLogger.logger.debug("Starting update CAMF description with QUELLE recommendation"); List<TNodeTemplate> nodes = ToscaStructureQuery.getNodeTemplateList(def); for (TNodeTemplate node : nodes) { EngineLogger.logger.debug("Checking node: " + node.getId()); RecommendationSummaries.RecommendationSummary flavorStr = resume .getFirstRecommendationOfRequirement(node.getName() + ".IaaS"); EngineLogger.logger.debug("flavorStr: " + flavorStr); if (flavorStr != null) { CAMFElasticityProperty flavorProp = new CAMFElasticityProperty(flavorStr.getDescription().trim()); node.getProperties().setAny(flavorProp); } } } }