Search in sources :

Example 1 with Capacity

use of com.netflix.titus.api.jobmanager.model.job.Capacity 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 2 with Capacity

use of com.netflix.titus.api.jobmanager.model.job.Capacity 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)

Example 3 with Capacity

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

the class DefaultAppScaleManagerTest method mockV3Operations.

private V3JobOperations mockV3Operations(String jobIdOne, String jobIdTwo) {
    V3JobOperations v3JobOperations = mock(V3JobOperations.class);
    // FIXME Use JobGenerator instead of mocking.
    Job jobOne = mock(Job.class);
    when(jobOne.getId()).thenReturn(jobIdOne);
    JobDescriptor jobDescriptorOne = mock(JobDescriptor.class);
    ServiceJobExt serviceJobExtOne = mock(ServiceJobExt.class);
    JobGroupInfo jobGroupInfoOne = buildMockJobGroupInfo(jobIdOne);
    Capacity capacityOne = mock(Capacity.class);
    when(capacityOne.getMax()).thenReturn(10);
    when(capacityOne.getMin()).thenReturn(1);
    when(serviceJobExtOne.getCapacity()).thenReturn(capacityOne);
    when(jobDescriptorOne.getExtensions()).thenReturn(serviceJobExtOne);
    when(jobOne.getJobDescriptor()).thenReturn(jobDescriptorOne);
    when(jobDescriptorOne.getJobGroupInfo()).thenReturn(jobGroupInfoOne);
    when(jobDescriptorOne.getApplicationName()).thenReturn("testApp1");
    Job jobTwo = mock(Job.class);
    when(jobTwo.getId()).thenReturn(jobIdTwo);
    JobDescriptor jobDescriptorTwo = mock(JobDescriptor.class);
    ServiceJobExt serviceJobExtTwo = mock(ServiceJobExt.class);
    Capacity capacityJobTwo = mock(Capacity.class);
    when(capacityJobTwo.getMin()).thenAnswer(new Answer<Integer>() {

        private int count = 0;

        @Override
        public Integer answer(InvocationOnMock invocation) throws Throwable {
            if (count++ < 2) {
                return 1;
            } else {
                return 5;
            }
        }
    });
    when(capacityJobTwo.getMax()).thenAnswer(new Answer<Integer>() {

        private int count = 0;

        @Override
        public Integer answer(InvocationOnMock invocation) throws Throwable {
            if (count++ < 2) {
                return 10;
            } else {
                return 15;
            }
        }
    });
    when(serviceJobExtTwo.getCapacity()).thenReturn(capacityJobTwo);
    when(jobDescriptorTwo.getExtensions()).thenReturn(serviceJobExtTwo);
    when(jobDescriptorTwo.getJobGroupInfo()).thenReturn(jobGroupInfoOne);
    when(jobDescriptorTwo.getApplicationName()).thenReturn("testApp2");
    when(jobTwo.getJobDescriptor()).thenReturn(jobDescriptorTwo);
    when(jobTwo.getStatus()).thenReturn(JobModel.newJobStatus().withState(JobState.Accepted).build());
    when(v3JobOperations.getJob(jobIdOne)).thenReturn(Optional.of(jobOne));
    when(v3JobOperations.getJob(jobIdTwo)).thenReturn(Optional.of(jobTwo));
    JobManagerEvent<?> jobUpdateEvent = JobUpdateEvent.newJob(jobTwo, callMetadata);
    when(v3JobOperations.observeJobs()).thenAnswer(invocation -> Observable.from(asList(jobUpdateEvent)));
    return v3JobOperations;
}
Also used : V3JobOperations(com.netflix.titus.api.jobmanager.service.V3JobOperations) JobDescriptor(com.netflix.titus.api.jobmanager.model.job.JobDescriptor) Capacity(com.netflix.titus.api.jobmanager.model.job.Capacity) InvocationOnMock(org.mockito.invocation.InvocationOnMock) ServiceJobExt(com.netflix.titus.api.jobmanager.model.job.ext.ServiceJobExt) JobGroupInfo(com.netflix.titus.api.jobmanager.model.job.JobGroupInfo) Job(com.netflix.titus.api.jobmanager.model.job.Job)

Example 4 with Capacity

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

the class DefaultAppScaleManagerTest method mockV3OperationsForJobs.

