Search in sources :

Example 6 with ServiceJobExt

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

the class JobDescriptorGenerator method oneTaskServiceJobDescriptor.

public static JobDescriptor<ServiceJobExt> oneTaskServiceJobDescriptor() {
    JobDescriptor<ServiceJobExt> jobDescriptor = serviceJobDescriptors().getValue();
    Image imageWithTag = JobModel.newImage().withName("titusops/alpine").withTag("latest").build();
    return JobModel.newJobDescriptor(jobDescriptor).withContainer(JobModel.newContainer(jobDescriptor.getContainer()).withImage(imageWithTag).build()).withDisruptionBudget(DisruptionBudgetGenerator.budget(DisruptionBudgetGenerator.perTaskRelocationLimitPolicy(3), DisruptionBudgetGenerator.hourlyRatePercentage(50), Collections.singletonList(DisruptionBudgetGenerator.officeHourTimeWindow()))).withExtensions(JobModel.newServiceJobExt(jobDescriptor.getExtensions()).withCapacity(Capacity.newBuilder().withMin(0).withDesired(1).withMax(2).build()).withRetryPolicy(JobModel.newImmediateRetryPolicy().withRetries(0).build()).withMigrationPolicy(JobModel.newSystemDefaultMigrationPolicy().build()).withEnabled(true).withServiceJobProcesses(ServiceJobProcesses.newBuilder().build()).build()).build();
}
Also used : ServiceJobExt(com.netflix.titus.api.jobmanager.model.job.ext.ServiceJobExt) Image(com.netflix.titus.api.jobmanager.model.job.Image)

Example 7 with ServiceJobExt

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

the class DefaultV3JobOperations method moveServiceTask.

@Override
public Observable<Void> moveServiceTask(String sourceJobId, String targetJobId, String taskId, CallMetadata callMetadata) {
    return Observable.defer(() -> {
        Pair<ReconciliationEngine<JobManagerReconcilerEvent>, EntityHolder> fromEngineTaskPair = reconciliationFramework.findEngineByChildId(taskId).orElseThrow(() -> JobManagerException.taskNotFound(taskId));
        ReconciliationEngine<JobManagerReconcilerEvent> engineFrom = fromEngineTaskPair.getLeft();
        Job<ServiceJobExt> jobFrom = engineFrom.getReferenceView().getEntity();
        if (!JobFunctions.isServiceJob(jobFrom)) {
            throw JobManagerException.notServiceJob(jobFrom.getId());
        }
        if (!jobFrom.getId().equals(sourceJobId)) {
            throw JobManagerException.taskJobMismatch(taskId, sourceJobId);
        }
        if (jobFrom.getId().equals(targetJobId)) {
            throw JobManagerException.sameJobs(jobFrom.getId());
        }
        ReconciliationEngine<JobManagerReconcilerEvent> engineTo = reconciliationFramework.findEngineByRootId(targetJobId).orElseThrow(() -> JobManagerException.jobNotFound(targetJobId));
        Job<ServiceJobExt> jobTo = engineTo.getReferenceView().getEntity();
        if (!JobFunctions.isServiceJob(jobTo)) {
            throw JobManagerException.notServiceJob(jobTo.getId());
        }
        JobCompatibility compatibility = JobCompatibility.of(jobFrom, jobTo);
        if (featureActivationConfiguration.isMoveTaskValidationEnabled() && !compatibility.isCompatible()) {
            Optional<String> diffReport = ProtobufExt.diffReport(GrpcJobManagementModelConverters.toGrpcJobDescriptor(compatibility.getNormalizedDescriptorFrom()), GrpcJobManagementModelConverters.toGrpcJobDescriptor(compatibility.getNormalizedDescriptorTo()));
            throw JobManagerException.notCompatible(jobFrom, jobTo, diffReport.orElse(""));
        }
        return reconciliationFramework.changeReferenceModel(new MoveTaskBetweenJobsAction(engineFrom, engineTo, taskId, store, callMetadata, versionSupplier), (rootId, modelUpdatesObservable) -> {
            String name;
            String summary;
            if (targetJobId.equals(rootId)) {
                name = "moveTask(to)";
                summary = "Moving a task to this job from job " + jobFrom.getId();
            } else {
                name = "moveTask(from)";
                summary = "Moving a task out of this job to job " + jobTo.getId();
            }
            return new TitusChangeAction(Trigger.API, rootId, null, name, summary, callMetadata) {

                @Override
                public Observable<List<ModelActionHolder>> apply() {
                    return modelUpdatesObservable;
                }
            };
        }, jobFrom.getId(), jobTo.getId());
    });
}
Also used : MoveTaskBetweenJobsAction(com.netflix.titus.master.jobmanager.service.service.action.MoveTaskBetweenJobsAction) EntityHolder(com.netflix.titus.common.framework.reconciler.EntityHolder) JobManagerReconcilerEvent(com.netflix.titus.master.jobmanager.service.event.JobManagerReconcilerEvent) JobCompatibility(com.netflix.titus.api.jobmanager.model.job.JobCompatibility) ReconciliationEngine(com.netflix.titus.common.framework.reconciler.ReconciliationEngine) ServiceJobExt(com.netflix.titus.api.jobmanager.model.job.ext.ServiceJobExt) TitusChangeAction(com.netflix.titus.master.jobmanager.service.common.action.TitusChangeAction) List(java.util.List) ArrayList(java.util.ArrayList)

