@Test public void testSimple() { ShareableResource rc = new ShareableResource("foo", 0, 0); Model mo = new DefaultModel(); VM vm1 = mo.newVM(); VM vm2 = mo.newVM(); VM vm3 = mo.newVM(); mo.attach(rc); rc.setConsumption(vm1, 3); LinearToAResourceActionDuration<VM> d = new LinearToAResourceActionDuration<>("foo", 3); Assert.assertEquals(d.getCoefficient(), 3.0); Assert.assertEquals(d.getOffset(), 0.0); Assert.assertEquals(d.getResourceId(), "foo"); Assert.assertEquals(d.evaluate(mo, vm1), 9); Assert.assertEquals(d.evaluate(mo, vm2), 0); d = new LinearToAResourceActionDuration<>("foo", 3, 4); Assert.assertEquals(d.evaluate(mo, vm1), 13); Assert.assertEquals(d.evaluate(mo, vm3), 4); d = new LinearToAResourceActionDuration<>("bar", 3, 4); Assert.assertEquals(d.evaluate(mo, vm3), -1); d.setCoefficient(5); d.setOffset(12); d.setResourceId("bar"); Assert.assertEquals(d.getCoefficient(), 5.0); Assert.assertEquals(d.getOffset(), 12.0); Assert.assertEquals(d.getResourceId(), "bar"); }
@Test public void testContinuousIsSatisfied() { Model mo = new DefaultModel(); List<VM> vms = Util.newVMs(mo, 5); List<Node> ns = Util.newNodes(mo, 5); Mapping map = mo.getMapping(); map.addOnlineNode(ns.get(0)); map.addOnlineNode(ns.get(1)); map.addOnlineNode(ns.get(2)); map.addRunningVM(vms.get(0), ns.get(0)); map.addRunningVM(vms.get(1), ns.get(1)); map.addReadyVM(vms.get(2)); map.addRunningVM(vms.get(3), ns.get(2)); Quarantine q = new Quarantine(ns.get(0)); ReconfigurationPlan plan = new DefaultReconfigurationPlan(mo); Assert.assertEquals(q.isSatisfied(plan), true); plan.add(new ShutdownVM(vms.get(1), ns.get(1), 1, 2)); Assert.assertEquals(q.isSatisfied(plan), true); plan.add(new BootVM(vms.get(2), ns.get(0), 0, 1)); Assert.assertEquals(q.isSatisfied(plan), false); plan = new DefaultReconfigurationPlan(mo); plan.add(new BootVM(vms.get(2), ns.get(2), 0, 1)); Assert.assertEquals(new Quarantine(ns.get(1)).isSatisfied(plan), true); plan.add(new MigrateVM(vms.get(3), ns.get(2), ns.get(1), 0, 1)); Assert.assertEquals(new Quarantine(ns.get(1)).isSatisfied(plan), false); plan = new DefaultReconfigurationPlan(mo); plan.add(new MigrateVM(vms.get(1), ns.get(1), ns.get(0), 0, 1)); Assert.assertEquals(q.isSatisfied(plan), false); }
@Test public void testViables() throws JSONConverterException { Model mo = new DefaultModel(); OverbookConverter conv = new OverbookConverter(); Overbook d = new Overbook(mo.newNode(), "foo", 1.4); Assert.assertEquals(conv.fromJSON(mo, conv.toJSON(d)), d); System.out.println(conv.toJSONString(d)); }
@Test public void testEqualsHashCode() { Model mo = new DefaultModel(); Node n = mo.newNode(); Quarantine q = new Quarantine(n); Assert.assertTrue(q.equals(q)); Assert.assertTrue(q.equals(new Quarantine(n))); Assert.assertEquals(q.hashCode(), new Quarantine(n).hashCode()); Assert.assertFalse(q.equals(new Quarantine(mo.newNode()))); }
@Test public void simpleTest() { OverbookSplitter splitter = new OverbookSplitter(); List<Instance> instances = new ArrayList<>(); Model m0 = new DefaultModel(); Node n = m0.newNode(0); m0.getMapping().addOnlineNode(n); m0.getMapping().addOnlineNode(m0.newNode(1)); Model m1 = new DefaultModel(); m1.getMapping().addOnlineNode(m1.newNode(2)); m1.getMapping().addOnlineNode(m1.newNode(3)); instances.add(new Instance(m0, new ArrayList<>(), new MinMTTR())); instances.add(new Instance(m1, new ArrayList<>(), new MinMTTR())); Set<Node> all = new HashSet<>(m0.getMapping().getAllNodes()); all.addAll(m1.getMapping().getAllNodes()); TIntIntHashMap nodeIndex = Instances.makeNodeIndex(instances); // Only nodes in m0 Overbook oSimple = new Overbook(n, "cpu", 2); Assert.assertTrue(splitter.split(oSimple, null, instances, new TIntIntHashMap(), nodeIndex)); Assert.assertTrue(instances.get(0).getSatConstraints().contains(oSimple)); Assert.assertFalse(instances.get(1).getSatConstraints().contains(oSimple)); }
@Test public void testViables() throws JSONConverterException, IOException { Model mo = new DefaultModel(); LonelyConverter conv = new LonelyConverter(); conv.setModel(mo); Lonely d = new Lonely(new HashSet<>(Arrays.asList(mo.newVM(), mo.newVM())), false); Lonely c = new Lonely(new HashSet<>(Arrays.asList(mo.newVM(), mo.newVM())), true); Assert.assertEquals(conv.fromJSON(conv.toJSONString(d)), d); Assert.assertEquals(conv.fromJSON(conv.toJSONString(c)), c); System.out.println(conv.toJSONString(d)); }
@Test public void testApply() { AllocateEvent na = new AllocateEvent(vms.get(0), "foo", 3); Model mo = new DefaultModel(); Mapping map = mo.getMapping(); map.addOnlineNode(ns.get(0)); map.addRunningVM(vms.get(0), ns.get(0)); Assert.assertFalse(na.apply(mo)); ShareableResource rc = new ShareableResource("foo"); mo.attach(rc); Assert.assertTrue(na.apply(mo)); Assert.assertEquals(3, rc.getConsumption(vms.get(0))); }
@Test public void testInstantiation() { Model mo = new DefaultModel(); Node n = mo.newNode(); Quarantine q = new Quarantine(n); Assert.assertNotNull(q.getChecker()); Assert.assertTrue(q.getInvolvedVMs().isEmpty()); Assert.assertEquals(q.getInvolvedNodes().iterator().next(), n); Assert.assertTrue(q.isContinuous()); Assert.assertFalse(q.setContinuous(false)); Assert.assertTrue(q.setContinuous(true)); Assert.assertFalse(q.toString().contains("null")); // Assert.assertEquals(q.isSatisfied(new DefaultModel()), SatConstraint.Sat.UNDEFINED); System.out.println(q); }
/** * A VM try to come into the quarantine zone. * * @throws org.btrplace.scheduler.SchedulerException */ @Test public void testWithNoSolution1() throws SchedulerException { Model mo = new DefaultModel(); VM vm1 = mo.newVM(); VM vm2 = mo.newVM(); VM vm3 = mo.newVM(); VM vm4 = mo.newVM(); Node n1 = mo.newNode(); Node n2 = mo.newNode(); Node n3 = mo.newNode(); Mapping map = new MappingFiller(mo.getMapping()) .on(n1, n2, n3) .run(n1, vm1) .run(n2, vm2, vm3) .run(n3, vm4) .get(); Quarantine q = new Quarantine(n1); List<SatConstraint> cstrs = new ArrayList<>(); cstrs.add(q); cstrs.add(new Fence(vm4, Collections.singleton(n1))); ChocoScheduler cra = new DefaultChocoScheduler(); ReconfigurationPlan p = cra.solve(mo, cstrs); Assert.assertNull(p); }
private boolean discreteCheck(Model mo) { Mapping map = mo.getMapping(); for (VM vm : getVMs()) { if (map.isRunning(vm)) { Node host = map.getVMLocation(vm); Set<VM> on = map.getRunningVMs(host); // Check for other VMs on the node. If they are not in the constraint // it's a violation for (VM vm2 : on) { if (!vm2.equals(vm) && !getVMs().contains(vm2)) { return false; } } } } return true; }
@Override public boolean startsWith(Model mo) { if (getConstraint().isContinuous()) { boolean ret = discreteCheck(mo); if (ret) { Mapping map = mo.getMapping(); for (VM vm : getVMs()) { if (map.isRunning(vm)) { privateNodes.add(map.getVMLocation(vm)); } } for (Node n : map.getOnlineNodes()) { if (map.getRunningVMs(n).isEmpty()) { idleNodes.add(n); } } } return ret; } return true; }
@Test public void testWithSatisfiedModel() throws SchedulerException { Model mo = new DefaultModel(); VM vm1 = mo.newVM(); VM vm2 = mo.newVM(); VM vm3 = mo.newVM(); VM vm4 = mo.newVM(); Node n1 = mo.newNode(); Node n2 = mo.newNode(); Node n3 = mo.newNode(); Mapping map = new MappingFiller(mo.getMapping()) .on(n1, n2, n3) .run(n1, vm1) .run(n2, vm2, vm3) .run(n3, vm4) .get(); Quarantine q = new Quarantine(n2); ChocoScheduler cra = new DefaultChocoScheduler(); ReconfigurationPlan p = cra.solve(mo, Collections.<SatConstraint>singleton(q)); Assert.assertNotNull(p); }
/** * Make a new model. * * @param p the RP to use as a basis. * @param e the VM managed by the action * @throws org.btrplace.scheduler.SchedulerException if an error occurred */ public RelocatableVM(ReconfigurationProblem p, VM e) throws SchedulerException { // Get vars vm = e; rp = p; src = rp.getSourceModel().getMapping().getVMLocation(e); org.chocosolver.solver.Model csp = rp.getModel(); Model mo = rp.getSourceModel(); // Default values start = rp.getStart(); end = rp.getStart(); duration = csp.intVar(0); state = csp.boolVar(true); // If not manageable, the VM stays on the current host if (!p.getManageableVMs().contains(e)) { stay = csp.boolVar(true); doReinstantiation = csp.boolVar(false); manageable = false; IntVar host = rp.makeCurrentHost(vm, PREFIX_STAY, vm, ").host"); cSlice = new SliceBuilder(rp, vm, PREFIX_STAY, vm.toString(), ").cSlice") .setHoster(host) .setEnd(rp.makeUnboundedDuration(PREFIX_STAY, vm, ").cSlice_end")) .build(); dSlice = new SliceBuilder(rp, vm, PREFIX_STAY, vm, ").dSlice") .setHoster(host) .setStart(cSlice.getEnd()) .build(); return; } // The VM can move (to re-instantiate or migrate) OR STAY to the same host stay = csp.boolVar(rp.makeVarLabel(vm, "stay")); cSlice = new SliceBuilder(rp, vm, PREFIX, vm, ").cSlice") .setHoster(rp.getNode(rp.getSourceModel().getMapping().getVMLocation(vm))) .setEnd(rp.makeUnboundedDuration(PREFIX, vm, ").cSlice_end")) .build(); dSlice = new SliceBuilder(rp, vm, PREFIX, vm, ").dSlice") .setStart(rp.makeUnboundedDuration(PREFIX, vm, ").dSlice_start")) .build(); // Update start and end vars of the action start = dSlice.getStart(); end = cSlice.getEnd(); csp.post(new Arithmetic(end, Operator.LE, rp.getEnd())); // Get some static durations from evaluators DurationEvaluators dev = rp.getDurationEvaluators(); int migrateDuration = dev.evaluate(rp.getSourceModel(), MigrateVM.class, vm); int bootDuration = dev.evaluate(rp.getSourceModel(), org.btrplace.plan.event.BootVM.class, vm); int forgeD = p.getDurationEvaluators() .evaluate(p.getSourceModel(), org.btrplace.plan.event.ForgeVM.class, vm); // Compute the re-instantiation duration int reInstantiateDuration = bootDuration + forgeD; reInstantiateDuration = forgeD; // Compliant with CMaxOnlineTest and others // Get the networking view if attached Network network = Network.get(mo); IntVar migrationDuration; if (network != null) { // Set the migration algorithm postCopy = mo.getAttributes().get(vm, "postCopy", false); // Create unbounded/large domain vars for migration duration and bandwidth migrationDuration = p.makeUnboundedDuration("migration(", vm, ").duration"); bandwidth = csp.intVar(PREFIX + vm + ").bandwidth", 0, Integer.MAX_VALUE / 100, true); } // No networking view, set the duration from the evaluator else { // The duration can still be 0 => the VM STAY ! migrationDuration = csp.intVar( rp.makeVarLabel("migration(", vm, ").duration"), new int[] {0, migrateDuration}); bandwidth = null; } // Possibly re-instantiate (if some attributes are defined) if (mo.getAttributes().get(vm, "clone", false) && mo.getAttributes().isSet(vm, "template")) { doReinstantiation = csp.boolVar(rp.makeVarLabel("relocation_method(", vm, ")")); duration = csp.intVar( rp.makeVarLabel(PREFIX, vm, ").duration"), Math.min(migrationDuration.getLB(), reInstantiateDuration), Math.max(migrationDuration.getUB(), reInstantiateDuration), true); // Re-instantiate or migrate // (Prefer the re-instantiation if the duration are the same, otherwise choose the min) rp.getModel() .ifThenElse( rp.getModel() .or( new Arithmetic( doReinstantiation, Operator.EQ, 0), // can be instantiated externally ! new Arithmetic(migrationDuration, Operator.LT, reInstantiateDuration)), new Arithmetic(duration, Operator.EQ, migrationDuration), new Arithmetic(duration, Operator.EQ, reInstantiateDuration)); // If it is a re-instantiation then specify that the dSlice must start AFTER the Forge delay IntVar time = csp.intVar(rp.makeVarLabel(doReinstantiation.getName(), " * ", forgeD), 0, forgeD, false); csp.post(csp.times(doReinstantiation, forgeD, time)); csp.post(new Arithmetic(start, Operator.GE, time)); // Be sure that doReinstantiation will be instantiated csp.post(new FastIFFEq(doReinstantiation, duration, reInstantiateDuration)); } // The VM either migrate or stay but won't be re-instantiated for sure else { doReinstantiation = csp.boolVar(false); duration = migrationDuration; } // If the VM stay (src host == dst host), then duration = 0 csp.post(new FastIFFEq(stay, dSlice.getHoster(), cSlice.getHoster().getValue())); csp.post(new FastIFFEq(stay, duration, 0)); // We have to force the migration duration equals to 0 if it stays // otherwise, the variable will be free csp.post(new FastIFFEq(stay, migrationDuration, 0)); // Create the task ('default' cumulative constraint with a height of 1) migrationTask = new Task(start, duration, end); }
/** * Unit tests for {@link AmongSplitter}. * * @author Fabien Hermenier */ public class AmongSplitterTest { public static final AmongSplitter splitter = new AmongSplitter(); public static final Model mo = new DefaultModel(); public static final VM vm1 = mo.newVM(); public static final VM vm2 = mo.newVM(); public static final VM vm3 = mo.newVM(); public static final VM vm4 = mo.newVM(); public static final VM vm5 = mo.newVM(); public static final Node n1 = mo.newNode(); public static final Node n2 = mo.newNode(); public static final Node n3 = mo.newNode(); public static final Node n4 = mo.newNode(); public static final Node n5 = mo.newNode(); public static final Mapping map = new MappingFiller(mo.getMapping()) .on(n1, n2, n3, n4) .run(n1, vm1, vm2) .run(n2, vm3) .run(n3, vm4) .run(n4, vm5) .get(); @Test public void testSplittable() throws SchedulerException { List<VM> vms = Arrays.asList(vm1, vm2, vm3); Collection<Collection<Node>> parts = new ArrayList<>(); parts.add(Arrays.asList(n1, n2)); parts.add(Arrays.asList(n3)); parts.add(Arrays.asList(n4)); Among single = new Among(vms, parts); /* N1 v1 v2 N2 v3 --- N3 v4 -- N4 v5 */ FixedNodeSetsPartitioning partitionner = new FixedNodeSetsPartitioning(parts); partitionner.setPartitions(parts); List<Instance> instances = partitionner.split( new DefaultParameters(), new Instance(mo, Collections.<SatConstraint>emptyList(), new MinMTTR())); TIntIntHashMap vmIndex = Instances.makeVMIndex(instances); TIntIntHashMap nodeIndex = Instances.makeNodeIndex(instances); splitter.split(single, new Instance(mo, new MinMTTR()), instances, vmIndex, nodeIndex); Among a = (Among) instances.get(0).getSatConstraints().iterator().next(); Assert.assertEquals(a.getGroupsOfNodes().size(), 1); Assert.assertEquals(a.getInvolvedNodes(), Arrays.asList(n1, n2)); for (Instance i : instances) { System.out.println(i.getSatConstraints()); } } }