Search in sources :

Example 21 with ServiceJobExt

use of com.netflix.titus.api.jobmanager.model.job.ext.ServiceJobExt in project titus-control-plane by Netflix.

the class KillInitiatedActions method createShrinkAction.

private static TitusModelAction createShrinkAction(TitusChangeAction.Builder changeActionBuilder, VersionSupplier versionSupplier) {
    return TitusModelAction.newModelUpdate(changeActionBuilder).summary("Shrinking job as a result of terminate and shrink request").jobUpdate(jobHolder -> {
        Job<ServiceJobExt> serviceJob = jobHolder.getEntity();
        ServiceJobExt oldExt = serviceJob.getJobDescriptor().getExtensions();
        Capacity oldCapacity = oldExt.getCapacity();
        // A job of size 0 may still have some tasks running just after job scale-down request.
        // We must make sure that we do not decrement the job size if it is already 0.
        int newDesired = Math.max(0, oldCapacity.getDesired() - 1);
        Capacity newCapacity = oldCapacity.toBuilder().withMin(Math.min(oldCapacity.getMin(), newDesired)).withDesired(newDesired).build();
        Job<ServiceJobExt> newJob = serviceJob.toBuilder().withJobDescriptor(serviceJob.getJobDescriptor().toBuilder().withExtensions(oldExt.toBuilder().withCapacity(newCapacity).build()).build()).build();
        newJob = VersionSuppliers.nextVersion(newJob, versionSupplier);
        return jobHolder.setEntity(newJob);
    });
}
Also used : Capacity(com.netflix.titus.api.jobmanager.model.job.Capacity) ServiceJobExt(com.netflix.titus.api.jobmanager.model.job.ext.ServiceJobExt)

Example 22 with ServiceJobExt

use of com.netflix.titus.api.jobmanager.model.job.ext.ServiceJobExt in project titus-control-plane by Netflix.

the class KillInitiatedActions method userInitiateTaskKillAction.

/**
 * Change a task to {@link TaskState#KillInitiated} state, store it, and send the kill command to the compute provider.
 * All models are updated when both operations complete.
 * This method is used for user initiated kill operations, so the store operation happens before response is sent back to the user.
 */
