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; }
/** * 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); }