/* * 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.vjob.constraint; import java.util.ArrayList; import java.util.List; import org.testng.Assert; import org.testng.annotations.Test; import choco.kernel.common.logging.ChocoLogging; import choco.kernel.common.logging.Verbosity; import entropy.configuration.Configuration; import entropy.configuration.ManagedElementSet; import entropy.configuration.Node; import entropy.configuration.SimpleConfiguration; import entropy.configuration.SimpleManagedElementSet; import entropy.configuration.SimpleNode; import entropy.configuration.SimpleVirtualMachine; import entropy.configuration.VirtualMachine; import entropy.plan.TimedReconfigurationPlan; import entropy.plan.choco.ChocoCustomRP; import entropy.plan.durationEvaluator.MockDurationEvaluator; import entropy.vjob.BasicVJob; import entropy.vjob.Capacity; import entropy.vjob.ExplodedSet; import entropy.vjob.VJob; /** * Unit tests for the capacity constraint * * @author Fabien Hermenier */ @Test(groups = {"unit"}) public class TestCapacity { /** * Basic test, all the VMs are online, so as the nodes * Move some VMs from one partition to another one */ public void test1() { //6 nodes, capacity of the 3 first of 5 VMs Configuration cfg = new SimpleConfiguration(); for (int i = 1; i <= 6; i++) { Node n = new SimpleNode("N" + i, 10, 10, 10); cfg.addOnline(n); } for (int i = 1; i <= 8; i++) { VirtualMachine vm = new SimpleVirtualMachine("VM" + i, 1, 1, 1); if (i % 3 == 0) { cfg.setRunOn(vm, cfg.getAllNodes().get("N1")); } else if (i % 2 == 0) { cfg.setRunOn(vm, cfg.getAllNodes().get("N2")); } else { cfg.setRunOn(vm, cfg.getAllNodes().get("N3")); } } for (int i = 9; i <= 12; i++) { VirtualMachine vm = new SimpleVirtualMachine("VM" + i, 1, 1, 1); if (i % 3 == 0) { cfg.setRunOn(vm, cfg.getAllNodes().get("N4")); } else if (i % 2 == 0) { cfg.setRunOn(vm, cfg.getAllNodes().get("N5")); } else { cfg.setRunOn(vm, cfg.getAllNodes().get("N6")); } } ExplodedSet<Node> set = new ExplodedSet<Node>(); set.add(cfg.getAllNodes().get("N1")); set.add(cfg.getAllNodes().get("N2")); set.add(cfg.getAllNodes().get("N3")); ChocoCustomRP plan = new ChocoCustomRP(new MockDurationEvaluator(3, 2, 3, 4, 5, 6, 7, 8)); ChocoLogging.setVerbosity(Verbosity.SILENT); plan.setRepairMode(false); List<VJob> vjobs = new ArrayList<VJob>(); try { VJob v = new BasicVJob("v1"); v.addVirtualMachines(new ExplodedSet<VirtualMachine>(cfg.getAllVirtualMachines())); Capacity c = new Capacity(set, 5); v.addConstraint(c); //Dumb Assert.assertEquals(c.getMaximumCapacity(), 5); vjobs.add(v); //plan.setTimeLimit(20); TimedReconfigurationPlan p = plan.compute(cfg, cfg.getRunnings(), cfg.getWaitings(), cfg.getSleepings(), new SimpleManagedElementSet<VirtualMachine>(), cfg.getOnlines(), cfg.getOfflines(), vjobs); System.err.println(p); p.getDestination(); Assert.assertEquals(p.size(), 3); } catch (Exception e) { Assert.fail(e.getMessage(), e); } finally { System.err.flush(); ChocoLogging.flushLogs(); } } /** * Trickier test. * while some VMs in the other partition will have to move to the restricted partition. * Last, one VM that was suspended on the restricted partition is resumed */ public void test2() { //6 nodes, capacity of the 3 first of 5 VMs Configuration cfg = new SimpleConfiguration(); for (int i = 1; i <= 6; i++) { if (i <= 3) { Node n = new SimpleNode("N" + i, 10, 10, 10); cfg.addOnline(n); } else { Node n = new SimpleNode("N" + i, 5, 5, 5); cfg.addOnline(n); } } for (int i = 1; i <= 8; i++) { VirtualMachine vm = new SimpleVirtualMachine("VM" + i, 1, 1, 1); if (i % 3 == 0) { cfg.setRunOn(vm, cfg.getAllNodes().get("N1")); } else if (i % 2 == 0) { cfg.setRunOn(vm, cfg.getAllNodes().get("N2")); } else { cfg.setRunOn(vm, cfg.getAllNodes().get("N3")); } } //A big VM on N6 that will have to move to N1 or N2 VirtualMachine vmFat = new SimpleVirtualMachine("VMfat", 3, 3, 3); vmFat.setCPUDemand(7); cfg.setRunOn(vmFat, cfg.getAllNodes().get("N6")); //One suspended VM on N1 for the fun VirtualMachine vmxx = new SimpleVirtualMachine("VMxx", 1, 1, 1); cfg.setSleepOn(vmxx, cfg.getAllNodes().get("N1")); //System.err.println(Configurations.futureOverloadedNodes(cfg)); //N3 will have to be turned off ManagedElementSet<Node> futureOnlines = cfg.getAllNodes().clone(); futureOnlines.remove(futureOnlines.get("N3")); ManagedElementSet<Node> futureOfflines = new SimpleManagedElementSet<Node>(); futureOnlines.add(cfg.getAllNodes().get("N3")); for (int i = 9; i <= 12; i++) { VirtualMachine vm = new SimpleVirtualMachine("VM" + i, 1, 1, 1); if (i % 3 == 0) { cfg.setRunOn(vm, cfg.getAllNodes().get("N4")); } else if (i % 2 == 0) { cfg.setRunOn(vm, cfg.getAllNodes().get("N5")); } else { cfg.setRunOn(vm, cfg.getAllNodes().get("N6")); } } ExplodedSet<Node> set = new ExplodedSet<Node>(); set.add(cfg.getAllNodes().get("N1")); set.add(cfg.getAllNodes().get("N2")); set.add(cfg.getAllNodes().get("N3")); ChocoCustomRP plan = new ChocoCustomRP(new MockDurationEvaluator(3, 2, 3, 4, 5, 6, 7, 8)); plan.setRepairMode(false); List<VJob> vjobs = new ArrayList<VJob>(); try { VJob v = new BasicVJob("v1"); v.addVirtualMachines(new ExplodedSet<VirtualMachine>(cfg.getAllVirtualMachines())); Capacity c = new Capacity(set, 5); v.addConstraint(c); //Dumb Assert.assertEquals(c.getMaximumCapacity(), 5); vjobs.add(v); //plan.setTimeLimit(10); TimedReconfigurationPlan p = plan.compute(cfg, cfg.getAllVirtualMachines(), cfg.getWaitings(), new SimpleManagedElementSet<VirtualMachine>(), new SimpleManagedElementSet<VirtualMachine>(), futureOnlines, futureOfflines, vjobs); System.err.println(p); p.getDestination(); //1 resume action //1 migration to the restricted partition //4 migrations to liberate the restricted partition ( 3 + 1 as a side effect of the incoming migration) Assert.assertEquals(p.size(), 6); } catch (Exception e) { Assert.fail(e.getMessage(), e); } finally { System.err.flush(); ChocoLogging.flushLogs(); } } public void testIsSatisfied() { Configuration cfg = new SimpleConfiguration(); for (int i = 1; i <= 6; i++) { if (i <= 3) { Node n = new SimpleNode("N" + i, 10, 10, 10); cfg.addOnline(n); } else { Node n = new SimpleNode("N" + i, 5, 5, 5); cfg.addOnline(n); } } for (int i = 1; i <= 8; i++) { VirtualMachine vm = new SimpleVirtualMachine("VM" + i, 1, 1, 1); if (i % 3 == 0) { cfg.setRunOn(vm, cfg.getAllNodes().get("N1")); } else if (i % 2 == 0) { cfg.setRunOn(vm, cfg.getAllNodes().get("N2")); } else { cfg.setRunOn(vm, cfg.getAllNodes().get("N3")); } } ExplodedSet<Node> set = new ExplodedSet<Node>(); set.add(cfg.getAllNodes().get("N1")); set.add(cfg.getAllNodes().get("N2")); set.add(cfg.getAllNodes().get("N3")); Capacity c = new Capacity(set, 5); Assert.assertFalse(c.isSatisfied(cfg)); } public void testMisPlacedHeuristics() { Configuration cfg = new SimpleConfiguration(); for (int i = 1; i <= 6; i++) { if (i <= 3) { Node n = new SimpleNode("N" + i, 10, 10, 10); cfg.addOnline(n); } else { Node n = new SimpleNode("N" + i, 5, 5, 5); cfg.addOnline(n); } } for (int i = 1; i <= 8; i++) { VirtualMachine vm = new SimpleVirtualMachine("VM" + i, 1, 1, 1); if (i % 3 == 0) { cfg.setRunOn(vm, cfg.getAllNodes().get("N1")); } else if (i % 2 == 0) { cfg.setRunOn(vm, cfg.getAllNodes().get("N2")); } else { cfg.setRunOn(vm, cfg.getAllNodes().get("N3")); } } ManagedElementSet<VirtualMachine> bad = cfg.getAllVirtualMachines().clone(); for (int i = 9; i <= 12; i++) { VirtualMachine vm = new SimpleVirtualMachine("VM" + i, 1, 1, 1); if (i % 3 == 0) { cfg.setRunOn(vm, cfg.getAllNodes().get("N4")); } else if (i % 2 == 0) { cfg.setRunOn(vm, cfg.getAllNodes().get("N5")); } else { cfg.setRunOn(vm, cfg.getAllNodes().get("N6")); } } ExplodedSet<Node> set = new ExplodedSet<Node>(); set.add(cfg.getAllNodes().get("N1")); set.add(cfg.getAllNodes().get("N2")); set.add(cfg.getAllNodes().get("N3")); Capacity c = new Capacity(set, 5); //System.err.println(c.getMisPlaced(cfg)); ExplodedSet<VirtualMachine> test = c.getMisPlaced(cfg); Assert.assertEquals(test.size(), bad.size()); Assert.assertTrue(test.containsAll(bad)); } }