public static ChangeAction userInitiateTaskKillAction(ReconciliationEngine<JobManagerReconcilerEvent> engine, JobServiceRuntime executionContext, JobStore jobStore, VersionSupplier versionSupplier, String taskId, boolean shrink, boolean preventMinSizeUpdate, String reasonCode, String reason, TitusRuntime titusRuntime, CallMetadata callMetadata) {
    return TitusChangeAction.newAction("userInitiateTaskKill").id(taskId).trigger(V3JobOperations.Trigger.API).summary(reason).callMetadata(callMetadata).changeWithModelUpdates(self -> JobEntityHolders.toTaskObservable(engine, taskId, titusRuntime).flatMap(task -> {
        TaskState taskState = task.getStatus().getState();
        if (taskState == TaskState.KillInitiated || taskState == TaskState.Finished) {
            return Observable.just(Collections.<ModelActionHolder>emptyList());
        }
        if (shrink) {
            Job<ServiceJobExt> job = engine.getReferenceView().getEntity();
            Capacity capacity = job.getJobDescriptor().getExtensions().getCapacity();
            if (preventMinSizeUpdate && capacity.getDesired() <= capacity.getMin()) {
                return Observable.<List<ModelActionHolder>>error(JobManagerException.terminateAndShrinkNotAllowed(job, task));
            }
        }
        Task taskWithKillInitiated = VersionSuppliers.nextVersion(JobFunctions.changeTaskStatus(task, TaskState.KillInitiated, reasonCode, reason, titusRuntime.getClock()), versionSupplier);
        Callable<List<ModelActionHolder>> modelUpdateActions = () -> JobEntityHolders.expectTask(engine, task.getId(), titusRuntime).map(current -> {
            List<ModelActionHolder> updateActions = new ArrayList<>();
            TitusModelAction stateUpdateAction = TitusModelAction.newModelUpdate(self).taskUpdate(taskWithKillInitiated);
            updateActions.addAll(ModelActionHolder.allModels(stateUpdateAction));
            if (shrink) {
                TitusModelAction shrinkAction = createShrinkAction(self, versionSupplier);
                updateActions.add(ModelActionHolder.reference(shrinkAction));
            }
            return updateActions;
        }).orElse(Collections.emptyList());
        return jobStore.updateTask(taskWithKillInitiated).andThen(createKillAction(executionContext, task)).andThen(Observable.fromCallable(modelUpdateActions));
    }));
}
Also used : Completable(rx.Completable) JobManagerConstants(com.netflix.titus.api.jobmanager.service.JobManagerConstants) JobServiceRuntime(com.netflix.titus.master.jobmanager.service.JobServiceRuntime) TitusChangeAction(com.netflix.titus.master.jobmanager.service.common.action.TitusChangeAction) Task(com.netflix.titus.api.jobmanager.model.job.Task) Callable(java.util.concurrent.Callable) ReactorExt(com.netflix.titus.common.util.rx.ReactorExt) ArrayList(java.util.ArrayList) Observable(rx.Observable) HashSet(java.util.HashSet) JobStatus(com.netflix.titus.api.jobmanager.model.job.JobStatus) JobState(com.netflix.titus.api.jobmanager.model.job.JobState) ChangeAction(com.netflix.titus.common.framework.reconciler.ChangeAction) JobManagerException(com.netflix.titus.api.jobmanager.service.JobManagerException) JobEntityHolders(com.netflix.titus.master.jobmanager.service.common.action.JobEntityHolders) JobStore(com.netflix.titus.api.jobmanager.store.JobStore) CallMetadata(com.netflix.titus.api.model.callmetadata.CallMetadata) Job(com.netflix.titus.api.jobmanager.model.job.Job) ServiceJobExt(com.netflix.titus.api.jobmanager.model.job.ext.ServiceJobExt) TaskStatus(com.netflix.titus.api.jobmanager.model.job.TaskStatus) Set(java.util.Set) JobFunctions(com.netflix.titus.api.jobmanager.model.job.JobFunctions) TitusModelAction(com.netflix.titus.master.jobmanager.service.common.action.TitusModelAction) TaskState(com.netflix.titus.api.jobmanager.model.job.TaskState) Capacity(com.netflix.titus.api.jobmanager.model.job.Capacity) EntityHolder(com.netflix.titus.common.framework.reconciler.EntityHolder) ModelActionHolder(com.netflix.titus.common.framework.reconciler.ModelActionHolder) List(java.util.List) V3JobOperations(com.netflix.titus.api.jobmanager.service.V3JobOperations) VersionSupplier(com.netflix.titus.master.jobmanager.service.VersionSupplier) ReconciliationEngine(com.netflix.titus.common.framework.reconciler.ReconciliationEngine) VersionSuppliers(com.netflix.titus.master.jobmanager.service.VersionSuppliers) Optional(java.util.Optional) JobManagerReconcilerEvent(com.netflix.titus.master.jobmanager.service.event.JobManagerReconcilerEvent) TitusRuntime(com.netflix.titus.common.runtime.TitusRuntime) Collections(java.util.Collections) TitusModelAction(com.netflix.titus.master.jobmanager.service.common.action.TitusModelAction) Task(com.netflix.titus.api.jobmanager.model.job.Task) Capacity(com.netflix.titus.api.jobmanager.model.job.Capacity) ArrayList(java.util.ArrayList) Job(com.netflix.titus.api.jobmanager.model.job.Job) TaskState(com.netflix.titus.api.jobmanager.model.job.TaskState) Callable(java.util.concurrent.Callable) ModelActionHolder(com.netflix.titus.common.framework.reconciler.ModelActionHolder)

Example 23 with ServiceJobExt

use of com.netflix.titus.api.jobmanager.model.job.ext.ServiceJobExt in project titus-control-plane by Netflix.

the class ServiceDifferenceResolver method applyStore.

