aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJon Bratseth <bratseth@oath.com>2018-04-19 15:31:52 +0200
committerJon Bratseth <bratseth@oath.com>2018-04-19 15:31:52 +0200
commit7ac8f3b0f6cd3ff3e6556e69cc5aa97aa9ae76b9 (patch)
tree1e35300d77b8c6cc0d73b0fc6fa6ccf616f7ec90
parent1e0a2f24d4159edf46b5b457f07b33121d7e5bbf (diff)
Load the minimal set of models needed in dev
-rw-r--r--config-model/src/main/java/com/yahoo/config/model/provision/Host.java10
-rw-r--r--config-model/src/main/java/com/yahoo/config/model/provision/InMemoryProvisioner.java10
-rw-r--r--config-model/src/main/java/com/yahoo/config/model/provision/SingleNodeProvisioner.java1
-rw-r--r--config-model/src/main/java/com/yahoo/vespa/model/HostResource.java12
-rw-r--r--config-model/src/main/java/com/yahoo/vespa/model/HostSystem.java4
-rw-r--r--config-provisioning/src/main/java/com/yahoo/config/provision/AllocatedHosts.java30
-rw-r--r--config-provisioning/src/main/java/com/yahoo/config/provision/ClusterSpec.java1
-rw-r--r--config-provisioning/src/main/java/com/yahoo/config/provision/HostSpec.java17
-rw-r--r--config-provisioning/src/main/java/com/yahoo/config/provision/ProvisionInfo.java2
-rw-r--r--configserver/src/main/java/com/yahoo/vespa/config/server/ApplicationRepository.java2
-rw-r--r--configserver/src/main/java/com/yahoo/vespa/config/server/modelfactory/ActivatedModelsBuilder.java7
-rw-r--r--configserver/src/main/java/com/yahoo/vespa/config/server/modelfactory/ModelsBuilder.java23
-rw-r--r--configserver/src/main/java/com/yahoo/vespa/config/server/modelfactory/PreparedModelsBuilder.java2
-rw-r--r--configserver/src/main/java/com/yahoo/vespa/config/server/session/SessionFactory.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/SessionZooKeeperClient.java1
-rw-r--r--configserver/src/test/java/com/yahoo/vespa/config/server/TestComponentRegistry.java24
-rw-r--r--configserver/src/test/java/com/yahoo/vespa/config/server/deploy/DeployTester.java72
-rw-r--r--configserver/src/test/java/com/yahoo/vespa/config/server/deploy/HostedDeployTest.java52
-rw-r--r--configserver/src/test/java/com/yahoo/vespa/config/server/zookeeper/ZKApplicationPackageTest.java4
-rw-r--r--node-repository/src/main/java/com/yahoo/vespa/hosted/provision/provisioning/NodeRepositoryProvisioner.java3
-rw-r--r--node-repository/src/test/java/com/yahoo/vespa/hosted/provision/provisioning/ProvisioningTest.java25
22 files changed, 258 insertions, 50 deletions
diff --git a/config-model/src/main/java/com/yahoo/config/model/provision/Host.java b/config-model/src/main/java/com/yahoo/config/model/provision/Host.java
index 0374afe4e43..8c8debbae43 100644
--- a/config-model/src/main/java/com/yahoo/config/model/provision/Host.java
+++ b/config-model/src/main/java/com/yahoo/config/model/provision/Host.java
@@ -2,6 +2,7 @@
package com.yahoo.config.model.provision;
import com.google.common.collect.ImmutableList;
+import com.yahoo.component.Version;
import com.yahoo.config.provision.Flavor;
import java.util.ArrayList;
@@ -18,6 +19,7 @@ public class Host {
private final String hostname;
private final ImmutableList<String> aliases;
private final Optional<Flavor> flavor;
+ private final Optional<Version> version;
public Host(String hostname) {
this(hostname, ImmutableList.of(), Optional.empty());
@@ -28,9 +30,14 @@ public class Host {
}
public Host(String hostname, List<String> hostAliases, Optional<Flavor> flavor) {
+ this(hostname, hostAliases, flavor, Optional.empty());
+ }
+
+ public Host(String hostname, List<String> hostAliases, Optional<Flavor> flavor, Optional<Version> version) {
this.hostname = hostname;
this.aliases = ImmutableList.copyOf(hostAliases);
this.flavor = flavor;
+ this.version = version;
}
public String hostname() { return hostname; }
@@ -40,6 +47,9 @@ public class Host {
public Optional<Flavor> flavor() { return flavor; }
+ /** The current Vespa version running on this host, or empty if not known */
+ public Optional<Version> version() { return version; }
+
@Override
public String toString() {
return hostname + (aliases.size() > 0 ? " (aliases: " + aliases + ")" : "" ) +
diff --git a/config-model/src/main/java/com/yahoo/config/model/provision/InMemoryProvisioner.java b/config-model/src/main/java/com/yahoo/config/model/provision/InMemoryProvisioner.java
index 2e1d507eea1..e6b89d7f390 100644
--- a/config-model/src/main/java/com/yahoo/config/model/provision/InMemoryProvisioner.java
+++ b/config-model/src/main/java/com/yahoo/config/model/provision/InMemoryProvisioner.java
@@ -103,7 +103,7 @@ public class InMemoryProvisioner implements HostProvisioner {
List<Host> defaultHosts = freeNodes.get("default");
if (defaultHosts.isEmpty()) throw new IllegalArgumentException("No more hosts of default flavor available");
Host newHost = freeNodes.removeValue("default", 0);
- HostSpec hostSpec = new HostSpec(newHost.hostname(), newHost.aliases(), newHost.flavor(), Optional.empty());
+ HostSpec hostSpec = new HostSpec(newHost.hostname(), newHost.aliases(), newHost.flavor(), Optional.empty(), newHost.version());
legacyMapping.put(alias, hostSpec);
return hostSpec;
}
@@ -148,7 +148,11 @@ public class InMemoryProvisioner implements HostProvisioner {
}
private HostSpec retire(HostSpec host) {
- return new HostSpec(host.hostname(), host.aliases(), host.membership().get().retire());
+ return new HostSpec(host.hostname(),
+ host.aliases(),
+ host.flavor(),
+ Optional.of(host.membership().get().retire()),
+ host.version());
}
private List<HostSpec> allocateHostGroup(ClusterSpec clusterGroup, String flavor, int nodesInGroup, int startIndex) {
@@ -160,7 +164,7 @@ public class InMemoryProvisioner implements HostProvisioner {
if (freeNodes.get(flavor).isEmpty()) throw new IllegalArgumentException("Insufficient capacity of flavor '" + flavor + "'");
Host newHost = freeNodes.removeValue(flavor, 0);
ClusterMembership membership = ClusterMembership.from(clusterGroup, nextIndex++);
- allocation.add(new HostSpec(newHost.hostname(), newHost.aliases(), newHost.flavor(), Optional.of(membership)));
+ allocation.add(new HostSpec(newHost.hostname(), newHost.aliases(), newHost.flavor(), Optional.of(membership), newHost.version()));
}
nextIndexInCluster.put(new Pair<>(clusterGroup.type(), clusterGroup.id()), nextIndex);
diff --git a/config-model/src/main/java/com/yahoo/config/model/provision/SingleNodeProvisioner.java b/config-model/src/main/java/com/yahoo/config/model/provision/SingleNodeProvisioner.java
index 99c079739b4..0af11fdb941 100644
--- a/config-model/src/main/java/com/yahoo/config/model/provision/SingleNodeProvisioner.java
+++ b/config-model/src/main/java/com/yahoo/config/model/provision/SingleNodeProvisioner.java
@@ -14,7 +14,6 @@ import java.util.List;
* application if one exists.
*
* @author hmusum
- * @since 5.11
*/
public class SingleNodeProvisioner implements HostProvisioner {
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 0f7c040bf02..5c5bbba301f 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
@@ -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.model;
+import com.yahoo.component.Version;
import com.yahoo.config.model.api.HostInfo;
import com.yahoo.config.provision.ClusterMembership;
import com.yahoo.config.provision.Flavor;
@@ -44,13 +45,21 @@ public class HostResource implements Comparable<HostResource> {
// Empty for self-hosted Vespa.
private Optional<Flavor> flavor = Optional.empty();
+ /** The current Vespa version running on this node, or empty if not known */
+ private final Optional<Version> version;
+
/**
* Create a new {@link HostResource} bound to a specific {@link com.yahoo.vespa.model.Host}.
*
* @param host {@link com.yahoo.vespa.model.Host} object to bind to.
*/
public HostResource(Host host) {
+ this(host, Optional.empty());
+ }
+
+ public HostResource(Host host, Optional<Version> version) {
this.host = host;
+ this.version = version;
}
/**
@@ -59,6 +68,9 @@ public class HostResource implements Comparable<HostResource> {
*/
public Host getHost() { return host; }
+ /** Returns the current Vespa version running on this node, or null if not known */
+ public Optional<Version> version() { return version; }
+
/**
* Returns the baseport of the first available port range of length numPorts,
* or 0 if there is no range of that length available.
diff --git a/config-model/src/main/java/com/yahoo/vespa/model/HostSystem.java b/config-model/src/main/java/com/yahoo/vespa/model/HostSystem.java
index 6ef6c208c0a..5f55755c5a4 100644
--- a/config-model/src/main/java/com/yahoo/vespa/model/HostSystem.java
+++ b/config-model/src/main/java/com/yahoo/vespa/model/HostSystem.java
@@ -111,7 +111,7 @@ public class HostSystem extends AbstractConfigProducer<Host> {
private HostResource addNewHost(HostSpec hostSpec) {
Host host = new Host(this, hostSpec.hostname());
- HostResource hostResource = new HostResource(host);
+ HostResource hostResource = new HostResource(host, hostSpec.version());
hostResource.setFlavor(hostSpec.flavor());
hostSpec.membership().ifPresent(hostResource::addClusterMembership);
hostname2host.put(host.getHostname(), hostResource);
@@ -162,7 +162,7 @@ public class HostSystem extends AbstractConfigProducer<Host> {
Set<HostSpec> getHostSpecs() {
return getHosts().stream()
.map(host -> new HostSpec(host.getHostname(), Collections.emptyList(),
- host.getFlavor(), host.primaryClusterMembership()))
+ host.getFlavor(), host.primaryClusterMembership(), host.version()))
.collect(Collectors.toCollection(LinkedHashSet::new));
}
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
index 13efc2b3337..cc343821e0b 100644
--- a/config-provisioning/src/main/java/com/yahoo/config/provision/AllocatedHosts.java
+++ b/config-provisioning/src/main/java/com/yahoo/config/provision/AllocatedHosts.java
@@ -29,8 +29,13 @@ public class AllocatedHosts {
private static final String hostSpecHostName = "hostName";
private static final String hostSpecMembership = "membership";
private static final String hostSpecFlavor = "flavor";
+
+ /** Wanted version */
private static final String hostSpecVespaVersion = "vespaVersion";
+ /** Current version */
+ private static final String hostSpecCurrentVespaVersion = "currentVespaVersion";
+
private final ImmutableSet<HostSpec> hosts;
AllocatedHosts(Set<HostSpec> hosts) {
@@ -49,12 +54,12 @@ public class AllocatedHosts {
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());
+ host.membership().ifPresent(membership -> {
+ cursor.setString(hostSpecMembership, membership.stringValue());
+ cursor.setString(hostSpecVespaVersion, membership.cluster().vespaVersion().toString());
+ });
+ host.flavor().ifPresent(flavor -> cursor.setString(hostSpecFlavor, flavor.name()));
+ host.version().ifPresent(version -> cursor.setString(hostSpecCurrentVespaVersion, version.toString()));
}
/** Returns the hosts of this allocation */
@@ -66,19 +71,21 @@ public class AllocatedHosts {
array.traverse(new ArrayTraverser() {
@Override
public void entry(int i, Inspector inspector) {
- hosts.add(hostsFromSlime(inspector.field(hostSpecKey), nodeFlavors));
+ hosts.add(hostFromSlime(inspector.field(hostSpecKey), nodeFlavors));
}
});
return new AllocatedHosts(hosts);
}
- static HostSpec hostsFromSlime(Inspector object, Optional<NodeFlavors> nodeFlavors) {
+ static HostSpec hostFromSlime(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();
+ Optional<com.yahoo.component.Version> version =
+ optionalString(object.field(hostSpecCurrentVespaVersion)).map(com.yahoo.component.Version::new);
- return new HostSpec(object.field(hostSpecHostName).asString(),Collections.emptyList(), flavor, membership);
+ return new HostSpec(object.field(hostSpecHostName).asString(), Collections.emptyList(), flavor, membership, version);
}
private static ClusterMembership membershipFromSlime(Inspector object) {
@@ -91,6 +98,11 @@ public class AllocatedHosts {
.orElse(Optional.empty());
}
+ private static Optional<String> optionalString(Inspector inspector) {
+ if ( ! inspector.valid()) return Optional.empty();
+ return Optional.of(inspector.asString());
+ }
+
public byte[] toJson() throws IOException {
Slime slime = new Slime();
toSlime(slime.setObject());
diff --git a/config-provisioning/src/main/java/com/yahoo/config/provision/ClusterSpec.java b/config-provisioning/src/main/java/com/yahoo/config/provision/ClusterSpec.java
index a0df2547631..837e062e356 100644
--- a/config-provisioning/src/main/java/com/yahoo/config/provision/ClusterSpec.java
+++ b/config-provisioning/src/main/java/com/yahoo/config/provision/ClusterSpec.java
@@ -38,6 +38,7 @@ public final class ClusterSpec {
/** Returns the cluster id */
public Id id() { return id; }
+ /** Returns the version of Vespa that we want this cluster to run */
public Version vespaVersion() { return vespaVersion; }
/** Returns the group within the cluster this specifies, or empty to specify the whole cluster */
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 dd8bc311939..a6607092d8e 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
@@ -27,14 +27,21 @@ public class HostSpec implements Comparable<HostSpec> {
private final Optional<Flavor> flavor;
+ private final Optional<com.yahoo.component.Version> version;
+
public HostSpec(String hostname, Optional<ClusterMembership> membership) {
this(hostname, new ArrayList<>(), Optional.empty(), membership);
}
+ // TODO: Remove after May 2018
public HostSpec(String hostname, ClusterMembership membership, Flavor flavor) {
this(hostname, new ArrayList<>(), Optional.of(flavor), Optional.of(membership));
}
+ public HostSpec(String hostname, ClusterMembership membership, Flavor flavor, Optional<com.yahoo.component.Version> version) {
+ this(hostname, new ArrayList<>(), Optional.of(flavor), Optional.of(membership), version);
+ }
+
public HostSpec(String hostname, List<String> aliases) {
this(hostname, aliases, Optional.empty(), Optional.empty());
}
@@ -44,11 +51,18 @@ public class HostSpec implements Comparable<HostSpec> {
}
public HostSpec(String hostname, List<String> aliases, Optional<Flavor> flavor, Optional<ClusterMembership> membership) {
+ this(hostname, aliases, flavor, membership, Optional.empty());
+ }
+
+ public HostSpec(String hostname, List<String> aliases, Optional<Flavor> flavor,
+ Optional<ClusterMembership> membership, Optional<com.yahoo.component.Version> version) {
if (hostname == null || hostname.isEmpty()) throw new IllegalArgumentException("Hostname must be specified");
+ Objects.requireNonNull(version, "Version cannot be null but can be empty");
this.hostname = hostname;
this.aliases = ImmutableList.copyOf(aliases);
this.flavor = flavor;
this.membership = membership;
+ this.version = version;
}
/** Returns the name identifying this host */
@@ -59,6 +73,9 @@ public class HostSpec implements Comparable<HostSpec> {
public Optional<Flavor> flavor() { return flavor; }
+ /** Returns the current version of Vespa running on this node, or empty if not known */
+ public Optional<com.yahoo.component.Version> version() { return version; }
+
/** Returns the membership of this host, or an empty value if not present */
public Optional<ClusterMembership> membership() { return membership; }
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 8444f2e10fc..ca8d531634b 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
@@ -39,7 +39,7 @@ public class ProvisionInfo extends AllocatedHosts {
array.traverse(new ArrayTraverser() {
@Override
public void entry(int i, Inspector inspector) {
- hosts.add(hostsFromSlime(inspector.field(hostSpecKey), nodeFlavors));
+ hosts.add(hostFromSlime(inspector.field(hostSpecKey), nodeFlavors));
}
});
return new ProvisionInfo(hosts);
diff --git a/configserver/src/main/java/com/yahoo/vespa/config/server/ApplicationRepository.java b/configserver/src/main/java/com/yahoo/vespa/config/server/ApplicationRepository.java
index 636ac7e7070..43be4e279f0 100644
--- a/configserver/src/main/java/com/yahoo/vespa/config/server/ApplicationRepository.java
+++ b/configserver/src/main/java/com/yahoo/vespa/config/server/ApplicationRepository.java
@@ -210,7 +210,7 @@ public class ApplicationRepository implements com.yahoo.config.provision.Deploye
}
private Deployment deployFromPreparedSession(LocalSession session, Tenant tenant, Duration timeout) {
- return Deployment.prepared(session, this, hostProvisioner, tenant,timeout, clock);
+ return Deployment.prepared(session, this, hostProvisioner, tenant, timeout, clock);
}
// ---------------- Application operations ----------------------------------------------------------------
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 1301f24788f..08fd0a7afda 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
@@ -49,12 +49,12 @@ public class ActivatedModelsBuilder extends ModelsBuilder<Application> {
private final ConfigDefinitionRepo configDefinitionRepo;
private final Metrics metrics;
private final Curator curator;
- private final Zone zone;
private final DeployLogger logger;
public ActivatedModelsBuilder(TenantName tenant, long appGeneration, SessionZooKeeperClient zkClient, GlobalComponentRegistry globalComponentRegistry) {
super(globalComponentRegistry.getModelFactoryRegistry(),
- globalComponentRegistry.getHostProvisioner().isPresent());
+ globalComponentRegistry.getHostProvisioner().isPresent(),
+ globalComponentRegistry.getZone());
this.tenant = tenant;
this.appGeneration = appGeneration;
this.zkClient = zkClient;
@@ -63,7 +63,6 @@ public class ActivatedModelsBuilder extends ModelsBuilder<Application> {
this.configDefinitionRepo = globalComponentRegistry.getConfigDefinitionRepo();
this.metrics = globalComponentRegistry.getMetrics();
this.curator = globalComponentRegistry.getCurator();
- this.zone = globalComponentRegistry.getZone();
this.logger = new SilentDeployLogger();
}
@@ -109,7 +108,7 @@ public class ActivatedModelsBuilder extends ModelsBuilder<Application> {
return createModelContextProperties(
applicationId,
configserverConfig,
- zone,
+ zone(),
new Rotations(curator, Tenants.getTenantPath(tenant)).readRotationsFromZooKeeper(applicationId));
}
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 daff32198a3..04e0c9a2902 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
@@ -9,6 +9,7 @@ import com.yahoo.config.model.api.ModelFactory;
import com.yahoo.config.provision.AllocatedHosts;
import com.yahoo.config.provision.ApplicationId;
import com.yahoo.config.provision.ApplicationLockException;
+import com.yahoo.config.provision.Environment;
import com.yahoo.config.provision.HostName;
import com.yahoo.config.provision.OutOfCapacityException;
import com.yahoo.config.provision.Rotation;
@@ -49,11 +50,17 @@ public abstract class ModelsBuilder<MODELRESULT extends ModelResult> {
/** True if we are running in hosted mode */
private final boolean hosted;
- protected ModelsBuilder(ModelFactoryRegistry modelFactoryRegistry, boolean hosted) {
+ private final Zone zone;
+
+ protected ModelsBuilder(ModelFactoryRegistry modelFactoryRegistry, boolean hosted, Zone zone) {
this.modelFactoryRegistry = modelFactoryRegistry;
this.hosted = hosted;
+ this.zone = zone;
}
+ /** Returns the zone this is running in */
+ protected Zone zone() { return zone; }
+
/**
* Builds all applicable model versions
*
@@ -137,6 +144,9 @@ public abstract class ModelsBuilder<MODELRESULT extends ModelResult> {
List<MODELRESULT> allApplicationVersions = new ArrayList<>();
allApplicationVersions.add(latestModelVersion);
+ if (zone().environment() == Environment.dev)
+ versions = keepThoseUsedOn(allocatedHosts.get(), versions);
+
// 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
@@ -170,6 +180,17 @@ public abstract class ModelsBuilder<MODELRESULT extends ModelResult> {
return versionList.get(versionList.size() - 1);
}
+ /** Returns the subset of the given versions which are in use on these hosts */
+ private Set<Version> keepThoseUsedOn(AllocatedHosts hosts, Set<Version> versions) {
+ return versions.stream().filter(version -> mayBeUsedOn(hosts, version)).collect(Collectors.toSet());
+ }
+
+ private boolean mayBeUsedOn(AllocatedHosts hosts, Version version) {
+ com.yahoo.component.Version v = new com.yahoo.component.Version(version.toString());
+ return hosts.getHosts().stream()
+ .anyMatch(host -> ! host.version().isPresent() || host.version().get().equals(v));
+ }
+
protected abstract MODELRESULT buildModelVersion(ModelFactory modelFactory, ApplicationPackage applicationPackage,
ApplicationId applicationId,
com.yahoo.component.Version wantedNodeVespaVersion,
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 c265e0f6c2e..d7b84d75b5c 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
@@ -62,7 +62,7 @@ public class PreparedModelsBuilder extends ModelsBuilder<PreparedModelsBuilder.P
PrepareParams params,
Optional<ApplicationSet> currentActiveApplicationSet,
ModelContext.Properties properties) {
- super(modelFactoryRegistry, properties.hostedVespa());
+ super(modelFactoryRegistry, properties.hostedVespa(), properties.zone());
this.permanentApplicationPackage = permanentApplicationPackage;
this.configDefinitionRepo = configDefinitionRepo;
diff --git a/configserver/src/main/java/com/yahoo/vespa/config/server/session/SessionFactory.java b/configserver/src/main/java/com/yahoo/vespa/config/server/session/SessionFactory.java
index 3c05d491b35..172620a643a 100644
--- a/configserver/src/main/java/com/yahoo/vespa/config/server/session/SessionFactory.java
+++ b/configserver/src/main/java/com/yahoo/vespa/config/server/session/SessionFactory.java
@@ -10,9 +10,9 @@ import java.io.File;
* A session factory responsible for creating deploy sessions.
*
* @author lulf
- * @since 5.1
*/
public interface SessionFactory {
+
/**
* Creates a new deployment session from an application package.
*
@@ -34,4 +34,5 @@ public interface SessionFactory {
* @return a new session
*/
LocalSession createSessionFromExisting(LocalSession existingSession, DeployLogger logger, TimeoutBudget timeoutBudget);
+
}
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 fdc681b5fb6..9bbaf35bce9 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
@@ -33,8 +33,7 @@ import java.util.logging.Logger;
* Serves as the factory of sessions. Takes care of copying files to the correct folder and initializing the
* session state.
*
- * @author lulf
- * @since 5.1
+ * @author Ulf Lilleengen
*/
public class SessionFactoryImpl implements SessionFactory, LocalSessionLoader {
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 f7d6b8f05fe..de903b7f2dd 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
@@ -210,6 +210,7 @@ public class SessionZooKeeperClient {
/**
* Create necessary paths atomically for a new session.
+ *
* @param createTime Time of session creation.
* @param timeUnit Time unit of createTime.
*/
diff --git a/configserver/src/test/java/com/yahoo/vespa/config/server/TestComponentRegistry.java b/configserver/src/test/java/com/yahoo/vespa/config/server/TestComponentRegistry.java
index 3b56b5b35bf..d026989a43e 100644
--- a/configserver/src/test/java/com/yahoo/vespa/config/server/TestComponentRegistry.java
+++ b/configserver/src/test/java/com/yahoo/vespa/config/server/TestComponentRegistry.java
@@ -30,8 +30,7 @@ import java.util.Optional;
import static com.yahoo.vespa.config.server.SuperModelRequestHandlerTest.emptyNodeFlavors;
/**
- * @author lulf
- * @since 5.1
+ * @author Ulf Lilleengen
*/
public class TestComponentRegistry implements GlobalComponentRegistry {
@@ -50,6 +49,7 @@ public class TestComponentRegistry implements GlobalComponentRegistry {
private final FileDistributionFactory fileDistributionFactory;
private final ModelFactoryRegistry modelFactoryRegistry;
private final Optional<Provisioner> hostProvisioner;
+ private final Zone zone;
private final Clock clock;
private TestComponentRegistry(Curator curator, ConfigCurator configCurator, Metrics metrics,
@@ -65,6 +65,7 @@ public class TestComponentRegistry implements GlobalComponentRegistry {
ConfigDefinitionRepo defRepo,
ReloadListener reloadListener,
TenantListener tenantListener,
+ Zone zone,
Clock clock) {
this.curator = curator;
this.configCurator = configCurator;
@@ -81,6 +82,7 @@ public class TestComponentRegistry implements GlobalComponentRegistry {
this.modelFactoryRegistry = modelFactoryRegistry;
this.hostProvisioner = hostProvisioner;
this.sessionPreparer = sessionPreparer;
+ this.zone = zone;
this.clock = clock;
}
@@ -101,6 +103,7 @@ public class TestComponentRegistry implements GlobalComponentRegistry {
private Optional<FileDistributionFactory> fileDistributionFactory = Optional.empty();
private ModelFactoryRegistry modelFactoryRegistry = new ModelFactoryRegistry(Collections.singletonList(new VespaModelFactory(new NullConfigModelRegistry())));
private Optional<Provisioner> hostProvisioner = Optional.empty();
+ private Zone zone = Zone.defaultZone();
private Clock clock = Clock.systemUTC();
public Builder configServerConfig(ConfigserverConfig configserverConfig) {
@@ -138,6 +141,11 @@ public class TestComponentRegistry implements GlobalComponentRegistry {
return this;
}
+ public Builder zone(Zone zone) {
+ this.zone = zone;
+ return this;
+ }
+
public Builder clock(Clock clock) {
this.clock = clock;
return this;
@@ -154,7 +162,7 @@ public class TestComponentRegistry implements GlobalComponentRegistry {
SessionPreparer sessionPreparer = new SessionPreparer(modelFactoryRegistry, fileDistributionFactory,
hostProvisionerProvider, permApp,
configserverConfig, defRepo, curator,
- new Zone(configserverConfig, emptyNodeFlavors()));
+ zone);
return new TestComponentRegistry(curator, configCurator.orElse(ConfigCurator.create(curator)),
metrics, modelFactoryRegistry,
permApp,
@@ -163,7 +171,7 @@ public class TestComponentRegistry implements GlobalComponentRegistry {
new ConfigServerDB(configserverConfig),
hostRegistries, configserverConfig, sessionPreparer,
hostProvisioner, defRepo, reloadListener,
- tenantListener, clock);
+ tenantListener, zone, clock);
}
}
@@ -193,19 +201,17 @@ public class TestComponentRegistry implements GlobalComponentRegistry {
public HostRegistries getHostRegistries() { return hostRegistries;}
@Override
public ModelFactoryRegistry getModelFactoryRegistry() { return modelFactoryRegistry; }
-
@Override
public Optional<Provisioner> getHostProvisioner() {
return hostProvisioner;
}
-
@Override
public Zone getZone() {
- return Zone.defaultZone();
+ return zone;
}
+ @Override
+ public Clock getClock() { return clock;}
public FileDistributionFactory getFileDistributionFactory() { return fileDistributionFactory; }
- @Override
- public Clock getClock() { return clock;}
}
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 95cfd17139d..2a57d85f3f7 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
@@ -25,6 +25,7 @@ import com.yahoo.config.provision.ProvisionLogger;
import com.yahoo.config.provision.Provisioner;
import com.yahoo.config.provision.TenantName;
import com.yahoo.config.provision.Version;
+import com.yahoo.config.provision.Zone;
import com.yahoo.transaction.NestedTransaction;
import com.yahoo.vespa.config.server.ApplicationRepository;
import com.yahoo.vespa.config.server.TestComponentRegistry;
@@ -91,9 +92,18 @@ public class DeployTester {
}
public DeployTester(String appPath, List<ModelFactory> modelFactories, ConfigserverConfig configserverConfig, Clock clock) {
+ this(appPath, modelFactories, configserverConfig, clock, Zone.defaultZone());
+ }
+
+ public DeployTester(String appPath, List<ModelFactory> modelFactories, ConfigserverConfig configserverConfig, Clock clock, Zone zone) {
+ this(appPath, modelFactories, configserverConfig, clock, Zone.defaultZone(), createProvisioner());
+ }
+
+ public DeployTester(String appPath, List<ModelFactory> modelFactories, ConfigserverConfig configserverConfig, Clock clock, Zone zone, HostProvisioner provisioner) {
this.clock = clock;
TestComponentRegistry componentRegistry = createComponentRegistry(new MockCurator(), Metrics.createTestMetrics(),
- modelFactories, configserverConfig, clock);
+ modelFactories, configserverConfig, clock, zone,
+ provisioner);
try {
this.testApp = new File(appPath);
this.tenants = new Tenants(componentRegistry, Collections.emptySet());
@@ -102,7 +112,7 @@ public class DeployTester {
catch (Exception e) {
throw new IllegalArgumentException(e);
}
- applicationRepository = new ApplicationRepository(tenants, createHostProvisioner(), clock);
+ applicationRepository = new ApplicationRepository(tenants, new ProvisionerAdapter(provisioner), clock);
}
public Tenant tenant() {
@@ -110,13 +120,13 @@ public class DeployTester {
}
/** Create a model factory for the version of this source*/
- public static ModelFactory createModelFactory(Clock clock) {
- return new VespaModelFactory(new NullConfigModelRegistry(), clock);
+ public static CountingModelFactory createModelFactory(Clock clock) {
+ return new CountingModelFactory(clock);
}
/** Create a model factory for a particular version */
- public static ModelFactory createModelFactory(Version version, Clock clock) {
- return new VespaModelFactory(version, new NullConfigModelRegistry(), clock);
+ public static CountingModelFactory createModelFactory(Version version, Clock clock) {
+ return new CountingModelFactory(version, clock);
}
/** Create a model factory which always fails validation */
@@ -168,24 +178,26 @@ public class DeployTester {
return applicationRepository;
}
- private Provisioner createHostProvisioner() {
- return new ProvisionerAdapter(new InMemoryProvisioner(true, "host0", "host1", "host2", "host3", "host4", "host5"));
+ private static HostProvisioner createProvisioner() {
+ return new InMemoryProvisioner(true, "host0", "host1", "host2", "host3", "host4", "host5");
}
private TestComponentRegistry createComponentRegistry(Curator curator, Metrics metrics,
List<ModelFactory> modelFactories,
ConfigserverConfig configserverConfig,
- Clock clock) {
+ Clock clock,
+ Zone zone,
+ HostProvisioner provisioner) {
TestComponentRegistry.Builder builder = new TestComponentRegistry.Builder();
- if (configserverConfig.hostedVespa()) {
- builder.provisioner(createHostProvisioner());
- }
+ if (configserverConfig.hostedVespa())
+ builder.provisioner(new ProvisionerAdapter(provisioner));
builder.configServerConfig(configserverConfig)
.curator(curator)
.modelFactoryRegistry(new ModelFactoryRegistry(modelFactories))
.metrics(metrics)
+ .zone(zone)
.clock(clock);
return builder.build();
}
@@ -252,4 +264,40 @@ public class DeployTester {
}
+ /** A wrapper of the regular model factory which counts the number of models it has created */
+ public static class CountingModelFactory implements ModelFactory {
+
+ private final VespaModelFactory wrapped;
+ private int creationCount;
+
+ public CountingModelFactory(Clock clock) {
+ this.wrapped = new VespaModelFactory(new NullConfigModelRegistry(), clock);
+ }
+
+ public CountingModelFactory(Version version, Clock clock) {
+ this.wrapped = new VespaModelFactory(version, new NullConfigModelRegistry(), clock);
+ }
+
+ /** Returns the number of models created successfully by this instance */
+ public int creationCount() { return creationCount; }
+
+ @Override
+ public Version getVersion() { return wrapped.getVersion(); }
+
+ @Override
+ public Model createModel(ModelContext modelContext) {
+ Model model = wrapped.createModel(modelContext);
+ creationCount++;
+ return model;
+ }
+
+ @Override
+ public ModelCreateResult createAndValidateModel(ModelContext modelContext, boolean ignoreValidationErrors) {
+ ModelCreateResult result = wrapped.createAndValidateModel(modelContext, ignoreValidationErrors);
+ creationCount++;
+ return result;
+ }
+
+ }
+
}
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 bd9c6476ad6..8271d6de452 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
@@ -4,14 +4,22 @@ package com.yahoo.vespa.config.server.deploy;
import com.google.common.io.Files;
import com.yahoo.cloud.config.ConfigserverConfig;
import com.yahoo.config.model.api.ModelFactory;
+import com.yahoo.config.model.provision.Host;
+import com.yahoo.config.model.provision.Hosts;
+import com.yahoo.config.model.provision.InMemoryProvisioner;
import com.yahoo.config.provision.ApplicationId;
+import com.yahoo.config.provision.Environment;
+import com.yahoo.config.provision.RegionName;
import com.yahoo.config.provision.Version;
+import com.yahoo.config.provision.Zone;
import com.yahoo.test.ManualClock;
+import static com.yahoo.vespa.config.server.deploy.DeployTester.CountingModelFactory;
import org.junit.Test;
import java.time.Duration;
import java.time.Instant;
import java.util.ArrayList;
+import java.util.Collections;
import java.util.List;
import java.util.Optional;
@@ -54,9 +62,47 @@ public class HostedDeployTest {
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());
+ DeployTester tester = new DeployTester("src/test/apps/hosted/", modelFactories, createConfigserverConfig(), clock, Zone.defaultZone());
ApplicationId app = tester.deployApp("myApp", Instant.now());
assertEquals(3, tester.getAllocatedHostsOf(app).getHosts().size());
+
+ }
+
+ /** Test that unused versions are skipped in dev */
+ @Test
+ public void testDeployMultipleVersionsInDev() {
+ List<Host> hosts = new ArrayList<>();
+ hosts.add(createHost("host1", "6.0.0"));
+ hosts.add(createHost("host2", "6.0.2"));
+ hosts.add(createHost("host3", "7.1.0"));
+ InMemoryProvisioner provisioner = new InMemoryProvisioner(new Hosts(hosts), true);
+ ManualClock clock = new ManualClock("2016-10-09T00:00:00");
+
+ CountingModelFactory factory600 = DeployTester.createModelFactory(Version.fromString("6.0.0"), clock);
+ CountingModelFactory factory610 = DeployTester.createModelFactory(Version.fromString("6.1.0"), clock);
+ CountingModelFactory factory620 = DeployTester.createModelFactory(Version.fromString("6.2.0"), clock);
+ CountingModelFactory factory700 = DeployTester.createModelFactory(Version.fromString("7.0.0"), clock);
+ CountingModelFactory factory710 = DeployTester.createModelFactory(Version.fromString("7.1.0"), clock);
+ CountingModelFactory factory720 = DeployTester.createModelFactory(Version.fromString("7.2.0"), clock);
+ List<ModelFactory> modelFactories = new ArrayList<>();
+ modelFactories.add(factory600);
+ modelFactories.add(factory610);
+ modelFactories.add(factory620);
+ modelFactories.add(factory700);
+ modelFactories.add(factory710);
+ modelFactories.add(factory720);
+
+ DeployTester tester = new DeployTester("src/test/apps/hosted/", modelFactories, createConfigserverConfig(),
+ clock, new Zone(Environment.dev, RegionName.defaultName()), provisioner);
+ ApplicationId app = tester.deployApp("myApp", Instant.now());
+ assertEquals(3, tester.getAllocatedHostsOf(app).getHosts().size());
+
+ assertEquals(1, factory600.creationCount());
+ assertEquals(0, factory610.creationCount());
+ assertEquals(1, factory620.creationCount());
+ assertEquals(0, factory700.creationCount());
+ assertEquals(1, factory710.creationCount());
+ assertEquals("Newest is always included", 1, factory720.creationCount());
}
@Test
@@ -107,4 +153,8 @@ public class HostedDeployTest {
.multitenant(true));
}
+ private Host createHost(String hostname, String version) {
+ return new Host(hostname, Collections.emptyList(), Optional.empty(), Optional.of(com.yahoo.component.Version.fromString(version)));
+ }
+
}
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 56ef3f340e2..f0c74d19af9 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
@@ -34,7 +34,8 @@ public class ZKApplicationPackageTest extends TestWithCurator {
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 AllocatedHosts ALLOCATED_HOSTS = AllocatedHosts.withHosts(
- Collections.singleton(new HostSpec("foo.yahoo.com", Collections.emptyList(), TEST_FLAVOR, Optional.empty())));
+ Collections.singleton(new HostSpec("foo.yahoo.com", Collections.emptyList(), TEST_FLAVOR, Optional.empty(),
+ Optional.of(com.yahoo.component.Version.fromString("6.0.1")))));
@Rule
public TemporaryFolder tmpDir = new TemporaryFolder();
@@ -67,6 +68,7 @@ public class ZKApplicationPackageTest extends TestWithCurator {
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));
+ assertEquals("6.0.1", readInfo.getHosts().iterator().next().version().get().toString());
assertTrue(zkApp.getDeployment().isPresent());
assertThat(DeploymentSpec.fromXml(zkApp.getDeployment().get()).globalServiceId().get(), is("mydisc"));
}
diff --git a/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/provisioning/NodeRepositoryProvisioner.java b/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/provisioning/NodeRepositoryProvisioner.java
index 304c867a886..3fa70b3242f 100644
--- a/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/provisioning/NodeRepositoryProvisioner.java
+++ b/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/provisioning/NodeRepositoryProvisioner.java
@@ -123,7 +123,8 @@ public class NodeRepositoryProvisioner implements Provisioner {
log.log(LogLevel.DEBUG, () -> "Prepared node " + node.hostname() + " - " + node.flavor());
hosts.add(new HostSpec(node.hostname(),
node.allocation().orElseThrow(IllegalStateException::new).membership(),
- node.flavor()));
+ node.flavor(),
+ node.status().vespaVersion()));
}
return hosts;
}
diff --git a/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/provisioning/ProvisioningTest.java b/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/provisioning/ProvisioningTest.java
index e00f058efaa..2ffe23cea07 100644
--- a/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/provisioning/ProvisioningTest.java
+++ b/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/provisioning/ProvisioningTest.java
@@ -140,6 +140,31 @@ public class ProvisioningTest {
}
@Test
+ public void nodeVersionIsReturnedIfSet() {
+ ProvisioningTester tester = new ProvisioningTester(new Zone(Environment.dev, RegionName.from("us-east")));
+
+ ApplicationId application1 = tester.makeApplicationId();
+
+ tester.makeReadyNodes(4, "default");
+
+ // deploy
+ SystemState state1 = prepare(application1, 1, 1, 1, 1, "default", tester);
+ tester.activate(application1, state1.allHosts);
+
+ HostSpec host1 = state1.container0.iterator().next();
+ assertFalse(host1.version().isPresent());
+ Node node1 = tester.nodeRepository().getNode(host1.hostname()).get();
+ tester.nodeRepository().write(node1.with(node1.status().withVespaVersion(Version.fromString("1.2.3"))));
+
+ // redeploy
+ SystemState state2 = prepare(application1, 1, 1, 1, 1, "default", tester);
+ tester.activate(application1, state2.allHosts);
+
+ host1 = state2.container0.iterator().next();
+ assertEquals(Version.fromString("1.2.3"), host1.version().get());
+ }
+
+ @Test
public void application_deployment_variable_application_size() {
ProvisioningTester tester = new ProvisioningTester(new Zone(Environment.prod, RegionName.from("us-east")));