private V3JobOperations mockV3OperationsForJobs(List<String> jobIds) {
    V3JobOperations v3JobOperations = mock(V3JobOperations.class);
    for (String jobId : jobIds) {
        // FIXME Use JobGenerator instead of mocking.
        Job job = mock(Job.class);
        when(job.getId()).thenReturn(jobId);
        JobDescriptor jobDescriptorOne = mock(JobDescriptor.class);
        ServiceJobExt serviceJobExtOne = mock(ServiceJobExt.class);
        JobGroupInfo jobGroupInfoOne = buildMockJobGroupInfo(jobId);
        Capacity capacityOne = mock(Capacity.class);
        when(capacityOne.getMax()).thenReturn(10);
        when(capacityOne.getMin()).thenReturn(1);
        when(serviceJobExtOne.getCapacity()).thenReturn(capacityOne);
        when(jobDescriptorOne.getExtensions()).thenReturn(serviceJobExtOne);
        when(job.getJobDescriptor()).thenReturn(jobDescriptorOne);
        when(jobDescriptorOne.getJobGroupInfo()).thenReturn(jobGroupInfoOne);
        when(jobDescriptorOne.getApplicationName()).thenReturn("testApp");
        when(v3JobOperations.getJob(jobId)).thenReturn(Optional.of(job));
        JobManagerEvent<?> jobUpdateEvent = JobUpdateEvent.newJob(job, callMetadata);
        when(v3JobOperations.observeJobs()).thenAnswer(invocation -> Observable.from(asList(jobUpdateEvent)));
    }
    return v3JobOperations;
}
Also used : V3JobOperations(com.netflix.titus.api.jobmanager.service.V3JobOperations) JobDescriptor(com.netflix.titus.api.jobmanager.model.job.JobDescriptor) Capacity(com.netflix.titus.api.jobmanager.model.job.Capacity) ServiceJobExt(com.netflix.titus.api.jobmanager.model.job.ext.ServiceJobExt) JobGroupInfo(com.netflix.titus.api.jobmanager.model.job.JobGroupInfo) Job(com.netflix.titus.api.jobmanager.model.job.Job)

Example 5 with Capacity

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

the class JobScenarioBuilder method updateJobCapacityMin.

public JobScenarioBuilder updateJobCapacityMin(int min, int expectedMax, int expectedDesired) {
    logger.info("[{}] Changing job {} capacity min to {}...", discoverActiveTest(), jobId, min);
    Stopwatch stopWatch = Stopwatch.createStarted();
    TestStreamObserver<Empty> responseObserver = new TestStreamObserver<>();
    client.updateJobCapacityWithOptionalAttributes(JobCapacityUpdateWithOptionalAttributes.newBuilder().setJobId(jobId).setJobCapacityWithOptionalAttributes(JobCapacityWithOptionalAttributes.newBuilder().setMin(UInt32Value.newBuilder().setValue(min).build()).build()).build(), responseObserver);
    rethrow(() -> responseObserver.awaitDone(TIMEOUT_MS, TimeUnit.MILLISECONDS));
    expectJobUpdateEvent(job -> {
        ServiceJobExt ext = (ServiceJobExt) job.getJobDescriptor().getExtensions();
        Capacity capacity = ext.getCapacity();
        return capacity.getMin() == min && capacity.getMax() == expectedMax && capacity.getDesired() == expectedDesired;
    }, "Job capacity update did not complete in time");
    logger.info("[{}] Job {} scaled to new min size in {}ms", discoverActiveTest(), jobId, stopWatch.elapsed(TimeUnit.MILLISECONDS));
    return this;
}
Also used : Empty(com.google.protobuf.Empty) TestStreamObserver(com.netflix.titus.testkit.grpc.TestStreamObserver) GrpcJobManagementModelConverters.toGrpcCapacity(com.netflix.titus.runtime.endpoint.v3.grpc.GrpcJobManagementModelConverters.toGrpcCapacity) Capacity(com.netflix.titus.api.jobmanager.model.job.Capacity) ServiceJobExt(com.netflix.titus.api.jobmanager.model.job.ext.ServiceJobExt) Stopwatch(com.google.common.base.Stopwatch)

Aggregations

Capacity (com.netflix.titus.api.jobmanager.model.job.Capacity)18 ServiceJobExt (com.netflix.titus.api.jobmanager.model.job.ext.ServiceJobExt)14 Job (com.netflix.titus.api.jobmanager.model.job.Job)6 JobDescriptor (com.netflix.titus.api.jobmanager.model.job.JobDescriptor)6 JobFunctions.changeServiceJobCapacity (com.netflix.titus.api.jobmanager.model.job.JobFunctions.changeServiceJobCapacity)6 Test (org.junit.Test)6 JobFunctions (com.netflix.titus.api.jobmanager.model.job.JobFunctions)4 JobState (com.netflix.titus.api.jobmanager.model.job.JobState)4 ServiceJobProcesses (com.netflix.titus.api.jobmanager.model.job.ServiceJobProcesses)4 TaskState (com.netflix.titus.api.jobmanager.model.job.TaskState)4 TaskStatus (com.netflix.titus.api.jobmanager.model.job.TaskStatus)4 JobManagerException (com.netflix.titus.api.jobmanager.service.JobManagerException)4 Stopwatch (com.google.common.base.Stopwatch)3 Empty (com.google.protobuf.Empty)3 JobGroupInfo (com.netflix.titus.api.jobmanager.model.job.JobGroupInfo)3 V3JobOperations (com.netflix.titus.api.jobmanager.service.V3JobOperations)3 RecordingCodeInvariants (com.netflix.titus.common.util.code.RecordingCodeInvariants)3 JobScenarioBuilder (com.netflix.titus.master.jobmanager.service.integration.scenario.JobScenarioBuilder)3 JobsScenarioBuilder (com.netflix.titus.master.jobmanager.service.integration.scenario.JobsScenarioBuilder)3 CONCURRENT_STORE_UPDATE_LIMIT (com.netflix.titus.master.jobmanager.service.integration.scenario.JobsScenarioBuilder.CONCURRENT_STORE_UPDATE_LIMIT)3