/* * Copyright (c) 2010 Ecole des Mines de Nantes. * * This file is part of Entropy. * * Entropy is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * Entropy is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with Entropy. If not, see <http://www.gnu.org/licenses/>. */ package entropy.decision.vjobScheduler; import java.util.ArrayList; import java.util.List; import entropy.configuration.Configuration; import entropy.configuration.ManagedElementSet; import entropy.configuration.Node; import entropy.configuration.SimpleConfiguration; import entropy.configuration.SimpleManagedElementSet; import entropy.configuration.VirtualMachine; import entropy.decision.AssignmentException; import entropy.decision.DecisionModule; import entropy.vjob.VJob; import entropy.vjob.queue.VJobsPool; /** * A VJob scheduler based on the algorithm First Fit. * The scheduler browse the queue. For each vjob, it tests * if a viable configuration exists. If it suceeds at assigning * all the VMs composing the vjob, then the VJobs will be in the running * state. Otherwise, depending on the current state of the job, it will * be in the waiting state or in the sleeping state. * All the VMs that do not belong to a VJobs will be stopped. * * @author Fabien Hermenier */ public class FirstFitVJobScheduler extends DecisionModule { /** * The queue. */ private VJobsPool queue; /** * Make a new scheduler. * * @param q the queue of VJobs. */ public FirstFitVJobScheduler(VJobsPool q) { this.queue = q; } /** * Compute a new configuration using the FirstFit algorithm * * @param current the current configuration * @return a new viable configuration that indicated the states of the VMs * @throws AssignmentException if an error occurs. */ @Override public Configuration compute(Configuration current) throws AssignmentException { // TODO Auto-generated method stub //Scan the submitted vjobs List<VJob> declaredVJobs = queue.getRunningPriorities(); ManagedElementSet<Node> tmpNodes = new SimpleManagedElementSet<Node>(); Configuration newConf = new SimpleConfiguration(); for (Node n : current.getOnlines()) { Node copy = n.clone(); tmpNodes.add(copy); newConf.addOnline(copy); } List<VirtualMachine> toAssign = new ArrayList<VirtualMachine>(); for (VJob l2 : declaredVJobs) { for (VirtualMachine vm : l2.getVirtualMachines()) { if (current.isRunning(vm)) { toAssign.add(current.getRunnings().get(vm.getName())); } else if (current.isWaiting(vm)) { toAssign.add(current.getWaitings().get(vm.getName())); } else if (current.isSleeping(vm)) { toAssign.add(current.getSleepings().get(vm.getName())); } else { throw new AssignmentException("Unable to get the VM '" + vm.getName() + "' from the configuration"); } } Configuration c = new SimpleConfiguration(); tmpNodes = new SimpleManagedElementSet<Node>(); for (Node n : current.getOnlines()) { Node copy = n.clone(); tmpNodes.add(copy); c.addOnline(copy); } boolean success = true; for (VirtualMachine vm : toAssign) { for (Node node : tmpNodes) { if (vm.getCPUConsumption() <= node.getCPUCapacity() && vm.getMemoryConsumption() <= node.getMemoryCapacity()) { c.setRunOn(vm.clone(), newConf.getOnlines().get(node.getName())); node.setCPUCapacity(node.getCPUCapacity() - vm.getCPUConsumption()); node.setMemoryCapacity(node.getMemoryCapacity() - vm.getMemoryConsumption()); break; } } if (!c.getRunnings().contains(vm)) { success = false; break; } } if (!success) { getLogger().debug("Fail at assigning '" + l2.id() + "'"); toAssign.removeAll(l2.getVirtualMachines()); for (VirtualMachine vm : l2.getVirtualMachines()) { Node node = c.getLocation(vm); //Old state ? //Was running if (current.getRunnings().contains(vm)) { //Go to sleep on the local node. newConf.setSleepOn(vm, current.getLocation(vm)); } else if (current.getSleepings().contains(vm)) { //Still sleeping on its old location newConf.setSleepOn(vm, current.getLocation(vm)); } else { //Still waiting newConf.addWaiting(vm); } if (node != null) { tmpNodes.get(node.getName()).setCPUCapacity(node.getCPUCapacity() + vm.getCPUConsumption()); tmpNodes.get(node.getName()).setMemoryCapacity(node.getMemoryCapacity() + vm.getMemoryConsumption()); } } } else { getLogger().debug("Succeed at assigning '" + l2.id() + "'"); for (VirtualMachine vm : l2.getVirtualMachines()) { newConf.setRunOn(vm, c.getLocation(vm)); } } } return newConf; } /*private Configuration reduceWithCP(Configuration c) { VirtualMachineAssignmentModel model = new VirtualMachineAssignmentModel(c); for (VirtualMachine vm : c.getRunnings()) { model.mustBeRunning(vm); } for (VirtualMachine vm : c.getWaitings()) { model.mustBeOnFarm(vm); //Store informations about their consumption this.suspendedInfos.remove(vm); this.suspendedInfos.add(vm); } for (VirtualMachine vm : c.getSleepings()) { model.mustBeOnFarm(vm); } model.lazyMaintainResourcesAccessibility(); VirtualMachineAssignmentSolver solver = new VirtualMachineAssignmentSolver(); solver.read(model); //solver.setVirtualMachineSelector(new BiggestUnassignedVirtualMachine(solver, solver.getVar(nodes), VirtualMachine.CPU_CONSUMPTION)); //solver.setNodeSelector(new BusiestNode(solver, solver.getVar(nodes), Node.CPU_CAPACITY, true)); solver.setVirtualMachineSelector(new BiggestVirtualMachinesFirst(solver, VirtualMachine.CPU_CONSUMPTION)); solver.setNodeSelector(new StayFirstNodeSelector(solver)); if (solver.solve(this.getTimeout())) { return solver.getResultingConfiguration(); } return solver.getResultingConfiguration(); } */ }