Example 8 with ServiceJobExt

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

the class BasicServiceJobActions method updateJobEnableStatus.

/**
 * Change job 'enable' status.
 */
public static TitusChangeAction updateJobEnableStatus(ReconciliationEngine<JobManagerReconcilerEvent> engine, boolean enabled, JobStore jobStore, VersionSupplier versionSupplier, CallMetadata callMetadata) {
    return TitusChangeAction.newAction("updateJobCapacityAction").id(engine.getReferenceView().getId()).trigger(V3JobOperations.Trigger.API).summary("Changing job enable status to: %s", enabled).callMetadata(callMetadata).changeWithModelUpdates(self -> {
        Job<ServiceJobExt> serviceJob = engine.getReferenceView().getEntity();
        if (serviceJob.getStatus().getState() != JobState.Accepted) {
            return Observable.error(JobManagerException.jobTerminating(serviceJob));
        }
        Job<ServiceJobExt> updatedJob = VersionSuppliers.nextVersion(JobFunctions.changeJobEnabledStatus(serviceJob, enabled), versionSupplier);
        TitusModelAction modelAction = TitusModelAction.newModelUpdate(self).jobUpdate(jobHolder -> jobHolder.setEntity(updatedJob));
        return jobStore.updateJob(updatedJob).andThen(Observable.just(ModelActionHolder.referenceAndStore(modelAction)));
    });
}
Also used : TitusModelAction(com.netflix.titus.master.jobmanager.service.common.action.TitusModelAction) ServiceJobExt(com.netflix.titus.api.jobmanager.model.job.ext.ServiceJobExt)

Example 9 with ServiceJobExt

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

the class BasicServiceJobActions method updateJobCapacityAction.

/**
 * Update job capacity.
 */
public static TitusChangeAction updateJobCapacityAction(ReconciliationEngine<JobManagerReconcilerEvent> engine, CapacityAttributes capacityAttributes, JobStore jobStore, VersionSupplier versionSupplier, CallMetadata callMetadata, EntitySanitizer entitySanitizer) {
    return TitusChangeAction.newAction("updateJobCapacityAction").id(engine.getReferenceView().getId()).trigger(V3JobOperations.Trigger.API).summary("Changing job capacity to: %s", capacityAttributes).callMetadata(callMetadata).changeWithModelUpdates(self -> {
        Job<ServiceJobExt> serviceJob = engine.getReferenceView().getEntity();
        if (serviceJob.getStatus().getState() != JobState.Accepted) {
            return Observable.error(JobManagerException.jobTerminating(serviceJob));
        }
        Capacity currentCapacity = serviceJob.getJobDescriptor().getExtensions().getCapacity();
        Capacity.Builder newCapacityBuilder = currentCapacity.toBuilder();
        capacityAttributes.getDesired().ifPresent(newCapacityBuilder::withDesired);
        capacityAttributes.getMax().ifPresent(newCapacityBuilder::withMax);
        capacityAttributes.getMin().ifPresent(newCapacityBuilder::withMin);
        if (capacityAttributes.getDesired().isPresent()) {
            newCapacityBuilder.withDesired(capacityAttributes.getDesired().get());
        } else {
            setDesiredBasedOnMinMax(newCapacityBuilder, currentCapacity, capacityAttributes);
        }
        Capacity newCapacity = newCapacityBuilder.build();
        if (currentCapacity.equals(newCapacity)) {
            return Observable.empty();
        }
        // model validation for capacity
        Set<ValidationError> violations = entitySanitizer.validate(newCapacity);
        if (!violations.isEmpty()) {
            return Observable.error(TitusServiceException.invalidArgument(String.format("Current %s", currentCapacity), violations));
        }
        // checking if service job processes allow changes to desired capacity
        if (isDesiredCapacityInvalid(newCapacity, serviceJob)) {
            return Observable.error(JobManagerException.invalidDesiredCapacity(serviceJob.getId(), newCapacity.getDesired(), serviceJob.getJobDescriptor().getExtensions().getServiceJobProcesses()));
        }
        // append callmetadata job attributes
        Job<ServiceJobExt> serviceJobExtCallMetadata = JobFunctions.appendCallMetadataJobAttributes(serviceJob, callMetadata);
        // ready to update job capacity
        Job<ServiceJobExt> updatedJob = VersionSuppliers.nextVersion(JobFunctions.changeServiceJobCapacity(serviceJobExtCallMetadata, newCapacity), versionSupplier);
        TitusModelAction modelAction = TitusModelAction.newModelUpdate(self).jobUpdate(jobHolder -> jobHolder.setEntity(updatedJob));
        return jobStore.updateJob(updatedJob).andThen(Observable.just(ModelActionHolder.referenceAndStore(modelAction)));
    });
}
Also used : TitusModelAction(com.netflix.titus.master.jobmanager.service.common.action.TitusModelAction) Capacity(com.netflix.titus.api.jobmanager.model.job.Capacity) ServiceJobExt(com.netflix.titus.api.jobmanager.model.job.ext.ServiceJobExt) ValidationError(com.netflix.titus.common.model.sanitizer.ValidationError)