private List<ChangeAction> applyStore(ReconciliationEngine<JobManagerReconcilerEvent> engine, ServiceJobView refJobView, EntityHolder storeJob, AtomicInteger allowedNewTasks) {
    if (!storeWriteRetryInterceptor.executionLimits(storeJob)) {
        return Collections.emptyList();
    }
    List<ChangeAction> actions = new ArrayList<>();
    EntityHolder refJobHolder = refJobView.getJobHolder();
    Job<ServiceJobExt> refJob = refJobHolder.getEntity();
    if (!refJobHolder.getEntity().equals(storeJob.getEntity())) {
        actions.add(storeWriteRetryInterceptor.apply(BasicJobActions.updateJobInStore(engine, jobStore)));
    }
    boolean isJobTerminating = refJob.getStatus().getState() == JobState.KillInitiated;
    for (EntityHolder referenceTaskHolder : refJobHolder.getChildren()) {
        ServiceJobTask refTask = referenceTaskHolder.getEntity();
        Optional<EntityHolder> storeHolder = storeJob.findById(referenceTaskHolder.getId());
        ServiceJobTask storeTask = storeHolder.get().getEntity();
        boolean refAndStoreInSync = areEquivalent(storeHolder.get(), referenceTaskHolder);
        boolean shouldRetry = !isJobTerminating && refTask.getStatus().getState() == TaskState.Finished && !refTask.getStatus().getReasonCode().equals(TaskStatus.REASON_SCALED_DOWN) && allowedNewTasks.get() > 0;
        if (refAndStoreInSync) {
            TaskState currentTaskState = refTask.getStatus().getState();
            if (currentTaskState == TaskState.Finished) {
                if (isJobTerminating || isScaledDown(storeTask) || hasEnoughTasksRunning(refJobView)) {
                    actions.add(removeFinishedServiceTaskAction(jobStore, storeTask));
                } else if (shouldRetry && TaskRetryers.shouldRetryNow(referenceTaskHolder, clock)) {
                    createNewTaskAction(refJobView, Optional.of(referenceTaskHolder), Collections.emptyList(), Collections.emptyList()).ifPresent(actions::add);
                }
            }
        } else {
            Task task = referenceTaskHolder.getEntity();
            CallMetadata callMetadata = RECONCILER_CALLMETADATA.toBuilder().withCallReason("Writing runtime state changes to store").build();
            actions.add(storeWriteRetryInterceptor.apply(BasicTaskActions.writeReferenceTaskToStore(jobStore, engine, task.getId(), callMetadata, titusRuntime)));
        }
        // Both current and delayed retries are counted
        if (shouldRetry) {
            allowedNewTasks.decrementAndGet();
        }
    }
    return actions;
}
Also used : Task(com.netflix.titus.api.jobmanager.model.job.Task) ServiceJobTask(com.netflix.titus.api.jobmanager.model.job.ServiceJobTask) TitusChangeAction(com.netflix.titus.master.jobmanager.service.common.action.TitusChangeAction) ChangeAction(com.netflix.titus.common.framework.reconciler.ChangeAction) CallMetadata(com.netflix.titus.api.model.callmetadata.CallMetadata) ServiceJobExt(com.netflix.titus.api.jobmanager.model.job.ext.ServiceJobExt) ArrayList(java.util.ArrayList) EntityHolder(com.netflix.titus.common.framework.reconciler.EntityHolder) ServiceJobTask(com.netflix.titus.api.jobmanager.model.job.ServiceJobTask) TaskState(com.netflix.titus.api.jobmanager.model.job.TaskState)

Example 24 with ServiceJobExt

use of com.netflix.titus.api.jobmanager.model.job.ext.ServiceJobExt in project titus-control-plane by Netflix.

the class DefaultLoadBalancerJobValidatorTest method testValidateMaxLoadBalancers.

