summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--config-application-package/src/main/java/com/yahoo/config/model/application/provider/DeployData.java2
-rw-r--r--config-application-package/src/test/java/com/yahoo/config/application/OverrideProcessorTest.java3
-rw-r--r--config-model-api/src/main/java/com/yahoo/config/application/api/ApplicationFile.java2
-rw-r--r--config-model-api/src/main/java/com/yahoo/config/application/api/ApplicationPackage.java18
-rw-r--r--config-model-api/src/main/java/com/yahoo/config/model/api/HostInfo.java1
-rw-r--r--config-model-api/src/main/java/com/yahoo/config/model/api/Model.java31
-rw-r--r--config-model-api/src/main/java/com/yahoo/config/model/api/ModelContext.java8
-rw-r--r--config-model-api/src/main/java/com/yahoo/config/model/api/ModelState.java2
-rw-r--r--config-model/src/main/java/com/yahoo/config/model/provision/HostsXmlProvisioner.java1
-rw-r--r--config-model/src/main/java/com/yahoo/config/model/test/MockApplicationPackage.java1
-rw-r--r--config-model/src/main/java/com/yahoo/vespa/model/HostResource.java2
-rw-r--r--config-model/src/main/java/com/yahoo/vespa/model/VespaModel.java16
-rw-r--r--config-model/src/main/java/com/yahoo/vespa/model/VespaModelFactory.java20
-rw-r--r--config-model/src/test/java/com/yahoo/config/model/provision/HostSpecTest.java5
-rw-r--r--config-model/src/test/java/com/yahoo/vespa/model/test/VespaModelTestCase.java4
-rw-r--r--config-provisioning/src/main/java/com/yahoo/config/provision/AllocatedHosts.java116
-rw-r--r--config-provisioning/src/main/java/com/yahoo/config/provision/HostSpec.java14
-rw-r--r--config-provisioning/src/main/java/com/yahoo/config/provision/ProvisionInfo.java84
-rw-r--r--config-provisioning/src/main/java/com/yahoo/config/provision/Provisioner.java3
-rw-r--r--config-provisioning/src/test/java/com/yahoo/config/provision/AllocatedHostsTest.java52
-rw-r--r--config-provisioning/src/test/java/com/yahoo/config/provision/ProvisionInfoTest.java66
-rw-r--r--configserver/src/main/java/com/yahoo/vespa/config/server/GlobalComponentRegistry.java3
-rw-r--r--configserver/src/main/java/com/yahoo/vespa/config/server/InjectedGlobalComponentRegistry.java3
-rw-r--r--configserver/src/main/java/com/yahoo/vespa/config/server/application/TenantApplications.java3
-rw-r--r--configserver/src/main/java/com/yahoo/vespa/config/server/application/ZKTenantApplications.java3
-rw-r--r--configserver/src/main/java/com/yahoo/vespa/config/server/deploy/Deployment.java2
-rw-r--r--configserver/src/main/java/com/yahoo/vespa/config/server/deploy/ModelContextImpl.java7
-rw-r--r--configserver/src/main/java/com/yahoo/vespa/config/server/deploy/ZooKeeperClient.java173
-rw-r--r--configserver/src/main/java/com/yahoo/vespa/config/server/deploy/ZooKeeperDeployer.java16
-rw-r--r--configserver/src/main/java/com/yahoo/vespa/config/server/host/HostRegistry.java1
-rw-r--r--configserver/src/main/java/com/yahoo/vespa/config/server/modelfactory/ActivatedModelsBuilder.java27
-rw-r--r--configserver/src/main/java/com/yahoo/vespa/config/server/modelfactory/ModelFactoryRegistry.java2
-rw-r--r--configserver/src/main/java/com/yahoo/vespa/config/server/modelfactory/ModelsBuilder.java79
-rw-r--r--configserver/src/main/java/com/yahoo/vespa/config/server/modelfactory/PreparedModelsBuilder.java31
-rw-r--r--configserver/src/main/java/com/yahoo/vespa/config/server/provision/HostProvisionerProvider.java8
-rw-r--r--configserver/src/main/java/com/yahoo/vespa/config/server/provision/ProvisionerAdapter.java4
-rw-r--r--configserver/src/main/java/com/yahoo/vespa/config/server/provision/StaticProvisioner.java35
-rw-r--r--configserver/src/main/java/com/yahoo/vespa/config/server/session/LocalSession.java11
-rw-r--r--configserver/src/main/java/com/yahoo/vespa/config/server/session/LocalSessionRepo.java1
-rw-r--r--configserver/src/main/java/com/yahoo/vespa/config/server/session/RemoteSession.java5
-rw-r--r--configserver/src/main/java/com/yahoo/vespa/config/server/session/RemoteSessionFactory.java3
-rw-r--r--configserver/src/main/java/com/yahoo/vespa/config/server/session/SessionContext.java3
-rw-r--r--configserver/src/main/java/com/yahoo/vespa/config/server/session/SessionFactoryImpl.java3
-rw-r--r--configserver/src/main/java/com/yahoo/vespa/config/server/session/SessionPreparer.java66
-rw-r--r--configserver/src/main/java/com/yahoo/vespa/config/server/session/SessionZooKeeperClient.java13
-rw-r--r--configserver/src/main/java/com/yahoo/vespa/config/server/tenant/TenantBuilder.java3
-rw-r--r--configserver/src/main/java/com/yahoo/vespa/config/server/tenant/Tenants.java6
-rw-r--r--configserver/src/main/java/com/yahoo/vespa/config/server/zookeeper/ConfigCurator.java2
-rw-r--r--configserver/src/main/java/com/yahoo/vespa/config/server/zookeeper/ZKApplicationPackage.java103
-rw-r--r--configserver/src/main/java/com/yahoo/vespa/config/server/zookeeper/ZKLiveApp.java7
-rw-r--r--configserver/src/test/java/com/yahoo/vespa/config/server/ModelStub.java4
-rw-r--r--configserver/src/test/java/com/yahoo/vespa/config/server/application/MockModel.java4
-rw-r--r--configserver/src/test/java/com/yahoo/vespa/config/server/deploy/DeployTester.java34
-rw-r--r--configserver/src/test/java/com/yahoo/vespa/config/server/deploy/HostedDeployTest.java26
-rw-r--r--configserver/src/test/java/com/yahoo/vespa/config/server/deploy/RedeployTest.java2
-rw-r--r--configserver/src/test/java/com/yahoo/vespa/config/server/deploy/ZooKeeperClientTest.java27
-rw-r--r--configserver/src/test/java/com/yahoo/vespa/config/server/deploy/ZooKeeperDeployerTest.java3
-rw-r--r--configserver/src/test/java/com/yahoo/vespa/config/server/http/v2/SessionActiveHandlerTest.java8
-rw-r--r--configserver/src/test/java/com/yahoo/vespa/config/server/provision/StaticProvisionerTest.java4
-rw-r--r--configserver/src/test/java/com/yahoo/vespa/config/server/session/LocalSessionTest.java18
-rw-r--r--configserver/src/test/java/com/yahoo/vespa/config/server/session/MockSessionZKClient.java15
-rw-r--r--configserver/src/test/java/com/yahoo/vespa/config/server/tenant/TenantRequestHandlerTest.java3
-rw-r--r--configserver/src/test/java/com/yahoo/vespa/config/server/zookeeper/ZKApplicationPackageTest.java11
-rw-r--r--node-repository/src/main/java/com/yahoo/vespa/hosted/provision/provisioning/CapacityPolicies.java5
-rw-r--r--vespajlib/src/main/java/com/yahoo/lang/SettableOptional.java41
65 files changed, 748 insertions, 531 deletions
diff --git a/config-application-package/src/main/java/com/yahoo/config/model/application/provider/DeployData.java b/config-application-package/src/main/java/com/yahoo/config/model/application/provider/DeployData.java
index d9a784a2dc5..f48dffecb27 100644
--- a/config-application-package/src/main/java/com/yahoo/config/model/application/provider/DeployData.java
+++ b/config-application-package/src/main/java/com/yahoo/config/model/application/provider/DeployData.java
@@ -5,7 +5,6 @@ package com.yahoo.config.model.application.provider;
* A class for holding values generated or computed during deployment
*
* @author hmusum
- * @since 5.1.11
*/
public class DeployData {
@@ -57,4 +56,5 @@ public class DeployData {
public String getApplicationName() {
return applicationName;
}
+
}
diff --git a/config-application-package/src/test/java/com/yahoo/config/application/OverrideProcessorTest.java b/config-application-package/src/test/java/com/yahoo/config/application/OverrideProcessorTest.java
index b80372ec9ff..32a1c4f847f 100644
--- a/config-application-package/src/test/java/com/yahoo/config/application/OverrideProcessorTest.java
+++ b/config-application-package/src/test/java/com/yahoo/config/application/OverrideProcessorTest.java
@@ -15,8 +15,7 @@ import java.io.IOException;
import java.io.StringReader;
/**
- * @author lulf
- * @since 5.22
+ * @author Ulf Lilleengen
*/
public class OverrideProcessorTest {
diff --git a/config-model-api/src/main/java/com/yahoo/config/application/api/ApplicationFile.java b/config-model-api/src/main/java/com/yahoo/config/application/api/ApplicationFile.java
index bcc8d222ca5..0384a5c7a1c 100644
--- a/config-model-api/src/main/java/com/yahoo/config/application/api/ApplicationFile.java
+++ b/config-model-api/src/main/java/com/yahoo/config/application/api/ApplicationFile.java
@@ -11,7 +11,7 @@ import java.util.List;
* An application file represents a file within an application package. This class can be used to traverse the entire
* application package file structure, as well as read and write files to it, and create directories.
*
- * @author Ulf Lillengen
+ * @author Ulf Lilleengen
*/
public abstract class ApplicationFile implements Comparable<ApplicationFile> {
diff --git a/config-model-api/src/main/java/com/yahoo/config/application/api/ApplicationPackage.java b/config-model-api/src/main/java/com/yahoo/config/application/api/ApplicationPackage.java
index 795e87b7690..c1a786194a2 100644
--- a/config-model-api/src/main/java/com/yahoo/config/application/api/ApplicationPackage.java
+++ b/config-model-api/src/main/java/com/yahoo/config/application/api/ApplicationPackage.java
@@ -1,7 +1,7 @@
// Copyright 2017 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
package com.yahoo.config.application.api;
-import com.yahoo.config.provision.ProvisionInfo;
+import com.yahoo.config.provision.AllocatedHosts;
import com.yahoo.config.provision.Version;
import com.yahoo.config.provision.Zone;
import com.yahoo.path.Path;
@@ -28,7 +28,7 @@ import java.util.jar.JarFile;
*
* Anyone wanting to access application data should use this interface.
*
- * @author vegardh
+ * @author Vegard Havdal
*/
public interface ApplicationPackage {
@@ -228,10 +228,22 @@ public interface ApplicationPackage {
throw new UnsupportedOperationException("This application package cannot write its metadata");
}
- default Map<Version, ProvisionInfo> getProvisionInfoMap() {
+ /**
+ * Returns the single host allocation info of this, or an empty map if no allocation is available
+ *
+ * @deprecated please use #getAllocatedHosts
+ */
+ // TODO: Remove on Vespa 7
+ @Deprecated
+ default Map<Version, AllocatedHosts> getProvisionInfoMap() {
return Collections.emptyMap();
}
+ /** Returns the host allocation info of this, or empty if no allocation is available */
+ default Optional<AllocatedHosts> getAllocatedHosts() {
+ return Optional.empty();
+ }
+
default Map<Version, FileRegistry> getFileRegistryMap() {
return Collections.emptyMap();
}
diff --git a/config-model-api/src/main/java/com/yahoo/config/model/api/HostInfo.java b/config-model-api/src/main/java/com/yahoo/config/model/api/HostInfo.java
index dcb875d02b5..589aee50d7c 100644
--- a/config-model-api/src/main/java/com/yahoo/config/model/api/HostInfo.java
+++ b/config-model-api/src/main/java/com/yahoo/config/model/api/HostInfo.java
@@ -7,7 +7,6 @@ import java.util.Collection;
* Contains information about a host and what services are running on it.
*
* @author lulf
- * @since 5.37
*/
public class HostInfo {
diff --git a/config-model-api/src/main/java/com/yahoo/config/model/api/Model.java b/config-model-api/src/main/java/com/yahoo/config/model/api/Model.java
index 0c038077fe4..f8f749ef070 100644
--- a/config-model-api/src/main/java/com/yahoo/config/model/api/Model.java
+++ b/config-model-api/src/main/java/com/yahoo/config/model/api/Model.java
@@ -1,12 +1,11 @@
// Copyright 2017 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
package com.yahoo.config.model.api;
-import com.yahoo.config.provision.ProvisionInfo;
+import com.yahoo.config.provision.AllocatedHosts;
import com.yahoo.vespa.config.ConfigKey;
import com.yahoo.vespa.config.ConfigPayload;
import com.yahoo.vespa.config.buildergen.ConfigDefinition;
-import java.time.Clock;
import java.time.Instant;
import java.util.Optional;
import java.util.Set;
@@ -16,8 +15,7 @@ import java.util.Collection;
* A {@link Model} represents the interface towards the model of an entire tenant, and defines methods
* for querying this model.
*
- * @author lulf
- * @since 5.1
+ * @author Ulf Lilleengen
*/
public interface Model {
@@ -60,9 +58,20 @@ public interface Model {
/**
* Get the provisioning info for this model.
- * @return {@link ProvisionInfo} instance, if available.
+ *
+ * @return {@link AllocatedHosts} instance, if available.
+ * @deprecated use allocatedHosts
*/
- Optional<ProvisionInfo> getProvisionInfo();
+ @Deprecated
+ // TODO: Remove this (and the implementation below) when no version older than 6.143 is deployed anywhere
+ default Optional<AllocatedHosts> getProvisionInfo() {
+ return Optional.of(allocatedHosts());
+ }
+
+ @SuppressWarnings("deprecation")
+ default AllocatedHosts allocatedHosts() {
+ return getProvisionInfo().get();
+ }
/**
* Returns whether this application allows serving config request for a different version.
@@ -71,11 +80,6 @@ public interface Model {
*/
default boolean allowModelVersionMismatch(Instant now) { return false; }
- /** @deprecated pass now. */
- // TODO: Remove this when no version older than 6.115 is deployed anywhere
- @Deprecated
- default boolean allowModelVersionMismatch() { return allowModelVersionMismatch(Clock.systemUTC().instant()); }
-
/**
* Returns whether old config models should be loaded (default) or not.
* Skipping old config models is a validation override which is useful when the old model
@@ -88,9 +92,4 @@ public interface Model {
*/
default boolean skipOldConfigModels(Instant now) { return false; }
- /** @deprecated pass now. */
- // TODO: Remove this when no version older than 6.115 is deployed anywhere
- @Deprecated
- default boolean skipOldConfigModels() { return skipOldConfigModels(Clock.systemUTC().instant()); }
-
}
diff --git a/config-model-api/src/main/java/com/yahoo/config/model/api/ModelContext.java b/config-model-api/src/main/java/com/yahoo/config/model/api/ModelContext.java
index 5afc570d81b..5b79415c132 100644
--- a/config-model-api/src/main/java/com/yahoo/config/model/api/ModelContext.java
+++ b/config-model-api/src/main/java/com/yahoo/config/model/api/ModelContext.java
@@ -17,7 +17,7 @@ import java.util.Set;
/**
* Model context containing state provided to model factories.
*
- * @author lulf
+ * @author Ulf Lilleengen
*/
public interface ModelContext {
@@ -31,11 +31,6 @@ public interface ModelContext {
Properties properties();
default Optional<File> appDir() { return Optional.empty();}
- /** @deprecated TODO: Remove this when no config models older than 6.98 are used */
- @SuppressWarnings("unused")
- @Deprecated
- default Optional<com.yahoo.config.provision.Version> vespaVersion() { return Optional.empty(); }
-
/** The Vespa version this model is built for */
Version modelVespaVersion();
@@ -50,4 +45,5 @@ public interface ModelContext {
Zone zone();
Set<Rotation> rotations();
}
+
}
diff --git a/config-model-api/src/main/java/com/yahoo/config/model/api/ModelState.java b/config-model-api/src/main/java/com/yahoo/config/model/api/ModelState.java
index 10153ca07df..c6ac913ad14 100644
--- a/config-model-api/src/main/java/com/yahoo/config/model/api/ModelState.java
+++ b/config-model-api/src/main/java/com/yahoo/config/model/api/ModelState.java
@@ -5,5 +5,7 @@ package com.yahoo.config.model.api;
* @author lulf
*/
public interface ModelState {
+
Model getModel();
+
}
diff --git a/config-model/src/main/java/com/yahoo/config/model/provision/HostsXmlProvisioner.java b/config-model/src/main/java/com/yahoo/config/model/provision/HostsXmlProvisioner.java
index 85f05116e5b..f909f3864da 100644
--- a/config-model/src/main/java/com/yahoo/config/model/provision/HostsXmlProvisioner.java
+++ b/config-model/src/main/java/com/yahoo/config/model/provision/HostsXmlProvisioner.java
@@ -14,7 +14,6 @@ import java.util.List;
* application if one exists. Pre-condition: A valid hosts file.
*
* @author hmusum
- * @since 5.11
*/
public class HostsXmlProvisioner implements HostProvisioner {
diff --git a/config-model/src/main/java/com/yahoo/config/model/test/MockApplicationPackage.java b/config-model/src/main/java/com/yahoo/config/model/test/MockApplicationPackage.java
index 133d94c745b..8b97eb2503e 100644
--- a/config-model/src/main/java/com/yahoo/config/model/test/MockApplicationPackage.java
+++ b/config-model/src/main/java/com/yahoo/config/model/test/MockApplicationPackage.java
@@ -25,6 +25,7 @@ import java.util.*;
* @author tonytv
*/
public class MockApplicationPackage implements ApplicationPackage {
+
public static final String MUSIC_SEARCHDEFINITION = createSearchDefinition("music", "foo");
public static final String BOOK_SEARCHDEFINITION = createSearchDefinition("book", "bar");
diff --git a/config-model/src/main/java/com/yahoo/vespa/model/HostResource.java b/config-model/src/main/java/com/yahoo/vespa/model/HostResource.java
index bc890755ca9..5e74a2ebc8a 100644
--- a/config-model/src/main/java/com/yahoo/vespa/model/HostResource.java
+++ b/config-model/src/main/java/com/yahoo/vespa/model/HostResource.java
@@ -22,7 +22,7 @@ import java.util.stream.Collectors;
* TODO: Merge with {@link Host}
* Host resources are ordered by their host order.
*
- * @author Ulf Lillengen
+ * @author Ulf Lilleengen
*/
public class HostResource implements Comparable<HostResource> {
diff --git a/config-model/src/main/java/com/yahoo/vespa/model/VespaModel.java b/config-model/src/main/java/com/yahoo/vespa/model/VespaModel.java
index c61435ca831..53cc8be9e96 100644
--- a/config-model/src/main/java/com/yahoo/vespa/model/VespaModel.java
+++ b/config-model/src/main/java/com/yahoo/vespa/model/VespaModel.java
@@ -20,7 +20,7 @@ import com.yahoo.config.model.deploy.DeployState;
import com.yahoo.config.model.producer.AbstractConfigProducer;
import com.yahoo.config.model.producer.AbstractConfigProducerRoot;
import com.yahoo.config.model.producer.UserConfigRepo;
-import com.yahoo.config.provision.ProvisionInfo;
+import com.yahoo.config.provision.AllocatedHosts;
import com.yahoo.log.LogLevel;
import com.yahoo.vespa.config.ConfigDefinitionKey;
import com.yahoo.vespa.config.ConfigKey;
@@ -83,7 +83,7 @@ public final class VespaModel extends AbstractConfigProducerRoot implements Seri
public static final Logger log = Logger.getLogger(VespaModel.class.getPackage().toString());
private ConfigModelRepo configModelRepo = new ConfigModelRepo();
- private final Optional<ProvisionInfo> info;
+ private final AllocatedHosts allocatedHosts;
/**
* The config id for the root config producer
@@ -146,7 +146,7 @@ public final class VespaModel extends AbstractConfigProducerRoot implements Seri
if (complete) { // create a a completed, frozen model
configModelRepo.readConfigModels(deployState, builder, root, configModelRegistry);
addServiceClusters(deployState.getApplicationPackage(), builder);
- this.info = Optional.of(createProvisionInfo()); // must happen after the two lines above
+ this.allocatedHosts = AllocatedHosts.withHosts(root.getHostSystem().getHostSpecs()); // must happen after the two lines above
setupRouting();
this.fileDistributor = root.getFileDistributionConfigProducer().getFileDistributor();
getAdmin().addPerHostServices(getHostSystem().getHosts(), deployState.getProperties());
@@ -157,7 +157,7 @@ public final class VespaModel extends AbstractConfigProducerRoot implements Seri
this.deployState = null;
}
else { // create a model with no services instantiated and the given file distributor
- this.info = Optional.of(createProvisionInfo());
+ this.allocatedHosts = AllocatedHosts.withHosts(root.getHostSystem().getHostSpecs());
this.fileDistributor = fileDistributor;
}
}
@@ -167,10 +167,6 @@ public final class VespaModel extends AbstractConfigProducerRoot implements Seri
return new VespaModel(new NullConfigModelRegistry(), deployState, false, new FileDistributor(deployState.getFileRegistry()));
}
- private ProvisionInfo createProvisionInfo() {
- return ProvisionInfo.withHosts(root.getHostSystem().getHostSpecs());
- }
-
private void validateWrapExceptions() {
try {
validate();
@@ -421,8 +417,8 @@ public final class VespaModel extends AbstractConfigProducerRoot implements Seri
}
@Override
- public Optional<ProvisionInfo> getProvisionInfo() {
- return info;
+ public AllocatedHosts allocatedHosts() {
+ return allocatedHosts;
}
private static Set<ConfigKey<?>> configsProduced(ConfigProducer cp) {
diff --git a/config-model/src/main/java/com/yahoo/vespa/model/VespaModelFactory.java b/config-model/src/main/java/com/yahoo/vespa/model/VespaModelFactory.java
index 64cb415fc7d..fc27f9e8dc7 100644
--- a/config-model/src/main/java/com/yahoo/vespa/model/VespaModelFactory.java
+++ b/config-model/src/main/java/com/yahoo/vespa/model/VespaModelFactory.java
@@ -34,7 +34,7 @@ import java.util.logging.Logger;
/**
* Factory for creating {@link VespaModel} instances.
*
- * @author lulf
+ * @author Ulf Lilleengen
*/
public class VespaModelFactory implements ModelFactory {
@@ -42,9 +42,17 @@ public class VespaModelFactory implements ModelFactory {
private final ConfigModelRegistry configModelRegistry;
private final Zone zone;
private final Clock clock;
+ private final Version version;
+ /** Creates a factory for vespa models for this version of the source */
@Inject
public VespaModelFactory(ComponentRegistry<ConfigModelPlugin> pluginRegistry, Zone zone) {
+ this(Version.fromIntValues(VespaVersion.major, VespaVersion.minor, VespaVersion.micro), pluginRegistry, zone);
+ }
+
+ /** Creates a factory for vespa models of a particular version */
+ public VespaModelFactory(Version version, ComponentRegistry<ConfigModelPlugin> pluginRegistry, Zone zone) {
+ this.version = version;
List<ConfigModelBuilder> modelBuilders = new ArrayList<>();
for (ConfigModelPlugin plugin : pluginRegistry.allComponents()) {
if (plugin instanceof ConfigModelBuilder) {
@@ -55,11 +63,15 @@ public class VespaModelFactory implements ModelFactory {
this.zone = zone;
this.clock = Clock.systemUTC();
}
-
+
public VespaModelFactory(ConfigModelRegistry configModelRegistry) {
this(configModelRegistry, Clock.systemUTC());
}
public VespaModelFactory(ConfigModelRegistry configModelRegistry, Clock clock) {
+ this(Version.fromIntValues(VespaVersion.major, VespaVersion.minor, VespaVersion.micro), configModelRegistry, clock);
+ }
+ public VespaModelFactory(Version version, ConfigModelRegistry configModelRegistry, Clock clock) {
+ this.version = version;
if (configModelRegistry == null) {
this.configModelRegistry = new NullConfigModelRegistry();
log.info("Will not load config models from plugins, as no registry is available");
@@ -72,9 +84,7 @@ public class VespaModelFactory implements ModelFactory {
/** Returns the version this model is build for */
@Override
- public Version getVersion() {
- return Version.fromIntValues(VespaVersion.major, VespaVersion.minor, VespaVersion.micro);
- }
+ public Version getVersion() { return version; }
@Override
public Model createModel(ModelContext modelContext) {
diff --git a/config-model/src/test/java/com/yahoo/config/model/provision/HostSpecTest.java b/config-model/src/test/java/com/yahoo/config/model/provision/HostSpecTest.java
index 6a17f314d26..51b039a7532 100644
--- a/config-model/src/test/java/com/yahoo/config/model/provision/HostSpecTest.java
+++ b/config-model/src/test/java/com/yahoo/config/model/provision/HostSpecTest.java
@@ -11,10 +11,10 @@ import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
/**
- * @author lulf
- * @since 5.11
+ * @author Ulf Lilleengen
*/
public class HostSpecTest {
+
@Test
public void testEquals() {
HostSpec h1 = new HostSpec("foo", Collections.<String>emptyList());
@@ -42,4 +42,5 @@ public class HostSpecTest {
assertFalse(h4.equals(h3));
assertTrue(h4.equals(h4));
}
+
}
diff --git a/config-model/src/test/java/com/yahoo/vespa/model/test/VespaModelTestCase.java b/config-model/src/test/java/com/yahoo/vespa/model/test/VespaModelTestCase.java
index 8102f358830..cc3f4a22966 100644
--- a/config-model/src/test/java/com/yahoo/vespa/model/test/VespaModelTestCase.java
+++ b/config-model/src/test/java/com/yahoo/vespa/model/test/VespaModelTestCase.java
@@ -18,7 +18,7 @@ import com.yahoo.config.model.provision.InMemoryProvisioner;
import com.yahoo.config.model.test.MockApplicationPackage;
import com.yahoo.config.model.test.TestDriver;
import com.yahoo.config.provision.ApplicationId;
-import com.yahoo.config.provision.ProvisionInfo;
+import com.yahoo.config.provision.AllocatedHosts;
import com.yahoo.document.config.DocumentmanagerConfig;
import com.yahoo.messagebus.MessagebusConfig;
import com.yahoo.net.HostName;
@@ -286,7 +286,7 @@ public class VespaModelTestCase {
.build())
.build();
VespaModel model = new VespaModel(new NullConfigModelRegistry(), deployState);
- ProvisionInfo info = model.getProvisionInfo().get();
+ AllocatedHosts info = model.allocatedHosts();
assertEquals("Admin version 3 is ignored, and there are no other hosts to borrow for admin services", 0, info.getHosts().size());
}
diff --git a/config-provisioning/src/main/java/com/yahoo/config/provision/AllocatedHosts.java b/config-provisioning/src/main/java/com/yahoo/config/provision/AllocatedHosts.java
new file mode 100644
index 00000000000..13efc2b3337
--- /dev/null
+++ b/config-provisioning/src/main/java/com/yahoo/config/provision/AllocatedHosts.java
@@ -0,0 +1,116 @@
+// Copyright 2017 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
+package com.yahoo.config.provision;
+
+import com.google.common.collect.ImmutableSet;
+import com.yahoo.slime.ArrayTraverser;
+import com.yahoo.slime.Cursor;
+import com.yahoo.slime.Inspector;
+import com.yahoo.slime.Slime;
+import com.yahoo.vespa.config.SlimeUtils;
+
+import java.io.IOException;
+import java.util.Collections;
+import java.util.LinkedHashSet;
+import java.util.Optional;
+import java.util.Set;
+
+/**
+ * The hosts allocated to an application.
+ * This can be serialized to/from JSON.
+ * This is immutable.
+ *
+ * @author Ulf Lilleengen
+ * @author bratseth
+ */
+public class AllocatedHosts {
+
+ private static final String mappingKey = "mapping";
+ private static final String hostSpecKey = "hostSpec";
+ private static final String hostSpecHostName = "hostName";
+ private static final String hostSpecMembership = "membership";
+ private static final String hostSpecFlavor = "flavor";
+ private static final String hostSpecVespaVersion = "vespaVersion";
+
+ private final ImmutableSet<HostSpec> hosts;
+
+ AllocatedHosts(Set<HostSpec> hosts) {
+ this.hosts = ImmutableSet.copyOf(hosts);
+ }
+
+ public static AllocatedHosts withHosts(Set<HostSpec> hosts) {
+ return new AllocatedHosts(hosts);
+ }
+
+ private void toSlime(Cursor cursor) {
+ Cursor array = cursor.setArray(mappingKey);
+ for (HostSpec host : hosts)
+ toSlime(host, array.addObject().setObject(hostSpecKey));
+ }
+
+ private void toSlime(HostSpec host, Cursor cursor) {
+ cursor.setString(hostSpecHostName, host.hostname());
+ if (host.membership().isPresent()) {
+ cursor.setString(hostSpecMembership, host.membership().get().stringValue());
+ cursor.setString(hostSpecVespaVersion, host.membership().get().cluster().vespaVersion().toString());
+ }
+ if (host.flavor().isPresent())
+ cursor.setString(hostSpecFlavor, host.flavor().get().name());
+ }
+
+ /** Returns the hosts of this allocation */
+ public Set<HostSpec> getHosts() { return hosts; }
+
+ private static AllocatedHosts fromSlime(Inspector inspector, Optional<NodeFlavors> nodeFlavors) {
+ Inspector array = inspector.field(mappingKey);
+ Set<HostSpec> hosts = new LinkedHashSet<>();
+ array.traverse(new ArrayTraverser() {
+ @Override
+ public void entry(int i, Inspector inspector) {
+ hosts.add(hostsFromSlime(inspector.field(hostSpecKey), nodeFlavors));
+ }
+ });
+ return new AllocatedHosts(hosts);
+ }
+
+ static HostSpec hostsFromSlime(Inspector object, Optional<NodeFlavors> nodeFlavors) {
+ Optional<ClusterMembership> membership =
+ object.field(hostSpecMembership).valid() ? Optional.of(membershipFromSlime(object)) : Optional.empty();
+ Optional<Flavor> flavor =
+ object.field(hostSpecFlavor).valid() ? flavorFromSlime(object, nodeFlavors) : Optional.empty();
+
+ return new HostSpec(object.field(hostSpecHostName).asString(),Collections.emptyList(), flavor, membership);
+ }
+
+ private static ClusterMembership membershipFromSlime(Inspector object) {
+ return ClusterMembership.from(object.field(hostSpecMembership).asString(),
+ com.yahoo.component.Version.fromString(object.field(hostSpecVespaVersion).asString()));
+ }
+
+ private static Optional<Flavor> flavorFromSlime(Inspector object, Optional<NodeFlavors> nodeFlavors) {
+ return nodeFlavors.map(flavorMapper -> flavorMapper.getFlavor(object.field(hostSpecFlavor).asString()))
+ .orElse(Optional.empty());
+ }
+
+ public byte[] toJson() throws IOException {
+ Slime slime = new Slime();
+ toSlime(slime.setObject());
+ return SlimeUtils.toJsonBytes(slime);
+ }
+
+ public static AllocatedHosts fromJson(byte[] json, Optional<NodeFlavors> nodeFlavors) {
+ return fromSlime(SlimeUtils.jsonToSlime(json).get(), nodeFlavors);
+ }
+
+ @Override
+ public boolean equals(Object other) {
+ if (other == this) return true;
+ if ( ! (other instanceof AllocatedHosts)) return false;
+ return ((AllocatedHosts) other).hosts.equals(this.hosts);
+ }
+
+ @Override
+ public int hashCode() {
+ return hosts.hashCode();
+ }
+
+}
diff --git a/config-provisioning/src/main/java/com/yahoo/config/provision/HostSpec.java b/config-provisioning/src/main/java/com/yahoo/config/provision/HostSpec.java
index 5d6b3fcaca4..dd8bc311939 100644
--- a/config-provisioning/src/main/java/com/yahoo/config/provision/HostSpec.java
+++ b/config-provisioning/src/main/java/com/yahoo/config/provision/HostSpec.java
@@ -5,11 +5,12 @@ import com.google.common.collect.ImmutableList;
import java.util.ArrayList;
import java.util.List;
+import java.util.Objects;
import java.util.Optional;
/**
* A specification of a host and its role.
- * The identity of a host is determined by its name.
+ * Equality and order is determined by the host name.
*
* @author hmusum
*/
@@ -19,7 +20,7 @@ public class HostSpec implements Comparable<HostSpec> {
private final String hostname;
/** Aliases of this host */
- private final List<String> aliases;
+ private final ImmutableList<String> aliases;
/** The current membership role of this host in the cluster it belongs to */
private final Optional<ClusterMembership> membership;
@@ -69,10 +70,11 @@ public class HostSpec implements Comparable<HostSpec> {
}
@Override
- public boolean equals(Object o) {
- if ( ! (o instanceof HostSpec)) return false;
- HostSpec other = (HostSpec) o;
- return this.hostname().equals(other.hostname());
+ public boolean equals(Object other) {
+ if (other == this) return true;
+ if ( ! (other instanceof HostSpec)) return false;
+
+ return ((HostSpec)other).hostname.equals(this.hostname);
}
@Override
diff --git a/config-provisioning/src/main/java/com/yahoo/config/provision/ProvisionInfo.java b/config-provisioning/src/main/java/com/yahoo/config/provision/ProvisionInfo.java
index 8bef1f7c9b7..dbb1b55aeb9 100644
--- a/config-provisioning/src/main/java/com/yahoo/config/provision/ProvisionInfo.java
+++ b/config-provisioning/src/main/java/com/yahoo/config/provision/ProvisionInfo.java
@@ -1,63 +1,35 @@
-// Copyright 2017 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
package com.yahoo.config.provision;
import com.yahoo.slime.ArrayTraverser;
-import com.yahoo.slime.Cursor;
import com.yahoo.slime.Inspector;
-import com.yahoo.slime.Slime;
import com.yahoo.vespa.config.SlimeUtils;
-import java.io.IOException;
-import java.util.Collections;
import java.util.LinkedHashSet;
import java.util.Optional;
import java.util.Set;
/**
- * Information about hosts provisioned for an application, and (de)serialization of this information to/from JSON.
- *
- * @author lulf
- * @since 5.12
+ * @author bratseth
+ * @deprecated use AllocatedHosts
*/
-public class ProvisionInfo {
+// TODO: Remove when no version older than 6.143 is in production anywhere
+@Deprecated
+@SuppressWarnings("unused")
+public class ProvisionInfo extends AllocatedHosts {
private static final String mappingKey = "mapping";
private static final String hostSpecKey = "hostSpec";
- private static final String hostSpecHostName = "hostName";
- private static final String hostSpecMembership = "membership";
- private static final String hostSpecFlavor = "flavor";
- private static final String hostSpecVespaVersion = "vespaVersion";
-
- private final Set<HostSpec> hosts = new LinkedHashSet<>();
private ProvisionInfo(Set<HostSpec> hosts) {
- this.hosts.addAll(hosts);
+ super(hosts);
}
public static ProvisionInfo withHosts(Set<HostSpec> hosts) {
return new ProvisionInfo(hosts);
}
- private void toSlime(Cursor cursor) {
- Cursor array = cursor.setArray(mappingKey);
- for (HostSpec host : hosts) {
- Cursor object = array.addObject();
- serializeHostSpec(object.setObject(hostSpecKey), host);
- }
- }
-
- private void serializeHostSpec(Cursor cursor, HostSpec host) {
- cursor.setString(hostSpecHostName, host.hostname());
- if (host.membership().isPresent()) {
- cursor.setString(hostSpecMembership, host.membership().get().stringValue());
- cursor.setString(hostSpecVespaVersion, host.membership().get().cluster().vespaVersion().toString());
- }
- if (host.flavor().isPresent())
- cursor.setString(hostSpecFlavor, host.flavor().get().name());
- }
-
- public Set<HostSpec> getHosts() {
- return Collections.unmodifiableSet(hosts);
+ public static ProvisionInfo fromJson(byte[] json, Optional<NodeFlavors> nodeFlavors) {
+ return fromSlime(SlimeUtils.jsonToSlime(json).get(), nodeFlavors);
}
private static ProvisionInfo fromSlime(Inspector inspector, Optional<NodeFlavors> nodeFlavors) {
@@ -66,46 +38,10 @@ public class ProvisionInfo {
array.traverse(new ArrayTraverser() {
@Override
public void entry(int i, Inspector inspector) {
- hosts.add(deserializeHostSpec(inspector.field(hostSpecKey), nodeFlavors));
+ hosts.add(hostsFromSlime(inspector.field(hostSpecKey), nodeFlavors));
}
});
return new ProvisionInfo(hosts);
}
- private static HostSpec deserializeHostSpec(Inspector object, Optional<NodeFlavors> nodeFlavors) {
- Optional<ClusterMembership> membership =
- object.field(hostSpecMembership).valid() ? Optional.of(readMembership(object)) : Optional.empty();
- Optional<Flavor> flavor =
- object.field(hostSpecFlavor).valid() ? readFlavor(object, nodeFlavors) : Optional.empty();
-
- return new HostSpec(object.field(hostSpecHostName).asString(),Collections.emptyList(), flavor, membership);
- }
-
- private static ClusterMembership readMembership(Inspector object) {
- return ClusterMembership.from(object.field(hostSpecMembership).asString(),
- com.yahoo.component.Version.fromString(object.field(hostSpecVespaVersion).asString()));
- }
-
- private static Optional<Flavor> readFlavor(Inspector object, Optional<NodeFlavors> nodeFlavors) {
- return nodeFlavors.map(flavorMapper -> flavorMapper.getFlavor(object.field(hostSpecFlavor).asString()))
- .orElse(Optional.empty());
- }
-
- public byte[] toJson() throws IOException {
- Slime slime = new Slime();
- toSlime(slime.setObject());
- return SlimeUtils.toJsonBytes(slime);
- }
-
- public static ProvisionInfo fromJson(byte[] json, Optional<NodeFlavors> nodeFlavors) {
- return fromSlime(SlimeUtils.jsonToSlime(json).get(), nodeFlavors);
- }
-
- public ProvisionInfo merge(ProvisionInfo provisionInfo) {
- Set<HostSpec> mergedSet = new LinkedHashSet<>();
- mergedSet.addAll(this.hosts);
- mergedSet.addAll(provisionInfo.getHosts());
- return ProvisionInfo.withHosts(mergedSet);
- }
-
}
diff --git a/config-provisioning/src/main/java/com/yahoo/config/provision/Provisioner.java b/config-provisioning/src/main/java/com/yahoo/config/provision/Provisioner.java
index 980cd4a00b9..6be1d49ebd3 100644
--- a/config-provisioning/src/main/java/com/yahoo/config/provision/Provisioner.java
+++ b/config-provisioning/src/main/java/com/yahoo/config/provision/Provisioner.java
@@ -9,8 +9,7 @@ import java.util.List;
/**
* Interface used by the config system to acquire hosts.
*
- * @author lulf
- * @since 5.11
+ * @author Ulf Lilleengen
*/
public interface Provisioner {
diff --git a/config-provisioning/src/test/java/com/yahoo/config/provision/AllocatedHostsTest.java b/config-provisioning/src/test/java/com/yahoo/config/provision/AllocatedHostsTest.java
new file mode 100644
index 00000000000..675af88596a
--- /dev/null
+++ b/config-provisioning/src/test/java/com/yahoo/config/provision/AllocatedHostsTest.java
@@ -0,0 +1,52 @@
+// Copyright 2017 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
+package com.yahoo.config.provision;
+
+import org.junit.Test;
+
+import java.io.IOException;
+import java.util.LinkedHashSet;
+import java.util.Optional;
+import java.util.Set;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+
+/**
+ * @author Ulf Lilleengen
+ */
+public class AllocatedHostsTest {
+
+ private final HostSpec h1 = new HostSpec("host1", Optional.empty());
+ private final HostSpec h2 = new HostSpec("host2", Optional.empty());
+ private final HostSpec h3 = new HostSpec("host3", Optional.of(ClusterMembership.from("container/test/0", com.yahoo.component.Version.fromString("6.73.1"))));
+
+ @Test
+ public void testAllocatedHostsSerialization() throws IOException {
+ Set<HostSpec> hosts = new LinkedHashSet<>();
+ hosts.add(h1);
+ hosts.add(h2);
+ hosts.add(h3);
+ AllocatedHosts info = AllocatedHosts.withHosts(hosts);
+ assertAllocatedHosts(info);
+ }
+
+ private void assertAllocatedHosts(AllocatedHosts info) throws IOException {
+ AllocatedHosts serializedAllocatedHosts = AllocatedHosts.fromJson(info.toJson(), Optional.empty());
+ assertEquals(info.getHosts().size(), serializedAllocatedHosts.getHosts().size());
+ assertTrue(serializedAllocatedHosts.getHosts().contains(h1));
+ assertTrue(serializedAllocatedHosts.getHosts().contains(h2));
+ assertTrue(serializedAllocatedHosts.getHosts().contains(h3));
+ assertTrue(!getHost(h1.hostname(), serializedAllocatedHosts.getHosts()).membership().isPresent());
+ assertEquals("container/test/0", getHost(h3.hostname(), serializedAllocatedHosts.getHosts()).membership().get().stringValue());
+ assertEquals(h3.membership().get().cluster().vespaVersion(), getHost(h3.hostname(),
+ serializedAllocatedHosts.getHosts()).membership().get().cluster().vespaVersion());
+ }
+
+ private HostSpec getHost(String hostname, Set<HostSpec> hosts) {
+ for (HostSpec host : hosts)
+ if (host.hostname().equals(hostname))
+ return host;
+ throw new IllegalArgumentException("No host " + hostname + " is present");
+ }
+
+}
diff --git a/config-provisioning/src/test/java/com/yahoo/config/provision/ProvisionInfoTest.java b/config-provisioning/src/test/java/com/yahoo/config/provision/ProvisionInfoTest.java
deleted file mode 100644
index 4fa69eb77e0..00000000000
--- a/config-provisioning/src/test/java/com/yahoo/config/provision/ProvisionInfoTest.java
+++ /dev/null
@@ -1,66 +0,0 @@
-// Copyright 2017 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
-package com.yahoo.config.provision;
-
-import org.junit.Test;
-
-import java.io.IOException;
-import java.util.Collections;
-import java.util.LinkedHashSet;
-import java.util.Optional;
-import java.util.Set;
-
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertTrue;
-
-/**
- * @author lulf
- * @since 5.12
- */
-public class ProvisionInfoTest {
-
- private final HostSpec h1 = new HostSpec("host1", Optional.empty());
- private final HostSpec h2 = new HostSpec("host2", Optional.empty());
- private final HostSpec h3 = new HostSpec("host3", Optional.of(ClusterMembership.from("container/test/0", com.yahoo.component.Version.fromString("6.73.1"))));
-
- @Test
- public void testProvisionInfoSerialization() throws IOException {
- Set<HostSpec> hosts = new LinkedHashSet<>();
- hosts.add(h1);
- hosts.add(h2);
- hosts.add(h3);
- ProvisionInfo info = ProvisionInfo.withHosts(hosts);
- assertProvisionInfo(info);
- }
-
- @Test
- public void testProvisionInfoMerging() throws IOException {
- Set<HostSpec> hostsA = new LinkedHashSet<>(Collections.singleton(h1));
- Set<HostSpec> hostsB = new LinkedHashSet<>();
- hostsB.add(h2);
- hostsB.add(h3);
-
- ProvisionInfo infoA = ProvisionInfo.withHosts(hostsA);
- ProvisionInfo infoB = ProvisionInfo.withHosts(hostsB);
- assertProvisionInfo(infoA.merge(infoB));
- assertProvisionInfo(infoB.merge(infoA));
- }
-
- private void assertProvisionInfo(ProvisionInfo info) throws IOException {
- ProvisionInfo serializedInfo = ProvisionInfo.fromJson(info.toJson(), Optional.empty());
- assertEquals(info.getHosts().size(), serializedInfo.getHosts().size());
- assertTrue(serializedInfo.getHosts().contains(h1));
- assertTrue(serializedInfo.getHosts().contains(h2));
- assertTrue(serializedInfo.getHosts().contains(h3));
- assertTrue(!getHost(h1.hostname(), serializedInfo.getHosts()).membership().isPresent());
- assertEquals("container/test/0", getHost(h3.hostname(), serializedInfo.getHosts()).membership().get().stringValue());
- assertEquals(h3.membership().get().cluster().vespaVersion(), getHost(h3.hostname(), serializedInfo.getHosts()).membership().get().cluster().vespaVersion());
- }
-
- private HostSpec getHost(String hostname, Set<HostSpec> hosts) {
- for (HostSpec host : hosts)
- if (host.hostname().equals(hostname))
- return host;
- throw new IllegalArgumentException("No host " + hostname + " is present");
- }
-
-}
diff --git a/configserver/src/main/java/com/yahoo/vespa/config/server/GlobalComponentRegistry.java b/configserver/src/main/java/com/yahoo/vespa/config/server/GlobalComponentRegistry.java
index 1bda8dcb69a..4f26cfa265b 100644
--- a/configserver/src/main/java/com/yahoo/vespa/config/server/GlobalComponentRegistry.java
+++ b/configserver/src/main/java/com/yahoo/vespa/config/server/GlobalComponentRegistry.java
@@ -19,8 +19,7 @@ import java.util.Optional;
/**
* Interface representing all global config server components used within the config server.
*
- * @author lulf
- * @since 5.1
+ * @author Ulf Lilleengen
*/
public interface GlobalComponentRegistry {
diff --git a/configserver/src/main/java/com/yahoo/vespa/config/server/InjectedGlobalComponentRegistry.java b/configserver/src/main/java/com/yahoo/vespa/config/server/InjectedGlobalComponentRegistry.java
index f88a0ef1a2d..fa5224732f6 100644
--- a/configserver/src/main/java/com/yahoo/vespa/config/server/InjectedGlobalComponentRegistry.java
+++ b/configserver/src/main/java/com/yahoo/vespa/config/server/InjectedGlobalComponentRegistry.java
@@ -22,8 +22,7 @@ import java.util.Optional;
/**
* Registry containing all the "static"/"global" components in a config server in one place.
*
- * @author lulf
- * @since 5.1
+ * @author Ulf Lilleengen
*/
public class InjectedGlobalComponentRegistry implements GlobalComponentRegistry {
diff --git a/configserver/src/main/java/com/yahoo/vespa/config/server/application/TenantApplications.java b/configserver/src/main/java/com/yahoo/vespa/config/server/application/TenantApplications.java
index 94abbc10046..0435c8e59db 100644
--- a/configserver/src/main/java/com/yahoo/vespa/config/server/application/TenantApplications.java
+++ b/configserver/src/main/java/com/yahoo/vespa/config/server/application/TenantApplications.java
@@ -9,8 +9,7 @@ import java.util.List;
/**
* The applications of a tenant
*
- * @author lulf
- * @since 5.1
+ * @author Ulf Lilleengen
*/
public interface TenantApplications {
diff --git a/configserver/src/main/java/com/yahoo/vespa/config/server/application/ZKTenantApplications.java b/configserver/src/main/java/com/yahoo/vespa/config/server/application/ZKTenantApplications.java
index ac318aba8e8..5260dd9228c 100644
--- a/configserver/src/main/java/com/yahoo/vespa/config/server/application/ZKTenantApplications.java
+++ b/configserver/src/main/java/com/yahoo/vespa/config/server/application/ZKTenantApplications.java
@@ -29,8 +29,7 @@ import java.util.logging.Logger;
* Each application is stored as a single file, named the same as the application id and containing the id
* of the session storing the content of the application.
*
- * @author lulf
- * @since 5.1
+ * @author Ulf Lilleengen
*/
// TODO: Merge into interface and separate out curator layer instead
public class ZKTenantApplications implements TenantApplications, PathChildrenCacheListener {
diff --git a/configserver/src/main/java/com/yahoo/vespa/config/server/deploy/Deployment.java b/configserver/src/main/java/com/yahoo/vespa/config/server/deploy/Deployment.java
index 61382af6a30..51995eb98cf 100644
--- a/configserver/src/main/java/com/yahoo/vespa/config/server/deploy/Deployment.java
+++ b/configserver/src/main/java/com/yahoo/vespa/config/server/deploy/Deployment.java
@@ -136,7 +136,7 @@ public class Deployment implements com.yahoo.config.provision.Deployment {
transaction.add(deactivateCurrentActivateNew(localSessionRepo.getActiveSession(session.getApplicationId()), session, ignoreSessionStaleFailure));
if (hostProvisioner.isPresent()) {
- hostProvisioner.get().activate(transaction, session.getApplicationId(), session.getProvisionInfo().getHosts());
+ hostProvisioner.get().activate(transaction, session.getApplicationId(), session.getAllocatedHosts().getHosts());
}
transaction.commit();
session.waitUntilActivated(timeoutBudget);
diff --git a/configserver/src/main/java/com/yahoo/vespa/config/server/deploy/ModelContextImpl.java b/configserver/src/main/java/com/yahoo/vespa/config/server/deploy/ModelContextImpl.java
index 820ad8e530c..70b677b4057 100644
--- a/configserver/src/main/java/com/yahoo/vespa/config/server/deploy/ModelContextImpl.java
+++ b/configserver/src/main/java/com/yahoo/vespa/config/server/deploy/ModelContextImpl.java
@@ -18,7 +18,7 @@ import java.util.Set;
/**
* Implementation of {@link ModelContext} for configserver.
*
- * @author lulf
+ * @author Ulf Lilleengen
*/
public class ModelContextImpl implements ModelContext {
@@ -83,6 +83,11 @@ public class ModelContextImpl implements ModelContext {
return permanentApplicationPackage;
}
+ /**
+ * Returns the host provisioner to use, or empty to use the default provisioner,
+ * creating hosts from the application package defined hosts
+ */
+ // TODO: Don't allow empty here but create the right provisioner when this is set up instead
@Override
public Optional<HostProvisioner> hostProvisioner() {
return hostProvisioner;
diff --git a/configserver/src/main/java/com/yahoo/vespa/config/server/deploy/ZooKeeperClient.java b/configserver/src/main/java/com/yahoo/vespa/config/server/deploy/ZooKeeperClient.java
index ea278596e80..69266620e45 100644
--- a/configserver/src/main/java/com/yahoo/vespa/config/server/deploy/ZooKeeperClient.java
+++ b/configserver/src/main/java/com/yahoo/vespa/config/server/deploy/ZooKeeperClient.java
@@ -6,7 +6,7 @@ import com.yahoo.config.application.api.DeployLogger;
import com.yahoo.config.application.api.ApplicationFile;
import com.yahoo.config.application.api.ApplicationPackage;
import com.yahoo.config.application.api.UnparsedConfigDefinition;
-import com.yahoo.config.provision.ProvisionInfo;
+import com.yahoo.config.provision.AllocatedHosts;
import com.yahoo.config.provision.Version;
import com.yahoo.io.reader.NamedReader;
import com.yahoo.log.LogLevel;
@@ -25,13 +25,12 @@ import java.util.*;
* A class used for reading and writing application data to zookeeper.
*
* @author hmusum
- * @since 5.1
*/
public class ZooKeeperClient {
private final ConfigCurator configCurator;
private final DeployLogger logger;
- private final boolean trace;
+ private final boolean logFine;
/* This is the generation that will be used for reading and writing application data. (1 more than last deployed application) */
private final Path rootPath;
@@ -42,10 +41,10 @@ public class ZooKeeperClient {
}
};
- public ZooKeeperClient(ConfigCurator configCurator, DeployLogger logger, boolean trace, Path rootPath) {
+ public ZooKeeperClient(ConfigCurator configCurator, DeployLogger logger, boolean logFine, Path rootPath) {
this.configCurator = configCurator;
this.logger = logger;
- this.trace = trace;
+ this.logFine = logFine;
this.rootPath = rootPath;
}
@@ -62,7 +61,7 @@ public class ZooKeeperClient {
try {
while (retries > 0) {
try {
- trace("Setting up ZooKeeper nodes for this application");
+ logFine("Setting up ZooKeeper nodes for this application");
createZooKeeperNodes();
break;
} catch (RuntimeException e) {
@@ -105,28 +104,28 @@ public class ZooKeeperClient {
*
* @param app the application package to feed to zookeeper
*/
- void feedZooKeeper(ApplicationPackage app) {
- trace("Feeding application config into ZooKeeper");
+ void write(ApplicationPackage app) {
+ logFine("Feeding application config into ZooKeeper");
// gives lots and lots of debug output: // BasicConfigurator.configure();
try {
- trace("zk operations: " + configCurator.getNumberOfOperations());
- trace("zk operations: " + configCurator.getNumberOfOperations());
- trace("Feeding user def files into ZooKeeper");
- feedZKUserDefs(app);
- trace("zk operations: " + configCurator.getNumberOfOperations());
- trace("Feeding application package into ZooKeeper");
+ logFine("zk operations: " + configCurator.getNumberOfOperations());
+ logFine("zk operations: " + configCurator.getNumberOfOperations());
+ logFine("Feeding user def files into ZooKeeper");
+ writeUserDefs(app);
+ logFine("zk operations: " + configCurator.getNumberOfOperations());
+ logFine("Feeding application package into ZooKeeper");
// TODO 1200 zk operations done in the below method
- feedZKAppPkg(app);
- feedSearchDefinitions(app);
- feedZKUserIncludeDirs(app, app.getUserIncludeDirs());
- trace("zk operations: " + configCurator.getNumberOfOperations());
- trace("zk read operations: " + configCurator.getNumberOfReadOperations());
- trace("zk write operations: " + configCurator.getNumberOfWriteOperations());
- trace("Feeding sd from docproc bundle into ZooKeeper");
- trace("zk operations: " + configCurator.getNumberOfOperations());
- trace("Write application metadata into ZooKeeper");
- feedZKAppMetaData(app.getMetaData());
- trace("zk operations: " + configCurator.getNumberOfOperations());
+ writeSomeOf(app);
+ writeSearchDefinitions(app);
+ writeUserIncludeDirs(app, app.getUserIncludeDirs());
+ logFine("zk operations: " + configCurator.getNumberOfOperations());
+ logFine("zk read operations: " + configCurator.getNumberOfReadOperations());
+ logFine("zk write operations: " + configCurator.getNumberOfWriteOperations());
+ logFine("Feeding sd from docproc bundle into ZooKeeper");
+ logFine("zk operations: " + configCurator.getNumberOfOperations());
+ logFine("Write application metadata into ZooKeeper");
+ write(app.getMetaData());
+ logFine("zk operations: " + configCurator.getNumberOfOperations());
} catch (Exception e) {
throw new IllegalStateException("Unable to write vespa model to config server(s) " + System.getProperty("configsources") + "\n" +
"Please ensure that cloudconfig_server is started on the config server node(s), " +
@@ -134,7 +133,7 @@ public class ZooKeeperClient {
}
}
- private void feedSearchDefinitions(ApplicationPackage app) throws IOException {
+ private void writeSearchDefinitions(ApplicationPackage app) throws IOException {
Collection<NamedReader> sds = app.getSearchDefinitions();
if (sds.isEmpty()) {
return;
@@ -142,7 +141,7 @@ public class ZooKeeperClient {
Path zkPath = getZooKeeperAppPath(ConfigCurator.USERAPP_ZK_SUBPATH).append(ApplicationPackage.SEARCH_DEFINITIONS_DIR);
configCurator.createNode(zkPath.getAbsolute());
// Ensures that ranking expressions and other files are also fed.
- feedDirZooKeeper(app.getFile(ApplicationPackage.SEARCH_DEFINITIONS_DIR), zkPath, false);
+ writeDir(app.getFile(ApplicationPackage.SEARCH_DEFINITIONS_DIR), zkPath, false);
for (NamedReader sd : sds) {
String name = sd.getName();
Reader reader = sd.getReader();
@@ -153,12 +152,12 @@ public class ZooKeeperClient {
}
/**
- * Puts the application package files into ZK
+ * Puts some of the application package files into ZK - see write(app).
*
* @param app The application package to use as input.
* @throws java.io.IOException if not able to write to Zookeeper
*/
- void feedZKAppPkg(ApplicationPackage app) throws IOException {
+ void writeSomeOf(ApplicationPackage app) throws IOException {
ApplicationFile.PathFilter srFilter = new ApplicationFile.PathFilter() {
@Override
public boolean accept(Path path) {
@@ -167,40 +166,40 @@ public class ZooKeeperClient {
};
// Copy app package files and subdirs into zk
// TODO: We should have a way of doing this which doesn't require repeating all the content
- feedFileZooKeeper(app.getFile(Path.fromString(ApplicationPackage.SERVICES)),
- getZooKeeperAppPath(ConfigCurator.USERAPP_ZK_SUBPATH));
- feedFileZooKeeper(app.getFile(Path.fromString(ApplicationPackage.HOSTS)),
- getZooKeeperAppPath(ConfigCurator.USERAPP_ZK_SUBPATH));
- feedFileZooKeeper(app.getFile(Path.fromString(ApplicationPackage.DEPLOYMENT_FILE.getName())),
- getZooKeeperAppPath(ConfigCurator.USERAPP_ZK_SUBPATH));
- feedFileZooKeeper(app.getFile(Path.fromString(ApplicationPackage.VALIDATION_OVERRIDES.getName())),
- getZooKeeperAppPath(ConfigCurator.USERAPP_ZK_SUBPATH));
+ writeFile(app.getFile(Path.fromString(ApplicationPackage.SERVICES)),
+ getZooKeeperAppPath(ConfigCurator.USERAPP_ZK_SUBPATH));
+ writeFile(app.getFile(Path.fromString(ApplicationPackage.HOSTS)),
+ getZooKeeperAppPath(ConfigCurator.USERAPP_ZK_SUBPATH));
+ writeFile(app.getFile(Path.fromString(ApplicationPackage.DEPLOYMENT_FILE.getName())),
+ getZooKeeperAppPath(ConfigCurator.USERAPP_ZK_SUBPATH));
+ writeFile(app.getFile(Path.fromString(ApplicationPackage.VALIDATION_OVERRIDES.getName())),
+ getZooKeeperAppPath(ConfigCurator.USERAPP_ZK_SUBPATH));
- feedDirZooKeeper(app.getFile(Path.fromString(ApplicationPackage.TEMPLATES_DIR)),
- getZooKeeperAppPath(ConfigCurator.USERAPP_ZK_SUBPATH),
- true);
- feedDirZooKeeper(app.getFile(ApplicationPackage.RULES_DIR),
- getZooKeeperAppPath(ConfigCurator.USERAPP_ZK_SUBPATH).append(ApplicationPackage.RULES_DIR),
- srFilter, true);
- feedDirZooKeeper(app.getFile(ApplicationPackage.QUERY_PROFILES_DIR),
- getZooKeeperAppPath(ConfigCurator.USERAPP_ZK_SUBPATH).append(ApplicationPackage.QUERY_PROFILES_DIR),
- xmlFilter, true);
- feedDirZooKeeper(app.getFile(ApplicationPackage.PAGE_TEMPLATES_DIR),
- getZooKeeperAppPath(ConfigCurator.USERAPP_ZK_SUBPATH).append(ApplicationPackage.PAGE_TEMPLATES_DIR),
- xmlFilter, true);
- feedDirZooKeeper(app.getFile(Path.fromString(ApplicationPackage.SEARCHCHAINS_DIR)),
- getZooKeeperAppPath(ConfigCurator.USERAPP_ZK_SUBPATH).append(ApplicationPackage.SEARCHCHAINS_DIR),
- xmlFilter, true);
- feedDirZooKeeper(app.getFile(Path.fromString(ApplicationPackage.DOCPROCCHAINS_DIR)),
- getZooKeeperAppPath(ConfigCurator.USERAPP_ZK_SUBPATH).append(ApplicationPackage.DOCPROCCHAINS_DIR),
- xmlFilter, true);
- feedDirZooKeeper(app.getFile(Path.fromString(ApplicationPackage.ROUTINGTABLES_DIR)),
- getZooKeeperAppPath(ConfigCurator.USERAPP_ZK_SUBPATH).append(ApplicationPackage.ROUTINGTABLES_DIR),
- xmlFilter, true);
+ writeDir(app.getFile(Path.fromString(ApplicationPackage.TEMPLATES_DIR)),
+ getZooKeeperAppPath(ConfigCurator.USERAPP_ZK_SUBPATH),
+ true);
+ writeDir(app.getFile(ApplicationPackage.RULES_DIR),
+ getZooKeeperAppPath(ConfigCurator.USERAPP_ZK_SUBPATH).append(ApplicationPackage.RULES_DIR),
+ srFilter, true);
+ writeDir(app.getFile(ApplicationPackage.QUERY_PROFILES_DIR),
+ getZooKeeperAppPath(ConfigCurator.USERAPP_ZK_SUBPATH).append(ApplicationPackage.QUERY_PROFILES_DIR),
+ xmlFilter, true);
+ writeDir(app.getFile(ApplicationPackage.PAGE_TEMPLATES_DIR),
+ getZooKeeperAppPath(ConfigCurator.USERAPP_ZK_SUBPATH).append(ApplicationPackage.PAGE_TEMPLATES_DIR),
+ xmlFilter, true);
+ writeDir(app.getFile(Path.fromString(ApplicationPackage.SEARCHCHAINS_DIR)),
+ getZooKeeperAppPath(ConfigCurator.USERAPP_ZK_SUBPATH).append(ApplicationPackage.SEARCHCHAINS_DIR),
+ xmlFilter, true);
+ writeDir(app.getFile(Path.fromString(ApplicationPackage.DOCPROCCHAINS_DIR)),
+ getZooKeeperAppPath(ConfigCurator.USERAPP_ZK_SUBPATH).append(ApplicationPackage.DOCPROCCHAINS_DIR),
+ xmlFilter, true);
+ writeDir(app.getFile(Path.fromString(ApplicationPackage.ROUTINGTABLES_DIR)),
+ getZooKeeperAppPath(ConfigCurator.USERAPP_ZK_SUBPATH).append(ApplicationPackage.ROUTINGTABLES_DIR),
+ xmlFilter, true);
}
- private void feedDirZooKeeper(ApplicationFile file, Path zooKeeperAppPath, boolean recurse) throws IOException {
- feedDirZooKeeper(file, zooKeeperAppPath, new ApplicationFile.PathFilter() {
+ private void writeDir(ApplicationFile file, Path zooKeeperAppPath, boolean recurse) throws IOException {
+ writeDir(file, zooKeeperAppPath, new ApplicationFile.PathFilter() {
@Override
public boolean accept(Path path) {
return true;
@@ -208,7 +207,7 @@ public class ZooKeeperClient {
}, recurse);
}
- private void feedDirZooKeeper(ApplicationFile dir, Path path, ApplicationFile.PathFilter filenameFilter, boolean recurse) throws IOException {
+ private void writeDir(ApplicationFile dir, Path path, ApplicationFile.PathFilter filenameFilter, boolean recurse) throws IOException {
if (!dir.isDirectory()) {
logger.log(LogLevel.FINE, dir.getPath().getAbsolute()+" is not a directory. Not feeding the files into ZooKeeper.");
return;
@@ -220,10 +219,10 @@ public class ZooKeeperClient {
if (file.isDirectory()) {
configCurator.createNode(path.append(name).getAbsolute());
if (recurse) {
- feedDirZooKeeper(file, path.append(name), filenameFilter, recurse);
+ writeDir(file, path.append(name), filenameFilter, recurse);
}
} else {
- feedFileZooKeeper(file, path);
+ writeFile(file, path);
}
}
}
@@ -248,7 +247,7 @@ public class ZooKeeperClient {
return ret;
}
- private void feedFileZooKeeper(ApplicationFile file, Path zkPath) throws IOException {
+ private void writeFile(ApplicationFile file, Path zkPath) throws IOException {
if (!file.exists()) {
return;
}
@@ -260,7 +259,7 @@ public class ZooKeeperClient {
}
}
- private void feedZKUserIncludeDirs(ApplicationPackage applicationPackage, List<String> userIncludeDirs) throws IOException {
+ private void writeUserIncludeDirs(ApplicationPackage applicationPackage, List<String> userIncludeDirs) throws IOException {
// User defined include directories
for (String userInclude : userIncludeDirs) {
ApplicationFile dir = applicationPackage.getFile(Path.fromString(userInclude));
@@ -268,9 +267,9 @@ public class ZooKeeperClient {
if (files == null || files.isEmpty()) {
configCurator.createNode(getZooKeeperAppPath(ConfigCurator.USERAPP_ZK_SUBPATH + "/" + userInclude).getAbsolute());
}
- feedDirZooKeeper(dir,
- getZooKeeperAppPath(ConfigCurator.USERAPP_ZK_SUBPATH + "/" + userInclude),
- xmlFilter, true);
+ writeDir(dir,
+ getZooKeeperAppPath(ConfigCurator.USERAPP_ZK_SUBPATH + "/" + userInclude),
+ xmlFilter, true);
}
}
@@ -278,22 +277,22 @@ public class ZooKeeperClient {
* Feeds all user-defined .def file from the application package into ZooKeeper (both into
* /defconfigs and /userdefconfigs
*/
- private void feedZKUserDefs(ApplicationPackage applicationPackage) {
+ private void writeUserDefs(ApplicationPackage applicationPackage) {
Map<ConfigDefinitionKey, UnparsedConfigDefinition> configDefs = applicationPackage.getAllExistingConfigDefs();
for (Map.Entry<ConfigDefinitionKey, UnparsedConfigDefinition> entry : configDefs.entrySet()) {
ConfigDefinitionKey key = entry.getKey();
String contents = entry.getValue().getUnparsedContent();
- feedDefToZookeeper(key.getName(), key.getNamespace(), getZooKeeperAppPath(ConfigCurator.USER_DEFCONFIGS_ZK_SUBPATH).getAbsolute(), contents);
- feedDefToZookeeper(key.getName(), key.getNamespace(), getZooKeeperAppPath(ConfigCurator.DEFCONFIGS_ZK_SUBPATH).getAbsolute(), contents);
+ write(key.getName(), key.getNamespace(), getZooKeeperAppPath(ConfigCurator.USER_DEFCONFIGS_ZK_SUBPATH).getAbsolute(), contents);
+ write(key.getName(), key.getNamespace(), getZooKeeperAppPath(ConfigCurator.DEFCONFIGS_ZK_SUBPATH).getAbsolute(), contents);
}
logger.log(LogLevel.FINE, configDefs.size() + " user config definitions");
}
- private void feedDefToZookeeper(String name, String namespace, String path, String data) {
- feedDefToZookeeper(name, namespace, "", path, com.yahoo.text.Utf8.toBytes(data));
+ private void write(String name, String namespace, String path, String data) {
+ write(name, namespace, "", path, com.yahoo.text.Utf8.toBytes(data));
}
- private void feedDefToZookeeper(String name, String namespace, String version, String path, byte[] data) {
+ private void write(String name, String namespace, String version, String path, byte[] data) {
configCurator.putDefData(
("".equals(namespace)) ? name : (namespace + "." + name),
version,
@@ -301,8 +300,8 @@ public class ZooKeeperClient {
data);
}
- private void feedZKFileRegistry(Version vespaVersion, FileRegistry fileRegistry) {
- trace("Feeding file registry data into ZooKeeper");
+ private void write(Version vespaVersion, FileRegistry fileRegistry) {
+ logFine("Feeding file registry data into ZooKeeper");
String exportedRegistry = PreGeneratedFileRegistry.exportRegistry(fileRegistry);
configCurator.putData(getZooKeeperAppPath(null).append(ZKApplicationPackage.fileRegistryNode).getAbsolute(),
@@ -316,12 +315,12 @@ public class ZooKeeperClient {
*
* @param metaData The application metadata.
*/
- private void feedZKAppMetaData(ApplicationMetaData metaData) {
+ private void write(ApplicationMetaData metaData) {
configCurator.putData(getZooKeeperAppPath(ConfigCurator.META_ZK_PATH).getAbsolute(), metaData.asJsonString());
}
void cleanupZooKeeper() {
- trace("Exception occurred. Cleaning up ZooKeeper");
+ logFine("Exception occurred. Cleaning up ZooKeeper");
try {
for (String subPath : Arrays.asList(
ConfigCurator.DEFCONFIGS_ZK_SUBPATH,
@@ -350,26 +349,20 @@ public class ZooKeeperClient {
}
}
- void trace(String msg) {
- if (trace) {
+ void logFine(String msg) {
+ if (logFine) {
logger.log(LogLevel.FINE, msg);
}
}
- private void feedProvisionInfo(Version version, ProvisionInfo info) throws IOException {
- byte[] json = info.toJson();
- configCurator.putData(rootPath.append(ZKApplicationPackage.allocatedHostsNode).append(version.toSerializedForm()).getAbsolute(), json);
+ public void write(AllocatedHosts info) throws IOException {
+ configCurator.putData(rootPath.append(ZKApplicationPackage.allocatedHostsNode).getAbsolute(), info.toJson());
}
- public void feedZKFileRegistries(Map<Version, FileRegistry> fileRegistryMap) {
+ public void write(Map<Version, FileRegistry> fileRegistryMap) {
for (Map.Entry<Version, FileRegistry> versionFileRegistryEntry : fileRegistryMap.entrySet()) {
- feedZKFileRegistry(versionFileRegistryEntry.getKey(), versionFileRegistryEntry.getValue());
+ write(versionFileRegistryEntry.getKey(), versionFileRegistryEntry.getValue());
}
}
- public void feedProvisionInfos(Map<Version, ProvisionInfo> provisionInfoMap) throws IOException {
- for (Map.Entry<Version, ProvisionInfo> versionProvisionInfoEntry : provisionInfoMap.entrySet()) {
- feedProvisionInfo(versionProvisionInfoEntry.getKey(), versionProvisionInfoEntry.getValue());
- }
- }
}
diff --git a/configserver/src/main/java/com/yahoo/vespa/config/server/deploy/ZooKeeperDeployer.java b/configserver/src/main/java/com/yahoo/vespa/config/server/deploy/ZooKeeperDeployer.java
index 246d7226cfd..22ce952481d 100644
--- a/configserver/src/main/java/com/yahoo/vespa/config/server/deploy/ZooKeeperDeployer.java
+++ b/configserver/src/main/java/com/yahoo/vespa/config/server/deploy/ZooKeeperDeployer.java
@@ -3,7 +3,7 @@ package com.yahoo.vespa.config.server.deploy;
import com.yahoo.config.application.api.ApplicationPackage;
import com.yahoo.config.application.api.FileRegistry;
-import com.yahoo.config.provision.ProvisionInfo;
+import com.yahoo.config.provision.AllocatedHosts;
import com.yahoo.config.provision.Version;
import java.io.IOException;
@@ -14,7 +14,6 @@ import java.util.Map;
* Initialize must be called before each deploy.
*
* @author lulf
- * @since 5.1
*/
public class ZooKeeperDeployer {
@@ -28,15 +27,16 @@ public class ZooKeeperDeployer {
* Deploys an application package to zookeeper. initialize() must be called before calling this method.
*
* @param applicationPackage The application package to persist.
- * @param fileRegistryMap The file registries to persist.
- * @param provisionInfoMap The provisioning infos to persist.
+ * @param fileRegistryMap the file registries to persist.
+ * @param allocatedHosts the provisioning info to persist.
* @throws IOException if deploying fails
*/
- public void deploy(ApplicationPackage applicationPackage, Map<Version, FileRegistry> fileRegistryMap, Map<Version, ProvisionInfo> provisionInfoMap) throws IOException {
+ public void deploy(ApplicationPackage applicationPackage, Map<Version, FileRegistry> fileRegistryMap,
+ AllocatedHosts allocatedHosts) throws IOException {
zooKeeperClient.setupZooKeeper();
- zooKeeperClient.feedZooKeeper(applicationPackage);
- zooKeeperClient.feedZKFileRegistries(fileRegistryMap);
- zooKeeperClient.feedProvisionInfos(provisionInfoMap);
+ zooKeeperClient.write(applicationPackage);
+ zooKeeperClient.write(fileRegistryMap);
+ zooKeeperClient.write(allocatedHosts);
}
public void cleanup() {
diff --git a/configserver/src/main/java/com/yahoo/vespa/config/server/host/HostRegistry.java b/configserver/src/main/java/com/yahoo/vespa/config/server/host/HostRegistry.java
index 36e7737163a..e61fc124d53 100644
--- a/configserver/src/main/java/com/yahoo/vespa/config/server/host/HostRegistry.java
+++ b/configserver/src/main/java/com/yahoo/vespa/config/server/host/HostRegistry.java
@@ -16,7 +16,6 @@ import com.yahoo.log.LogLevel;
* TODO: Is there a generalized version of this pattern? Need some sort mix of Bimap and Multimap
*
* @author lulf
- * @since 5.3
*/
public class HostRegistry<T> implements HostValidator<T> {
diff --git a/configserver/src/main/java/com/yahoo/vespa/config/server/modelfactory/ActivatedModelsBuilder.java b/configserver/src/main/java/com/yahoo/vespa/config/server/modelfactory/ActivatedModelsBuilder.java
index bbd1e189e29..1301f24788f 100644
--- a/configserver/src/main/java/com/yahoo/vespa/config/server/modelfactory/ActivatedModelsBuilder.java
+++ b/configserver/src/main/java/com/yahoo/vespa/config/server/modelfactory/ActivatedModelsBuilder.java
@@ -5,12 +5,11 @@ import com.yahoo.cloud.config.ConfigserverConfig;
import com.yahoo.config.application.api.ApplicationPackage;
import com.yahoo.config.application.api.DeployLogger;
import com.yahoo.config.model.api.ConfigDefinitionRepo;
-import com.yahoo.config.model.api.HostProvisioner;
import com.yahoo.config.model.api.ModelContext;
import com.yahoo.config.model.api.ModelFactory;
import com.yahoo.config.model.application.provider.MockFileRegistry;
import com.yahoo.config.provision.ApplicationId;
-import com.yahoo.config.provision.ProvisionInfo;
+import com.yahoo.config.provision.AllocatedHosts;
import com.yahoo.config.provision.TenantName;
import com.yahoo.config.provision.Version;
import com.yahoo.config.provision.Zone;
@@ -24,7 +23,6 @@ import com.yahoo.vespa.config.server.application.PermanentApplicationPackage;
import com.yahoo.vespa.config.server.deploy.ModelContextImpl;
import com.yahoo.vespa.config.server.monitoring.MetricUpdater;
import com.yahoo.vespa.config.server.monitoring.Metrics;
-import com.yahoo.vespa.config.server.provision.StaticProvisioner;
import com.yahoo.vespa.config.server.session.SessionZooKeeperClient;
import com.yahoo.vespa.config.server.session.SilentDeployLogger;
import com.yahoo.vespa.curator.Curator;
@@ -47,7 +45,6 @@ public class ActivatedModelsBuilder extends ModelsBuilder<Application> {
private final long appGeneration;
private final SessionZooKeeperClient zkClient;
private final Optional<PermanentApplicationPackage> permanentApplicationPackage;
- private final Optional<com.yahoo.config.provision.Provisioner> hostProvisioner;
private final ConfigserverConfig configserverConfig;
private final ConfigDefinitionRepo configDefinitionRepo;
private final Metrics metrics;
@@ -56,7 +53,8 @@ public class ActivatedModelsBuilder extends ModelsBuilder<Application> {
private final DeployLogger logger;
public ActivatedModelsBuilder(TenantName tenant, long appGeneration, SessionZooKeeperClient zkClient, GlobalComponentRegistry globalComponentRegistry) {
- super(globalComponentRegistry.getModelFactoryRegistry());
+ super(globalComponentRegistry.getModelFactoryRegistry(),
+ globalComponentRegistry.getHostProvisioner().isPresent());
this.tenant = tenant;
this.appGeneration = appGeneration;
this.zkClient = zkClient;
@@ -64,17 +62,17 @@ public class ActivatedModelsBuilder extends ModelsBuilder<Application> {
this.configserverConfig = globalComponentRegistry.getConfigserverConfig();
this.configDefinitionRepo = globalComponentRegistry.getConfigDefinitionRepo();
this.metrics = globalComponentRegistry.getMetrics();
- this.hostProvisioner = globalComponentRegistry.getHostProvisioner();
this.curator = globalComponentRegistry.getCurator();
this.zone = globalComponentRegistry.getZone();
this.logger = new SilentDeployLogger();
}
@Override
- protected Application buildModelVersion(ModelFactory modelFactory,
+ protected Application buildModelVersion(ModelFactory modelFactory,
ApplicationPackage applicationPackage,
- ApplicationId applicationId,
+ ApplicationId applicationId,
com.yahoo.component.Version wantedNodeVespaVersion,
+ Optional<AllocatedHosts> ignored, // Ignored since we have this in the app package for activated models
Instant now) {
log.log(LogLevel.DEBUG, String.format("Loading model version %s for session %s application %s",
modelFactory.getVersion(), appGeneration, applicationId));
@@ -86,7 +84,7 @@ public class ActivatedModelsBuilder extends ModelsBuilder<Application> {
logger,
configDefinitionRepo,
getForVersionOrLatest(applicationPackage.getFileRegistryMap(), modelFactory.getVersion()).orElse(new MockFileRegistry()),
- createHostProvisioner(getForVersionOrLatest(applicationPackage.getProvisionInfoMap(), modelFactory.getVersion())),
+ createStaticProvisioner(applicationPackage.getAllocatedHosts()),
createModelContextProperties(applicationId),
Optional.empty(),
new com.yahoo.component.Version(modelFactory.getVersion().toString()),
@@ -96,17 +94,6 @@ public class ActivatedModelsBuilder extends ModelsBuilder<Application> {
applicationMetricUpdater, applicationId);
}
- private Optional<HostProvisioner> createHostProvisioner(Optional<ProvisionInfo> provisionInfo) {
- if (hostProvisioner.isPresent() && provisionInfo.isPresent()) {
- return Optional.of(createStaticProvisioner(provisionInfo.get()));
- }
- return Optional.empty();
- }
-
- private HostProvisioner createStaticProvisioner(ProvisionInfo provisionInfo) {
- return new StaticProvisioner(provisionInfo);
- }
-
private static <T> Optional<T> getForVersionOrLatest(Map<Version, T> map, Version version) {
if (map.isEmpty()) {
return Optional.empty();
diff --git a/configserver/src/main/java/com/yahoo/vespa/config/server/modelfactory/ModelFactoryRegistry.java b/configserver/src/main/java/com/yahoo/vespa/config/server/modelfactory/ModelFactoryRegistry.java
index ab1c84eb5dd..1c2c9c731d1 100644
--- a/configserver/src/main/java/com/yahoo/vespa/config/server/modelfactory/ModelFactoryRegistry.java
+++ b/configserver/src/main/java/com/yahoo/vespa/config/server/modelfactory/ModelFactoryRegistry.java
@@ -13,7 +13,7 @@ import java.util.*;
* A registry of model factories. Allows querying for a specific version of a {@link ModelFactory} or
* simply returning all of them. Keeps track of the latest {@link com.yahoo.config.provision.Version} supported.
*
- * @author lulf
+ * @author Ulf Lilleengen
*/
public class ModelFactoryRegistry {
diff --git a/configserver/src/main/java/com/yahoo/vespa/config/server/modelfactory/ModelsBuilder.java b/configserver/src/main/java/com/yahoo/vespa/config/server/modelfactory/ModelsBuilder.java
index cc7a12801d3..6a4ab40d843 100644
--- a/configserver/src/main/java/com/yahoo/vespa/config/server/modelfactory/ModelsBuilder.java
+++ b/configserver/src/main/java/com/yahoo/vespa/config/server/modelfactory/ModelsBuilder.java
@@ -3,16 +3,20 @@ package com.yahoo.vespa.config.server.modelfactory;
import com.yahoo.cloud.config.ConfigserverConfig;
import com.yahoo.config.application.api.ApplicationPackage;
+import com.yahoo.config.model.api.HostProvisioner;
import com.yahoo.config.model.api.ModelContext;
import com.yahoo.config.model.api.ModelFactory;
import com.yahoo.config.provision.ApplicationId;
import com.yahoo.config.provision.OutOfCapacityException;
+import com.yahoo.config.provision.AllocatedHosts;
import com.yahoo.config.provision.Rotation;
import com.yahoo.config.provision.Version;
import com.yahoo.config.provision.Zone;
+import com.yahoo.lang.SettableOptional;
import com.yahoo.vespa.config.server.ConfigServerSpec;
import com.yahoo.vespa.config.server.deploy.ModelContextImpl;
import com.yahoo.vespa.config.server.http.UnknownVespaVersionException;
+import com.yahoo.vespa.config.server.provision.StaticProvisioner;
import java.time.Instant;
import java.util.ArrayList;
@@ -37,13 +41,24 @@ public abstract class ModelsBuilder<MODELRESULT extends ModelResult> {
private final ModelFactoryRegistry modelFactoryRegistry;
- protected ModelsBuilder(ModelFactoryRegistry modelFactoryRegistry) {
+ /** True if we are running in hosted mode */
+ private final boolean hosted;
+
+ protected ModelsBuilder(ModelFactoryRegistry modelFactoryRegistry, boolean hosted) {
this.modelFactoryRegistry = modelFactoryRegistry;
+ this.hosted = hosted;
}
+ /**
+ * 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();
@@ -52,7 +67,7 @@ public abstract class ModelsBuilder<MODELRESULT extends ModelResult> {
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 unloadable
+ // 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()
@@ -65,7 +80,8 @@ public abstract class ModelsBuilder<MODELRESULT extends ModelResult> {
for (int i = 0; i < majorVersions.size(); i++) {
try {
allApplicationModels.addAll(buildModelVersion(filterByMajorVersion(majorVersions.get(i), versions),
- applicationId, wantedNodeVespaVersion, applicationPackage, now));
+ 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))
@@ -91,30 +107,43 @@ public abstract class ModelsBuilder<MODELRESULT extends ModelResult> {
private List<MODELRESULT> buildModelVersion(Set<Version> versions, ApplicationId applicationId,
com.yahoo.component.Version wantedNodeVespaVersion,
ApplicationPackage applicationPackage,
+ SettableOptional<AllocatedHosts> allocatedHosts,
Instant now) {
Version latest = findLatest(versions);
// load latest application version
- MODELRESULT latestApplicationVersion = buildModelVersion(modelFactoryRegistry.getFactory(latest),
+ MODELRESULT latestModelVersion = buildModelVersion(modelFactoryRegistry.getFactory(latest),
applicationPackage,
applicationId,
wantedNodeVespaVersion,
+ allocatedHosts.asOptional(),
now);
- if (latestApplicationVersion.getModel().skipOldConfigModels(now)) {
- return Collections.singletonList(latestApplicationVersion);
- }
- else { // load old model versions
- List<MODELRESULT> allApplicationVersions = new ArrayList<>();
- allApplicationVersions.add(latestApplicationVersion);
- for (Version version : versions) {
- if (version.equals(latest)) continue; // already loaded
- allApplicationVersions.add(buildModelVersion(modelFactoryRegistry.getFactory(version),
- applicationPackage,
- applicationId,
- wantedNodeVespaVersion,
- now));
- }
- return allApplicationVersions;
+ allocatedHosts.set(latestModelVersion.getModel().allocatedHosts()); // Update with additional clusters allocated
+
+ if (latestModelVersion.getModel().skipOldConfigModels(now))
+ return Collections.singletonList(latestModelVersion);
+
+ // load old model versions
+ List<MODELRESULT> allApplicationVersions = new ArrayList<>();
+ allApplicationVersions.add(latestModelVersion);
+
+ // TODO: We use the allocated hosts from the newest version when building older model versions.
+ // This is correct except for the case where an old model specifies a cluster which the new version
+ // does not. In that case we really want to extend the set of allocated hosts to include those of that
+ // cluster as well. To do that, create a new provisioner which uses static provisioning for known
+ // clusters and the node repository provisioner as fallback.
+ for (Version version : versions) {
+ if (version.equals(latest)) continue; // already loaded
+
+ MODELRESULT modelVersion = buildModelVersion(modelFactoryRegistry.getFactory(version),
+ applicationPackage,
+ applicationId,
+ wantedNodeVespaVersion,
+ allocatedHosts.asOptional(),
+ now);
+ allocatedHosts.set(modelVersion.getModel().allocatedHosts()); // Update with additional clusters allocated
+ allApplicationVersions.add(modelVersion);
}
+ return allApplicationVersions;
}
private Set<Version> filterByMajorVersion(int majorVersion, Set<Version> versions) {
@@ -133,6 +162,7 @@ public abstract class ModelsBuilder<MODELRESULT extends ModelResult> {
protected abstract MODELRESULT buildModelVersion(ModelFactory modelFactory, ApplicationPackage applicationPackage,
ApplicationId applicationId,
com.yahoo.component.Version wantedNodeVespaVersion,
+ Optional<AllocatedHosts> allocatedHosts,
Instant now);
protected ModelContext.Properties createModelContextProperties(ApplicationId applicationId,
@@ -147,4 +177,15 @@ public abstract class ModelsBuilder<MODELRESULT extends ModelResult> {
rotations);
}
+ /**
+ * Returns a host provisioner returning the previously allocated hosts if available and when on hosted Vespa,
+ * returns empty otherwise, which may either mean that no hosts are allocated or that we are running
+ * non-hosted and should default to use hosts defined in the application package, depending on context
+ */
+ protected Optional<HostProvisioner> createStaticProvisioner(Optional<AllocatedHosts> allocatedHosts) {
+ if (hosted && allocatedHosts.isPresent())
+ return Optional.of(new StaticProvisioner(allocatedHosts.get()));
+ return Optional.empty();
+ }
+
}
diff --git a/configserver/src/main/java/com/yahoo/vespa/config/server/modelfactory/PreparedModelsBuilder.java b/configserver/src/main/java/com/yahoo/vespa/config/server/modelfactory/PreparedModelsBuilder.java
index b2dca075c4f..78d660b347e 100644
--- a/configserver/src/main/java/com/yahoo/vespa/config/server/modelfactory/PreparedModelsBuilder.java
+++ b/configserver/src/main/java/com/yahoo/vespa/config/server/modelfactory/PreparedModelsBuilder.java
@@ -12,6 +12,7 @@ import com.yahoo.config.model.api.ModelCreateResult;
import com.yahoo.config.model.api.ModelFactory;
import com.yahoo.config.model.application.provider.FilesApplicationPackage;
import com.yahoo.config.provision.ApplicationId;
+import com.yahoo.config.provision.AllocatedHosts;
import com.yahoo.config.provision.Version;
import com.yahoo.log.LogLevel;
import com.yahoo.vespa.config.server.application.ApplicationSet;
@@ -21,6 +22,7 @@ import com.yahoo.vespa.config.server.deploy.ModelContextImpl;
import com.yahoo.vespa.config.server.filedistribution.FileDistributionProvider;
import com.yahoo.vespa.config.server.provision.HostProvisionerProvider;
import com.yahoo.vespa.config.server.provision.ProvisionerAdapter;
+import com.yahoo.vespa.config.server.provision.StaticProvisioner;
import com.yahoo.vespa.config.server.session.FileDistributionFactory;
import com.yahoo.vespa.config.server.session.PrepareParams;
import com.yahoo.vespa.config.server.session.SessionContext;
@@ -60,7 +62,7 @@ public class PreparedModelsBuilder extends ModelsBuilder<PreparedModelsBuilder.P
PrepareParams params,
Optional<ApplicationSet> currentActiveApplicationSet,
ModelContext.Properties properties) {
- super(modelFactoryRegistry);
+ super(modelFactoryRegistry, properties.hostedVespa());
this.permanentApplicationPackage = permanentApplicationPackage;
this.configDefinitionRepo = configDefinitionRepo;
@@ -79,14 +81,17 @@ public class PreparedModelsBuilder extends ModelsBuilder<PreparedModelsBuilder.P
protected PreparedModelResult buildModelVersion(ModelFactory modelFactory,
ApplicationPackage applicationPackage,
ApplicationId applicationId,
- com.yahoo.component.Version wantedNodeVespaVersion, Instant now) {
+ com.yahoo.component.Version wantedNodeVespaVersion,
+ Optional<AllocatedHosts> allocatedHosts,
+ Instant now) {
Version modelVersion = modelFactory.getVersion();
log.log(LogLevel.DEBUG, "Building model " + modelVersion + " for " + applicationId);
FileDistributionProvider fileDistributionProvider = fileDistributionFactory.createProvider(
context.getServerDBSessionDir(),
applicationId);
- Optional<HostProvisioner> hostProvisioner = createHostProvisionerAdapter(properties);
+ // Use empty on non-hosted systems, use already allocated hosts if available, create connection to a host provisioner otherwise
+ Optional<HostProvisioner> hostProvisioner = createHostProvisioner(allocatedHosts);
Optional<Model> previousModel = currentActiveApplicationSet
.map(set -> set.getForVersionOrLatest(Optional.of(modelVersion), now).getModel());
ModelContext modelContext = new ModelContextImpl(
@@ -109,6 +114,24 @@ public class PreparedModelsBuilder extends ModelsBuilder<PreparedModelsBuilder.P
return new PreparedModelsBuilder.PreparedModelResult(modelVersion, result.getModel(), fileDistributionProvider, result.getConfigChangeActions());
}
+ // This method is an excellent demonstration of what happens when one is too liberal with Optional
+ // -bratseth, who had to write the below :-\
+ private Optional<HostProvisioner> createHostProvisioner(Optional<AllocatedHosts> allocatedHosts) {
+ Optional<HostProvisioner> nodeRepositoryProvisioner = createNodeRepositoryProvisioner(properties);
+ if ( ! allocatedHosts.isPresent()) return nodeRepositoryProvisioner;
+
+ Optional<HostProvisioner> staticProvisioner = createStaticProvisioner(allocatedHosts);
+ if ( ! staticProvisioner.isPresent()) return Optional.empty(); // Since we have hosts allocated this means we are on non-hosted
+
+ // The following option should not be possible, but since there is a right action for it we can take it
+ if ( ! nodeRepositoryProvisioner.isPresent())
+ return Optional.of(new StaticProvisioner(allocatedHosts.get()));
+
+ // Nodes are already allocated by a model and we should use them unless this model requests hosts from a
+ // previously unallocated cluster. This allows future models to stop allocate certain clusters.
+ return Optional.of(new StaticProvisioner(allocatedHosts.get(), nodeRepositoryProvisioner.get()));
+ }
+
private Optional<File> getAppDir(ApplicationPackage applicationPackage) {
try {
return applicationPackage instanceof FilesApplicationPackage ?
@@ -124,7 +147,7 @@ public class PreparedModelsBuilder extends ModelsBuilder<PreparedModelsBuilder.P
.collect(Collectors.toList()));
}
- private Optional<HostProvisioner> createHostProvisionerAdapter(ModelContext.Properties properties) {
+ private Optional<HostProvisioner> createNodeRepositoryProvisioner(ModelContext.Properties properties) {
return hostProvisionerProvider.getHostProvisioner().map(
provisioner -> new ProvisionerAdapter(provisioner, properties.applicationId()));
}
diff --git a/configserver/src/main/java/com/yahoo/vespa/config/server/provision/HostProvisionerProvider.java b/configserver/src/main/java/com/yahoo/vespa/config/server/provision/HostProvisionerProvider.java
index 619ee7499e2..32a641a3bc7 100644
--- a/configserver/src/main/java/com/yahoo/vespa/config/server/provision/HostProvisionerProvider.java
+++ b/configserver/src/main/java/com/yahoo/vespa/config/server/provision/HostProvisionerProvider.java
@@ -13,21 +13,18 @@ import java.util.logging.Logger;
/**
* This class is necessary to support both having and not having a host provisioner. We inject
* a component registry here, which then enables us to check whether or not we have a provisioner available.
+ * We only have a provisioner if we are running in hosted mode.
*
- * @author lulf
- * @since 5.15
+ * @author Ulf Lilleengen
*/
public class HostProvisionerProvider {
- private static final Logger log = Logger.getLogger(HostProvisionerProvider.class.getName());
private final Optional<Provisioner> hostProvisioner;
public HostProvisionerProvider(ComponentRegistry<Provisioner> hostProvisionerRegistry, ConfigserverConfig configserverConfig) {
if (hostProvisionerRegistry.allComponents().isEmpty() || ! configserverConfig.hostedVespa()) {
- log.info("Host provisioner is missing, provisioner component count: " + hostProvisionerRegistry.allComponents().size() + ", is hosted Vespa: " + configserverConfig.hostedVespa());
hostProvisioner = Optional.empty();
} else {
- log.log(LogLevel.DEBUG, "Host provisioner injected. Will be used for all deployments");
hostProvisioner = Optional.of(hostProvisionerRegistry.allComponents().get(0));
}
}
@@ -36,6 +33,7 @@ public class HostProvisionerProvider {
this(componentRegistry, new ConfigserverConfig(new ConfigserverConfig.Builder()));
}
+ /** Returns the host provisioner, or empty if we are not in hosted mode */
public Optional<Provisioner> getHostProvisioner() {
return hostProvisioner;
}
diff --git a/configserver/src/main/java/com/yahoo/vespa/config/server/provision/ProvisionerAdapter.java b/configserver/src/main/java/com/yahoo/vespa/config/server/provision/ProvisionerAdapter.java
index ad0ee3b3eb9..32380b296dd 100644
--- a/configserver/src/main/java/com/yahoo/vespa/config/server/provision/ProvisionerAdapter.java
+++ b/configserver/src/main/java/com/yahoo/vespa/config/server/provision/ProvisionerAdapter.java
@@ -16,8 +16,7 @@ import java.util.*;
* behavior to the config model. Adapts interface from a {@link HostProvisioner} to a
* {@link Provisioner}.
*
- * @author lulf
- * @since 5.11
+ * @author Ulf Lilleengen
*/
public class ProvisionerAdapter implements HostProvisioner {
@@ -31,6 +30,7 @@ public class ProvisionerAdapter implements HostProvisioner {
@Override
public HostSpec allocateHost(String alias) {
+ // Wow. Such mess. TODO: Actually support polymorphy or stop pretending to, see also ModelContextImpl.getHostProvisioner
throw new UnsupportedOperationException("Allocating a single host in a hosted environment is not possible");
}
diff --git a/configserver/src/main/java/com/yahoo/vespa/config/server/provision/StaticProvisioner.java b/configserver/src/main/java/com/yahoo/vespa/config/server/provision/StaticProvisioner.java
index 1cad735879a..7e97690331f 100644
--- a/configserver/src/main/java/com/yahoo/vespa/config/server/provision/StaticProvisioner.java
+++ b/configserver/src/main/java/com/yahoo/vespa/config/server/provision/StaticProvisioner.java
@@ -5,19 +5,35 @@ import com.yahoo.config.model.api.HostProvisioner;
import com.yahoo.config.provision.*;
import java.util.List;
+import java.util.Optional;
import java.util.stream.Collectors;
/**
- * Host provisioning from an existing {@link ProvisionInfo} instance.
+ * Host provisioning from an existing {@link AllocatedHosts} instance.
*
* @author bratseth
*/
public class StaticProvisioner implements HostProvisioner {
- private final ProvisionInfo provisionInfo;
+ private final AllocatedHosts allocatedHosts;
+
+ /** The fallback provisioner to use for unknown clusters, or null to not fall back */
+ private final HostProvisioner fallback;
- public StaticProvisioner(ProvisionInfo provisionInfo) {
- this.provisionInfo = provisionInfo;
+ /**
+ * Creates a static host provisioner with no fallback
+ */
+ public StaticProvisioner(AllocatedHosts allocatedHosts) {
+ this(allocatedHosts, null);
+ }
+
+ /**
+ * Creates a static host provisioner which will fall back to using the given provisioner
+ * if a request is made for nodes in a cluster which is not present in this allocation.
+ */
+ public StaticProvisioner(AllocatedHosts allocatedHosts, HostProvisioner fallback) {
+ this.allocatedHosts = allocatedHosts;
+ this.fallback = fallback;
}
@Override
@@ -27,9 +43,14 @@ public class StaticProvisioner implements HostProvisioner {
@Override
public List<HostSpec> prepare(ClusterSpec cluster, Capacity capacity, int groups, ProvisionLogger logger) {
- return provisionInfo.getHosts().stream()
- .filter(host -> host.membership().isPresent() && matches(host.membership().get().cluster(), cluster))
- .collect(Collectors.toList());
+ List<HostSpec> hostsAlreadyAllocatedToCluster =
+ allocatedHosts.getHosts().stream()
+ .filter(host -> host.membership().isPresent() && matches(host.membership().get().cluster(), cluster))
+ .collect(Collectors.toList());
+ if ( ! hostsAlreadyAllocatedToCluster.isEmpty())
+ return hostsAlreadyAllocatedToCluster;
+ else
+ return fallback.prepare(cluster, capacity, groups, logger);
}
private boolean matches(ClusterSpec nodeCluster, ClusterSpec requestedCluster) {
diff --git a/configserver/src/main/java/com/yahoo/vespa/config/server/session/LocalSession.java b/configserver/src/main/java/com/yahoo/vespa/config/server/session/LocalSession.java
index a222182f87a..308ca31f278 100644
--- a/configserver/src/main/java/com/yahoo/vespa/config/server/session/LocalSession.java
+++ b/configserver/src/main/java/com/yahoo/vespa/config/server/session/LocalSession.java
@@ -6,7 +6,7 @@ import com.yahoo.config.application.api.ApplicationFile;
import com.yahoo.config.application.api.ApplicationPackage;
import com.yahoo.config.application.api.ApplicationMetaData;
import com.yahoo.config.application.api.DeployLogger;
-import com.yahoo.config.provision.ProvisionInfo;
+import com.yahoo.config.provision.AllocatedHosts;
import com.yahoo.transaction.AbstractTransaction;
import com.yahoo.transaction.NestedTransaction;
import com.yahoo.transaction.Transaction;
@@ -30,11 +30,10 @@ import java.util.Optional;
* prepared. Deleting a local session will ensure that the local filesystem state and global zookeeper state is
* cleaned for this session.
*
- * @author lulf
- * @since 5.1
+ * @author Ulf Lilleengen
*/
// This is really the store of an application, whether it is active or in an edit session
-// TODO: Separate the "application store" and "session" aspects - the latter belongs in the HTTP layer
+// TODO: Separate the "application store" and "session" aspects - the latter belongs in the HTTP layer -bratseth
public class LocalSession extends Session implements Comparable<LocalSession> {
private final ApplicationPackage applicationPackage;
@@ -172,8 +171,8 @@ public class LocalSession extends Session implements Comparable<LocalSession> {
public Version getVespaVersion() { return zooKeeperClient.readVespaVersion(); }
- public ProvisionInfo getProvisionInfo() {
- return zooKeeperClient.getProvisionInfo();
+ public AllocatedHosts getAllocatedHosts() {
+ return zooKeeperClient.getAllocatedHosts();
}
@Override
diff --git a/configserver/src/main/java/com/yahoo/vespa/config/server/session/LocalSessionRepo.java b/configserver/src/main/java/com/yahoo/vespa/config/server/session/LocalSessionRepo.java
index 7fff132dd7d..ae15be83062 100644
--- a/configserver/src/main/java/com/yahoo/vespa/config/server/session/LocalSessionRepo.java
+++ b/configserver/src/main/java/com/yahoo/vespa/config/server/session/LocalSessionRepo.java
@@ -18,7 +18,6 @@ import java.util.logging.Logger;
* File-based session repository for LocalSessions. Contains state for the local instance of the configserver.
*
* @author lulf
- * @since 5.1
*/
public class LocalSessionRepo extends SessionRepo<LocalSession> {
diff --git a/configserver/src/main/java/com/yahoo/vespa/config/server/session/RemoteSession.java b/configserver/src/main/java/com/yahoo/vespa/config/server/session/RemoteSession.java
index c20f6e0b853..5f3cf46e0de 100644
--- a/configserver/src/main/java/com/yahoo/vespa/config/server/session/RemoteSession.java
+++ b/configserver/src/main/java/com/yahoo/vespa/config/server/session/RemoteSession.java
@@ -2,6 +2,7 @@
package com.yahoo.vespa.config.server.session;
import com.yahoo.config.provision.*;
+import com.yahoo.lang.SettableOptional;
import com.yahoo.vespa.config.server.*;
import com.yahoo.log.LogLevel;
import com.yahoo.vespa.config.server.application.ApplicationSet;
@@ -19,8 +20,7 @@ import java.util.logging.Logger;
* A RemoteSession represents a session created on another config server. This session can
* be regarded as read only, and this interface only allows reading information about a session.
*
- * @author lulf
- * @since 5.1
+ * @author Ulf Lilleengen
*/
public class RemoteSession extends Session {
@@ -57,6 +57,7 @@ public class RemoteSession extends Session {
return ApplicationSet.fromList(applicationLoader.buildModels(zooKeeperClient.readApplicationId(),
zooKeeperClient.readVespaVersion(),
zooKeeperClient.loadApplicationPackage(),
+ new SettableOptional<>(),
clock.instant()));
}
diff --git a/configserver/src/main/java/com/yahoo/vespa/config/server/session/RemoteSessionFactory.java b/configserver/src/main/java/com/yahoo/vespa/config/server/session/RemoteSessionFactory.java
index 0f1e65aaf2b..298acaca901 100644
--- a/configserver/src/main/java/com/yahoo/vespa/config/server/session/RemoteSessionFactory.java
+++ b/configserver/src/main/java/com/yahoo/vespa/config/server/session/RemoteSessionFactory.java
@@ -12,8 +12,7 @@ import com.yahoo.vespa.curator.Curator;
import java.time.Clock;
/**
- * @author lulf
- * @since 5.1.24
+ * @author Ulf Lilleengen
*/
public class RemoteSessionFactory {
diff --git a/configserver/src/main/java/com/yahoo/vespa/config/server/session/SessionContext.java b/configserver/src/main/java/com/yahoo/vespa/config/server/session/SessionContext.java
index a840e5d5a97..323c2667d30 100644
--- a/configserver/src/main/java/com/yahoo/vespa/config/server/session/SessionContext.java
+++ b/configserver/src/main/java/com/yahoo/vespa/config/server/session/SessionContext.java
@@ -12,8 +12,7 @@ import java.io.File;
/**
* The dependencies needed for a local session to be edited and prepared.
*
- * @author lulf
- * @since 5.1
+ * @author Ulf Lilleengen
*/
public class SessionContext {
diff --git a/configserver/src/main/java/com/yahoo/vespa/config/server/session/SessionFactoryImpl.java b/configserver/src/main/java/com/yahoo/vespa/config/server/session/SessionFactoryImpl.java
index 19651041ea4..c2655d1a1b3 100644
--- a/configserver/src/main/java/com/yahoo/vespa/config/server/session/SessionFactoryImpl.java
+++ b/configserver/src/main/java/com/yahoo/vespa/config/server/session/SessionFactoryImpl.java
@@ -170,7 +170,8 @@ public class SessionFactoryImpl implements SessionFactory, LocalSessionLoader {
defRepo,
serverId,
nodeFlavors);
- SessionContext context = new SessionContext(applicationPackage, sessionZKClient, sessionDir, applicationRepo, hostRegistry, superModelGenerationCounter);
+ SessionContext context = new SessionContext(applicationPackage, sessionZKClient, sessionDir, applicationRepo,
+ hostRegistry, superModelGenerationCounter);
return new LocalSession(tenant, sessionId, sessionPreparer, context);
}
diff --git a/configserver/src/main/java/com/yahoo/vespa/config/server/session/SessionPreparer.java b/configserver/src/main/java/com/yahoo/vespa/config/server/session/SessionPreparer.java
index 0b76c57e142..beb62cf3ac9 100644
--- a/configserver/src/main/java/com/yahoo/vespa/config/server/session/SessionPreparer.java
+++ b/configserver/src/main/java/com/yahoo/vespa/config/server/session/SessionPreparer.java
@@ -10,6 +10,7 @@ import com.yahoo.config.application.api.FileRegistry;
import com.yahoo.config.model.api.ConfigDefinitionRepo;
import com.yahoo.config.model.api.ModelContext;
import com.yahoo.config.provision.*;
+import com.yahoo.lang.SettableOptional;
import com.yahoo.log.LogLevel;
import com.yahoo.path.Path;
import com.yahoo.vespa.config.server.application.ApplicationSet;
@@ -42,8 +43,7 @@ import javax.xml.transform.TransformerException;
/**
* A SessionPreparer is responsible for preparing a session given an application package.
*
- * @author lulf
- * @since 5.1
+ * @author Ulf Lilleengen
*/
public class SessionPreparer {
@@ -92,8 +92,8 @@ public class SessionPreparer {
Preparation preparation = new Preparation(context, logger, params, currentActiveApplicationSet, tenantPath);
preparation.preprocess();
try {
- preparation.buildModels(now);
- preparation.makeResult();
+ AllocatedHosts allocatedHosts = preparation.buildModels(now);
+ preparation.makeResult(allocatedHosts);
if ( ! params.isDryRun()) {
preparation.writeStateZK();
preparation.writeRotZK();
@@ -177,13 +177,16 @@ public class SessionPreparer {
checkTimeout("preprocess");
}
- void buildModels(Instant now) {
- this.modelResultList = preparedModelsBuilder.buildModels(applicationId, vespaVersion, applicationPackage, now);
+ AllocatedHosts buildModels(Instant now) {
+ SettableOptional<AllocatedHosts> allocatedHosts = new SettableOptional<>();
+ this.modelResultList = preparedModelsBuilder.buildModels(applicationId, vespaVersion,
+ applicationPackage, allocatedHosts, now);
checkTimeout("build models");
+ return allocatedHosts.get();
}
- void makeResult() {
- this.prepareResult = new PrepareResult(modelResultList);
+ void makeResult(AllocatedHosts allocatedHosts) {
+ this.prepareResult = new PrepareResult(allocatedHosts, modelResultList);
checkTimeout("making result from models");
}
@@ -195,7 +198,7 @@ public class SessionPreparer {
vespaVersion,
logger,
prepareResult.getFileRegistries(),
- prepareResult.getProvisionInfos());
+ prepareResult.allocatedHosts());
checkTimeout("write state to zookeeper");
}
@@ -236,10 +239,10 @@ public class SessionPreparer {
com.yahoo.component.Version vespaVersion,
DeployLogger deployLogger,
Map<Version, FileRegistry> fileRegistryMap,
- Map<Version, ProvisionInfo> provisionInfoMap) {
+ AllocatedHosts allocatedHosts) {
ZooKeeperDeployer zkDeployer = zooKeeperClient.createDeployer(deployLogger);
try {
- zkDeployer.deploy(applicationPackage, fileRegistryMap, provisionInfoMap);
+ zkDeployer.deploy(applicationPackage, fileRegistryMap, allocatedHosts);
zooKeeperClient.writeApplicationId(applicationId);
zooKeeperClient.writeVespaVersion(vespaVersion);
} catch (RuntimeException | IOException e) {
@@ -251,21 +254,19 @@ public class SessionPreparer {
/** The result of preparation over all model versions */
private static class PrepareResult {
+ private final AllocatedHosts allocatedHosts;
private final ImmutableList<PreparedModelsBuilder.PreparedModelResult> results;
-
- public PrepareResult(List<PreparedModelsBuilder.PreparedModelResult> results) {
+
+ public PrepareResult(AllocatedHosts allocatedHosts, List<PreparedModelsBuilder.PreparedModelResult> results) {
+ this.allocatedHosts = allocatedHosts;
this.results = ImmutableList.copyOf(results);
}
/** Returns the results for each model as an immutable list */
public List<PreparedModelsBuilder.PreparedModelResult> asList() { return results; }
- public Map<Version, ProvisionInfo> getProvisionInfos() {
- return results.stream()
- .filter(result -> result.model.getProvisionInfo().isPresent())
- .collect(Collectors.toMap((prepareResult -> prepareResult.version),
- (prepareResult -> prepareResult.model.getProvisionInfo().get())));
- }
+ /** Returns the host allocations resulting from this preparation. */
+ public AllocatedHosts allocatedHosts() { return allocatedHosts; }
public Map<Version, FileRegistry> getFileRegistries() {
return results.stream()
@@ -290,4 +291,31 @@ public class SessionPreparer {
}
+ /**
+ * During model building each model version will request nodes allocated (from the node allocator)
+ * for each cluster specified by that model. As allocations are stable this should usually
+ * result in the same allocations for the same clusters across all model versions,
+ * otherwise we should fail this preparation as such inconsistencies lead to undefined behavior,
+ * and there is really just one true allocation (for a given cluster) to be activated in the node repository.
+ *
+ * However, these disagreements between allocations in each model version are allowed:
+ * - A node may be retired in some model version but not another. This allows model versions to change cluster sizes,
+ * and is ok because the system will converge on the latest version's opinion
+ * - Clusters may be present on some version but not on another. This does not lead to inconsistency
+ * and allows new model versions to introduce new clusters.
+ *
+ * For each cluster, the newest model version which has that cluster decides the correct retirement status of nodes
+ * (and all model versions having the cluster must have the same nodes).
+ *
+ * This class ensures these constraints and returns a reconciliated set of nodes which should be activated,
+ * given a set of model activation results.
+ */
+ private static final class ReconciliatedHostAllocations {
+
+ public ReconciliatedHostAllocations(List<PreparedModelsBuilder.PreparedModelResult> results) {
+
+ }
+
+ }
+
}
diff --git a/configserver/src/main/java/com/yahoo/vespa/config/server/session/SessionZooKeeperClient.java b/configserver/src/main/java/com/yahoo/vespa/config/server/session/SessionZooKeeperClient.java
index a677c5cb7f9..09fc83e225d 100644
--- a/configserver/src/main/java/com/yahoo/vespa/config/server/session/SessionZooKeeperClient.java
+++ b/configserver/src/main/java/com/yahoo/vespa/config/server/session/SessionZooKeeperClient.java
@@ -6,8 +6,7 @@ import com.yahoo.component.Vtag;
import com.yahoo.config.application.api.ApplicationPackage;
import com.yahoo.config.application.api.DeployLogger;
import com.yahoo.config.provision.NodeFlavors;
-import com.yahoo.config.provision.ProvisionInfo;
-import com.yahoo.config.provision.TenantName;
+import com.yahoo.config.provision.AllocatedHosts;
import com.yahoo.transaction.Transaction;
import com.yahoo.log.LogLevel;
import com.yahoo.path.Path;
@@ -31,8 +30,7 @@ import java.util.concurrent.TimeUnit;
* Zookeeper client for a specific session. Can be used to read and write session status
* and create and get prepare and active barrier.
*
- * @author lulf
- * @since 5.1
+ * @author Ulf Lilleengen
*/
public class SessionZooKeeperClient {
@@ -189,10 +187,9 @@ public class SessionZooKeeperClient {
return rootPath.append(CREATE_TIME_PATH).getAbsolute();
}
- ProvisionInfo getProvisionInfo() {
- return loadApplicationPackage().getProvisionInfoMap().values().stream()
- .reduce((infoA, infoB) -> infoA.merge(infoB))
- .orElseThrow(() -> new IllegalStateException("Trying to read provision info, but no provision info exists"));
+ AllocatedHosts getAllocatedHosts() {
+ return loadApplicationPackage().getAllocatedHosts()
+ .orElseThrow(() -> new IllegalStateException("Allocated hosts does not exists"));
}
public ZooKeeperDeployer createDeployer(DeployLogger logger) {
diff --git a/configserver/src/main/java/com/yahoo/vespa/config/server/tenant/TenantBuilder.java b/configserver/src/main/java/com/yahoo/vespa/config/server/tenant/TenantBuilder.java
index 144bbf10dc6..f4a5e941ac2 100644
--- a/configserver/src/main/java/com/yahoo/vespa/config/server/tenant/TenantBuilder.java
+++ b/configserver/src/main/java/com/yahoo/vespa/config/server/tenant/TenantBuilder.java
@@ -27,8 +27,7 @@ import java.util.concurrent.Executors;
/**
* Builder for helping out with tenant creation. Each of a tenants dependencies may be overridden for testing.
*
- * @author lulf
- * @since 5.1
+ * @author Ulf Lilleengen
*/
public class TenantBuilder {
diff --git a/configserver/src/main/java/com/yahoo/vespa/config/server/tenant/Tenants.java b/configserver/src/main/java/com/yahoo/vespa/config/server/tenant/Tenants.java
index 28bae587e2a..377b3997e43 100644
--- a/configserver/src/main/java/com/yahoo/vespa/config/server/tenant/Tenants.java
+++ b/configserver/src/main/java/com/yahoo/vespa/config/server/tenant/Tenants.java
@@ -48,12 +48,12 @@ import java.util.logging.Logger;
* Once a tenant is deleted from zookeeper, the zookeeper watcher thread will get notified on all configservers, and
* shutdown and delete any per-configserver state.
*
- * @author vegardh
- * @author lulf
- * @since 5.1.26
+ * @author Vegard Havdal
+ * @author Ulf Lilleengen
*/
//TODO Rename to TenantRepository
public class Tenants implements ConnectionStateListener, PathChildrenCacheListener {
+
public static final TenantName HOSTED_VESPA_TENANT = TenantName.from("hosted-vespa");
private static final TenantName DEFAULT_TENANT = TenantName.defaultName();
private static final List<TenantName> SYSTEM_TENANT_NAMES = Arrays.asList(
diff --git a/configserver/src/main/java/com/yahoo/vespa/config/server/zookeeper/ConfigCurator.java b/configserver/src/main/java/com/yahoo/vespa/config/server/zookeeper/ConfigCurator.java
index 80c1c44546f..c09fe5ae4bb 100644
--- a/configserver/src/main/java/com/yahoo/vespa/config/server/zookeeper/ConfigCurator.java
+++ b/configserver/src/main/java/com/yahoo/vespa/config/server/zookeeper/ConfigCurator.java
@@ -146,7 +146,7 @@ public class ConfigCurator {
/**
* Returns the data at a path, or null if the path does not exist.
*
- * @param path a String with a pathname.
+ * @param path a String with a pathname.
* @return a byte array with data.
*/
public byte[] getBytes(String path) {
diff --git a/configserver/src/main/java/com/yahoo/vespa/config/server/zookeeper/ZKApplicationPackage.java b/configserver/src/main/java/com/yahoo/vespa/config/server/zookeeper/ZKApplicationPackage.java
index 4f591278a38..05c301ddba8 100644
--- a/configserver/src/main/java/com/yahoo/vespa/config/server/zookeeper/ZKApplicationPackage.java
+++ b/configserver/src/main/java/com/yahoo/vespa/config/server/zookeeper/ZKApplicationPackage.java
@@ -2,6 +2,8 @@
package com.yahoo.vespa.config.server.zookeeper;
import com.google.common.base.Joiner;
+import com.google.common.collect.ImmutableSet;
+import com.yahoo.component.Version;
import com.yahoo.config.application.api.ApplicationMetaData;
import com.yahoo.config.application.api.ComponentInfo;
import com.yahoo.config.application.api.FileRegistry;
@@ -10,9 +12,9 @@ import com.yahoo.config.codegen.DefParser;
import com.yahoo.config.application.api.ApplicationFile;
import com.yahoo.config.application.api.ApplicationPackage;
import com.yahoo.config.model.application.provider.*;
+import com.yahoo.config.provision.HostSpec;
import com.yahoo.config.provision.NodeFlavors;
-import com.yahoo.config.provision.ProvisionInfo;
-import com.yahoo.config.provision.Version;
+import com.yahoo.config.provision.AllocatedHosts;
import com.yahoo.io.IOUtils;
import com.yahoo.path.Path;
import com.yahoo.io.reader.NamedReader;
@@ -24,20 +26,26 @@ import com.yahoo.vespa.config.util.ConfigUtils;
import java.io.File;
import java.io.Reader;
import java.io.StringReader;
-import java.util.*;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Optional;
/**
* Represents an application residing in zookeeper.
*
- * @author tonytv
+ * @author Tony Vaagenes
*/
public class ZKApplicationPackage implements ApplicationPackage {
private ZKLiveApp liveApp;
- private final Map<Version, PreGeneratedFileRegistry> fileRegistryMap = new HashMap<>();
- private final Map<Version, ProvisionInfo> provisionInfoMap = new HashMap<>();
- private static final Version legacyVersion = Version.fromIntValues(0, 0, 0);
+ private final Map<com.yahoo.config.provision.Version, PreGeneratedFileRegistry> fileRegistryMap = new HashMap<>();
+ private final Optional<AllocatedHosts> allocatedHosts;
+ private static final com.yahoo.config.provision.Version legacyVersion = com.yahoo.config.provision.Version.fromIntValues(0, 0, 0);
public static final String fileRegistryNode = "fileregistry";
public static final String allocatedHostsNode = "allocatedHosts";
@@ -48,34 +56,56 @@ public class ZKApplicationPackage implements ApplicationPackage {
liveApp = new ZKLiveApp(zk, appPath);
metaData = readMetaDataFromLiveApp(liveApp);
importFileRegistries(fileRegistryNode);
- importProvisionInfos(allocatedHostsNode, nodeFlavors);
+ allocatedHosts = importAllocatedHosts(allocatedHostsNode, nodeFlavors);
}
- private void importProvisionInfos(String allocatedHostsNode, Optional<NodeFlavors> nodeFlavors) {
- List<String> provisionInfoNodes = liveApp.getChildren(allocatedHostsNode);
- if (provisionInfoNodes.isEmpty()) {
- Optional<ProvisionInfo> provisionInfo = importProvisionInfo(allocatedHostsNode, nodeFlavors);
- provisionInfo.ifPresent(info -> provisionInfoMap.put(legacyVersion, info));
- } else {
- provisionInfoNodes.stream()
- .forEach(versionStr -> {
- Version version = Version.fromString(versionStr);
- Optional<ProvisionInfo> provisionInfo = importProvisionInfo(Joiner.on("/").join(allocatedHostsNode, versionStr),
- nodeFlavors);
- provisionInfo.ifPresent(info -> provisionInfoMap.put(version, info));
- });
+ private Optional<AllocatedHosts> importAllocatedHosts(String allocatedHostsPath, Optional<NodeFlavors> nodeFlavors) {
+ if ( ! liveApp.exists(allocatedHostsPath)) return Optional.empty();
+ Optional<AllocatedHosts> allocatedHosts = readAllocatedHosts(allocatedHostsPath, nodeFlavors);
+ if ( ! allocatedHosts.isPresent()) { // Read from legacy location. TODO: Remove when 6.143 is in production everywhere
+ List<String> allocatedHostsByVersionNodes = liveApp.getChildren(allocatedHostsPath);
+ allocatedHosts = merge(readAllocatedHostsByVersion(allocatedHostsByVersionNodes, nodeFlavors));
+ }
+ return allocatedHosts;
+ }
+
+ private Map<Version, AllocatedHosts> readAllocatedHostsByVersion(List<String> allocatedHostsByVersionNodes,
+ Optional<NodeFlavors> nodeFlavors) {
+ Map<Version, AllocatedHosts> allocatedHostsByVersion = new HashMap<>();
+ allocatedHostsByVersionNodes.stream()
+ .forEach(versionStr -> {
+ Version version = Version.fromString(versionStr);
+ Optional<AllocatedHosts> allocatedHosts = readAllocatedHosts(Joiner.on("/").join(allocatedHostsNode, versionStr),
+ nodeFlavors);
+ allocatedHosts.ifPresent(info -> allocatedHostsByVersion.put(version, info));
+ });
+ return allocatedHostsByVersion;
+ }
+
+ private Optional<AllocatedHosts> merge(Map<Version, AllocatedHosts> allocatedHostsByVersion) {
+ // Merge the allocated hosts in any order. This is wrong but preserves current behavior (modulo order differences)
+ if (allocatedHostsByVersion.isEmpty()) return Optional.empty();
+
+ Map<String, HostSpec> merged = new HashMap<>();
+ for (Map.Entry<Version, AllocatedHosts> entry : allocatedHostsByVersion.entrySet()) {
+ for (HostSpec host : entry.getValue().getHosts())
+ merged.put(host.hostname(), host);
}
+ return Optional.of(AllocatedHosts.withHosts(ImmutableSet.copyOf(merged.values())));
}
- private Optional<ProvisionInfo> importProvisionInfo(String provisionInfoNode, Optional<NodeFlavors> nodeFlavors) {
+ /**
+ * Reads allocated hosts at the given node.
+ *
+ * @return the allocated hosts at this node or empty if there is no data at this path
+ */
+ private Optional<AllocatedHosts> readAllocatedHosts(String allocatedHostsPath, Optional<NodeFlavors> nodeFlavors) {
try {
- if (liveApp.exists(provisionInfoNode)) {
- return Optional.of(ProvisionInfo.fromJson(liveApp.getBytes(provisionInfoNode), nodeFlavors));
- } else {
- return Optional.empty();
- }
+ byte[] data = liveApp.getBytes(allocatedHostsPath);
+ if (data.length == 0) return Optional.empty(); // TODO: Remove this line (and make return non-optional) when 6.143 is in production everywhere
+ return Optional.of(AllocatedHosts.fromJson(data, nodeFlavors));
} catch (Exception e) {
- throw new RuntimeException("Unable to read provision info", e);
+ throw new RuntimeException("Unable to read allocated hosts", e);
}
}
@@ -85,9 +115,9 @@ public class ZKApplicationPackage implements ApplicationPackage {
fileRegistryMap.put(legacyVersion, importFileRegistry(fileRegistryNode));
} else {
fileRegistryNodes.stream()
- .forEach(versionStr -> {
- Version version = Version.fromString(versionStr);
- fileRegistryMap.put(version, importFileRegistry(Joiner.on("/").join(fileRegistryNode, versionStr)));
+ .forEach(version -> {
+ fileRegistryMap.put(com.yahoo.config.provision.Version.fromString(version),
+ importFileRegistry(Joiner.on("/").join(fileRegistryNode, version)));
});
}
}
@@ -147,16 +177,17 @@ public class ZKApplicationPackage implements ApplicationPackage {
return ret;
}
- public Map<Version, ProvisionInfo> getProvisionInfoMap() {
- return Collections.unmodifiableMap(provisionInfoMap);
+ @Override
+ public Optional<AllocatedHosts> getAllocatedHosts() {
+ return allocatedHosts;
}
@Override
- public Map<Version, FileRegistry> getFileRegistryMap() {
+ public Map<com.yahoo.config.provision.Version, FileRegistry> getFileRegistryMap() {
return Collections.unmodifiableMap(fileRegistryMap);
}
- private Optional<PreGeneratedFileRegistry> getPreGeneratedFileRegistry(Version vespaVersion) {
+ private Optional<PreGeneratedFileRegistry> getPreGeneratedFileRegistry(com.yahoo.config.provision.Version vespaVersion) {
// Assumes at least one file registry, which we always have.
Optional<PreGeneratedFileRegistry> fileRegistry = Optional.ofNullable(fileRegistryMap.get(vespaVersion));
if (!fileRegistry.isPresent()) {
@@ -243,7 +274,7 @@ public class ZKApplicationPackage implements ApplicationPackage {
}
@Override
- public List<ComponentInfo> getComponentsInfo(Version vespaVersion) {
+ public List<ComponentInfo> getComponentsInfo(com.yahoo.config.provision.Version vespaVersion) {
List<ComponentInfo> components = new ArrayList<>();
PreGeneratedFileRegistry fileRegistry = getPreGeneratedFileRegistry(vespaVersion).get();
for (String path : fileRegistry.getPaths()) {
diff --git a/configserver/src/main/java/com/yahoo/vespa/config/server/zookeeper/ZKLiveApp.java b/configserver/src/main/java/com/yahoo/vespa/config/server/zookeeper/ZKLiveApp.java
index 88748cb7689..8084be1cefa 100644
--- a/configserver/src/main/java/com/yahoo/vespa/config/server/zookeeper/ZKLiveApp.java
+++ b/configserver/src/main/java/com/yahoo/vespa/config/server/zookeeper/ZKLiveApp.java
@@ -173,14 +173,11 @@ public class ZKLiveApp {
* Returns the full list of children (file names) in the given path.
*
* @param path a path relative to the currently active application
- * @return a list of file names
+ * @return a list of file names, which is empty (never null) if the path does not exist
*/
public List<String> getChildren(String path) {
String fullPath = getFullPath(path);
- if (! zk.exists(fullPath)) {
- log.fine("ZKApplicationPackage: " + fullPath + " is not a valid dir");
- return Collections.emptyList();
- }
+ if (! zk.exists(fullPath)) return Collections.emptyList();
return zk.getChildren(fullPath);
}
diff --git a/configserver/src/test/java/com/yahoo/vespa/config/server/ModelStub.java b/configserver/src/test/java/com/yahoo/vespa/config/server/ModelStub.java
index b892abc67af..2ccce9727a3 100644
--- a/configserver/src/test/java/com/yahoo/vespa/config/server/ModelStub.java
+++ b/configserver/src/test/java/com/yahoo/vespa/config/server/ModelStub.java
@@ -4,7 +4,7 @@ package com.yahoo.vespa.config.server;
import com.yahoo.config.model.api.FileDistribution;
import com.yahoo.config.model.api.HostInfo;
import com.yahoo.config.model.api.Model;
-import com.yahoo.config.provision.ProvisionInfo;
+import com.yahoo.config.provision.AllocatedHosts;
import com.yahoo.vespa.config.ConfigKey;
import com.yahoo.vespa.config.ConfigPayload;
import com.yahoo.vespa.config.buildergen.ConfigDefinition;
@@ -44,7 +44,7 @@ public class ModelStub implements Model {
}
@Override
- public Optional<ProvisionInfo> getProvisionInfo() {
+ public AllocatedHosts allocatedHosts() {
return null;
}
diff --git a/configserver/src/test/java/com/yahoo/vespa/config/server/application/MockModel.java b/configserver/src/test/java/com/yahoo/vespa/config/server/application/MockModel.java
index 5806c7991fc..cf5463b7f4c 100644
--- a/configserver/src/test/java/com/yahoo/vespa/config/server/application/MockModel.java
+++ b/configserver/src/test/java/com/yahoo/vespa/config/server/application/MockModel.java
@@ -7,7 +7,7 @@ import com.yahoo.config.model.api.Model;
import com.yahoo.config.model.api.PortInfo;
import com.yahoo.config.model.api.ServiceInfo;
import com.yahoo.config.provision.ClusterSpec;
-import com.yahoo.config.provision.ProvisionInfo;
+import com.yahoo.config.provision.AllocatedHosts;
import com.yahoo.vespa.config.ConfigKey;
import com.yahoo.vespa.config.ConfigPayload;
import com.yahoo.vespa.config.buildergen.ConfigDefinition;
@@ -93,7 +93,7 @@ class MockModel implements Model {
}
@Override
- public Optional<ProvisionInfo> getProvisionInfo() {
+ public AllocatedHosts allocatedHosts() {
throw new UnsupportedOperationException();
}
}
diff --git a/configserver/src/test/java/com/yahoo/vespa/config/server/deploy/DeployTester.java b/configserver/src/test/java/com/yahoo/vespa/config/server/deploy/DeployTester.java
index c9556425dda..5fea15a7b10 100644
--- a/configserver/src/test/java/com/yahoo/vespa/config/server/deploy/DeployTester.java
+++ b/configserver/src/test/java/com/yahoo/vespa/config/server/deploy/DeployTester.java
@@ -20,7 +20,7 @@ import com.yahoo.config.provision.ClusterSpec;
import com.yahoo.config.provision.HostFilter;
import com.yahoo.config.provision.HostSpec;
import com.yahoo.config.provision.InstanceName;
-import com.yahoo.config.provision.ProvisionInfo;
+import com.yahoo.config.provision.AllocatedHosts;
import com.yahoo.config.provision.ProvisionLogger;
import com.yahoo.config.provision.Provisioner;
import com.yahoo.config.provision.Version;
@@ -69,7 +69,7 @@ public class DeployTester {
private ApplicationId id;
public DeployTester(String appPath) {
- this(appPath, Collections.singletonList(createDefaultModelFactory(Clock.systemUTC())));
+ this(appPath, Collections.singletonList(createModelFactory(Clock.systemUTC())));
}
public DeployTester(String appPath, List<ModelFactory> modelFactories) {
@@ -80,7 +80,7 @@ public class DeployTester {
public DeployTester(String appPath, ConfigserverConfig configserverConfig) {
this(appPath,
- Collections.singletonList(createDefaultModelFactory(Clock.systemUTC())),
+ Collections.singletonList(createModelFactory(Clock.systemUTC())),
configserverConfig);
}
@@ -99,9 +99,16 @@ public class DeployTester {
public Tenant tenant() { return tenants.defaultTenant(); }
- /** Create the model factory which will be used in production */
- public static ModelFactory createDefaultModelFactory(Clock clock) { return new VespaModelFactory(new NullConfigModelRegistry(), clock); }
-
+ /** Create a model factory for the version of this source*/
+ public static ModelFactory createModelFactory(Clock clock) {
+ return new VespaModelFactory(new NullConfigModelRegistry(), clock);
+ }
+
+ /** Create a model factory for a particular version */
+ public static ModelFactory createModelFactory(Version version, Clock clock) {
+ return new VespaModelFactory(version, new NullConfigModelRegistry(), clock);
+ }
+
/** Create a model factory which always fails validation */
public static ModelFactory createFailingModelFactory(Version version) { return new FailingModelFactory(version); }
@@ -109,20 +116,19 @@ public class DeployTester {
* Do the initial "deploy" with the existing API-less code as the deploy API doesn't support first deploys yet.
*/
public ApplicationId deployApp(String appName, Instant now) {
- return deployApp(appName, Optional.empty(), now);
+ return deployApp(appName, null, now);
}
/**
* Do the initial "deploy" with the existing API-less code as the deploy API doesn't support first deploys yet.
*/
- public ApplicationId deployApp(String appName, Optional<String> vespaVersion, Instant now) {
+ public ApplicationId deployApp(String appName, String vespaVersion, Instant now) {
Tenant tenant = tenant();
LocalSession session = tenant.getSessionFactory().createSession(testApp, appName, new TimeoutBudget(Clock.systemUTC(), Duration.ofSeconds(60)));
ApplicationId id = ApplicationId.from(tenant.getName(), ApplicationName.from(appName), InstanceName.defaultName());
- PrepareParams.Builder paramsBuilder = new PrepareParams.Builder()
- .applicationId(id);
- if (vespaVersion.isPresent())
- paramsBuilder.vespaVersion(vespaVersion.get());
+ PrepareParams.Builder paramsBuilder = new PrepareParams.Builder().applicationId(id);
+ if (vespaVersion != null)
+ paramsBuilder.vespaVersion(vespaVersion);
session.prepare(new SilentDeployLogger(),
paramsBuilder.build(),
Optional.empty(),
@@ -134,11 +140,11 @@ public class DeployTester {
return id;
}
- public ProvisionInfo getProvisionInfoFromDeployedApp(ApplicationId applicationId) {
+ public AllocatedHosts getAllocatedHostsOf(ApplicationId applicationId) {
Tenant tenant = tenant();
LocalSession session = tenant.getLocalSessionRepo().getSession(tenant.getApplicationRepo()
.getSessionIdForApplication(applicationId));
- return session.getProvisionInfo();
+ return session.getAllocatedHosts();
}
public ApplicationId applicationId() { return id; }
diff --git a/configserver/src/test/java/com/yahoo/vespa/config/server/deploy/HostedDeployTest.java b/configserver/src/test/java/com/yahoo/vespa/config/server/deploy/HostedDeployTest.java
index 31e92cc9f93..301ae63fb8c 100644
--- a/configserver/src/test/java/com/yahoo/vespa/config/server/deploy/HostedDeployTest.java
+++ b/configserver/src/test/java/com/yahoo/vespa/config/server/deploy/HostedDeployTest.java
@@ -32,7 +32,7 @@ public class HostedDeployTest {
@Test
public void testRedeployWithVersion() throws InterruptedException, IOException {
DeployTester tester = new DeployTester("src/test/apps/hosted/", createConfigserverConfig());
- tester.deployApp("myApp", Optional.of("4.5.6"), Instant.now());
+ tester.deployApp("myApp", "4.5.6", Instant.now());
Optional<com.yahoo.config.provision.Deployment> deployment = tester.redeployFromLocalActive();
assertTrue(deployment.isPresent());
@@ -53,11 +53,23 @@ public class HostedDeployTest {
}
@Test
+ public void testDeployMultipleVersions() throws InterruptedException, IOException {
+ ManualClock clock = new ManualClock("2016-10-09T00:00:00");
+ List<ModelFactory> modelFactories = new ArrayList<>();
+ modelFactories.add(DeployTester.createModelFactory(Version.fromString("6.1.0"), clock));
+ modelFactories.add(DeployTester.createModelFactory(Version.fromString("6.2.0"), clock));
+ modelFactories.add(DeployTester.createModelFactory(Version.fromString("7.0.0"), clock));
+ DeployTester tester = new DeployTester("src/test/apps/hosted/", modelFactories, createConfigserverConfig());
+ ApplicationId app = tester.deployApp("myApp", Instant.now());
+ assertEquals(3, tester.getAllocatedHostsOf(app).getHosts().size());
+ }
+
+ @Test
public void testRedeployAfterExpiredValidationOverride() throws InterruptedException, IOException {
// Old version of model fails, but application disables loading old models until 2016-10-10, so deployment works
ManualClock clock = new ManualClock("2016-10-09T00:00:00");
List<ModelFactory> modelFactories = new ArrayList<>();
- modelFactories.add(DeployTester.createDefaultModelFactory(clock));
+ modelFactories.add(DeployTester.createModelFactory(clock));
modelFactories.add(DeployTester.createFailingModelFactory(Version.fromIntValues(1, 0, 0))); // older than default
DeployTester tester = new DeployTester("src/test/apps/validationOverride/", modelFactories, createConfigserverConfig());
tester.deployApp("myApp", clock.instant());
@@ -97,19 +109,19 @@ public class HostedDeployTest {
public void testDeployWithDockerImage() throws InterruptedException, IOException {
final String vespaVersion = "6.51.1";
DeployTester tester = new DeployTester("src/test/apps/hosted/", createConfigserverConfig());
- ApplicationId applicationId = tester.deployApp("myApp", Optional.of(vespaVersion), Instant.now());
- assertProvisionInfo(vespaVersion, tester, applicationId);
+ ApplicationId applicationId = tester.deployApp("myApp", vespaVersion, Instant.now());
+ assertAllocatedHosts(vespaVersion, tester, applicationId);
System.out.println("Redeploy");
Optional<com.yahoo.config.provision.Deployment> deployment = tester.redeployFromLocalActive();
assertTrue(deployment.isPresent());
deployment.get().prepare();
deployment.get().activate();
- //assertProvisionInfo(vespaVersion, tester, applicationId);
+ //assertAllocatedHosts(vespaVersion, tester, applicationId);
}
- private void assertProvisionInfo(String vespaVersion, DeployTester tester, ApplicationId applicationId) {
- tester.getProvisionInfoFromDeployedApp(applicationId).getHosts().stream()
+ private void assertAllocatedHosts(String vespaVersion, DeployTester tester, ApplicationId applicationId) {
+ tester.getAllocatedHostsOf(applicationId).getHosts().stream()
.forEach(h -> assertEquals(vespaVersion, h.membership().get().cluster().vespaVersion()));
}
diff --git a/configserver/src/test/java/com/yahoo/vespa/config/server/deploy/RedeployTest.java b/configserver/src/test/java/com/yahoo/vespa/config/server/deploy/RedeployTest.java
index 5658e0fb2aa..49e40321321 100644
--- a/configserver/src/test/java/com/yahoo/vespa/config/server/deploy/RedeployTest.java
+++ b/configserver/src/test/java/com/yahoo/vespa/config/server/deploy/RedeployTest.java
@@ -47,7 +47,7 @@ public class RedeployTest {
@Test
public void testNoRedeploy() {
List<ModelFactory> modelFactories = new ArrayList<>();
- modelFactories.add(DeployTester.createDefaultModelFactory(Clock.systemUTC()));
+ modelFactories.add(DeployTester.createModelFactory(Clock.systemUTC()));
modelFactories.add(DeployTester.createFailingModelFactory(Version.fromIntValues(1, 0, 0)));
DeployTester tester = new DeployTester("ignored/app/path", modelFactories);
ApplicationId id = ApplicationId.from(TenantName.from("default"),
diff --git a/configserver/src/test/java/com/yahoo/vespa/config/server/deploy/ZooKeeperClientTest.java b/configserver/src/test/java/com/yahoo/vespa/config/server/deploy/ZooKeeperClientTest.java
index ac029c12b17..bf7f7038c1a 100644
--- a/configserver/src/test/java/com/yahoo/vespa/config/server/deploy/ZooKeeperClientTest.java
+++ b/configserver/src/test/java/com/yahoo/vespa/config/server/deploy/ZooKeeperClientTest.java
@@ -1,6 +1,7 @@
// Copyright 2017 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
package com.yahoo.vespa.config.server.deploy;
+import com.google.common.collect.ImmutableSet;
import com.yahoo.config.application.api.ApplicationMetaData;
import com.yahoo.config.application.api.ApplicationPackage;
import com.yahoo.config.application.api.FileRegistry;
@@ -46,8 +47,8 @@ public class ZooKeeperClientTest extends TestWithCurator {
Map<Version, FileRegistry> fileRegistries = createFileRegistries();
app.writeMetaData();
zkc.setupZooKeeper();
- zkc.feedZooKeeper(app);
- zkc.feedZKFileRegistries(fileRegistries);
+ zkc.write(app);
+ zkc.write(fileRegistries);
}
private Map<Version, FileRegistry> createFileRegistries() {
@@ -174,23 +175,15 @@ public class ZooKeeperClientTest extends TestWithCurator {
Path app = Path.fromString("/1");
ZooKeeperClient zooKeeperClient = new ZooKeeperClient(zk, logger, true, app);
zooKeeperClient.setupZooKeeper();
- zooKeeperClient.feedProvisionInfos(createProvisionInfos());
+ HostSpec host1 = new HostSpec("host1.yahoo.com", Collections.emptyList());
+ HostSpec host2 = new HostSpec("host2.yahoo.com", Collections.emptyList());
+ ImmutableSet<HostSpec> hosts = ImmutableSet.of(host1, host2);
+ zooKeeperClient.write(AllocatedHosts.withHosts(hosts));
Path hostsPath = app.append(ZKApplicationPackage.allocatedHostsNode);
assertTrue(zk.exists(hostsPath.getAbsolute()));
- assertEquals(0, zk.getBytes(hostsPath.getAbsolute()).length); // Changed from null
- assertTrue(zk.exists(hostsPath.append("1.2.3").getAbsolute()));
- assertTrue(zk.exists(hostsPath.append("3.2.1").getAbsolute()));
- assertTrue(zk.getBytes(hostsPath.append("1.2.3").getAbsolute()).length > 0);
- assertTrue(zk.getBytes(hostsPath.append("3.2.1").getAbsolute()).length > 0);
- }
-
- private Map<Version, ProvisionInfo> createProvisionInfos() {
- Map<Version, ProvisionInfo> provisionInfoMap = new HashMap<>();
- ProvisionInfo a = ProvisionInfo.withHosts(Collections.singleton(new HostSpec("host.yahoo.com", Collections.emptyList())));
- ProvisionInfo b = ProvisionInfo.withHosts(Collections.singleton(new HostSpec("host2.yahoo.com", Collections.emptyList())));
- provisionInfoMap.put(Version.fromIntValues(1, 2, 3), a);
- provisionInfoMap.put(Version.fromIntValues(3, 2, 1), b);
- return provisionInfoMap;
+
+ AllocatedHosts deserialized = AllocatedHosts.fromJson(zk.getBytes(hostsPath.getAbsolute()), Optional.empty());
+ assertEquals(hosts, deserialized.getHosts());
}
}
diff --git a/configserver/src/test/java/com/yahoo/vespa/config/server/deploy/ZooKeeperDeployerTest.java b/configserver/src/test/java/com/yahoo/vespa/config/server/deploy/ZooKeeperDeployerTest.java
index 9c7f12c2147..b256079d259 100644
--- a/configserver/src/test/java/com/yahoo/vespa/config/server/deploy/ZooKeeperDeployerTest.java
+++ b/configserver/src/test/java/com/yahoo/vespa/config/server/deploy/ZooKeeperDeployerTest.java
@@ -4,6 +4,7 @@ package com.yahoo.vespa.config.server.deploy;
import com.yahoo.config.application.api.ApplicationPackage;
import com.yahoo.config.application.api.DeployLogger;
import com.yahoo.config.model.application.provider.*;
+import com.yahoo.config.provision.AllocatedHosts;
import com.yahoo.config.provision.Version;
import com.yahoo.io.IOUtils;
import com.yahoo.path.Path;
@@ -52,7 +53,7 @@ public class ZooKeeperDeployerTest {
ZooKeeperClient client = new ZooKeeperClient(configCurator, logger, true, appPath);
ZooKeeperDeployer deployer = new ZooKeeperDeployer(client);
- deployer.deploy(applicationPackage, Collections.singletonMap(Version.fromIntValues(1, 0, 0), new MockFileRegistry()), Collections.emptyMap());
+ deployer.deploy(applicationPackage, Collections.singletonMap(Version.fromIntValues(1, 0, 0), new MockFileRegistry()), AllocatedHosts.withHosts(Collections.emptySet()));
assertTrue(configCurator.exists(appPath.getAbsolute()));
}
diff --git a/configserver/src/test/java/com/yahoo/vespa/config/server/http/v2/SessionActiveHandlerTest.java b/configserver/src/test/java/com/yahoo/vespa/config/server/http/v2/SessionActiveHandlerTest.java
index 5e10f364aeb..7fca78b087b 100644
--- a/configserver/src/test/java/com/yahoo/vespa/config/server/http/v2/SessionActiveHandlerTest.java
+++ b/configserver/src/test/java/com/yahoo/vespa/config/server/http/v2/SessionActiveHandlerTest.java
@@ -13,7 +13,7 @@ import com.yahoo.config.provision.ApplicationId;
import com.yahoo.config.provision.ApplicationName;
import com.yahoo.config.provision.HostSpec;
import com.yahoo.config.provision.InstanceName;
-import com.yahoo.config.provision.ProvisionInfo;
+import com.yahoo.config.provision.AllocatedHosts;
import com.yahoo.config.provision.TenantName;
import com.yahoo.config.provision.Zone;
import com.yahoo.container.jdisc.HttpResponse;
@@ -217,8 +217,8 @@ public class SessionActiveHandlerTest extends SessionHandlerTest {
zkClient.writeStatus(status);
ZooKeeperClient zkC = new ZooKeeperClient(configCurator, new BaseDeployLogger(), false, pathProvider.getSessionDirs().append(String.valueOf(sessionId)));
VespaModelFactory modelFactory = new VespaModelFactory(new NullConfigModelRegistry());
- zkC.feedZKFileRegistries(Collections.singletonMap(modelFactory.getVersion(), new MockFileRegistry()));
- zkC.feedProvisionInfos(Collections.singletonMap(modelFactory.getVersion(), ProvisionInfo.withHosts(Collections.emptySet())));
+ zkC.write(Collections.singletonMap(modelFactory.getVersion(), new MockFileRegistry()));
+ zkC.write(AllocatedHosts.withHosts(Collections.emptySet()));
TestComponentRegistry componentRegistry = new TestComponentRegistry.Builder()
.curator(curator)
.configCurator(configCurator)
@@ -318,7 +318,7 @@ public class SessionActiveHandlerTest extends SessionHandlerTest {
ActivateRequest invoke(boolean createLocalSession) throws Exception {
SessionZooKeeperClient zkClient = new MockSessionZKClient(curator, pathProvider.getSessionDirs().append(String.valueOf(sessionId)),
- Optional.of(ProvisionInfo.withHosts(Collections.singleton(new HostSpec("bar", Collections.emptyList())))));
+ Optional.of(AllocatedHosts.withHosts(Collections.singleton(new HostSpec("bar", Collections.emptyList())))));
session = createRemoteSession(sessionId, initialStatus, zkClient, clock);
if (createLocalSession) {
LocalSessionRepo repo = addLocalSession(sessionId, deployData, zkClient);
diff --git a/configserver/src/test/java/com/yahoo/vespa/config/server/provision/StaticProvisionerTest.java b/configserver/src/test/java/com/yahoo/vespa/config/server/provision/StaticProvisionerTest.java
index c54514eb097..badcdf53b77 100644
--- a/configserver/src/test/java/com/yahoo/vespa/config/server/provision/StaticProvisionerTest.java
+++ b/configserver/src/test/java/com/yahoo/vespa/config/server/provision/StaticProvisionerTest.java
@@ -20,7 +20,7 @@ import java.io.IOException;
import static org.junit.Assert.assertEquals;
/**
- * @author lulf
+ * @author Ulf Lilleengen
*/
public class StaticProvisionerTest {
@@ -30,7 +30,7 @@ public class StaticProvisionerTest {
InMemoryProvisioner inMemoryHostProvisioner = new InMemoryProvisioner(false, "host1.yahoo.com", "host2.yahoo.com", "host3.yahoo.com", "host4.yahoo.com");
VespaModel firstModel = createModel(app, inMemoryHostProvisioner);
- StaticProvisioner staticProvisioner = new StaticProvisioner(firstModel.getProvisionInfo().get());
+ StaticProvisioner staticProvisioner = new StaticProvisioner(firstModel.allocatedHosts());
VespaModel secondModel = createModel(app, staticProvisioner);
assertModelConfig(firstModel, secondModel);
diff --git a/configserver/src/test/java/com/yahoo/vespa/config/server/session/LocalSessionTest.java b/configserver/src/test/java/com/yahoo/vespa/config/server/session/LocalSessionTest.java
index f0086eabd26..be98f41c82a 100644
--- a/configserver/src/test/java/com/yahoo/vespa/config/server/session/LocalSessionTest.java
+++ b/configserver/src/test/java/com/yahoo/vespa/config/server/session/LocalSessionTest.java
@@ -120,19 +120,19 @@ public class LocalSessionTest {
@Test(expected = IllegalStateException.class)
public void require_that_no_provision_info_throws_exception() throws Exception {
- createSession(TenantName.defaultName(), 3).getProvisionInfo();
+ createSession(TenantName.defaultName(), 3).getAllocatedHosts();
}
@Test
public void require_that_provision_info_can_be_read() throws Exception {
- ProvisionInfo input = ProvisionInfo.withHosts(Collections.singleton(new HostSpec("myhost", Collections.<String>emptyList())));
+ AllocatedHosts input = AllocatedHosts.withHosts(Collections.singleton(new HostSpec("myhost", Collections.<String>emptyList())));
LocalSession session = createSession(TenantName.defaultName(), 3, new SessionTest.MockSessionPreparer(), Optional.of(input));
ApplicationId origId = new ApplicationId.Builder()
.tenant("tenant")
.applicationName("foo").instanceName("quux").build();
doPrepare(session, new PrepareParams.Builder().applicationId(origId).build(), Instant.now());
- ProvisionInfo info = session.getProvisionInfo();
+ AllocatedHosts info = session.getAllocatedHosts();
assertNotNull(info);
assertThat(info.getHosts().size(), is(1));
assertTrue(info.getHosts().contains(new HostSpec("myhost", Collections.emptyList())));
@@ -151,18 +151,18 @@ public class LocalSessionTest {
}
private LocalSession createSession(TenantName tenant, long sessionId, SessionTest.MockSessionPreparer preparer) throws Exception {
- return createSession(tenant, sessionId, preparer, Optional.<ProvisionInfo>empty());
+ return createSession(tenant, sessionId, preparer, Optional.<AllocatedHosts>empty());
}
- private LocalSession createSession(TenantName tenant, long sessionId, SessionTest.MockSessionPreparer preparer, Optional<ProvisionInfo> provisionInfo) throws Exception {
+ private LocalSession createSession(TenantName tenant, long sessionId, SessionTest.MockSessionPreparer preparer, Optional<AllocatedHosts> allocatedHosts) throws Exception {
Path appPath = Path.fromString("/" + sessionId);
- SessionZooKeeperClient zkc = new MockSessionZKClient(curator, appPath, provisionInfo);
+ SessionZooKeeperClient zkc = new MockSessionZKClient(curator, appPath, allocatedHosts);
zkc.createWriteStatusTransaction(Session.Status.NEW).commit();
ZooKeeperClient zkClient = new ZooKeeperClient(configCurator, new BaseDeployLogger(), false, appPath);
- if (provisionInfo.isPresent()) {
- zkClient.feedProvisionInfos(Collections.singletonMap(Version.fromIntValues(0, 0, 0), provisionInfo.get()));
+ if (allocatedHosts.isPresent()) {
+ zkClient.write(allocatedHosts.get());
}
- zkClient.feedZKFileRegistries(Collections.singletonMap(Version.fromIntValues(0, 0, 0), new MockFileRegistry()));
+ zkClient.write(Collections.singletonMap(Version.fromIntValues(0, 0, 0), new MockFileRegistry()));
File sessionDir = new File(tenantFileSystemDirs.path(), String.valueOf(sessionId));
sessionDir.createNewFile();
return new LocalSession(tenant, sessionId, preparer, new SessionContext(FilesApplicationPackage.fromFile(testApp), zkc, sessionDir, new MemoryTenantApplications(), new HostRegistry<>(), superModelGenerationCounter));
diff --git a/configserver/src/test/java/com/yahoo/vespa/config/server/session/MockSessionZKClient.java b/configserver/src/test/java/com/yahoo/vespa/config/server/session/MockSessionZKClient.java
index 9b658a807b9..412e7881a26 100644
--- a/configserver/src/test/java/com/yahoo/vespa/config/server/session/MockSessionZKClient.java
+++ b/configserver/src/test/java/com/yahoo/vespa/config/server/session/MockSessionZKClient.java
@@ -3,7 +3,7 @@ package com.yahoo.vespa.config.server.session;
import com.yahoo.config.application.api.ApplicationPackage;
import com.yahoo.config.model.test.MockApplicationPackage;
-import com.yahoo.config.provision.ProvisionInfo;
+import com.yahoo.config.provision.AllocatedHosts;
import com.yahoo.transaction.Transaction;
import com.yahoo.path.Path;
import com.yahoo.vespa.curator.Curator;
@@ -14,22 +14,21 @@ import java.util.Optional;
/**
* Overrides application package fetching, because this part is hard to do without feeding a full app.
*
- * @author lulf
- * @since 5.1
+ * @author Ulf Lilleengen
*/
public class MockSessionZKClient extends SessionZooKeeperClient {
private ApplicationPackage app = null;
- private Optional<ProvisionInfo> info = null;
+ private Optional<AllocatedHosts> info = null;
private Session.Status sessionStatus;
public MockSessionZKClient(Curator curator, Path rootPath) {
this(curator, rootPath, (ApplicationPackage)null);
}
- public MockSessionZKClient(Curator curator, Path rootPath, Optional<ProvisionInfo> provisionInfo) {
+ public MockSessionZKClient(Curator curator, Path rootPath, Optional<AllocatedHosts> allocatedHosts) {
this(curator, rootPath);
- this.info = provisionInfo;
+ this.info = allocatedHosts;
}
public MockSessionZKClient(Curator curator, Path rootPath, ApplicationPackage application) {
@@ -49,8 +48,8 @@ public class MockSessionZKClient extends SessionZooKeeperClient {
}
@Override
- ProvisionInfo getProvisionInfo() {
- return info.orElseThrow(() -> new IllegalStateException("Trying to read provision info, but no provision info exists"));
+ AllocatedHosts getAllocatedHosts() {
+ return info.orElseThrow(() -> new IllegalStateException("Could not find allocated hosts"));
}
@Override
diff --git a/configserver/src/test/java/com/yahoo/vespa/config/server/tenant/TenantRequestHandlerTest.java b/configserver/src/test/java/com/yahoo/vespa/config/server/tenant/TenantRequestHandlerTest.java
index 65f546e149a..3b67597c43c 100644
--- a/configserver/src/test/java/com/yahoo/vespa/config/server/tenant/TenantRequestHandlerTest.java
+++ b/configserver/src/test/java/com/yahoo/vespa/config/server/tenant/TenantRequestHandlerTest.java
@@ -8,6 +8,7 @@ import com.yahoo.config.model.application.provider.BaseDeployLogger;
import com.yahoo.config.model.application.provider.FilesApplicationPackage;
import com.yahoo.config.model.application.provider.MockFileRegistry;
import com.yahoo.config.provision.ApplicationName;
+import com.yahoo.config.provision.AllocatedHosts;
import com.yahoo.config.provision.Version;
import com.yahoo.io.IOUtils;
import com.yahoo.path.Path;
@@ -94,7 +95,7 @@ public class TenantRequestHandlerTest extends TestWithCurator {
File app = tempFolder.newFolder();
IOUtils.copyDirectory(appDir, app);
ZooKeeperDeployer deployer = zkc.createDeployer(new BaseDeployLogger());
- deployer.deploy(FilesApplicationPackage.fromFile(appDir), Collections.singletonMap(vespaVersion, new MockFileRegistry()), Collections.emptyMap());
+ deployer.deploy(FilesApplicationPackage.fromFile(appDir), Collections.singletonMap(vespaVersion, new MockFileRegistry()), AllocatedHosts.withHosts(Collections.emptySet()));
}
private ApplicationSet reloadConfig(long id, Clock clock) {
diff --git a/configserver/src/test/java/com/yahoo/vespa/config/server/zookeeper/ZKApplicationPackageTest.java b/configserver/src/test/java/com/yahoo/vespa/config/server/zookeeper/ZKApplicationPackageTest.java
index abc77a91c51..adf26dbfa32 100644
--- a/configserver/src/test/java/com/yahoo/vespa/config/server/zookeeper/ZKApplicationPackageTest.java
+++ b/configserver/src/test/java/com/yahoo/vespa/config/server/zookeeper/ZKApplicationPackageTest.java
@@ -16,7 +16,7 @@ import com.yahoo.config.model.deploy.DeployState;
import com.yahoo.config.provision.Flavor;
import com.yahoo.config.provision.HostSpec;
import com.yahoo.config.provision.NodeFlavors;
-import com.yahoo.config.provision.ProvisionInfo;
+import com.yahoo.config.provision.AllocatedHosts;
import com.yahoo.config.provision.Version;
import com.yahoo.config.provisioning.FlavorsConfig;
import com.yahoo.path.Path;
@@ -33,7 +33,7 @@ public class ZKApplicationPackageTest extends TestWithCurator {
private static final String APP = "src/test/apps/zkapp";
private static final String TEST_FLAVOR_NAME = "test-flavor";
private static final Optional<Flavor> TEST_FLAVOR = new MockNodeFlavors().getFlavor(TEST_FLAVOR_NAME);
- private static final ProvisionInfo provisionInfo = ProvisionInfo.withHosts(
+ private static final AllocatedHosts ALLOCATED_HOSTS = AllocatedHosts.withHosts(
Collections.singleton(new HostSpec("foo.yahoo.com", Collections.emptyList(), TEST_FLAVOR, Optional.empty())));
@Rule
@@ -64,9 +64,8 @@ public class ZKApplicationPackageTest extends TestWithCurator {
assertTrue(zkApp.getFileRegistryMap().containsKey(goodVersion));
assertFalse(zkApp.getFileRegistryMap().containsKey(Version.fromIntValues(0, 0, 0)));
assertThat(zkApp.getFileRegistryMap().get(goodVersion).fileSourceHost(), is("dummyfiles"));
- assertTrue(zkApp.getProvisionInfoMap().containsKey(goodVersion));
- ProvisionInfo readInfo = zkApp.getProvisionInfoMap().get(goodVersion);
- assertThat(Utf8.toString(readInfo.toJson()), is(Utf8.toString(provisionInfo.toJson())));
+ AllocatedHosts readInfo = zkApp.getAllocatedHosts().get();
+ assertThat(Utf8.toString(readInfo.toJson()), is(Utf8.toString(ALLOCATED_HOSTS.toJson())));
assertThat(readInfo.getHosts().iterator().next().flavor(), is(TEST_FLAVOR));
assertTrue(zkApp.getDeployment().isPresent());
assertThat(DeploymentSpec.fromXml(zkApp.getDeployment().get()).globalServiceId().get(), is("mydisc"));
@@ -78,7 +77,7 @@ public class ZKApplicationPackageTest extends TestWithCurator {
String metaData = "{\"deploy\":{\"user\":\"foo\",\"from\":\"bar\",\"timestamp\":1},\"application\":{\"name\":\"foo\",\"checksum\":\"abc\",\"generation\":4,\"previousActiveGeneration\":3}}";
zk.putData("/0", ConfigCurator.META_ZK_PATH, metaData);
zk.putData("/0/" + ZKApplicationPackage.fileRegistryNode + "/3.0.0", "dummyfiles");
- zk.putData("/0/" + ZKApplicationPackage.allocatedHostsNode + "/3.0.0", provisionInfo.toJson());
+ zk.putData("/0/" + ZKApplicationPackage.allocatedHostsNode + "/3.0.0", ALLOCATED_HOSTS.toJson());
}
private static class MockNodeFlavors extends NodeFlavors{
diff --git a/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/provisioning/CapacityPolicies.java b/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/provisioning/CapacityPolicies.java
index 914658302b6..e2ff17ba782 100644
--- a/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/provisioning/CapacityPolicies.java
+++ b/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/provisioning/CapacityPolicies.java
@@ -24,7 +24,6 @@ public class CapacityPolicies {
this.flavors = flavors;
}
- /** provides capacity defaults for various environments */
public int decideSize(Capacity requestedCapacity) {
int requestedNodes = requestedCapacity.nodeCount();
if (requestedCapacity.isRequired()) return requestedNodes;
@@ -39,10 +38,10 @@ public class CapacityPolicies {
}
public Flavor decideFlavor(Capacity requestedCapacity, ClusterSpec cluster, Optional<String> defaultFlavorOverride) {
- // for now, always use requested docker flavor when requested
+ // for now, always use the requested flavor if a docker flavor is requested
Optional<String> requestedFlavor = requestedCapacity.flavor();
if (requestedFlavor.isPresent() &&
- flavors.getFlavorOrThrow(requestedFlavor.get()).getType() == Flavor.Type.DOCKER_CONTAINER)
+ flavors.getFlavorOrThrow(requestedFlavor.get()).getType() == Flavor.Type.DOCKER_CONTAINER)
return flavors.getFlavorOrThrow(requestedFlavor.get());
String defaultFlavorName = defaultFlavorOverride.isPresent() ?
diff --git a/vespajlib/src/main/java/com/yahoo/lang/SettableOptional.java b/vespajlib/src/main/java/com/yahoo/lang/SettableOptional.java
new file mode 100644
index 00000000000..00ff06b8f01
--- /dev/null
+++ b/vespajlib/src/main/java/com/yahoo/lang/SettableOptional.java
@@ -0,0 +1,41 @@
+package com.yahoo.lang;
+
+import java.util.NoSuchElementException;
+import java.util.Optional;
+
+/**
+ * An optional which contains a settable value
+ *
+ * @author bratseth
+ */
+public final class SettableOptional<T> {
+
+ private T value = null;
+
+ /** Creates a new empty settable optional */
+ public SettableOptional() {}
+
+ /** Creates a new settable optional with the given value */
+ public SettableOptional(T value) { this.value = value; }
+
+ public boolean isPresent() {
+ return value != null;
+ }
+
+ public T get() {
+ if (value == null)
+ throw new NoSuchElementException("No value present");
+ return value;
+ }
+
+ public void set(T value) {
+ this.value = value;
+ }
+
+ public Optional<T> asOptional() {
+ if (value == null) return Optional.empty();
+ return Optional.of(value);
+ }
+
+}
+