Example 10 with ServiceJobExt

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

the class MoveTaskBetweenJobsAction method apply.

@Override
public Observable<Map<String, List<ModelActionHolder>>> apply() {
    return Observable.defer(() -> {
        // Validate data
        Job<ServiceJobExt> jobFrom = engineFrom.getReferenceView().getEntity();
        Job<ServiceJobExt> jobTo = engineTo.getReferenceView().getEntity();
        EntityHolder taskFromReferenceHolder = engineFrom.getReferenceView().findChildById(taskId).orElseThrow(() -> JobManagerException.taskJobMismatch(taskId, jobFrom.getId()));
        if (jobFrom.getStatus().getState() != JobState.Accepted) {
            throw JobManagerException.unexpectedJobState(jobTo, JobState.Accepted);
        }
        Capacity capacityFrom = jobFrom.getJobDescriptor().getExtensions().getCapacity();
        if (capacityFrom.getMin() >= capacityFrom.getDesired()) {
            throw JobManagerException.belowMinCapacity(jobFrom, 1);
        }
        if (jobTo.getStatus().getState() != JobState.Accepted) {
            throw JobManagerException.unexpectedJobState(jobTo, JobState.Accepted);
        }
        Capacity capacityTo = jobTo.getJobDescriptor().getExtensions().getCapacity();
        if (capacityTo.getDesired() >= capacityTo.getMax()) {
            throw JobManagerException.aboveMaxCapacity(jobTo, 1);
        }
        Task taskFromReference = taskFromReferenceHolder.getEntity();
        Optional<EntityHolder> taskFromRunningHolder = engineFrom.getRunningView().findChildById(taskId);
        // Compute new model entities
        // Decrement job size by 1
        Job<ServiceJobExt> updatedJobFrom = nextVersion(JobFunctions.incrementJobSize(jobFrom, -1), versionSupplier);
        Job<ServiceJobExt> updatedJobTo = nextVersion(JobFunctions.incrementJobSize(jobTo, 1), versionSupplier);
        Task updatedReferenceTaskTo = VersionSuppliers.nextVersion(JobFunctions.moveTask(jobFrom.getId(), jobTo.getId(), taskFromReference), versionSupplier);
        // Move the task
        return titusStore.moveTask(updatedJobFrom, updatedJobTo, updatedReferenceTaskTo).andThen(Observable.fromCallable(() -> ImmutableMap.of(jobFrom.getId(), createModelUpdateActionsFrom(updatedJobFrom, updatedJobTo, taskFromReference, callMetadata), jobTo.getId(), createModelUpdateActionsTo(updatedJobFrom, updatedJobTo, updatedReferenceTaskTo, taskFromRunningHolder, callMetadata))));
    });
}
Also used : Task(com.netflix.titus.api.jobmanager.model.job.Task) Capacity(com.netflix.titus.api.jobmanager.model.job.Capacity) ServiceJobExt(com.netflix.titus.api.jobmanager.model.job.ext.ServiceJobExt) EntityHolder(com.netflix.titus.common.framework.reconciler.EntityHolder)

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