/* * 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 gipad.placementconstraint; import gipad.configuration.configuration.Configuration; import gipad.configuration.configuration.Node; import gipad.configuration.configuration.VirtualMachine; import gipad.plan.choco.ReconfigurationProblem; import gipad.plan.choco.actionmodel.slice.Slice; import gipad.tools.ManagedElementList; import gipad.tools.SimpleManagedElementList; /** * A constraint to enforce a set of virtual machines to avoid * to be hosted on a group of nodes. * * @author Fabien Hermenier */ public class Ban implements PlacementConstraint { /** * The set of nodes to exlude. */ private ManagedElementList<Node> nodes; /** * The set of VMs involved in the constraint. */ private ManagedElementList<VirtualMachine> vms; /** * Make a new constraint. * * @param vms the VMs to assign * @param nodes the nodes to exclude */ public Ban(ManagedElementList<VirtualMachine> vms, ManagedElementList<Node> nodes) { this.nodes = nodes; this.vms = vms; } /** * Get the set of nodes involved in the constraint. * * @return a set of nodes */ @Override public ManagedElementList<Node> getNodes() { return (ManagedElementList<Node>) this.nodes; } /** * Get all the virtual machines involved in the constraint. * * @return a set of VMs. Should not be empty */ public ManagedElementList<VirtualMachine> getVirtualMachines() { return this.vms; } /** * Get all the virtual machines involved in the constraint. * * @return a set of VMs. Should not be empty */ @Override public ManagedElementList<VirtualMachine> getAllVirtualMachines() { return (ManagedElementList<VirtualMachine>) this.vms; } @Override public boolean equals(Object o) { if (this == o) { return true; } if (o == null || getClass() != o.getClass()) { return false; } Ban that = (Ban) o; return (nodes.equals(that.nodes) && getAllVirtualMachines().equals(that.getAllVirtualMachines())); } @Override public int hashCode() { int result = getAllVirtualMachines().hashCode(); result = 31 * result + nodes.hashCode(); return result; } @Override public String toString() { StringBuilder buffer = new StringBuilder(); buffer.append("ban(").append(vms.prettyOut()); buffer.append(", "); buffer.append(nodes.prettyOut()); buffer.append(")"); return buffer.toString(); } /** * Apply the constraint to the plan to all the VMs in a future running state. * FIXME: What about running VMs that will be suspended ? * * @param core the plan to customize. Must implement {@link entropy.plan.choco.ChocoCustomizablePlannerModule} */ @Override public void inject(ReconfigurationProblem core) { //Get only the future running VMS ManagedElementList<VirtualMachine> runnings = new SimpleManagedElementList<VirtualMachine>(); ManagedElementList<VirtualMachine> ignored = new SimpleManagedElementList<VirtualMachine>(); for (VirtualMachine vm : getAllVirtualMachines()) { if (core.getFutureRunnings().contains(vm)) { runnings.add(vm); } else { ignored.add(vm); } } if (runnings.size() == 0) { //FIXME debug log VJob.logger.debug(this + " is entailed. No VMs are running"); } else { if (ignored.size() > 0) { //FIXME debug log VJob.logger.debug(this + " ignores non-running VMs: " + ignored); } //Exclude all the nodes from the assign vars if (runnings.size() > 0) { int[] nodesIdx = new int[getNodes().size()]; int i = 0; for (Node n : getNodes()) { nodesIdx[i++] = core.getNode(n); } for (VirtualMachine vm : runnings) { Slice t = core.getAssociatedAction(vm).getDemandingSlice(); if (t != null) { for (int x = 0; x < nodesIdx.length; x++) { try { t.hoster().removeValue(nodesIdx[x],null); } catch (Exception e) { //FIXME debug log VJob.logger.error(e.getMessage(), e); } } } } } } } /** * Check that the constraint is satified in a configuration. * * @param cfg the configuration to check * @return true if the VMs are not running on the banned nodes. */ @Override public boolean isSatisfied(Configuration cfg) { ManagedElementList<Node> ns = (ManagedElementList<Node>) getNodes(); for (VirtualMachine vm : getAllVirtualMachines()) { if (cfg.isRunning(vm) && ns.contains(cfg.getLocation(vm))) { return false; } } return true; } @Override public ManagedElementList<VirtualMachine> getMisPlaced(Configuration cfg) { ManagedElementList<VirtualMachine> bad = new SimpleManagedElementList<VirtualMachine>(); for (VirtualMachine vm : getAllVirtualMachines()) { if (cfg.isRunning(vm) && getNodes().contains(cfg.getLocation(vm))) { bad.add(vm); } } return bad; } }