/** * Copyright 2013 Technische Universitat Wien (TUW), Distributed SystemsGroup * E184. * This work was partially supported by the European Commission in terms * of the CELAR FP7 project (FP7-ICT-2011-8 #317790). * * 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. */ /** * Author : Georgiana Copil - e.copil@dsg.tuwien.ac.at */ package at.ac.tuwien.dsg.rSybl.planningEngine; import java.util.ArrayList; import java.util.Date; import java.util.HashMap; import java.util.List; import at.ac.tuwien.dsg.csdg.DependencyGraph; import at.ac.tuwien.dsg.csdg.Node; import at.ac.tuwien.dsg.csdg.Node.NodeType; import at.ac.tuwien.dsg.csdg.Relationship; import at.ac.tuwien.dsg.csdg.Relationship.RelationshipType; import at.ac.tuwien.dsg.csdg.elasticityInformation.ElasticityRequirement; import at.ac.tuwien.dsg.csdg.elasticityInformation.elasticityRequirements.Condition; import at.ac.tuwien.dsg.csdg.elasticityInformation.elasticityRequirements.SYBLSpecification; import at.ac.tuwien.dsg.csdg.elasticityInformation.elasticityRequirements.Strategy; import at.ac.tuwien.dsg.csdg.inputProcessing.multiLevelModel.abstractModelXML.SYBLDirectiveMappingFromXML; import at.ac.tuwien.dsg.csdg.outputProcessing.eventsNotification.CustomEvent; import at.ac.tuwien.dsg.csdg.outputProcessing.eventsNotification.EventNotification; import at.ac.tuwien.dsg.csdg.outputProcessing.eventsNotification.IEvent; import at.ac.tuwien.dsg.rSybl.cloudInteractionUnit.api.EnforcementAPIInterface; import at.ac.tuwien.dsg.rSybl.dataProcessingUnit.api.MonitoringAPIInterface; import at.ac.tuwien.dsg.rSybl.planningEngine.ContextRepresentation.Pair; import at.ac.tuwien.dsg.rSybl.planningEngine.utils.Configuration; import at.ac.tuwien.dsg.rSybl.planningEngine.staticData.ActionEffect; import at.ac.tuwien.dsg.rSybl.planningEngine.staticData.ActionEffects; import at.ac.tuwien.dsg.rSybl.planningEngine.utils.PlanningLogger; import java.util.logging.Level; import java.util.logging.Logger; public class PlanningGreedyAlgorithmWithPolynomialElasticityRelationships implements PlanningAlgorithmInterface { private Thread t; private boolean toCleanup = true; private ContextRepresentation contextRepresentation; private MonitoringAPIInterface monitoringAPI; private EnforcementAPIInterface enforcementAPI; private DependencyGraph dependencyGraph; private ContextRepresentation lastContextRepresentation; private String strategiesThatNeedToBeImproved = ""; private int REFRESH_PERIOD = 120000; private EventNotification eventNotification; public PlanningGreedyAlgorithmWithPolynomialElasticityRelationships(DependencyGraph cloudService, MonitoringAPIInterface monitoringAPI, EnforcementAPIInterface enforcementAPI) { this.dependencyGraph = cloudService; this.monitoringAPI = monitoringAPI; eventNotification = EventNotification.getEventNotification(); this.enforcementAPI = enforcementAPI; this.eventNotification = eventNotification; REFRESH_PERIOD = Configuration.getRefreshPeriod(); t = new Thread(this); } public boolean checkIfActionPossible(ActionEffect actionEffect) { Node entity = dependencyGraph.getNodeWithID(actionEffect.getTargetedEntityID()); // System.out.println("Targeted entity id " // +actionEffect.getTargetedEntityID()+entity); boolean possible = true; if (actionEffect.getActionType().equalsIgnoreCase("scalein")) { if (entity.getNodeType() == NodeType.CLOUD_SERVICE) { List<String> ips = entity.getAssociatedIps(); PlanningLogger.logger.info("For action " + actionEffect.getActionName() + entity.getAllRelatedNodesOfType(RelationshipType.HOSTED_ON_RELATIONSHIP, NodeType.VIRTUAL_MACHINE).size() + " hosts"); if (entity.getAllRelatedNodesOfType(RelationshipType.HOSTED_ON_RELATIONSHIP, NodeType.VIRTUAL_MACHINE).size() > 4) { return true; } } if (entity.getNodeType() == NodeType.SERVICE_TOPOLOGY) { Node master = dependencyGraph.findParentNode(entity.getId()); List<String> ips = master.getAssociatedIps(); int numberPrivateIps = 0; for (String ip : ips) { if (ip.split("\\.")[0].length() == 2) { numberPrivateIps++; } } if (entity.getAllRelatedNodesOfType(RelationshipType.HOSTED_ON_RELATIONSHIP, NodeType.VIRTUAL_MACHINE).size() > 4) { return true; } } } return possible; } public void findStrategies() { for (ElasticityRequirement elasticityRequirement : dependencyGraph.getAllElasticityRequirements()) { SYBLSpecification syblSpecification = SYBLDirectiveMappingFromXML.mapFromSYBLAnnotation(elasticityRequirement.getAnnotation()); MonitoredEntity monitoredEntity = contextRepresentation.findMonitoredEntity(syblSpecification.getComponentId()); if (monitoredEntity == null) { PlanningLogger.logger.info("Not finding monitored entity " + monitoredEntity + " " + syblSpecification.getComponentId()); } for (Strategy strategy : syblSpecification.getStrategy()) { Condition condition = strategy.getCondition(); if (contextRepresentation.evaluateCondition(condition, monitoredEntity)) { if (strategy.getToEnforce().getActionName().toLowerCase().contains("maximize") || strategy.getToEnforce().getActionName().toLowerCase().contains("minimize")) { if (strategy.getToEnforce().getActionName().toLowerCase().contains("maximize")) { //PlanningLogger.logger.info("Current value for "+ strategy.getToEnforce().getParameter()+" is "+ monitoredEntity.getMonitoredValue(strategy.getToEnforce().getParameter())+" .Previous value was "+previousContextRepresentation.getValueForMetric(monitoredEntity,strategy.getToEnforce().getParameter())); if (monitoredEntity.getMonitoredValue(strategy.getToEnforce().getParameter()) <= lastContextRepresentation.getValueForMetric(monitoredEntity, strategy.getToEnforce().getParameter())) { strategiesThatNeedToBeImproved += strategy.getId() + " "; } } if (strategy.getToEnforce().getActionName().toLowerCase().contains("minimize")) { PlanningLogger.logger.info("Current value for " + strategy.getToEnforce().getParameter() + " is " + monitoredEntity.getMonitoredValue(strategy.getToEnforce().getParameter()) + " .Previous value was " + lastContextRepresentation.getValueForMetric(monitoredEntity, strategy.getToEnforce().getParameter())); if (monitoredEntity.getMonitoredValue(strategy.getToEnforce().getParameter()) >= lastContextRepresentation.getValueForMetric(monitoredEntity, strategy.getToEnforce().getParameter())) { strategiesThatNeedToBeImproved += strategy.getId() + " "; } } } } } } } public void checkInstantiation(){ List<Relationship> instantiationRelationships=dependencyGraph.getAllRelationshipsOfType(RelationshipType.INSTANTIATION); //for } public ActionEffect checkActions( String target){ HashMap<String, List<ActionEffect>> actionEffects = ActionEffects.getActionEffects(); int maxConstraints= 0; ActionEffect maxConstraintsAction=null; PlanningLogger.logger.info("~~~~~~~~~~~Evaluating complimentary actions for "+target); for (List<ActionEffect> actionEffect:actionEffects.values()){ for (ActionEffect effect:actionEffect){ if (effect.getAffectedNodes().contains(target)){ int beforeConstraints= contextRepresentation.countViolatedConstraints(); MonitoredCloudService monitoredCloudService = contextRepresentation.getMonitoredCloudService().clone(); ContextRepresentation beforeContext = new ContextRepresentation(monitoredCloudService, monitoringAPI); contextRepresentation.doAction(effect); int improvedStrategies = contextRepresentation.countFixedStrategies(beforeContext); int afterConstraints = contextRepresentation.countViolatedConstraints(); PlanningLogger.logger.info("With "+effect.getActionType()+" on "+effect.getTargetedEntityID()+improvedStrategies+" and constraints "+(beforeConstraints-afterConstraints)+" violated constraints "+contextRepresentation.getViolatedConstraints()); contextRepresentation.undoAction(effect); if (beforeConstraints-afterConstraints+improvedStrategies>maxConstraints && (beforeConstraints-afterConstraints+improvedStrategies)>0){ maxConstraints=beforeConstraints-afterConstraints+improvedStrategies; maxConstraintsAction=effect; } } } } if (maxConstraintsAction!=null) PlanningLogger.logger.info("Returning "+maxConstraintsAction.getActionType()+" on "+maxConstraintsAction.getTargetedEntityID()); else PlanningLogger.logger.info("Returning null "); return maxConstraintsAction; } public void findAndExecuteBestActions() { strategiesThatNeedToBeImproved = ""; if (lastContextRepresentation != null) { findStrategies(); } lastContextRepresentation = new ContextRepresentation(dependencyGraph, monitoringAPI); lastContextRepresentation.initializeContext(); //PlanningLogger.logger.info("Strategies that could be enforced. ... "+strategiesThatNeedToBeImproved+" Violated constraints: "+contextRepresentation.getViolatedConstraints()); HashMap<String, List<ActionEffect>> actionEffects = ActionEffects.getActionEffects(); int numberOfBrokenConstraints = contextRepresentation .countViolatedConstraints(); PlanningLogger.logger.info("Violated constraints number: " + numberOfBrokenConstraints); int lastFixed = 1; ArrayList<Pair<ActionEffect, Integer>> result = new ArrayList<Pair<ActionEffect, Integer>>(); int numberOfRemainingConstraints = numberOfBrokenConstraints; if (!strategiesThatNeedToBeImproved.equalsIgnoreCase("") || numberOfBrokenConstraints > 0) { // while (contextRepresentation.countViolatedConstraints() > 0 // && numberOfRemainingConstraints > 0 && lastFixed>0) { Date date = new Date(); HashMap<Integer,List<Pair<ActionEffect,Integer>>> fixedDirectives = new HashMap<Integer,List<Pair<ActionEffect,Integer>>>(); HashMap<Integer,List<Pair<ActionEffect,Integer>>> fixedStrategies = new HashMap<Integer,List<Pair<ActionEffect,Integer>>>(); // PlanningLogger.logger.info("~~~~~~~~~~~Number of actions possible: "+actionEffects.values().size()); for (List<ActionEffect> list : actionEffects.values()) { for (ActionEffect actionEffect : list) { if (checkIfActionPossible(actionEffect)) { List<Pair<ActionEffect,Integer>> foundActions = new ArrayList<Pair<ActionEffect,Integer>>(); for (Pair<ActionEffect, Integer> a : result) { for (int i = 0; i < a.getSecond(); i++) { PlanningLogger.logger.info("Executing the already found action" + a.getFirst().getActionName()); contextRepresentation.doAction(a.getFirst()); PlanningLogger.logger.info("At " + date.getDay() + "_" + date.getMonth() + "_" + date.getHours() + "_" + date.getMinutes() + ". The violated constraints are the following: " + contextRepresentation.getViolatedConstraints()); } } int initiallyBrokenConstraints = contextRepresentation .countViolatedConstraints(); MonitoredCloudService monitoredCloudService = contextRepresentation.getMonitoredCloudService().clone(); ContextRepresentation beforeActionContextRepresentation = new ContextRepresentation(monitoredCloudService, monitoringAPI); // TODO: Try from 1 to 10 actions of the same type // for (int i = 0; i < 10; i++) { // for (int current = 0; current < i; current++) { // contextRepresentation.doAction(actionEffect); // } contextRepresentation.doAction(actionEffect); foundActions.add(contextRepresentation.new Pair<ActionEffect, Integer>(actionEffect, 1)); int fixedStr = contextRepresentation.countFixedStrategies(beforeActionContextRepresentation, strategiesThatNeedToBeImproved); PlanningLogger.logger.info("PlanningAlgorithm: Trying the action " + actionEffect.getActionName() + "constraints violated : " + contextRepresentation.getViolatedConstraints() + " Strategies improved " + contextRepresentation.getImprovedStrategies(beforeActionContextRepresentation, strategiesThatNeedToBeImproved)); fixedDirectives .put(initiallyBrokenConstraints - contextRepresentation .countViolatedConstraints() + fixedStr, foundActions); fixedStrategies .put( fixedStr,foundActions); /////////////////////~~~~~~~~~~~Check complimentary actions needed~~~~~~~~~~~~~~~~// List<String> targets = contextRepresentation.simulateDataImpact(beforeActionContextRepresentation, actionEffect); for (String target:targets){ ActionEffect dataAction=checkActions(target); if (dataAction!=null){ MonitoredCloudService newMonitoredCloudService = contextRepresentation.getMonitoredCloudService().clone(); ContextRepresentation beforeContext = new ContextRepresentation(newMonitoredCloudService, monitoringAPI); int beforeC = contextRepresentation.countViolatedConstraints(); contextRepresentation.doAction(dataAction); int afterC= contextRepresentation.countViolatedConstraints(); int improvedStrategies=contextRepresentation.countFixedStrategies(beforeContext); int req = initiallyBrokenConstraints-afterC+improvedStrategies; PlanningLogger.logger.info("PlanningAlgorithm: Trying the action due to DATA " + dataAction.getActionName() + "constraints violated : " + contextRepresentation.getViolatedConstraints() + " Strategies improved " + contextRepresentation.getImprovedStrategies(beforeActionContextRepresentation, strategiesThatNeedToBeImproved)); foundActions.add(contextRepresentation.new Pair<ActionEffect, Integer>(dataAction, 1)); fixedDirectives .put(req, foundActions); fixedStrategies .put( improvedStrategies,foundActions); contextRepresentation.undoAction(dataAction); } } contextRepresentation.undoDataImpactSimulation(beforeActionContextRepresentation, actionEffect); targets = contextRepresentation.simulateLoadImpact(beforeActionContextRepresentation, actionEffect); for (String target:targets){ MonitoredCloudService newMonitoredCloudService = contextRepresentation.getMonitoredCloudService().clone(); ContextRepresentation beforeContext = new ContextRepresentation(newMonitoredCloudService, monitoringAPI); ActionEffect loadAction=checkActions(target); if (loadAction!=null){ int beforeC = contextRepresentation.countViolatedConstraints(); contextRepresentation.doAction(loadAction); int afterC= contextRepresentation.countViolatedConstraints(); int improvedStrategies=contextRepresentation.countFixedStrategies(beforeContext); int req = initiallyBrokenConstraints-afterC+improvedStrategies; PlanningLogger.logger.info("PlanningAlgorithm: Trying the action due to LOAD " + loadAction.getActionName() + "constraints violated : " + contextRepresentation.getViolatedConstraints() + " Strategies improved " + contextRepresentation.getImprovedStrategies(beforeActionContextRepresentation, strategiesThatNeedToBeImproved)); foundActions.add(contextRepresentation.new Pair<ActionEffect, Integer>(loadAction, 1)); fixedDirectives .put(req, foundActions); fixedStrategies .put( improvedStrategies,foundActions); contextRepresentation.undoAction(loadAction); } } contextRepresentation.undoLoadImpactSimulation(beforeActionContextRepresentation, actionEffect); contextRepresentation.undoAction(actionEffect); // for (int current = 0; current < i; current++) { // contextRepresentation.undoAction(actionEffect); // } // } // System.out.println("Action "+actionEffect.getTargetedEntityID()+" "+actionEffect.getActionType()+" fixes "+(numberOfBrokenConstraints-contextRepresentation.countViolatedConstraints())+" constraints."); for (int i = result.size() - 1; i > 0; i--) { //System.out.println("Undoing action " //+ actionEffect.getActionName()); for (int j = 0; j < result.get(i).getSecond(); j++) { PlanningLogger.logger.info("Undo-ing the already found action" + result.get(i).getFirst().getActionName()); contextRepresentation.undoAction(result.get(i) .getFirst()); } } } } toCleanup = true; } int maxAction = -20; List<Pair<ActionEffect, Integer>> action = null; for (Integer val : fixedDirectives.keySet()) { PlanningLogger.logger.info("fixed directives "+fixedDirectives.get(val).size()); if (val > maxAction) { maxAction = val; action=fixedDirectives.get(val); } } int minStrat = 0; for (Integer v : fixedStrategies.keySet()){ if (fixedStrategies.get(v).equals(fixedDirectives.get(maxAction)) && minStrat<v){ minStrat=v; action = fixedStrategies.get(minStrat); } } // PlanningLogger.logger.info("Found action "+ action); // Find cloudService = SYBLRMI enforce action with action type, if (maxAction>0 && action!=null && !result.contains(action)) { for (Pair<ActionEffect, Integer> actionEffect:action){ for (int i=0;i<actionEffect.getSecond();i++){ PlanningLogger.logger.info("Found action "+(i+1)+"x" + ((ActionEffect) actionEffect.getFirst()).getActionType() + " on " + ((ActionEffect) actionEffect.getFirst()) .getTargetedEntityID() + " Number of directives fixed: " + maxAction); lastFixed = maxAction; Node entity = dependencyGraph.getNodeWithID(((ActionEffect) actionEffect.getFirst()) .getTargetedEntityID()); ((ActionEffect) actionEffect.getFirst()).setTargetedEntity(entity); if (maxAction > 0) { // result.add(actionEffect); } } } result.addAll(action); } else { lastFixed = 0; } numberOfRemainingConstraints -= lastFixed; } if (result.size()==0 && contextRepresentation.countViolatedConstraints()>0){ EventNotification eventNotification = EventNotification.getEventNotification(); CustomEvent customEvent = new CustomEvent(); customEvent.setCloudServiceID(this.dependencyGraph.getCloudService().getId()); customEvent.setType(IEvent.Type.NOTIFICATION); customEvent.setTarget(contextRepresentation.getViolatedConstraints()); customEvent.setMessage("Requirements " + contextRepresentation.getViolatedConstraints() + " are violated, and rSYBL can not solve the problem."); eventNotification.sendEvent(customEvent); monitoringAPI.sendMessageToAnalysisService("Requirements"+contextRepresentation.getViolatedConstraints()+" are violated, and rSYBL can't solve the problem."); }else{ ActionPlanEnforcement actionPlanEnforcement = new ActionPlanEnforcement(enforcementAPI); actionPlanEnforcement.enforceResult(result, dependencyGraph,contextRepresentation.getFixedConstraintsAsConstraints(lastContextRepresentation),contextRepresentation.getImprovedStrategiesAsStrategies(lastContextRepresentation, strategiesThatNeedToBeImproved)); } } @Override public void run() { while (true) { if (dependencyGraph.isInControlState()){ try { Thread.sleep(REFRESH_PERIOD); } catch (InterruptedException e) { // TODO Auto-generated catch block PlanningLogger.logger.error(e.toString()); } Node cloudService = monitoringAPI.getControlledService(); dependencyGraph.setCloudService(cloudService); contextRepresentation = new ContextRepresentation(dependencyGraph, monitoringAPI); contextRepresentation.initializeContext(); findAndExecuteBestActions(); } } } @Override public void start() { t.start(); } @Override public void stop() { boolean ok= false; while (!ok){ if (enforcementAPI.getPluginsExecutingActions().size()>0){ try { Thread.sleep(1000); } catch (InterruptedException ex) { Logger.getLogger(PlanningGreedyAlgorithm.class.getName()).log(Level.SEVERE, null, ex); } }else{ ok=true; } } t.stop(); } @Override public void setEffects(String effects) { // TODO Auto-generated method stub ActionEffects.setActionEffects(effects); } @Override public void replaceDependencyGraph(DependencyGraph dependencyGraph) { this.dependencyGraph=dependencyGraph; } @Override public void takeMainRole() { throw new UnsupportedOperationException("Not supported yet."); } }