/* * Copyright (c) Fabien Hermenier * * 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.plan.choco.constraint.pack; import java.util.ArrayList; import java.util.Collections; import java.util.HashMap; import java.util.LinkedList; import java.util.List; import java.util.ListIterator; import java.util.Map; import choco.kernel.model.variables.integer.IntegerVariable; import choco.kernel.model.variables.set.SetVariable; import choco.kernel.solver.variables.integer.IntDomainVar; import choco.kernel.solver.variables.set.SetVar; import entropy.configuration.Configuration; import entropy.configuration.Node; import entropy.configuration.VirtualMachine; import entropy.plan.Plan; import entropy.plan.choco.ReconfigurationProblem; import entropy.plan.choco.actionModel.slice.DemandingSlice; import entropy.plan.choco.actionModel.slice.Slice; import entropy.plan.choco.actionModel.slice.SliceComparator; import entropy.vjob.ExplodedSet; /** * A constraint to assign a host with a sufficient amount of resources to satisfy * all the heights of the demanding slices. * The constraint is based on two dynamic bin packing constraints. * * @author Fabien Hermenier */ public class SatisfyDemandingSlicesHeightsSimpleBP implements SatisfyDemandingSliceHeights { private SetVariable[] bins; private Map<IntegerVariable, Integer> idxVM2Hoster = new HashMap<IntegerVariable, Integer>(); private SimpleBinPacking cPack; private SimpleBinPacking mPack; public SatisfyDemandingSlicesHeightsSimpleBP() { } public SetVariable getBin(int idx) { return bins[idx]; } public int getHosterBinIndex(IntegerVariable v) { return idxVM2Hoster.get(v); } @Override public void add(ReconfigurationProblem rp) { //SetVar []bins = new SetVar[rp.getNodes().length]; List<DemandingSlice> demandingCPU = new ArrayList<DemandingSlice>(rp.getDemandingSlices()); List<DemandingSlice> demandingMem = new ArrayList<DemandingSlice>(rp.getDemandingSlices()); //Remove slices with an height = 0 for (ListIterator<DemandingSlice> ite = demandingCPU.listIterator(); ite.hasNext(); ) { DemandingSlice d = ite.next(); if (d.getCPUheight() == 0) { ite.remove(); } } for (ListIterator<DemandingSlice> ite = demandingMem.listIterator(); ite.hasNext(); ) { DemandingSlice d = ite.next(); if (d.getMemoryheight() == 0) { ite.remove(); } } new LinkedList<String>(); //ManagedElementSet<Node> ns = cfg.getAllNodes(); //Node[] ns = model.getNodes(); Node[] ns = rp.getNodes(); if (demandingCPU.size() != 0) { List<IntDomainVar> demandCPU = new ArrayList<IntDomainVar>(); List<IntDomainVar> assignsCPU = new ArrayList<IntDomainVar>(); SetVar[] sets = new SetVar[ns.length]; IntDomainVar[] capaCPU = new IntDomainVar[sets.length]; for (int i = 0; i < ns.length; i++) { //if (model.getSourceConfiguration().isOnline(ns[i])) { capaCPU[i] = rp.getFreeCPU(ns[i]); sets[i] = rp.createEnumSetVar("slicesCPU(" + ns[i].getName() + ")", 0, demandingCPU.size() - 1); /*} else { capaCPU[i] = constant(0); sets[i] = emptySet();//makeSetVar("slicesCPU(" + n.getName() + ")", new int[]{}); } */ //bins = sets; } //Sort in descending order Collections.sort(demandingCPU, new SliceComparator(false, SliceComparator.ResourceType.cpuConsumption)); for (int i = 0; i < demandingCPU.size(); i++) { demandCPU.add(rp.createIntegerConstant(i + " #dCPU", demandingCPU.get(i).getCPUheight())); assignsCPU.add(demandingCPU.get(i).hoster()); // this.idxVM2Hoster.put(assignsCPU.get(i), i); } IntDomainVar[] demands = demandCPU.toArray(new IntDomainVar[demandCPU.size()]); //Plan.logger.debug("Pack \n\tcapa:" + Arrays.toString(capaCPU) + "\n\tdemand: " + demandCPU + "\n\tassigns" + assignsCPU); IntDomainVar nbNonEmpty = rp.createBoundIntVar("non-empty", 0, sets.length); cPack = new SimpleBinPacking(rp.getEnvironment(), sets, capaCPU, demands, assignsCPU.toArray(new IntDomainVar[assignsCPU.size()]), nbNonEmpty); //cPack.readOptions(opts); //TODO: options rp.post(cPack); } //opts.add(SimpleBinPacking.ADDITIONAL_RULES.getOption()); if (demandingMem.size() != 0) { List<IntDomainVar> demandMem = new ArrayList<IntDomainVar>(); List<IntDomainVar> assignsMem = new ArrayList<IntDomainVar>(); SetVar[] sets = new SetVar[ns.length]; IntDomainVar[] capaMem = new IntDomainVar[sets.length]; for (int i = 0; i < ns.length; i++) { capaMem[i] = rp.getFreeMem(ns[i]); sets[i] = rp.createEnumSetVar("slicesMem(" + ns[i].getName() + ")", 0, demandingMem.size() - 1); } Collections.sort(demandingMem, new SliceComparator(false, SliceComparator.ResourceType.memoryConsumption)); for (Slice task : demandingMem) { demandMem.add(rp.createIntegerConstant(task.getName() + "#dMem", task.getMemoryheight())); assignsMem.add(task.hoster()); } IntDomainVar[] demands = demandMem.toArray(new IntDomainVar[demandMem.size()]); //Plan.logger.debug("Pack \n\tcapa:" + Arrays.toString(capaMem) + "\n\tdemand: " + demandMem + "\n\tassigns" + assignsMem); IntDomainVar nbNonEmpty = rp.createBoundIntVar("non-empty", 0, sets.length); mPack = new SimpleBinPacking(rp.getEnvironment(), sets, capaMem, demands, assignsMem.toArray(new IntDomainVar[assignsMem.size()]), nbNonEmpty); //mPack.readOptions(opts); rp.post(mPack); } Plan.logger.debug("SatisfyDemandingSlicesHeightsSimpleBP branched"); } @Override public CustomPack getCoreCPUPacking() { return cPack; } @Override public CustomPack getCoreMemPacking() { return mPack; } @Override public boolean isSatisfied(Configuration cfg) { return false; //To change body of implemented methods use File | Settings | File Templates. } @Override public ExplodedSet<VirtualMachine> getAllVirtualMachines() { return null; //To change body of implemented methods use File | Settings | File Templates. } @Override public ExplodedSet<VirtualMachine> getMisPlaced(Configuration cfg) { return null; //To change body of implemented methods use File | Settings | File Templates. } @Override public int getRemainingCPU(int bin) { return cPack == null ? 0 : cPack.getRemainingSpace(bin); } @Override public int getRemainingMemory(int bin) { return mPack == null ? 0 : mPack.getRemainingSpace(bin); } }