use of com.netflix.titus.supplementary.relocation.model.DeschedulingResult in project titus-control-plane by Netflix.
the class TaskMigrationDeschedulerTest method testImmediateMigrations.
@Test
public void testImmediateMigrations() {
relocationConnectorStubs.addJobAttribute("jobToMigrate", RelocationAttributes.RELOCATION_REQUIRED_BY_IMMEDIATELY, "" + (clock.wallTime() + 1));
Task task0 = jobOperations.getTasks("jobToMigrate").get(0);
relocationConnectorStubs.place("active1", task0);
Map<String, DeschedulingResult> immediateEvictions = newDescheduler(Collections.emptyMap()).findAllImmediateEvictions();
assertThat(immediateEvictions).hasSize(1).containsKey(task0.getId());
}
use of com.netflix.titus.supplementary.relocation.model.DeschedulingResult in project titus-control-plane by Netflix.
the class TaskMigrationDeschedulerTest method testJobRequiredMigrationBy.
@Test
public void testJobRequiredMigrationBy() {
Task job1Task0 = jobOperations.getTasks("job1").get(0);
relocationConnectorStubs.place("active1", job1Task0);
relocationConnectorStubs.setQuota("job1", 1);
relocationConnectorStubs.addJobAttribute("job1", RelocationAttributes.RELOCATION_REQUIRED_BY, "" + clock.wallTime());
clock.advanceTime(Duration.ofSeconds(1));
Map<String, DeschedulingResult> results = newDescheduler(Collections.emptyMap()).findRequestedJobOrTaskMigrations();
assertThat(results).isNotEmpty();
}
use of com.netflix.titus.supplementary.relocation.model.DeschedulingResult in project titus-control-plane by Netflix.
the class DefaultDeschedulerService method deschedule.
@Override
public List<DeschedulingResult> deschedule(Map<String, TaskRelocationPlan> plannedAheadTaskRelocationPlans) {
List<Pair<Job, List<Task>>> allJobsAndTasks = jobOperations.getJobsAndTasks();
Map<String, Job<?>> jobs = allJobsAndTasks.stream().map(Pair::getLeft).collect(Collectors.toMap(Job::getId, j -> j));
Map<String, Task> tasksById = allJobsAndTasks.stream().flatMap(p -> p.getRight().stream()).collect(Collectors.toMap(Task::getId, t -> t));
EvacuatedAgentsAllocationTracker evacuatedAgentsAllocationTracker = new EvacuatedAgentsAllocationTracker(nodeDataResolver.resolve(), tasksById);
EvictionQuotaTracker evictionQuotaTracker = new EvictionQuotaTracker(evictionOperations, jobs);
TaskMigrationDescheduler taskMigrationDescheduler = new TaskMigrationDescheduler(plannedAheadTaskRelocationPlans, evacuatedAgentsAllocationTracker, evictionQuotaTracker, evictionConfiguration, jobs, tasksById, titusRuntime);
Map<String, DeschedulingResult> requestedImmediateEvictions = taskMigrationDescheduler.findAllImmediateEvictions();
Map<String, DeschedulingResult> requestedEvictions = taskMigrationDescheduler.findRequestedJobOrTaskMigrations();
Map<String, DeschedulingResult> allRequestedEvictions = CollectionsExt.merge(requestedImmediateEvictions, requestedEvictions);
Map<String, DeschedulingResult> regularEvictions = new HashMap<>();
Optional<Pair<TitusNode, List<Task>>> bestMatch;
while ((bestMatch = taskMigrationDescheduler.nextBestMatch()).isPresent()) {
TitusNode agent = bestMatch.get().getLeft();
List<Task> tasks = bestMatch.get().getRight();
tasks.forEach(task -> {
if (!allRequestedEvictions.containsKey(task.getId())) {
Optional<TaskRelocationPlan> relocationPlanForTask = getRelocationPlanForTask(agent, task, plannedAheadTaskRelocationPlans);
relocationPlanForTask.ifPresent(rp -> regularEvictions.put(task.getId(), DeschedulingResult.newBuilder().withTask(task).withAgentInstance(agent).withTaskRelocationPlan(rp).build()));
}
});
}
// Find eviction which could not be scheduled now.
for (Task task : tasksById.values()) {
if (allRequestedEvictions.containsKey(task.getId()) || regularEvictions.containsKey(task.getId())) {
continue;
}
if (evacuatedAgentsAllocationTracker.isEvacuated(task)) {
DeschedulingFailure failure = taskMigrationDescheduler.getDeschedulingFailure(task);
TaskRelocationPlan relocationPlan = plannedAheadTaskRelocationPlans.get(task.getId());
if (relocationPlan == null) {
relocationPlan = newNotDelayedRelocationPlan(task, false);
}
TitusNode agent = evacuatedAgentsAllocationTracker.getRemovableAgent(task);
regularEvictions.put(task.getId(), DeschedulingResult.newBuilder().withTask(task).withAgentInstance(agent).withTaskRelocationPlan(relocationPlan).withFailure(failure).build());
}
}
return CollectionsExt.merge(new ArrayList<>(allRequestedEvictions.values()), new ArrayList<>(regularEvictions.values()));
}
use of com.netflix.titus.supplementary.relocation.model.DeschedulingResult in project titus-control-plane by Netflix.
the class TaskMigrationDescheduler method findRequestedJobOrTaskMigrations.
Map<String, DeschedulingResult> findRequestedJobOrTaskMigrations() {
long now = clock.wallTime();
Map<String, DeschedulingResult> result = new HashMap<>();
tasksById.values().forEach(task -> {
Job<?> job = jobsById.get(task.getJobId());
TitusNode instance = evacuatedAgentsAllocationTracker.getAgent(task);
if (job != null && instance != null) {
RelocationPredicates.checkIfRelocationRequired(job, task).ifPresent(reason -> {
if (isSystemEvictionQuotaAvailable(job) && canTerminate(task)) {
long quota = evictionQuotaTracker.getJobEvictionQuota(task.getJobId());
if (quota > 0) {
evictionQuotaTracker.consumeQuota(task.getJobId(), isJobExemptFromSystemDisruptionWindow(job));
result.put(task.getId(), newDeschedulingResultForRequestedRelocation(now, task, instance, reason.getRight()));
}
}
});
}
});
return result;
}
use of com.netflix.titus.supplementary.relocation.model.DeschedulingResult in project titus-control-plane by Netflix.
the class DeschedulerStep method deschedule.
/**
* Accepts collection of tasks that must be relocated, and their relocation was planned ahead of time.
* For certain scenarios ahead of planning is not possible or desirable. For example during agent defragmentation,
* the defragmentation process must be down quickly, otherwise it may become quickly obsolete.
*
* @return a collection of tasks to terminate now. This collection may include tasks from the 'mustBeRelocatedTasks'
* collection if their deadline has passed. It may also include tasks that were not planned ahead of time
* for relocation.
*/
public Map<String, DeschedulingResult> deschedule(Map<String, TaskRelocationPlan> tasksToEvict) {
Stopwatch stopwatch = Stopwatch.createStarted();
try {
Map<String, DeschedulingResult> result = execute(tasksToEvict);
metrics.onSuccess(result.size(), stopwatch.elapsed(TimeUnit.MILLISECONDS));
logger.debug("Descheduling result: {}", result);
return result;
} catch (Exception e) {
logger.error("Step processing error", e);
metrics.onError(stopwatch.elapsed(TimeUnit.MILLISECONDS));
throw e;
}
}
Aggregations