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)));
});
}
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))));
});
}
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;
}
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;
}
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;
}
Aggregations