/* * 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.plan.choco; import org.testng.Assert; import org.testng.annotations.Test; import choco.cp.solver.search.integer.valselector.MinVal; import choco.kernel.common.logging.ChocoLogging; import choco.kernel.common.logging.Verbosity; import choco.kernel.solver.ContradictionException; import entropy.TestHelper; import entropy.configuration.Configuration; import entropy.configuration.Configurations; import entropy.configuration.Node; import entropy.configuration.SimpleConfiguration; import entropy.configuration.SimpleNode; import entropy.configuration.SimpleVirtualMachine; import entropy.configuration.VirtualMachine; import entropy.plan.TimedReconfigurationPlan; import entropy.plan.action.Action; import entropy.plan.action.Migration; import entropy.plan.action.Shutdown; import entropy.plan.action.Startup; import entropy.plan.choco.actionModel.TimedReconfigurationPlanModelHelper; /** * Unit tests for TimedReconfigurationPlanSolver. * * @author Fabien Hermenier */ @Test(groups = {"unit", "RP-core"}) public class TestTimedReconfigurationPlanSolver { /** * Location of resources used for tests. */ public static final String RESOURCES_LOCATION = "src/test/resources/entropy/plan/choco/TestTimedReconfigurationPlanSolver."; /** * Make a migration on a node previously offline. * The node must be booted before performing the migration. */ public void testMigrateOnaBootingNode() { //ChocoLogging.setVerbosity(Verbosity.SEARCH); Node n1 = new SimpleNode("N1", 1, 2, 3); Node n2 = new SimpleNode("N2", 1, 4, 5); VirtualMachine vm1 = new SimpleVirtualMachine("VM1", 1, 1, 2); vm1.setCPUDemand(4); vm1.setMemoryDemand(4); Configuration src = new SimpleConfiguration(); src.addOnline(n1); src.addOffline(n2); src.setRunOn(vm1, n1); Configuration dst = src.clone(); dst.addOnline(n2); ReconfigurationProblem model = TimedReconfigurationPlanModelHelper.makeBasicModel(src, dst); Assert.assertTrue(model.solve(false)); TimedReconfigurationPlan plan = model.extractSolution(); //System.err.println(plan); for (Action a : plan) { if (a instanceof Migration) { Migration m = (Migration) a; Assert.assertEquals(m.getVirtualMachine(), vm1); Assert.assertEquals(m.getFinishMoment(), 8); Assert.assertEquals(m.getStartMoment(), 7); Assert.assertEquals(m.getHost(), n1); Assert.assertEquals(m.getDestination(), n2); } else if (a instanceof Startup) { Startup s = (Startup) a; Assert.assertEquals(s.getNode(), n2); Assert.assertEquals(s.getStartMoment(), 0); Assert.assertEquals(s.getFinishMoment(), 7); } else { Assert.fail("Bad action: " + a.getClass()); } } Configuration c = plan.getDestination(); Assert.assertEquals(c.getLocation(vm1), n2); Assert.assertTrue(c.isOnline(n2)); } /** * Test a plan where the destination of a migration has to be * booted first while the host is turned off after the migration. */ public void testShutdownAnHostingNode() { Node n1 = new SimpleNode("N1", 1, 2, 3); Node n2 = new SimpleNode("N2", 1, 4, 5); VirtualMachine vm1 = new SimpleVirtualMachine("VM1", 1, 1, 2); Configuration src = new SimpleConfiguration(); src.addOnline(n1); src.addOnline(n2); src.setRunOn(vm1, n1); Configuration dst = new SimpleConfiguration(); dst.addOnline(n2); dst.addOffline(n1); dst.setRunOn(vm1, n2); ReconfigurationProblem model = TimedReconfigurationPlanModelHelper.makeBasicModel(src, dst); /*try { model.getEnd().setSup(30); } catch (ContradictionException e) { Assert.fail(e.getMessage()); } */ Assert.assertTrue(model.minimize(model.getEnd(), false)); TimedReconfigurationPlan plan = model.extractSolution(); //Check the plan // System.err.println(plan); Assert.assertEquals(plan.size(), 2); for (Action a : plan) { if (a instanceof Shutdown) { Shutdown s = (Shutdown) a; Assert.assertEquals(s.getNode(), n1); Assert.assertEquals(s.getStartMoment(), 1); Assert.assertEquals(s.getFinishMoment(), 9); } else if (a instanceof Migration) { Migration m = (Migration) a; Assert.assertEquals(m.getHost(), n1); Assert.assertEquals(m.getDestination(), n2); Assert.assertEquals(m.getVirtualMachine(), vm1); Assert.assertEquals(m.getStartMoment(), 0); Assert.assertEquals(m.getFinishMoment(), 1); } else { Assert.fail("Unexpected action: " + a); } } Configuration c = plan.getDestination(); Assert.assertTrue(c.isOffline(n1), c.toString()); Assert.assertEquals(c.getLocation(vm1), n2); } /** * A migration on an offline node, plan to be booted. */ public void testBootingAnHostingNode() { ChocoLogging.setVerbosity(Verbosity.SILENT); Node n1 = new SimpleNode("N1", 1, 2, 9); Node n2 = new SimpleNode("N2", 1, 7, 5); VirtualMachine vm1 = new SimpleVirtualMachine("VM1", 1, 1, 2); vm1.setCPUDemand(4); Configuration src = new SimpleConfiguration(); src.addOnline(n1); src.addOffline(n2); src.setRunOn(vm1, n1); Configuration dst = new SimpleConfiguration(); dst.addOnline(n2); dst.addOnline(n1); dst.setRunOn(vm1, n1); ReconfigurationProblem model = TimedReconfigurationPlanModelHelper.makeBasicModel(src, dst); model.setTimeLimit(5000); Assert.assertTrue(model.solve(false)); Assert.assertTrue(model.checkSolution()); TimedReconfigurationPlan plan = model.extractSolution(); Configuration c = plan.getDestination(); Assert.assertEquals(Configurations.futureOverloadedNodes(c).size(), 0); //Check the plan Assert.assertEquals(plan.size(), 2); for (Action a : plan) { if (a instanceof Startup) { Startup s = (Startup) a; Assert.assertEquals(s.getNode(), n2); Assert.assertEquals(s.getStartMoment(), 0); Assert.assertEquals(s.getFinishMoment(), 7); } else if (a instanceof Migration) { Migration m = (Migration) a; Assert.assertEquals(m.getHost(), n1); Assert.assertEquals(m.getDestination(), n2); Assert.assertEquals(m.getVirtualMachine(), vm1); Assert.assertEquals(m.getStartMoment(), 7); Assert.assertEquals(m.getFinishMoment(), 8); } else { Assert.fail("Unexpected action: " + a); } } Assert.assertEquals(c.getLocation(vm1), n2); Assert.assertTrue(c.isOnline(n2)); } /** * Test the startup action. */ public void testBoot() { Node n1 = new SimpleNode("N1", 1, 1, 1); Configuration src = new SimpleConfiguration(); src.addOffline(n1); Configuration dst = src.clone(); dst.addOnline(n1); ReconfigurationProblem model = TimedReconfigurationPlanModelHelper.makeBasicModel(src, dst); Assert.assertEquals(Boolean.TRUE, model.solve()); TimedReconfigurationPlan plan = model.extractSolution(); Configuration c = plan.getDestination(); Assert.assertEquals(plan.size(), 1); for (Action a : plan) { Assert.assertEquals(a.getClass(), Startup.class); Startup s = (Startup) a; Assert.assertEquals(s.getNode(), n1); Assert.assertEquals(s.getStartMoment(), 0); Assert.assertEquals(s.getFinishMoment(), 7); } Assert.assertTrue(c.isOnline(n1)); } /** * Test a shutdown action. */ public void testShutdown() { Node n1 = new SimpleNode("N1", 1, 1, 1); Configuration src = new SimpleConfiguration(); src.addOnline(n1); Configuration dst = src.clone(); dst.addOffline(n1); ReconfigurationProblem model = TimedReconfigurationPlanModelHelper.makeBasicModel(src, dst); Assert.assertTrue(model.solve(false)); TimedReconfigurationPlan plan = model.extractSolution(); Configuration c = plan.getDestination(); Assert.assertEquals(plan.size(), 1); for (Action a : plan) { Assert.assertEquals(a.getClass(), Shutdown.class); Shutdown s = (Shutdown) a; Assert.assertEquals(s.getNode(), n1); Assert.assertEquals(s.getStartMoment(), 0); Assert.assertEquals(s.getFinishMoment(), 8); } Assert.assertTrue(c.isOffline(n1)); } /** * Test solve process when all resources requirements are satisfied. */ public void testIdlePlan() { //ChocoLogging.setVerbosity(Verbosity.SEARCH); Configuration src = TestHelper.readConfiguration(RESOURCES_LOCATION + "smallSequencing_src.txt"); Configuration dst = TestHelper.readConfiguration(RESOURCES_LOCATION + "smallSequencing_dst.txt"); ReconfigurationProblem model = TimedReconfigurationPlanModelHelper.makeBasicModel(src, dst); try { model.getEnd().setSup(50); } catch (ContradictionException e) { Assert.fail(e.getMessage()); } Assert.assertEquals(model.solve(), Boolean.TRUE); TimedReconfigurationPlan plan = model.extractSolution(); Configuration c = plan.getDestination(); Assert.assertEquals(Configurations.currentlyOverloadedNodes(c).size(), 0); } /** * Test strictMaintainOfResources with a feasible problem. */ public void testFeasibleStrictMaintainOfResources() { Configuration src = new SimpleConfiguration(); Configuration dst = new SimpleConfiguration(); Node n1 = new SimpleNode("N1", 1, 1, 5); Node n2 = new SimpleNode("N2", 1, 2, 5); src.addOnline(n1); src.addOnline(n2); dst.addOnline(n1); dst.addOnline(n2); VirtualMachine vm1 = new SimpleVirtualMachine("VM1", 1, 1, 5); vm1.setCPUDemand(2); src.setRunOn(vm1, n1); dst.setRunOn(vm1, n1); ReconfigurationProblem model = TimedReconfigurationPlanModelHelper.makeBasicModel(src, dst); try { model.getEnd().setSup(50); } catch (ContradictionException e) { Assert.fail(e.getMessage()); } model.setValIntSelector(new MinVal()); Assert.assertEquals(model.solve(), Boolean.TRUE); TimedReconfigurationPlan plan = model.extractSolution(); for (Action a : plan) { Migration m = (Migration) a; Assert.assertEquals(m.getDestination(), n2); } Configuration c = plan.getDestination(); Assert.assertEquals(c.getLocation(vm1), n2); } /** * Test strictMaintainOfResouces with a unfeasible problem. */ public void testStrictMaintainOfResourcesWithUnFeasiblePb() { Node n1 = new SimpleNode("N1", 1, 1, 5); // ChocoLogging.setVerbosity(Verbosity.SEARCH); VirtualMachine vm1 = new SimpleVirtualMachine("VM1", 1, 1, 5); vm1.setCPUDemand(2); Configuration src = new SimpleConfiguration(); Configuration dst = new SimpleConfiguration(); src.addOnline(n1); dst.addOnline(n1); src.setRunOn(vm1, n1); dst.setRunOn(vm1, n1); ReconfigurationProblem model = TimedReconfigurationPlanModelHelper.makeBasicModel(src, dst); try { model.getEnd().setSup(100); } catch (ContradictionException e) { Assert.fail(e.getMessage()); } //model.setTimeLimit(10); Assert.assertEquals(model.solve(), Boolean.FALSE); } /** * Boot a node then start a VM on it. */ public void testBootThenStart() { Node n = new SimpleNode("N1", 1, 1, 1); VirtualMachine vm = new SimpleVirtualMachine("VM1", 1, 1, 1); Configuration src = new SimpleConfiguration(); src.addOffline(n); src.addWaiting(vm); Configuration dst = new SimpleConfiguration(); dst.addOnline(n); dst.setRunOn(vm, n); ReconfigurationProblem m = TimedReconfigurationPlanModelHelper.makeBasicModel(src, dst); Assert.assertTrue(m.solve()); m.extractSolution(); } public void testWithStayingOfflineNode() { Node n = new SimpleNode("N1", 1, 1, 1); Configuration src = new SimpleConfiguration(); src.addOffline(n); Configuration dst = new SimpleConfiguration(); dst.addOffline(n); ReconfigurationProblem m = TimedReconfigurationPlanModelHelper.makeBasicModel(src, dst); Assert.assertTrue(m.solve()); m.extractSolution(); } }