Skip to main content

AvoidAssignments

Type: Constraint

Forbid specific objects from being placed on specific scope items. For example, keep certain tasks off certain hosts (say, because those hosts lack hardware the task needs).

Parameters​

ParameterTypeRequiredDefaultDescription
namestringNo""Descriptive name for logging/debugging.
scopestringYes-The scope the listed scope items belong to (e.g. "host").
assignmentslist of AvoidAssignmentYesemptyThe forbidden (object, scope item) pairs.

AvoidAssignment entries​

Each AvoidAssignment forbids one object from a set of scope items:

FieldTypeDescription
objectstringThe object being restricted
scopeItemslist of stringThe scope items this object may not be placed on

Example​

An example use: tasks on hosts, where certain tasks may not go on certain hosts. Forbid t0 from h0 and h1, t1 from h0 and h2, and t2 from h0.

solver.setObjectName("task");
solver.setContainerName("host");

solver.setAssignment(std::map<std::string, std::vector<std::string>>{
{"h0", {"t0", "t1"}},
{"h1", {"t2"}},
{"h2", {"t3"}},
});

auto forbid = [](std::string object, std::vector<std::string> scopeItems) {
AvoidAssignment entry;
entry.object() = std::move(object);
entry.scopeItems() = std::move(scopeItems);
return entry;
};

AvoidAssignmentsSpec avoidSpec;
avoidSpec.scope() = "host";
avoidSpec.assignments() = {
forbid("t0", {"h0", "h1"}),
forbid("t1", {"h0", "h2"}),
forbid("t2", {"h0"}),
};
solver.addConstraint(avoidSpec);

t0 and t1 both start on h0, which is forbidden for both, so they move: t0 to h2 (its only allowed host) and t1 to h1. t2 is already on an allowed host (h1) and stays. t3 is unconstrained.

Constraint only​

AvoidAssignmentsSpec cannot be used as a goal; passing it to addGoal throws.

If the initial assignment already respects every forbidden pair, so does the final one. If an object starts on a scope item it is forbidden from, that pair is initially broken, and the general constraint policy takes over: under the default policy Rebalancer moves the offending objects off as best it can without breaking constraints that held initially.

Avoiding many pairs​

Listing every pair gets unwieldy when a large share of objects must be kept off a scope item. An equivalent formulation scales better: add a dynamic object dimension (addDynamicObjectDimension) that is 1 for each disallowed (scope item, object) placement and 0 otherwise, choosing the defaultValue (0 or 1) that leaves fewer explicit entries. Then add a CapacitySpec on it with an ABSOLUTE MAX limit of 0, so no disallowed placement fits.

Source​