summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJon Bratseth <bratseth@verizonmedia.com>2019-10-30 12:35:34 +0100
committerJon Bratseth <bratseth@verizonmedia.com>2019-10-30 12:35:34 +0100
commite06a6964a293de546dde991a98fb8b2426ca54e1 (patch)
tree0e59cebf8b16573c79d22355e5e5fcaf35d14411
parentdf12f4734894f1a5e37f97f9d8457f58b1481001 (diff)
Remember requested resources on nodes
This may be different from assigned resources e.g in that requested resources may specify DiskSpeed.any while assigned resources always have a definite disk speed.
-rw-r--r--config-provisioning/abi-spec.json2
-rw-r--r--config-provisioning/src/main/java/com/yahoo/config/provision/HostSpec.java20
-rw-r--r--config-provisioning/src/main/java/com/yahoo/config/provision/serialization/AllocatedHostsSerializer.java79
-rw-r--r--config-provisioning/src/test/java/com/yahoo/config/provision/serialization/AllocatedHostsSerializerTest.java8
-rw-r--r--node-repository/src/main/java/com/yahoo/vespa/hosted/provision/Node.java5
-rw-r--r--node-repository/src/main/java/com/yahoo/vespa/hosted/provision/node/Allocation.java29
-rw-r--r--node-repository/src/main/java/com/yahoo/vespa/hosted/provision/persistence/NodeSerializer.java47
-rw-r--r--node-repository/src/main/java/com/yahoo/vespa/hosted/provision/provisioning/Activator.java16
-rw-r--r--node-repository/src/main/java/com/yahoo/vespa/hosted/provision/provisioning/NodeAllocation.java12
-rw-r--r--node-repository/src/main/java/com/yahoo/vespa/hosted/provision/provisioning/NodePrioritizer.java2
-rw-r--r--node-repository/src/main/java/com/yahoo/vespa/hosted/provision/provisioning/NodeRepositoryProvisioner.java8
-rw-r--r--node-repository/src/main/java/com/yahoo/vespa/hosted/provision/provisioning/NodeSpec.java12
-rw-r--r--node-repository/src/main/java/com/yahoo/vespa/hosted/provision/provisioning/Preparer.java3
-rw-r--r--node-repository/src/test/java/com/yahoo/vespa/hosted/provision/maintenance/CapacityCheckerTester.java2
-rw-r--r--node-repository/src/test/java/com/yahoo/vespa/hosted/provision/maintenance/DynamicProvisioningMaintainerTest.java1
-rw-r--r--node-repository/src/test/java/com/yahoo/vespa/hosted/provision/maintenance/MetricsReporterTest.java7
-rw-r--r--node-repository/src/test/java/com/yahoo/vespa/hosted/provision/persistence/SerializationTest.java32
-rw-r--r--node-repository/src/test/java/com/yahoo/vespa/hosted/provision/provisioning/AllocationSimulator.java5
-rw-r--r--node-repository/src/test/java/com/yahoo/vespa/hosted/provision/provisioning/DynamicDockerAllocationTest.java2
-rw-r--r--node-repository/src/test/java/com/yahoo/vespa/hosted/provision/provisioning/InfraDeployerImplTest.java2
-rw-r--r--node-repository/src/test/java/com/yahoo/vespa/hosted/provision/provisioning/ProvisioningTest.java32
-rw-r--r--node-repository/src/test/java/com/yahoo/vespa/hosted/provision/provisioning/ProvisioningTester.java3
22 files changed, 212 insertions, 117 deletions
diff --git a/config-provisioning/abi-spec.json b/config-provisioning/abi-spec.json
index 4e50d31d74a..d8b17009b65 100644
--- a/config-provisioning/abi-spec.json
+++ b/config-provisioning/abi-spec.json
@@ -477,12 +477,14 @@
"public void <init>(java.lang.String, java.util.List, java.util.Optional, java.util.Optional)",
"public void <init>(java.lang.String, java.util.List, java.util.Optional, java.util.Optional, java.util.Optional)",
"public void <init>(java.lang.String, java.util.List, java.util.Optional, java.util.Optional, java.util.Optional, java.util.Optional)",
+ "public void <init>(java.lang.String, java.util.List, java.util.Optional, java.util.Optional, java.util.Optional, java.util.Optional, java.util.Optional)",
"public java.lang.String hostname()",
"public java.util.List aliases()",
"public java.util.Optional flavor()",
"public java.util.Optional version()",
"public java.util.Optional membership()",
"public java.util.Optional networkPorts()",
+ "public java.util.Optional requestedResources()",
"public java.lang.String toString()",
"public boolean equals(java.lang.Object)",
"public int 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 ba7a3c2f06b..a046df1ac9a 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
@@ -29,6 +29,8 @@ public class HostSpec implements Comparable<HostSpec> {
private final Optional<NetworkPorts> networkPorts;
+ private Optional<NodeResources> requestedResources;
+
public HostSpec(String hostname, Optional<ClusterMembership> membership) {
this(hostname, new ArrayList<>(), Optional.empty(), membership);
}
@@ -61,15 +63,22 @@ public class HostSpec implements Comparable<HostSpec> {
public HostSpec(String hostname, List<String> aliases, Optional<Flavor> flavor,
Optional<ClusterMembership> membership, Optional<com.yahoo.component.Version> version,
Optional<NetworkPorts> networkPorts) {
+ this(hostname, aliases, flavor, membership, version, networkPorts, Optional.empty());
+ }
+
+ public HostSpec(String hostname, List<String> aliases, Optional<Flavor> flavor,
+ Optional<ClusterMembership> membership, Optional<com.yahoo.component.Version> version,
+ Optional<NetworkPorts> networkPorts, Optional<NodeResources> requestedResources) {
if (hostname == null || hostname.isEmpty()) throw new IllegalArgumentException("Hostname must be specified");
- Objects.requireNonNull(version, "Version cannot be null but can be empty");
- Objects.requireNonNull(networkPorts, "Network ports cannot be null but can be empty");
+
+
this.hostname = hostname;
this.aliases = List.copyOf(aliases);
this.flavor = flavor;
this.membership = membership;
- this.version = version;
- this.networkPorts = networkPorts;
+ this.version = Objects.requireNonNull(version, "Version cannot be null but can be empty");;
+ this.networkPorts = Objects.requireNonNull(networkPorts, "Network ports cannot be null but can be empty");;
+ this.requestedResources = Objects.requireNonNull(requestedResources, "RequestedResources cannot be null");
}
/** Returns the name identifying this host */
@@ -89,6 +98,9 @@ public class HostSpec implements Comparable<HostSpec> {
/** Returns the network port allocations on this host, or empty if not present */
public Optional<NetworkPorts> networkPorts() { return networkPorts; }
+ /** Returns the requested resources leading to this host being provisioned, or empty if not known */
+ public Optional<NodeResources> requestedResources() { return requestedResources; }
+
@Override
public String toString() {
return hostname +
diff --git a/config-provisioning/src/main/java/com/yahoo/config/provision/serialization/AllocatedHostsSerializer.java b/config-provisioning/src/main/java/com/yahoo/config/provision/serialization/AllocatedHostsSerializer.java
index a7ba286baa7..4a060fb5143 100644
--- a/config-provisioning/src/main/java/com/yahoo/config/provision/serialization/AllocatedHostsSerializer.java
+++ b/config-provisioning/src/main/java/com/yahoo/config/provision/serialization/AllocatedHostsSerializer.java
@@ -49,6 +49,7 @@ public class AllocatedHostsSerializer {
private static final String flavorKey = "flavor";
private static final String resourcesKey = "resources";
+ private static final String requestedResourcesKey = "requestedResources";
private static final String vcpuKey = "vcpu";
private static final String memoryKey = "memory";
private static final String diskKey = "disk";
@@ -75,16 +76,17 @@ public class AllocatedHostsSerializer {
toSlime(host, array.addObject().setObject(hostSpecKey));
}
- private static void toSlime(HostSpec host, Cursor cursor) {
- cursor.setString(hostSpecHostNameKey, host.hostname());
- aliasesToSlime(host, cursor);
+ private static void toSlime(HostSpec host, Cursor object) {
+ object.setString(hostSpecHostNameKey, host.hostname());
+ aliasesToSlime(host, object);
host.membership().ifPresent(membership -> {
- cursor.setString(hostSpecMembershipKey, membership.stringValue());
- cursor.setString(hostSpecVespaVersionKey, membership.cluster().vespaVersion().toFullString());
+ object.setString(hostSpecMembershipKey, membership.stringValue());
+ object.setString(hostSpecVespaVersionKey, membership.cluster().vespaVersion().toFullString());
});
- host.flavor().ifPresent(flavor -> toSlime(flavor, cursor));
- host.version().ifPresent(version -> cursor.setString(hostSpecCurrentVespaVersionKey, version.toFullString()));
- host.networkPorts().ifPresent(ports -> NetworkPortsSerializer.toSlime(ports, cursor.setArray(hostSpecNetworkPortsKey)));
+ host.flavor().ifPresent(flavor -> toSlime(flavor, object));
+ host.requestedResources().ifPresent(resources -> toSlime(resources, object.setObject(requestedResourcesKey)));
+ host.version().ifPresent(version -> object.setString(hostSpecCurrentVespaVersionKey, version.toFullString()));
+ host.networkPorts().ifPresent(ports -> NetworkPortsSerializer.toSlime(ports, object.setArray(hostSpecNetworkPortsKey)));
}
private static void aliasesToSlime(HostSpec spec, Cursor cursor) {
@@ -95,20 +97,19 @@ public class AllocatedHostsSerializer {
}
private static void toSlime(Flavor flavor, Cursor object) {
- if (flavor.isConfigured()) {
+ if (flavor.isConfigured())
object.setString(flavorKey, flavor.name());
- }
- else {
- NodeResources resources = flavor.resources();
- Cursor resourcesObject = object.setObject(resourcesKey);
- resourcesObject.setDouble(vcpuKey, resources.vcpu());
- resourcesObject.setDouble(memoryKey, resources.memoryGb());
- resourcesObject.setDouble(diskKey, resources.diskGb());
- resourcesObject.setDouble(bandwidthKey, resources.bandwidthGbps());
- resourcesObject.setString(diskSpeedKey, diskSpeedToString(resources.diskSpeed()));
- }
+ else
+ toSlime(flavor.resources(), object.setObject(resourcesKey));
}
+ private static void toSlime(NodeResources resources, Cursor resourcesObject) {
+ resourcesObject.setDouble(vcpuKey, resources.vcpu());
+ resourcesObject.setDouble(memoryKey, resources.memoryGb());
+ resourcesObject.setDouble(diskKey, resources.diskGb());
+ resourcesObject.setDouble(bandwidthKey, resources.bandwidthGbps());
+ resourcesObject.setString(diskSpeedKey, diskSpeedToString(resources.diskSpeed()));
+ }
public static AllocatedHosts fromJson(byte[] json, Optional<NodeFlavors> nodeFlavors) {
return fromSlime(SlimeUtils.jsonToSlime(json).get(), nodeFlavors);
@@ -122,14 +123,13 @@ public class AllocatedHostsSerializer {
}
private static HostSpec hostFromSlime(Inspector object, Optional<NodeFlavors> nodeFlavors) {
- Optional<ClusterMembership> membership =
- object.field(hostSpecMembershipKey).valid() ? Optional.of(membershipFromSlime(object)) : Optional.empty();
- Optional<Flavor> flavor = flavorFromSlime(object, nodeFlavors);
- Optional<com.yahoo.component.Version> version =
- optionalString(object.field(hostSpecCurrentVespaVersionKey)).map(com.yahoo.component.Version::new);
- Optional<NetworkPorts> networkPorts =
- NetworkPortsSerializer.fromSlime(object.field(hostSpecNetworkPortsKey));
- return new HostSpec(object.field(hostSpecHostNameKey).asString(), aliasesFromSlime(object), flavor, membership, version, networkPorts);
+ return new HostSpec(object.field(hostSpecHostNameKey).asString(),
+ aliasesFromSlime(object),
+ flavorFromSlime(object, nodeFlavors),
+ object.field(hostSpecMembershipKey).valid() ? Optional.of(membershipFromSlime(object)) : Optional.empty(),
+ optionalString(object.field(hostSpecCurrentVespaVersionKey)).map(com.yahoo.component.Version::new),
+ NetworkPortsSerializer.fromSlime(object.field(hostSpecNetworkPortsKey)),
+ nodeResourcesFromSlime(object.field(requestedResourcesKey)));
}
private static List<String> aliasesFromSlime(Inspector object) {
@@ -140,20 +140,19 @@ public class AllocatedHostsSerializer {
}
private static Optional<Flavor> flavorFromSlime(Inspector object, Optional<NodeFlavors> nodeFlavors) {
- if (object.field(flavorKey).valid() && nodeFlavors.isPresent() && nodeFlavors.get().exists(object.field(flavorKey).asString())) {
+ if (object.field(flavorKey).valid() && nodeFlavors.isPresent() && nodeFlavors.get().exists(object.field(flavorKey).asString()))
return nodeFlavors.get().getFlavor(object.field(flavorKey).asString());
- }
- else if (object.field(resourcesKey).valid()) {
- Inspector resources = object.field(resourcesKey);
- return Optional.of(new Flavor(new NodeResources(resources.field(vcpuKey).asDouble(),
- resources.field(memoryKey).asDouble(),
- resources.field(diskKey).asDouble(),
- resources.field(bandwidthKey).asDouble(),
- diskSpeedFromSlime(resources.field(diskSpeedKey)))));
- }
- else {
- return Optional.empty();
- }
+ else
+ return nodeResourcesFromSlime(object.field(resourcesKey)).map(resources -> new Flavor(resources));
+ }
+
+ private static Optional<NodeResources> nodeResourcesFromSlime(Inspector resources) {
+ if ( ! resources.valid()) return Optional.empty();
+ return Optional.of(new NodeResources(resources.field(vcpuKey).asDouble(),
+ resources.field(memoryKey).asDouble(),
+ resources.field(diskKey).asDouble(),
+ resources.field(bandwidthKey).asDouble(),
+ diskSpeedFromSlime(resources.field(diskSpeedKey))));
}
private static NodeResources.DiskSpeed diskSpeedFromSlime(Inspector diskSpeed) {
diff --git a/config-provisioning/src/test/java/com/yahoo/config/provision/serialization/AllocatedHostsSerializerTest.java b/config-provisioning/src/test/java/com/yahoo/config/provision/serialization/AllocatedHostsSerializerTest.java
index a5af9aa0cb5..afec242de0b 100644
--- a/config-provisioning/src/test/java/com/yahoo/config/provision/serialization/AllocatedHostsSerializerTest.java
+++ b/config-provisioning/src/test/java/com/yahoo/config/provision/serialization/AllocatedHostsSerializerTest.java
@@ -42,7 +42,12 @@ public class AllocatedHostsSerializerTest {
hosts.add(new HostSpec("flavor-from-resources-1",
Collections.emptyList(), new Flavor(new NodeResources(0.5, 3.1, 4, 1))));
hosts.add(new HostSpec("flavor-from-resources-2",
- Collections.emptyList(), new Flavor(new NodeResources(0.5, 3.1, 4, 1, NodeResources.DiskSpeed.any))));
+ Collections.emptyList(),
+ Optional.of(new Flavor(new NodeResources(0.5, 3.1, 4, 1, NodeResources.DiskSpeed.slow))),
+ Optional.empty(),
+ Optional.empty(),
+ Optional.empty(),
+ Optional.of(new NodeResources(0.5, 3.1, 4, 1, NodeResources.DiskSpeed.any))));
hosts.add(new HostSpec("configured-flavor",
Collections.emptyList(), configuredFlavors.getFlavorOrThrow("C/12/45/100")));
hosts.add(new HostSpec("with-version",
@@ -67,6 +72,7 @@ public class AllocatedHostsSerializerTest {
assertEquals(expectedHost.version(), deserializedHost.version());
assertEquals(expectedHost.networkPorts(), deserializedHost.networkPorts());
assertEquals(expectedHost.aliases(), deserializedHost.aliases());
+ assertEquals(expectedHost.requestedResources(), deserializedHost.requestedResources());
}
}
diff --git a/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/Node.java b/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/Node.java
index 80b59bb40d0..49f96d65c81 100644
--- a/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/Node.java
+++ b/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/Node.java
@@ -249,8 +249,9 @@ public final class Node {
}
/** Returns a copy of this with allocation set as specified. <code>node.state</code> is *not* changed. */
- public Node allocate(ApplicationId owner, ClusterMembership membership, Instant at) {
- return this.with(new Allocation(owner, membership, new Generation(0, 0), false))
+ public Node allocate(ApplicationId owner, ClusterMembership membership, NodeResources requestedResources, Instant at) {
+ return this
+ .with(new Allocation(owner, membership, requestedResources, new Generation(0, 0), false))
.with(history.with(new History.Event(History.Event.Type.reserved, Agent.application, at)));
}
diff --git a/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/node/Allocation.java b/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/node/Allocation.java
index 53e1ae3721e..30ef84c6927 100644
--- a/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/node/Allocation.java
+++ b/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/node/Allocation.java
@@ -4,6 +4,7 @@ package com.yahoo.vespa.hosted.provision.node;
import com.yahoo.config.provision.ApplicationId;
import com.yahoo.config.provision.ClusterMembership;
import com.yahoo.config.provision.NetworkPorts;
+import com.yahoo.config.provision.NodeResources;
import java.util.Optional;
@@ -17,6 +18,8 @@ public class Allocation {
private final ApplicationId owner;
private final ClusterMembership clusterMembership;
+ private final NodeResources requestedResources;
+
/**
* Restart generation, see {@link com.yahoo.vespa.hosted.provision.node.Generation},
* wanted is increased when a restart of the services on the node is needed, current is updated
@@ -30,15 +33,16 @@ public class Allocation {
private final Optional<NetworkPorts> networkPorts;
- public Allocation(ApplicationId owner, ClusterMembership clusterMembership,
+ public Allocation(ApplicationId owner, ClusterMembership clusterMembership, NodeResources requestedResources,
Generation restartGeneration, boolean removable) {
- this(owner, clusterMembership, restartGeneration, removable, Optional.empty());
+ this(owner, clusterMembership, requestedResources, restartGeneration, removable, Optional.empty());
}
- public Allocation(ApplicationId owner, ClusterMembership clusterMembership,
+ public Allocation(ApplicationId owner, ClusterMembership clusterMembership, NodeResources requestedResources,
Generation restartGeneration, boolean removable, Optional<NetworkPorts> networkPorts) {
this.owner = owner;
this.clusterMembership = clusterMembership;
+ this.requestedResources = requestedResources;
this.restartGeneration = restartGeneration;
this.removable = removable;
this.networkPorts = networkPorts;
@@ -50,6 +54,9 @@ public class Allocation {
/** Returns the role this node is allocated to */
public ClusterMembership membership() { return clusterMembership; }
+ /** Returns the node resources requested, leading to this allocation on this node */
+ public NodeResources requestedResources() { return requestedResources; }
+
/** Returns the restart generation (wanted and current) of this */
public Generation restartGeneration() { return restartGeneration; }
@@ -58,33 +65,37 @@ public class Allocation {
/** Returns a copy of this which is retired */
public Allocation retire() {
- return new Allocation(owner, clusterMembership.retire(), restartGeneration, removable, networkPorts);
+ return new Allocation(owner, clusterMembership.retire(), requestedResources, restartGeneration, removable, networkPorts);
}
/** Returns a copy of this which is not retired */
public Allocation unretire() {
- return new Allocation(owner, clusterMembership.unretire(), restartGeneration, removable, networkPorts);
+ return new Allocation(owner, clusterMembership.unretire(), requestedResources, restartGeneration, removable, networkPorts);
}
/** Return whether this node is ready to be removed from the application */
public boolean isRemovable() { return removable; }
+ public Allocation withRequestedResources(NodeResources resources) {
+ return new Allocation(owner, clusterMembership, resources, restartGeneration, removable, networkPorts);
+ }
+
/** Returns a copy of this with the current restart generation set to generation */
public Allocation withRestart(Generation generation) {
- return new Allocation(owner, clusterMembership, generation, removable, networkPorts);
+ return new Allocation(owner, clusterMembership, requestedResources, generation, removable, networkPorts);
}
/** Returns a copy of this allocation where removable is set to true */
public Allocation removable() {
- return new Allocation(owner, clusterMembership, restartGeneration, true, networkPorts);
+ return new Allocation(owner, clusterMembership, requestedResources, restartGeneration, true, networkPorts);
}
public Allocation with(ClusterMembership newMembership) {
- return new Allocation(owner, newMembership, restartGeneration, removable, networkPorts);
+ return new Allocation(owner, newMembership, requestedResources, restartGeneration, removable, networkPorts);
}
public Allocation withNetworkPorts(NetworkPorts ports) {
- return new Allocation(owner, clusterMembership, restartGeneration, removable, Optional.of(ports));
+ return new Allocation(owner, clusterMembership, requestedResources, restartGeneration, removable, Optional.of(ports));
}
@Override
diff --git a/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/persistence/NodeSerializer.java b/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/persistence/NodeSerializer.java
index f4277408956..39473ed0b3a 100644
--- a/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/persistence/NodeSerializer.java
+++ b/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/persistence/NodeSerializer.java
@@ -92,6 +92,7 @@ public class NodeSerializer {
private static final String applicationIdKey = "applicationId";
private static final String instanceIdKey = "instanceId";
private static final String serviceIdKey = "serviceId"; // legacy name, TODO: change to membership with backwards compat
+ private static final String requestedResourcesKey = "requestedResources";
private static final String restartGenerationKey = "restartGeneration";
private static final String currentRestartGenerationKey = "currentRestartGeneration";
private static final String removableKey = "removable";
@@ -155,17 +156,20 @@ public class NodeSerializer {
}
}
else {
- NodeResources resources = flavor.resources();
- Cursor resourcesObject = object.setObject(resourcesKey);
- resourcesObject.setDouble(vcpuKey, resources.vcpu());
- resourcesObject.setDouble(memoryKey, resources.memoryGb());
- resourcesObject.setDouble(diskKey, resources.diskGb());
- resourcesObject.setDouble(bandwidthKey, resources.bandwidthGbps());
- resourcesObject.setString(diskSpeedKey, diskSpeedToString(resources.diskSpeed()));
+ toSlime(flavor.resources(), object.setObject(resourcesKey));
}
}
+ private void toSlime(NodeResources resources, Cursor resourcesObject) {
+ resourcesObject.setDouble(vcpuKey, resources.vcpu());
+ resourcesObject.setDouble(memoryKey, resources.memoryGb());
+ resourcesObject.setDouble(diskKey, resources.diskGb());
+ resourcesObject.setDouble(bandwidthKey, resources.bandwidthGbps());
+ resourcesObject.setString(diskSpeedKey, diskSpeedToString(resources.diskSpeed()));
+ }
+
private void toSlime(Allocation allocation, Cursor object) {
+ toSlime(allocation.requestedResources(), object.setObject(requestedResourcesKey));
object.setString(tenantIdKey, allocation.owner().tenant().value());
object.setString(applicationIdKey, allocation.owner().application().value());
object.setString(instanceIdKey, allocation.owner().instance().value());
@@ -200,15 +204,16 @@ public class NodeSerializer {
}
private Node nodeFromSlime(Node.State state, Inspector object) {
+ Flavor flavor = flavorFromSlime(object);
return new Node(object.field(idKey).asString(),
new IP.Config(ipAddressesFromSlime(object, ipAddressesKey),
ipAddressesFromSlime(object, ipAddressPoolKey)),
object.field(hostnameKey).asString(),
parentHostnameFromSlime(object),
- flavorFromSlime(object),
+ flavor,
statusFromSlime(object),
state,
- allocationFromSlime(object.field(instanceKey)),
+ allocationFromSlime(flavor.resources(), object.field(instanceKey)),
historyFromSlime(object.field(historyKey)),
nodeTypeFromString(object.field(nodeTypeKey).asString()),
Reports.fromSlime(object.field(reportsKey)),
@@ -235,18 +240,25 @@ public class NodeSerializer {
return flavor.with(FlavorOverrides.ofDisk(resources.field(diskKey).asDouble()));
}
else {
- return new Flavor(new NodeResources(resources.field(vcpuKey).asDouble(),
- resources.field(memoryKey).asDouble(),
- resources.field(diskKey).asDouble(),
- resources.field(bandwidthKey).asDouble(),
- diskSpeedFromSlime(resources.field(diskSpeedKey))));
+ return new Flavor(resourcesFromSlime(resources).get());
}
}
- private Optional<Allocation> allocationFromSlime(Inspector object) {
- if ( ! object.valid()) return Optional.empty();
+ private Optional<NodeResources> resourcesFromSlime(Inspector resources) {
+ if ( ! resources.valid()) return Optional.empty();
+
+ return Optional.of(new NodeResources(resources.field(vcpuKey).asDouble(),
+ resources.field(memoryKey).asDouble(),
+ resources.field(diskKey).asDouble(),
+ resources.field(bandwidthKey).asDouble(),
+ diskSpeedFromSlime(resources.field(diskSpeedKey))));
+ }
+
+ private Optional<Allocation> allocationFromSlime(NodeResources assignedResources, Inspector object) {
+ if ( ! object.valid()) return Optional.empty(); // TODO: Remove this line (and to the simplifications that follows) after November 2019
return Optional.of(new Allocation(applicationIdFromSlime(object),
clusterMembershipFromSlime(object),
+ resourcesFromSlime(object.field(requestedResourcesKey)).orElse(assignedResources),
generationFromSlime(object, restartGenerationKey, currentRestartGenerationKey),
object.field(removableKey).asBool(),
NetworkPortsSerializer.fromSlime(object.field(networkPortsKey))));
@@ -367,8 +379,6 @@ public class NodeSerializer {
}
private Agent eventAgentFromSlime(Inspector eventAgentField) {
- if ( ! eventAgentField.valid()) return Agent.system; // TODO: Remove after April 2017
-
switch (eventAgentField.asString()) {
case "application" : return Agent.application;
case "system" : return Agent.system;
@@ -416,7 +426,6 @@ public class NodeSerializer {
}
private static NodeResources.DiskSpeed diskSpeedFromSlime(Inspector diskSpeed) {
- if ( ! diskSpeed.valid()) return NodeResources.DiskSpeed.fast; // TODO: Remove this line after June 2019
switch (diskSpeed.asString()) {
case "fast" : return NodeResources.DiskSpeed.fast;
case "slow" : return NodeResources.DiskSpeed.slow;
diff --git a/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/provisioning/Activator.java b/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/provisioning/Activator.java
index 8a6f308eb34..e994e86d07c 100644
--- a/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/provisioning/Activator.java
+++ b/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/provisioning/Activator.java
@@ -138,21 +138,21 @@ class Activator {
return notFoundHosts.isEmpty();
}
- /**
- * Returns the input nodes with the changes resulting from applying the settings in hosts to the given list of nodes.
- */
+ /** Returns the input nodes with the changes resulting from applying the settings in hosts to the given list of nodes. */
private List<Node> updateFrom(Collection<HostSpec> hosts, List<Node> nodes) {
List<Node> updated = new ArrayList<>();
for (Node node : nodes) {
HostSpec hostSpec = getHost(node.hostname(), hosts);
node = hostSpec.membership().get().retired() ? node.retire(nodeRepository.clock().instant()) : node.unretire();
- Allocation allocation = node.allocation().get().with(hostSpec.membership().get());
- if (hostSpec.networkPorts().isPresent()) {
- allocation = allocation.withNetworkPorts(hostSpec.networkPorts().get());
- }
- node = node.with(allocation);
if (hostSpec.flavor().isPresent()) // Docker nodes may change flavor
node = node.with(hostSpec.flavor().get());
+ Allocation allocation = node.allocation().get()
+ .with(hostSpec.membership().get())
+ .withRequestedResources(hostSpec.requestedResources()
+ .orElse(node.flavor().resources()));
+ if (hostSpec.networkPorts().isPresent())
+ allocation = allocation.withNetworkPorts(hostSpec.networkPorts().get());
+ node = node.with(allocation);
updated.add(node);
}
return updated;
diff --git a/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/provisioning/NodeAllocation.java b/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/provisioning/NodeAllocation.java
index f6822f64570..e381fdc654e 100644
--- a/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/provisioning/NodeAllocation.java
+++ b/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/provisioning/NodeAllocation.java
@@ -140,6 +140,7 @@ class NodeAllocation {
}
offeredPriority.node = offered.allocate(application,
ClusterMembership.from(cluster, highestIndex.add(1)),
+ requestedNodes.resources().orElse(offeredPriority.node.flavor().resources()),
clock.instant());
accepted.add(acceptNode(offeredPriority, false));
}
@@ -223,6 +224,10 @@ class NodeAllocation {
private Node acceptNode(PrioritizableNode prioritizableNode, boolean wantToRetire) {
Node node = prioritizableNode.node;
+
+ if (node.allocation().isPresent()) // Record the currently requested resources
+ node = node.with(node.allocation().get().withRequestedResources(requestedNodes.resources().orElse(node.flavor().resources())));
+
if (! wantToRetire) {
if ( ! node.state().equals(Node.State.active)) {
// reactivated node - make sure its not retired
@@ -278,14 +283,13 @@ class NodeAllocation {
* Returns {@link FlavorCount} describing the docker node deficit for the given {@link NodeSpec}.
*
* @return empty if the requested spec is not count based or the requested flavor type is not docker or
- * the request is already fulfilled. Otherwise returns {@link FlavorCount} containing the required flavor
- * and node count to cover the deficit.
+ * the request is already fulfilled. Otherwise returns {@link FlavorCount} containing the required flavor
+ * and node count to cover the deficit.
*/
Optional<FlavorCount> getFulfilledDockerDeficit() {
return Optional.of(requestedNodes)
.filter(NodeSpec.CountNodeSpec.class::isInstance)
- .map(NodeSpec.CountNodeSpec.class::cast)
- .map(spec -> new FlavorCount(spec.resources(), spec.fulfilledDeficitCount(acceptedOfRequestedFlavor)))
+ .map(spec -> new FlavorCount(spec.resources().get(), spec.fulfilledDeficitCount(acceptedOfRequestedFlavor)))
.filter(flavorCount -> flavorCount.getCount() > 0);
}
diff --git a/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/provisioning/NodePrioritizer.java b/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/provisioning/NodePrioritizer.java
index cc27b1b2196..a7081060f2e 100644
--- a/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/provisioning/NodePrioritizer.java
+++ b/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/provisioning/NodePrioritizer.java
@@ -219,7 +219,7 @@ public class NodePrioritizer {
private static NodeResources resources(NodeSpec requestedNodes) {
if ( ! (requestedNodes instanceof NodeSpec.CountNodeSpec)) return null;
- return ((NodeSpec.CountNodeSpec)requestedNodes).resources();
+ return requestedNodes.resources().get();
}
private boolean isDocker() {
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 e437fd4211a..f78eaf40f60 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
@@ -103,7 +103,8 @@ public class NodeRepositoryProvisioner implements Provisioner {
effectiveGroups = 1; // type request with multiple groups is not supported
}
- return asSortedHosts(preparer.prepare(application, cluster, requestedNodes, effectiveGroups));
+ return asSortedHosts(preparer.prepare(application, cluster, requestedNodes, effectiveGroups),
+ requestedCapacity.nodeResources());
}
@Override
@@ -123,7 +124,7 @@ public class NodeRepositoryProvisioner implements Provisioner {
loadBalancerProvisioner.ifPresent(lbProvisioner -> lbProvisioner.deactivate(application, transaction));
}
- private List<HostSpec> asSortedHosts(List<Node> nodes) {
+ private List<HostSpec> asSortedHosts(List<Node> nodes, Optional<NodeResources> requestedResources) {
nodes.sort(Comparator.comparingInt(node -> node.allocation().get().membership().index()));
List<HostSpec> hosts = new ArrayList<>(nodes.size());
for (Node node : nodes) {
@@ -134,7 +135,8 @@ public class NodeRepositoryProvisioner implements Provisioner {
Optional.of(node.flavor()),
Optional.of(nodeAllocation.membership()),
node.status().vespaVersion(),
- nodeAllocation.networkPorts()));
+ nodeAllocation.networkPorts(),
+ requestedResources));
if (nodeAllocation.networkPorts().isPresent()) {
log.log(LogLevel.DEBUG, () -> "Prepared node " + node.hostname() + " has port allocations");
}
diff --git a/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/provisioning/NodeSpec.java b/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/provisioning/NodeSpec.java
index da8d6a2ccf6..8eaa6662187 100644
--- a/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/provisioning/NodeSpec.java
+++ b/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/provisioning/NodeSpec.java
@@ -8,6 +8,7 @@ import com.yahoo.config.provision.NodeType;
import com.yahoo.vespa.hosted.provision.Node;
import java.util.Objects;
+import java.util.Optional;
/**
* A specification of a set of nodes.
@@ -60,6 +61,9 @@ public interface NodeSpec {
*/
Node assignRequestedFlavor(Node node);
+ /** Returns the resources requested by this or empty if none are explicitly requested */
+ Optional<NodeResources> resources();
+
static NodeSpec from(int nodeCount, NodeResources flavor, boolean exclusive, boolean canFail) {
return new CountNodeSpec(nodeCount, flavor, exclusive, canFail);
}
@@ -83,8 +87,9 @@ public interface NodeSpec {
this.canFail = canFail;
}
- public NodeResources resources() {
- return requestedNodeResources;
+ @Override
+ public Optional<NodeResources> resources() {
+ return Optional.of(requestedNodeResources);
}
@Override
@@ -199,6 +204,9 @@ public interface NodeSpec {
public Node assignRequestedFlavor(Node node) { return node; }
@Override
+ public Optional<NodeResources> resources() { return Optional.empty(); }
+
+ @Override
public String toString() { return "request for all nodes of type '" + type + "'"; }
}
diff --git a/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/provisioning/Preparer.java b/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/provisioning/Preparer.java
index 6054e298277..e387645888c 100644
--- a/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/provisioning/Preparer.java
+++ b/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/provisioning/Preparer.java
@@ -14,6 +14,7 @@ import java.util.ArrayList;
import java.util.List;
import java.util.ListIterator;
import java.util.Optional;
+import java.util.stream.Collectors;
/**
* Performs preparation of node activation changes for an application.
@@ -51,7 +52,7 @@ class Preparer {
// Note: This operation may make persisted changes to the set of reserved and inactive nodes,
// but it may not change the set of active nodes, as the active nodes must stay in sync with the
// active config model which is changed on activate
- public List<Node> prepareNodes(ApplicationId application, ClusterSpec cluster, NodeSpec requestedNodes, int wantedGroups) {
+ private List<Node> prepareNodes(ApplicationId application, ClusterSpec cluster, NodeSpec requestedNodes, int wantedGroups) {
List<Node> surplusNodes = findNodesInRemovableGroups(application, cluster, wantedGroups);
MutableInteger highestIndex = new MutableInteger(findHighestIndex(application, cluster));
diff --git a/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/maintenance/CapacityCheckerTester.java b/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/maintenance/CapacityCheckerTester.java
index 3a29204d2f4..b2bc21d1cf1 100644
--- a/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/maintenance/CapacityCheckerTester.java
+++ b/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/maintenance/CapacityCheckerTester.java
@@ -266,7 +266,7 @@ public class CapacityCheckerTester {
nodeModel.parentHostname, f, nodeModel.type);
if (membership != null) {
- return node.allocate(owner, membership, Instant.now());
+ return node.allocate(owner, membership, node.flavor().resources(), Instant.now());
} else {
return node;
}
diff --git a/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/maintenance/DynamicProvisioningMaintainerTest.java b/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/maintenance/DynamicProvisioningMaintainerTest.java
index 0a4ca831d3d..71788fb1a30 100644
--- a/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/maintenance/DynamicProvisioningMaintainerTest.java
+++ b/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/maintenance/DynamicProvisioningMaintainerTest.java
@@ -199,6 +199,7 @@ public class DynamicProvisioningMaintainerTest {
.map(app -> new Allocation(
app,
ClusterMembership.from("container/default/0/0", Version.fromString("7.3")),
+ flavor.resources(),
Generation.initial(),
false));
var ipConfig = new IP.Config(state == Node.State.active ? Set.of("::1") : Set.of(), Set.of());
diff --git a/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/maintenance/MetricsReporterTest.java b/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/maintenance/MetricsReporterTest.java
index db4ba661b64..ed6e6c6e9a7 100644
--- a/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/maintenance/MetricsReporterTest.java
+++ b/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/maintenance/MetricsReporterTest.java
@@ -126,12 +126,12 @@ public class MetricsReporterTest {
Node container1 = Node.createDockerNode(Set.of("::2"), "container1",
"dockerHost", new NodeResources(1, 3, 2, 1), NodeType.tenant);
- container1 = container1.with(allocation(Optional.of("app1")).get());
+ container1 = container1.with(allocation(Optional.of("app1"), container1).get());
nodeRepository.addDockerNodes(new LockedNodeList(List.of(container1), nodeRepository.lockAllocation()));
Node container2 = Node.createDockerNode(Set.of("::3"), "container2",
"dockerHost", new NodeResources(2, 4, 4, 1), NodeType.tenant);
- container2 = container2.with(allocation(Optional.of("app2")).get());
+ container2 = container2.with(allocation(Optional.of("app2"), container2).get());
nodeRepository.addDockerNodes(new LockedNodeList(List.of(container2), nodeRepository.lockAllocation()));
Orchestrator orchestrator = mock(Orchestrator.class);
@@ -171,10 +171,11 @@ public class MetricsReporterTest {
.instanceName("default").build();
}
- private Optional<Allocation> allocation(Optional<String> tenant) {
+ private Optional<Allocation> allocation(Optional<String> tenant, Node owner) {
if (tenant.isPresent()) {
Allocation allocation = new Allocation(app(tenant.get()),
ClusterMembership.from("container/id1/0/3", new Version()),
+ owner.flavor().resources(),
Generation.initial(),
false);
return Optional.of(allocation);
diff --git a/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/persistence/SerializationTest.java b/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/persistence/SerializationTest.java
index 0cfdf80a8a1..5a4c87aaf77 100644
--- a/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/persistence/SerializationTest.java
+++ b/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/persistence/SerializationTest.java
@@ -10,6 +10,7 @@ import com.yahoo.config.provision.ClusterMembership;
import com.yahoo.config.provision.InstanceName;
import com.yahoo.config.provision.NetworkPorts;
import com.yahoo.config.provision.NodeFlavors;
+import com.yahoo.config.provision.NodeResources;
import com.yahoo.config.provision.NodeType;
import com.yahoo.config.provision.TenantName;
import com.yahoo.config.provision.host.FlavorOverrides;
@@ -70,6 +71,7 @@ public class SerializationTest {
@Test
public void testReservedNodeSerialization() {
Node node = createNode();
+ NodeResources requestedResources = new NodeResources(1.2, 3.4, 5.6, 7.8, NodeResources.DiskSpeed.any);
clock.advance(Duration.ofMinutes(3));
assertEquals(0, node.history().events().size());
@@ -77,6 +79,7 @@ public class SerializationTest {
ApplicationName.from("myApplication"),
InstanceName.from("myInstance")),
ClusterMembership.from("content/myId/0/0", Vtag.currentVersion),
+ requestedResources,
clock.instant());
assertEquals(1, node.history().events().size());
node = node.withRestart(new Generation(1, 2));
@@ -99,6 +102,7 @@ public class SerializationTest {
assertEquals(2, copy.status().failCount());
assertEquals(node.allocation().get().owner(), copy.allocation().get().owner());
assertEquals(node.allocation().get().membership(), copy.allocation().get().membership());
+ assertEquals(node.allocation().get().requestedResources(), copy.allocation().get().requestedResources());
assertEquals(node.allocation().get().isRemovable(), copy.allocation().get().isRemovable());
assertEquals(1, copy.history().events().size());
assertEquals(clock.instant().truncatedTo(MILLIS), copy.history().event(History.Event.Type.reserved).get().at());
@@ -106,17 +110,6 @@ public class SerializationTest {
}
@Test
- public void testDefaultType() {
- Node node = createNode().allocate(ApplicationId.from(TenantName.from("myTenant"),
- ApplicationName.from("myApplication"),
- InstanceName.from("myInstance")),
- ClusterMembership.from("content/myId/0/0", Vtag.currentVersion),
- clock.instant());
- Node copy = nodeSerializer.fromJson(Node.State.provisioned, nodeSerializer.toJson(node));
- assertEquals(NodeType.host, copy.type());
- }
-
- @Test
public void testRebootAndRestartAndTypeNoCurrentValuesSerialization() {
String nodeData =
"{\n" +
@@ -127,11 +120,13 @@ public class SerializationTest {
" \"history\" : [\n" +
" {\n" +
" \"type\" : \"provisioned\",\n" +
- " \"at\" : 1444391401389\n" +
+ " \"at\" : 1444391401389,\n" +
+ " \"agent\" : \"system\"\n" +
" },\n" +
" {\n" +
" \"type\" : \"reserved\",\n" +
- " \"at\" : 1444391402611\n" +
+ " \"at\" : 1444391402611,\n" +
+ " \"agent\" : \"system\"\n" +
" }\n" +
" ],\n" +
" \"instance\" : {\n" +
@@ -172,6 +167,7 @@ public class SerializationTest {
ApplicationName.from("myApplication"),
InstanceName.from("myInstance")),
ClusterMembership.from("content/myId/0/0", Vtag.currentVersion),
+ node.flavor().resources(),
clock.instant());
assertEquals(1, node.history().events().size());
clock.advance(Duration.ofMinutes(2));
@@ -221,6 +217,7 @@ public class SerializationTest {
ApplicationName.from("myApplication"),
InstanceName.from("myInstance")),
ClusterMembership.from("content/myId/0/0", Vtag.currentVersion),
+ node.flavor().resources(),
clock.instant());
node = node.with(node.status().setFailCount(0));
@@ -405,6 +402,7 @@ public class SerializationTest {
ApplicationName.from("myApplication"),
InstanceName.from("myInstance")),
ClusterMembership.from("content/myId/0/0", Vtag.currentVersion),
+ node.flavor().resources(),
clock.instant());
assertTrue(node.allocation().isPresent());
node = node.with(node.allocation().get().withNetworkPorts(ports));
@@ -437,7 +435,13 @@ public class SerializationTest {
}
private Node createNode() {
- return Node.create("myId", new IP.Config(Set.of("127.0.0.1"), Set.of()), "myHostname", Optional.empty(), Optional.empty(), nodeFlavors.getFlavorOrThrow("default"), NodeType.host);
+ return Node.create("myId",
+ new IP.Config(Set.of("127.0.0.1"), Set.of()),
+ "myHostname",
+ Optional.empty(),
+ Optional.empty(),
+ nodeFlavors.getFlavorOrThrow("default"),
+ NodeType.tenant);
}
}
diff --git a/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/provisioning/AllocationSimulator.java b/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/provisioning/AllocationSimulator.java
index e3aefdd4512..9cd95e401a9 100644
--- a/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/provisioning/AllocationSimulator.java
+++ b/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/provisioning/AllocationSimulator.java
@@ -80,7 +80,7 @@ public class AllocationSimulator {
private Node node(String hostname, Flavor flavor, Optional<String> parent, Optional<String> tenant) {
var ipConfig = new IP.Config(Set.of("127.0.0.1"), parent.isPresent() ? Set.of() : getAdditionalIP());
return new Node("fake", ipConfig, hostname, parent, flavor, Status.initial(),
- parent.isPresent() ? Node.State.ready : Node.State.active, allocation(tenant), History.empty(),
+ parent.isPresent() ? Node.State.ready : Node.State.active, allocation(tenant, flavor), History.empty(),
parent.isPresent() ? NodeType.tenant : NodeType.host, new Reports(), Optional.empty());
}
@@ -90,10 +90,11 @@ public class AllocationSimulator {
return h;
}
- private Optional<Allocation> allocation(Optional<String> tenant) {
+ private Optional<Allocation> allocation(Optional<String> tenant, Flavor flavor) {
if (tenant.isPresent()) {
Allocation allocation = new Allocation(app(tenant.get()),
ClusterMembership.from("container/id1/3", new Version()),
+ flavor.resources(),
Generation.initial(),
false);
return Optional.of(allocation);
diff --git a/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/provisioning/DynamicDockerAllocationTest.java b/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/provisioning/DynamicDockerAllocationTest.java
index a3512c480d3..618df82e38b 100644
--- a/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/provisioning/DynamicDockerAllocationTest.java
+++ b/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/provisioning/DynamicDockerAllocationTest.java
@@ -426,7 +426,7 @@ public class DynamicDockerAllocationTest {
Node node1a = Node.create("open1", new IP.Config(Set.of("127.0.233." + index), Set.of()), hostname, Optional.of(parentHostname), Optional.empty(), new Flavor(flavor), NodeType.tenant);
ClusterMembership clusterMembership1 = ClusterMembership.from(
clusterSpec.with(Optional.of(ClusterSpec.Group.from(0))), index); // Need to add group here so that group is serialized in node allocation
- Node node1aAllocation = node1a.allocate(id, clusterMembership1, Instant.now());
+ Node node1aAllocation = node1a.allocate(id, clusterMembership1, node1a.flavor().resources(), Instant.now());
tester.nodeRepository().addNodes(Collections.singletonList(node1aAllocation));
NestedTransaction transaction = new NestedTransaction().add(new CuratorTransaction(tester.getCurator()));
diff --git a/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/provisioning/InfraDeployerImplTest.java b/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/provisioning/InfraDeployerImplTest.java
index da77bebccda..48bd091011e 100644
--- a/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/provisioning/InfraDeployerImplTest.java
+++ b/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/provisioning/InfraDeployerImplTest.java
@@ -140,7 +140,7 @@ public class InfraDeployerImplTest {
Optional<Node> nodeWithAllocation = wantedVespaVersion.map(version -> {
ClusterSpec clusterSpec = application.getClusterSpecWithVersion(version).with(Optional.of(ClusterSpec.Group.from(0)));
ClusterMembership membership = ClusterMembership.from(clusterSpec, 1);
- Allocation allocation = new Allocation(application.getApplicationId(), membership, Generation.initial(), false);
+ Allocation allocation = new Allocation(application.getApplicationId(), membership, node.flavor().resources(), Generation.initial(), false);
return node.with(allocation);
});
return nodeRepository.database().writeTo(state, nodeWithAllocation.orElse(node), Agent.system, Optional.empty());
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 877038b8722..a8b534e02ef 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
@@ -320,6 +320,38 @@ public class ProvisioningTest {
}
@Test
+ public void requested_resources_info_is_retained() {
+ ProvisioningTester tester = new ProvisioningTester.Builder().zone(new Zone(Environment.prod, RegionName.from("us-east"))).build();
+
+ tester.makeReadyNodes(13, defaultResources, NodeType.host, 1);
+ tester.prepareAndActivateInfraApplication(tester.makeApplicationId(), NodeType.host);
+ ApplicationId application = tester.makeApplicationId();
+
+ {
+ // Deploy with disk-speed any and make sure that information is retained
+ SystemState state = prepare(application, 0, 0, 3, 3,
+ defaultResources.anySpeed(),
+ tester);
+ assertEquals(6, state.allHosts.size());
+ tester.activate(application, state.allHosts);
+ assertTrue(state.allHosts.stream().allMatch(host -> host.requestedResources().get().diskSpeed() == NodeResources.DiskSpeed.any));
+ assertTrue(tester.nodeRepository().getNodes(application).stream().allMatch(node -> node.allocation().get().requestedResources().diskSpeed() == NodeResources.DiskSpeed.any));
+ }
+
+ {
+ // Deploy (with some additional nodes) with disk-speed fast and make sure *that* information is retained
+ // even though it does not lead to new nodes
+ SystemState state = prepare(application, 0, 0, 5, 3,
+ defaultResources,
+ tester);
+ assertEquals(8, state.allHosts.size());
+ tester.activate(application, state.allHosts);
+ assertTrue(state.allHosts.stream().allMatch(host -> host.requestedResources().get().diskSpeed() == NodeResources.DiskSpeed.fast));
+ assertTrue(tester.nodeRepository().getNodes(application).stream().allMatch(node -> node.allocation().get().requestedResources().diskSpeed() == NodeResources.DiskSpeed.fast));
+ }
+ }
+
+ @Test
public void deploy_specific_vespa_version() {
ProvisioningTester tester = new ProvisioningTester.Builder().zone(new Zone(Environment.dev, RegionName.from("us-east"))).build();
diff --git a/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/provisioning/ProvisioningTester.java b/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/provisioning/ProvisioningTester.java
index af635ada89d..242b0d8ca9e 100644
--- a/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/provisioning/ProvisioningTester.java
+++ b/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/provisioning/ProvisioningTester.java
@@ -148,12 +148,13 @@ public class ProvisioningTester {
return hosts1;
}
- public void activate(ApplicationId application, Collection<HostSpec> hosts) {
+ public Collection<HostSpec> activate(ApplicationId application, Collection<HostSpec> hosts) {
NestedTransaction transaction = new NestedTransaction();
transaction.add(new CuratorTransaction(curator));
provisioner.activate(transaction, application, hosts);
transaction.commit();
assertEquals(toHostNames(hosts), toHostNames(nodeRepository.getNodes(application, Node.State.active)));
+ return hosts;
}
public void prepareAndActivateInfraApplication(ApplicationId application, NodeType nodeType, Version version) {