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.QUELLE; import at.ac.tuwien.dsg.cloud.salsa.engine.smartdeployment.QUELLE.RecommendationSummaries.RecommendationSummary; 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.mela.common.requirements.Requirements; import at.ac.tuwien.dsg.quelle.cloudServicesModel.concepts.CloudOfferedService; import at.ac.tuwien.dsg.quelle.cloudServicesModel.concepts.CloudProvider; import at.ac.tuwien.dsg.quelle.cloudServicesModel.requirements.MultiLevelRequirements; import at.ac.tuwien.dsg.quelle.cloudServicesModel.requirements.Strategy; import at.ac.tuwien.dsg.quelle.elasticityQuantification.dtos.CloudServiceConfigurationRecommendation; import at.ac.tuwien.dsg.quelle.elasticityQuantification.dtos.ServiceUnitServicesRecommendation; import at.ac.tuwien.dsg.quelle.elasticityQuantification.engines.CloudServiceElasticityAnalysisEngine; import at.ac.tuwien.dsg.quelle.elasticityQuantification.engines.CloudServiceUnitAnalysisEngine; import at.ac.tuwien.dsg.quelle.elasticityQuantification.engines.RequirementsMatchingEngine; import at.ac.tuwien.dsg.quelle.elasticityQuantification.engines.ServiceUnitComparators; import at.ac.tuwien.dsg.quelle.elasticityQuantification.requirements.RequirementsResolutionResult; import at.ac.tuwien.dsg.quelle.elasticityQuantification.requirements.ServiceUnitConfigurationSolution; import java.io.File; import java.io.FilenameFilter; import java.io.InputStream; import java.util.ArrayList; import java.util.List; import java.util.Map; 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.Produces; import javax.ws.rs.QueryParam; import javax.ws.rs.core.MediaType; import javax.xml.bind.JAXBContext; import javax.xml.bind.JAXBException; import javax.xml.bind.Marshaller; import javax.xml.bind.Unmarshaller; import org.springframework.stereotype.Service; /** * This service integrate with QUELLE to * * @author Duc-Hung Le */ @Service @Path("/quelle") public class QuelleService { private final RequirementsMatchingEngine requirementsMatchingEngine = new RequirementsMatchingEngine(); private final ServiceUnitComparators serviceUnitComparators = new ServiceUnitComparators(); private final String cloudDescriptionFileExtension = ".cloud.data"; @GET @Path("/health") public String health() { return "Quelle is healthy"; } @POST @Path("/recommend") @Consumes(MediaType.APPLICATION_XML) @Produces(MediaType.APPLICATION_XML) public Recommendations getRecommendation(MultiLevelRequirements multiLevelRequirements) { EngineLogger.logger .debug("Getting recommendation for multiple requirement: " + multiLevelRequirements.getName()); List<MultiLevelRequirements> individualServiceUnitRequirements = multiLevelRequirements.flatten(); List<ServiceUnitServicesRecommendation> recommendations = new ArrayList<>(); // load cloud provider List<CloudProvider> cloudProviders = loadCloudAllDescription(); EngineLogger.logger.debug("Loaded " + cloudProviders.size() + " provider done."); if (cloudProviders.isEmpty()) { EngineLogger.logger .error("Do not found any cloud provider infomation. Please submit at least one first !"); return null; } for (MultiLevelRequirements reqs : individualServiceUnitRequirements) { RequirementsResolutionResult requirementsMatchingResult = requirementsMatchingEngine .analyzeMultiLevelRequirements(cloudProviders, reqs); Map<MultiLevelRequirements, Map<Requirements, List<ServiceUnitConfigurationSolution>>> bestElasticity = requirementsMatchingResult .getConcreteConfigurations(serviceUnitComparators); List<CloudServiceConfigurationRecommendation> recommendedConfigurations = new ArrayList<>(); { for (MultiLevelRequirements levelRequirements : bestElasticity.keySet()) { Map<Requirements, List<ServiceUnitConfigurationSolution>> solutions = bestElasticity .get(levelRequirements); String strategies = ""; for (Strategy s : levelRequirements.getOptimizationStrategies()) { strategies += "_" + s.getStrategyCategory(); } for (Requirements requirements : solutions.keySet()) { String solutionsNames = ""; int solutionsCount = solutions.get(requirements).size(); // compute average elasticities double averageCostElasticity = 0d; double averageSUElasticity = 0d; double averageResourceElasticity = 0d; double averageQualityElasticity = 0d; double minCostElasticity = Double.POSITIVE_INFINITY; double minSUElasticity = Double.POSITIVE_INFINITY; double minResourceElasticity = Double.POSITIVE_INFINITY; double minQualityElasticity = Double.POSITIVE_INFINITY; double maxCostElasticity = Double.NEGATIVE_INFINITY; double maxSUElasticity = Double.NEGATIVE_INFINITY; double maxResourceElasticity = Double.NEGATIVE_INFINITY; double maxQualityElasticity = Double.NEGATIVE_INFINITY; for (ServiceUnitConfigurationSolution solutionConfiguration : solutions.get(requirements)) { CloudServiceUnitAnalysisEngine cloudServiceElasticityAnalysisEngine = new CloudServiceUnitAnalysisEngine(); CloudServiceUnitAnalysisEngine.AnalysisResult analysisResult = cloudServiceElasticityAnalysisEngine .analyzeElasticity(solutionConfiguration.getServiceUnit()); solutionsNames += " " + solutionConfiguration.getServiceUnit().getName(); double costElasticity = (Integer) analysisResult .getValue(CloudServiceElasticityAnalysisEngine.COST_ELASTICITY); double sUElasticity = (Integer) analysisResult.getValue( CloudServiceElasticityAnalysisEngine.SERVICE_UNIT_ASSOCIATION_ELASTICITY); double resourceElasticity = (Integer) analysisResult .getValue(CloudServiceElasticityAnalysisEngine.RESOURCE_ELASTICITY); double qualityElasticity = (Integer) analysisResult .getValue(CloudServiceElasticityAnalysisEngine.QUALITY_ELASTICITY); averageCostElasticity += costElasticity; averageSUElasticity += sUElasticity; averageResourceElasticity += resourceElasticity; averageQualityElasticity += qualityElasticity; if (minCostElasticity > costElasticity) { minCostElasticity = costElasticity; } if (minSUElasticity > sUElasticity) { minSUElasticity = sUElasticity; } if (minResourceElasticity > resourceElasticity) { minResourceElasticity = resourceElasticity; } if (minQualityElasticity > qualityElasticity) { minQualityElasticity = qualityElasticity; } if (maxCostElasticity < costElasticity) { maxCostElasticity = costElasticity; } if (maxSUElasticity < sUElasticity) { maxSUElasticity = sUElasticity; } if (maxResourceElasticity < resourceElasticity) { maxResourceElasticity = resourceElasticity; } if (maxQualityElasticity < qualityElasticity) { maxQualityElasticity = qualityElasticity; } recommendedConfigurations.add(new CloudServiceConfigurationRecommendation() .withServiceUnitConfigurationSolution(requirements.getName(), solutionConfiguration, costElasticity, sUElasticity, resourceElasticity, qualityElasticity)); // ObjectMapper mapper = new ObjectMapper(); // System.out.println("solutionConfiguration" + mapper.writeValueAsString(solutionConfiguration)); // System.out.println("recommendedConfigurations: " + mapper.writeValueAsString(recommendedConfigurations)); recommendations.add(new ServiceUnitServicesRecommendation() .withSolutionRecommendation(requirements, recommendedConfigurations)); } // averageCostElasticity /= solutionsCount; // averageSUElasticity /= solutionsCount; // averageResourceElasticity /= solutionsCount; // averageQualityElasticity /= solutionsCount; // System.out.println(requirements.getName() + "," + strategies + "," + solutionsNames + "," + solutionsCount + "," + averageCostElasticity + "," // + minCostElasticity + "," + maxCostElasticity + "," + averageSUElasticity + "," + minSUElasticity + "," + maxSUElasticity // + "," + averageResourceElasticity + "," + minResourceElasticity + "," + maxResourceElasticity + "," // + averageQualityElasticity + "," + minQualityElasticity + "," + maxQualityElasticity); // System.out.println("\n"); } } } } EngineLogger.logger.debug("Quelle recommendation is done, returning result ...."); // wrapping return new Recommendations(recommendations); // File saveAs = new File("/tmp/quelleresult"); // Writer result = new StringWriter(); // JAXBContext jaxbContext; // try { // jaxbContext = JAXBContext.newInstance(Recommendations.class); // Marshaller jaxbMarshaller = jaxbContext.createMarshaller(); // jaxbMarshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true); // jaxbMarshaller.marshal(new Recommendations(recommendations), saveAs); // // jaxbMarshaller.marshal(new Recommendations(recommendations), result); // } catch (JAXBException ex) { // ex.printStackTrace(); // } // return result.toString(); } @POST @Path("/recommend/summary") // @Consumes(MediaType.APPLICATION_XML) @Produces(MediaType.APPLICATION_XML) public RecommendationSummaries getRecommendationSummary(MultiLevelRequirements multiLevelRequirements) { EngineLogger.logger.debug("Summarizing the recommendation..."); List<ServiceUnitServicesRecommendation> recommendations = getRecommendation(multiLevelRequirements) .getRecommendation(); RecommendationSummaries sums = new RecommendationSummaries(); List<CloudProvider> providers = loadCloudAllDescription(); for (ServiceUnitServicesRecommendation recom : recommendations) { EngineLogger.logger.debug("Found one recommendation. SU: " + recom.getUnitReqs().getName() + ", description:" + recom.getDescription()); String uuid = recom.getServicesRecommendations().get(0).getServiceUnit().getUuid().toString(); CloudOfferedService ofs = findCloudOfferedServiceByUUID(providers, uuid); CloudProvider p = findProviderThatOfferServiceWithUUID(providers, uuid); String details = ""; for (CloudServiceConfigurationRecommendation cloudRecom : recom.getServicesRecommendations()) { } sums.hasRecommendation( new RecommendationSummary(recom.getUnitReqs().getName(), ofs.getName(), p.getName(), details)); } return sums; } @POST @Path("/submitCloudDescription") @Consumes(MediaType.APPLICATION_XML) public boolean submitCloudProviderDescription(CloudProvider provider, @DefaultValue("true") @QueryParam("overwrite") boolean overwrite) { File saveAs = new File(SalsaConfiguration.getCloudProviderDescriptionDir() + File.separator + provider.getName() + cloudDescriptionFileExtension); if (saveAs.exists() && overwrite == false) { EngineLogger.logger.debug("Do not overwrite file : " + saveAs); return false; } try { JAXBContext jaxbContext = JAXBContext.newInstance(CloudProvider.class); Marshaller jaxbMarshaller = jaxbContext.createMarshaller(); jaxbMarshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true); jaxbMarshaller.marshal(provider, saveAs); } catch (JAXBException e) { EngineLogger.logger.debug("Fail to pass the cloud description !"); e.printStackTrace(); } EngineLogger.logger.debug("Saved/Updated cloud description in : " + saveAs); return true; } public List<CloudProvider> loadDefaultDescription() { List<CloudProvider> defaultList = new ArrayList<>(); String resourceFile = "/quelle_default/amazonDescription.xml"; EngineLogger.logger.debug("Loading default cloud description in the resource folder: " + resourceFile); InputStream is = QuelleService.class.getResourceAsStream(resourceFile); JAXBContext jaxbContext; try { jaxbContext = JAXBContext.newInstance(CloudProvider.class); Unmarshaller jaxbUnmarshaller = jaxbContext.createUnmarshaller(); CloudProvider provider = (CloudProvider) jaxbUnmarshaller.unmarshal(is); if (provider != null) { EngineLogger.logger.debug("Default cloud provider load done: " + provider.getName()); } defaultList.add(provider); } catch (JAXBException ex) { EngineLogger.logger.debug("Cannot load cloud description file in resource folder: " + resourceFile); ex.printStackTrace(); } return defaultList; } public List<CloudProvider> loadCloudAllDescription() { List<CloudProvider> providers = new ArrayList<>(); CloudDataExtensionFilter filter = new CloudDataExtensionFilter(cloudDescriptionFileExtension); File dir = new File(SalsaConfiguration.getCloudProviderDescriptionDir()); if (dir.isDirectory() == false) { EngineLogger.logger.debug("Error: Cannot find the directory storing cloud descriptions"); return loadDefaultDescription(); } String[] list = dir.list(filter); if (list.length == 0) { EngineLogger.logger.debug("No file with extension : " + cloudDescriptionFileExtension + " is found. No cloud provider description is load."); return loadDefaultDescription(); } for (String file : list) { String temp = new StringBuffer(SalsaConfiguration.getCloudProviderDescriptionDir()) .append(File.separator).append(file).toString(); EngineLogger.logger.debug("Loading cloud description in file: " + temp); File loadingFile = new File(temp); JAXBContext jaxbContext; try { jaxbContext = JAXBContext.newInstance(CloudProvider.class); Unmarshaller jaxbUnmarshaller = jaxbContext.createUnmarshaller(); CloudProvider provider = (CloudProvider) jaxbUnmarshaller.unmarshal(loadingFile); providers.add(provider); } catch (JAXBException ex) { EngineLogger.logger.debug("Cannot load cloud description file: " + temp); ex.printStackTrace(); } } return providers; } public CloudProvider loadSpecificCloudProvider(String name) { File dir = new File(SalsaConfiguration.getCloudProviderDescriptionDir()); CloudDataExtensionFilter filter = new CloudDataExtensionFilter(cloudDescriptionFileExtension); if (dir.isDirectory() == false) { EngineLogger.logger.debug("Error: Cannot find the directory storing cloud descriptions"); return null; } String[] list = dir.list(filter); if (list.length == 0) { EngineLogger.logger.debug("No file with extension : " + cloudDescriptionFileExtension + " is found. No cloud provider description is load."); return null; } for (String file : list) { String temp = new StringBuffer(SalsaConfiguration.getCloudProviderDescriptionDir()) .append(File.separator).append(file).toString(); EngineLogger.logger.debug("Loading cloud description in file: " + temp); File loadingFile = new File(temp); JAXBContext jaxbContext; try { jaxbContext = JAXBContext.newInstance(CloudProvider.class); Unmarshaller jaxbUnmarshaller = jaxbContext.createUnmarshaller(); CloudProvider provider = (CloudProvider) jaxbUnmarshaller.unmarshal(loadingFile); if (provider.getName().equals(name)) { EngineLogger.logger.debug("Found cloud provider with name: " + name + ". Load file: " + temp); return provider; } else { EngineLogger.logger.debug("Loaded file: " + temp + ", but the provider name is " + provider.getName() + " is not what we are looking for: " + name); } } catch (JAXBException ex) { EngineLogger.logger.debug("Cannot load cloud description file: " + temp); ex.printStackTrace(); } } EngineLogger.logger.debug("Found no cloud provider with name: " + name); return null; } // inner class, .cloud.data extension filter private class CloudDataExtensionFilter implements FilenameFilter { private final String ext; public CloudDataExtensionFilter(String ext) { this.ext = ext; } @Override public boolean accept(File dir, String name) { return (name.endsWith(ext)); } } private CloudOfferedService findCloudOfferedServiceByUUID(List<CloudProvider> providers, String uuid) { for (CloudProvider p : providers) { for (CloudOfferedService ofs : p.getCloudOfferedServices()) { if (ofs.getUuid().toString().equals(uuid)) { return ofs; } } } return null; } private CloudProvider findProviderThatOfferServiceWithUUID(List<CloudProvider> providers, String uuid) { for (CloudProvider p : providers) { for (CloudOfferedService ofs : p.getCloudOfferedServices()) { if (ofs.getUuid().toString().equals(uuid)) { return p; } } } return null; } }