@Test
public void testValidateMaxLoadBalancers() throws Exception {
    when(jobOperations.getJob(JOB_ID)).thenReturn(Optional.of(Job.<ServiceJobExt>newBuilder().withId(JOB_ID).withStatus(JobStatus.newBuilder().withState(JobState.Accepted).build()).withJobDescriptor(JobDescriptor.<ServiceJobExt>newBuilder().withExtensions(ServiceJobExt.newBuilder().build()).withContainer(Container.newBuilder().withImage(Image.newBuilder().build()).withContainerResources(ContainerResources.newBuilder().withAllocateIP(true).build()).build()).build()).build()));
    when(loadBalancerValidationConfiguration.getMaxLoadBalancersPerJob()).thenReturn(30);
    for (int i = 0; i < loadBalancerValidationConfiguration.getMaxLoadBalancersPerJob() + 1; i++) {
        loadBalancerStore.addOrUpdateLoadBalancer(new JobLoadBalancer(JOB_ID, "LoadBalancer-" + i), JobLoadBalancer.State.ASSOCIATED).await(TIMEOUT_MS, TimeUnit.MILLISECONDS);
    }
    Throwable thrown = catchThrowable(() -> loadBalancerValidator.validateJobId(JOB_ID));
    assertThat(thrown).isInstanceOf(LoadBalancerException.class);
    assertThat(((LoadBalancerException) thrown).getErrorCode()).isEqualTo(LoadBalancerException.ErrorCode.JobMaxLoadBalancers);
}
Also used : ServiceJobExt(com.netflix.titus.api.jobmanager.model.job.ext.ServiceJobExt) LoadBalancerException(com.netflix.titus.api.loadbalancer.service.LoadBalancerException) AssertionsForClassTypes.catchThrowable(org.assertj.core.api.AssertionsForClassTypes.catchThrowable) JobLoadBalancer(com.netflix.titus.api.loadbalancer.model.JobLoadBalancer) Test(org.junit.Test)

Example 25 with ServiceJobExt

use of com.netflix.titus.api.jobmanager.model.job.ext.ServiceJobExt in project titus-control-plane by Netflix.

the class DefaultAppScaleManager method getJobScalingConstraints.

private JobScalingConstraints getJobScalingConstraints(String policyRefId, String jobId) {
    // V3 API
    if (v3JobOperations == null) {
        return new JobScalingConstraints(0, 0);
    }
    Optional<Job<?>> job = v3JobOperations.getJob(jobId);
    if (job.isPresent()) {
        if (job.get().getJobDescriptor().getExtensions() instanceof ServiceJobExt) {
            ServiceJobExt serviceJobExt = (ServiceJobExt) job.get().getJobDescriptor().getExtensions();
            int minCapacity = serviceJobExt.getCapacity().getMin();
            int maxCapacity = serviceJobExt.getCapacity().getMax();
            return new JobScalingConstraints(minCapacity, maxCapacity);
        } else {
            logger.info("Not a service job (V3) {}", jobId);
            throw AutoScalePolicyException.wrapJobManagerException(policyRefId, JobManagerException.notServiceJob(jobId));
        }
    } else {
        throw AutoScalePolicyException.wrapJobManagerException(policyRefId, JobManagerException.jobNotFound(jobId));
    }
}
Also used : ServiceJobExt(com.netflix.titus.api.jobmanager.model.job.ext.ServiceJobExt) Job(com.netflix.titus.api.jobmanager.model.job.Job)

Aggregations

ServiceJobExt (com.netflix.titus.api.jobmanager.model.job.ext.ServiceJobExt)42 Test (org.junit.Test)17 Capacity (com.netflix.titus.api.jobmanager.model.job.Capacity)13 JobDescriptor (com.netflix.titus.api.jobmanager.model.job.JobDescriptor)13 Job (com.netflix.titus.api.jobmanager.model.job.Job)11 JobFunctions (com.netflix.titus.api.jobmanager.model.job.JobFunctions)8 Task (com.netflix.titus.api.jobmanager.model.job.Task)8 TaskState (com.netflix.titus.api.jobmanager.model.job.TaskState)8 List (java.util.List)7 Assertions.assertThat (org.assertj.core.api.Assertions.assertThat)7 Stopwatch (com.google.common.base.Stopwatch)6 Empty (com.google.protobuf.Empty)6 ServiceJobTask (com.netflix.titus.api.jobmanager.model.job.ServiceJobTask)6 JobManagerException (com.netflix.titus.api.jobmanager.service.JobManagerException)6 TestStreamObserver (com.netflix.titus.testkit.grpc.TestStreamObserver)6 JobState (com.netflix.titus.api.jobmanager.model.job.JobState)5 JobScenarioBuilder (com.netflix.titus.master.jobmanager.service.integration.scenario.JobScenarioBuilder)5 JobDescriptorGenerator.oneTaskServiceJobDescriptor (com.netflix.titus.testkit.model.job.JobDescriptorGenerator.oneTaskServiceJobDescriptor)5 ArrayList (java.util.ArrayList)5 BatchJobExt (com.netflix.titus.api.jobmanager.model.job.ext.BatchJobExt)4