use of com.yahoo.config.provision.OutOfCapacityException in project vespa by vespa-engine.
the class SessionPreparer method prepare.
/**
* Prepares a session (validates, builds model, writes to zookeeper and distributes files)
*
* @param context Contains classes needed to read/write session data.
* @param logger For storing logs returned in response to client.
* @param params parameters controlling behaviour of prepare.
* @param currentActiveApplicationSet Set of currently active applications.
* @param tenantPath Zookeeper path for the tenant for this session
* @return the config change actions that must be done to handle the activation of the models prepared.
*/
public ConfigChangeActions prepare(SessionContext context, DeployLogger logger, PrepareParams params, Optional<ApplicationSet> currentActiveApplicationSet, Path tenantPath, Instant now) {
Preparation preparation = new Preparation(context, logger, params, currentActiveApplicationSet, tenantPath);
preparation.preprocess();
try {
AllocatedHosts allocatedHosts = preparation.buildModels(now);
preparation.makeResult(allocatedHosts);
if (!params.isDryRun()) {
preparation.writeStateZK();
preparation.writeRotZK();
preparation.distribute();
}
log.log(LogLevel.DEBUG, () -> "time used " + params.getTimeoutBudget().timesUsed() + " : " + params.getApplicationId());
return preparation.result();
} catch (OutOfCapacityException e) {
throw e;
} catch (IllegalArgumentException e) {
throw new InvalidApplicationException("Invalid application package", e);
}
}
use of com.yahoo.config.provision.OutOfCapacityException in project vespa by vespa-engine.
the class ModelsBuilder method buildModels.
/**
* Builds all applicable model versions
*
* @param allocatedHosts the newest version (major and minor) (which is loaded first) decides the allocated hosts
* and assigns to this SettableOptional such that it can be used after this method returns
*/
public List<MODELRESULT> buildModels(ApplicationId applicationId, com.yahoo.component.Version wantedNodeVespaVersion, ApplicationPackage applicationPackage, SettableOptional<AllocatedHosts> allocatedHosts, Instant now) {
Set<Version> versions = modelFactoryRegistry.allVersions();
// If the application specifies a major, load models only for that
Optional<Integer> requestedMajorVersion = applicationPackage.getMajorVersion();
if (requestedMajorVersion.isPresent())
versions = filterByMajorVersion(requestedMajorVersion.get(), versions);
// Load models by one major version at the time as new major versions are allowed to be non-loadable
// in the case where an existing application is incompatible with a new major version
// (which is possible by the definition of major)
List<Integer> majorVersions = versions.stream().map(Version::getMajor).distinct().sorted(Comparator.reverseOrder()).collect(Collectors.toList());
List<MODELRESULT> allApplicationModels = new ArrayList<>();
for (int i = 0; i < majorVersions.size(); i++) {
try {
allApplicationModels.addAll(buildModelVersion(filterByMajorVersion(majorVersions.get(i), versions), applicationId, wantedNodeVespaVersion, applicationPackage, allocatedHosts, now));
// skip old config models if requested after we have found a major version which works
if (allApplicationModels.size() > 0 && allApplicationModels.get(0).getModel().skipOldConfigModels(now))
break;
} catch (OutOfCapacityException | ApplicationLockException e) {
// caused by the state of the system, not the model version/application combination
throw e;
} catch (RuntimeException e) {
boolean isOldestMajor = i == majorVersions.size() - 1;
if (isOldestMajor) {
if (e instanceof NullPointerException || e instanceof NoSuchElementException) {
log.log(LogLevel.WARNING, "Unexpected error when building model ", e);
throw new InternalServerException(applicationId + ": Error loading model", e);
} else {
log.log(LogLevel.WARNING, "Input error when building model ", e);
throw new IllegalArgumentException(applicationId + ": Error loading model", e);
}
} else {
log.log(Level.INFO, applicationId + ": Skipping major version " + majorVersions.get(i), e);
}
}
}
return allApplicationModels;
}
use of com.yahoo.config.provision.OutOfCapacityException in project vespa by vespa-engine.
the class SessionPrepareHandlerTest method test_out_of_capacity_response.
@Test
public void test_out_of_capacity_response() throws InterruptedException, IOException {
String message = "Internal error";
SessionThrowingException session = new SessionThrowingException(new OutOfCapacityException(message));
localRepo.addSession(session);
HttpResponse response = createHandler().handle(SessionHandlerTest.createTestRequest(pathPrefix, HttpRequest.Method.PUT, Cmd.PREPARED, 1L));
assertEquals(400, response.getStatus());
Slime data = getData(response);
assertThat(data.get().field("error-code").asString(), is(HttpErrorResponse.errorCodes.OUT_OF_CAPACITY.name()));
assertThat(data.get().field("message").asString(), is(message));
}
use of com.yahoo.config.provision.OutOfCapacityException in project vespa by vespa-engine.
the class DynamicDockerProvisioningTest method spare_capacity_used_only_when_replacement.
@Test
public void spare_capacity_used_only_when_replacement() {
// Use spare capacity only when replacement (i.e one node is failed)
// Test should allocate as much capacity as possible, verify that it is not possible to allocate one more unit
// Verify that there is still capacity (available spare)
// Fail one node and redeploy, Verify that one less node is empty.
ProvisioningTester tester = new ProvisioningTester(new Zone(Environment.prod, RegionName.from("us-east")), flavorsConfig());
// Only run test if there _is_ spare capacity
if (tester.provisioner().getSpareCapacityProd() == 0) {
return;
}
// Setup test
ApplicationId application1 = tester.makeApplicationId();
tester.makeReadyNodes(5, "host-small", NodeType.host, 32);
deployZoneApp(tester);
Flavor flavor = tester.nodeRepository().getAvailableFlavors().getFlavorOrThrow("d-3");
// Deploy initial state (can max deploy 3 nodes due to redundancy requirements)
List<HostSpec> hosts = tester.prepare(application1, ClusterSpec.request(ClusterSpec.Type.content, ClusterSpec.Id.from("myContent"), Version.fromString("6.100"), false), 3, 1, flavor.canonicalName());
tester.activate(application1, ImmutableSet.copyOf(hosts));
DockerHostCapacity capacity = new DockerHostCapacity(tester.nodeRepository().getNodes(Node.State.values()));
assertThat(capacity.freeCapacityInFlavorEquivalence(flavor), greaterThan(0));
List<Node> initialSpareCapacity = findSpareCapacity(tester);
assertThat(initialSpareCapacity.size(), is(2));
try {
hosts = tester.prepare(application1, ClusterSpec.request(ClusterSpec.Type.content, ClusterSpec.Id.from("myContent"), Version.fromString("6.100"), false), 4, 1, flavor.canonicalName());
fail("Was able to deploy with 4 nodes, should not be able to use spare capacity");
} catch (OutOfCapacityException e) {
}
tester.fail(hosts.get(0));
hosts = tester.prepare(application1, ClusterSpec.request(ClusterSpec.Type.content, ClusterSpec.Id.from("myContent"), Version.fromString("6.100"), false), 3, 1, flavor.canonicalName());
tester.activate(application1, ImmutableSet.copyOf(hosts));
List<Node> finalSpareCapacity = findSpareCapacity(tester);
assertThat(finalSpareCapacity.size(), is(1));
}
use of com.yahoo.config.provision.OutOfCapacityException in project vespa by vespa-engine.
the class ProvisioningTest method application_deployment_above_then_at_capacity_limit.
@Test
public void application_deployment_above_then_at_capacity_limit() {
ProvisioningTester tester = new ProvisioningTester(new Zone(Environment.prod, RegionName.from("us-east")));
ApplicationId application1 = tester.makeApplicationId();
tester.makeReadyNodes(5, "default");
// deploy
SystemState state1 = prepare(application1, 2, 0, 3, 0, "default", tester);
tester.activate(application1, state1.allHosts);
// redeploy a too large application
try {
SystemState state2 = prepare(application1, 3, 0, 3, 0, "default", tester);
fail("Expected out of capacity exception");
} catch (OutOfCapacityException expected) {
}
// deploy first state again
SystemState state3 = prepare(application1, 2, 0, 3, 0, "default", tester);
tester.activate(application1, state3.allHosts);
}
Aggregations