summaryrefslogtreecommitdiffstats
path: root/node-repository
diff options
context:
space:
mode:
authorJon Bratseth <bratseth@gmail.com>2020-05-26 21:38:28 +0200
committerJon Bratseth <bratseth@gmail.com>2020-05-26 21:38:28 +0200
commit539e048479d1bf89400ff090f853c067818b5401 (patch)
tree025ae4a2fc8576689e3adae2f0767e3e4bae735b /node-repository
parentc2f6a3263989d0d4943e7b42af515d152b125a3c (diff)
Prepare to take overhead into account when allocating shared
Diffstat (limited to 'node-repository')
-rw-r--r--node-repository/src/main/java/com/yahoo/vespa/hosted/provision/autoscale/AllocatableClusterResources.java26
-rw-r--r--node-repository/src/main/java/com/yahoo/vespa/hosted/provision/autoscale/AllocationOptimizer.java6
-rw-r--r--node-repository/src/main/java/com/yahoo/vespa/hosted/provision/autoscale/ResourceTarget.java9
-rw-r--r--node-repository/src/main/java/com/yahoo/vespa/hosted/provision/provisioning/EmptyProvisionServiceProvider.java9
-rw-r--r--node-repository/src/main/java/com/yahoo/vespa/hosted/provision/provisioning/HostResourcesCalculator.java17
-rw-r--r--node-repository/src/test/java/com/yahoo/vespa/hosted/provision/autoscale/AutoscalingTest.java100
-rw-r--r--node-repository/src/test/java/com/yahoo/vespa/hosted/provision/autoscale/AutoscalingTester.java26
-rw-r--r--node-repository/src/test/java/com/yahoo/vespa/hosted/provision/provisioning/DockerProvisioningTest.java74
-rw-r--r--node-repository/src/test/java/com/yahoo/vespa/hosted/provision/provisioning/DynamicDockerProvisionTest.java32
-rw-r--r--node-repository/src/test/java/com/yahoo/vespa/hosted/provision/provisioning/ProvisioningTester.java3
10 files changed, 203 insertions, 99 deletions
diff --git a/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/autoscale/AllocatableClusterResources.java b/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/autoscale/AllocatableClusterResources.java
index ff2ef433506..17a163eed2a 100644
--- a/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/autoscale/AllocatableClusterResources.java
+++ b/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/autoscale/AllocatableClusterResources.java
@@ -122,6 +122,11 @@ public class AllocatableClusterResources {
/**
* Returns the best matching allocatable node resources given ideal node resources,
* or empty if none available within the limits.
+ *
+ * @param resources the real resources that should ideally be allocated
+ * @param exclusive whether resources should be allocated on entire hosts
+ * (in which case the allocated resources will be all the real resources of the host
+ * and limits are required to encompass the full resources of candidate host flavors)
*/
public static Optional<AllocatableClusterResources> from(ClusterResources resources,
boolean exclusive,
@@ -131,26 +136,25 @@ public class AllocatableClusterResources {
NodeResources cappedNodeResources = limits.cap(resources.nodeResources());
cappedNodeResources = new NodeResourceLimits(nodeRepository).enlargeToLegal(cappedNodeResources, clusterType);
- if (nodeRepository.zone().getCloud().allowHostSharing()) {
- // return the requested resources, or empty if they cannot fit on existing hosts
+ if ( !exclusive && nodeRepository.zone().getCloud().allowHostSharing()) { // Check if any flavor can fit these hosts
+ // We decide resources: Add overhead to what we'll request (advertised) to make sure real becomes (at least) cappedNodeResources
+ NodeResources advertisedResources = cappedNodeResources.add(nodeRepository.resourcesCalculator().overheadAllocating(cappedNodeResources, exclusive));
+ NodeResources realResources = cappedNodeResources;
for (Flavor flavor : nodeRepository.flavors().getFlavors()) {
- NodeResources realNodeResources = nodeRepository.resourcesCalculator().lowestRealResourcesAllocating(cappedNodeResources,
- exclusive);
- if (flavor.resources().satisfies(cappedNodeResources))
- return Optional.of(new AllocatableClusterResources(resources.with(realNodeResources),
- cappedNodeResources,
+ if (flavor.resources().satisfies(cappedNodeResources)) // TODO: advertisedResources
+ return Optional.of(new AllocatableClusterResources(resources.with(realResources),
+ cappedNodeResources, // TODO: advertisedResources
resources.nodeResources(),
clusterType));
}
return Optional.empty();
}
- else {
- // return the cheapest flavor satisfying the target resources, if any
+ else { // Return the cheapest flavor satisfying the requested resources, if any
Optional<AllocatableClusterResources> best = Optional.empty();
for (Flavor flavor : nodeRepository.flavors().getFlavors()) {
+ // Flavor decide resources: Real resources are the worst case real resources we'll get if we ask for these advertised resources
NodeResources advertisedResources = nodeRepository.resourcesCalculator().advertisedResourcesOf(flavor);
-
- NodeResources realResources = nodeRepository.resourcesCalculator().lowestRealResourcesAllocating(advertisedResources, exclusive);
+ NodeResources realResources = advertisedResources.subtract(nodeRepository.resourcesCalculator().overheadAllocating(advertisedResources, exclusive));
// Adjust where we don't need exact match to the flavor
if (flavor.resources().storageType() == NodeResources.StorageType.remote) {
diff --git a/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/autoscale/AllocationOptimizer.java b/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/autoscale/AllocationOptimizer.java
index d2589b15421..de53fd8e5b6 100644
--- a/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/autoscale/AllocationOptimizer.java
+++ b/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/autoscale/AllocationOptimizer.java
@@ -44,6 +44,7 @@ public class AllocationOptimizer {
limits = Limits.of(new ClusterResources(minimumNodes, 1, NodeResources.unspecified()),
new ClusterResources(maximumNodes, maximumNodes, NodeResources.unspecified()));
Optional<AllocatableClusterResources> bestAllocation = Optional.empty();
+ System.out.println("Optimizing for " + target);
for (int groups = limits.min().groups(); groups <= limits.max().groups(); groups++) {
for (int nodes = limits.min().nodes(); nodes <= limits.max().nodes(); nodes++) {
if (nodes % groups != 0) continue;
@@ -60,8 +61,11 @@ public class AllocationOptimizer {
var allocatableResources = AllocatableClusterResources.from(next, exclusive, current.clusterType(), limits, nodeRepository);
if (allocatableResources.isEmpty()) continue;
- if (bestAllocation.isEmpty() || allocatableResources.get().preferableTo(bestAllocation.get()))
+ System.out.println("Considering " + allocatableResources.get());
+ if (bestAllocation.isEmpty() || allocatableResources.get().preferableTo(bestAllocation.get())) {
+ System.out.println(" ... better");
bestAllocation = allocatableResources;
+ }
}
}
diff --git a/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/autoscale/ResourceTarget.java b/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/autoscale/ResourceTarget.java
index 9359d8251f7..f7c2a51436a 100644
--- a/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/autoscale/ResourceTarget.java
+++ b/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/autoscale/ResourceTarget.java
@@ -11,7 +11,7 @@ public class ResourceTarget {
private final boolean adjustForRedundancy;
- /** The target resources per node, assuming the node assignment in current */
+ /** The target resources per node, assuming the node assignment where this was decided */
private final double cpu, memory, disk;
private ResourceTarget(double cpu, double memory, double disk, boolean adjustForRedundancy) {
@@ -33,6 +33,13 @@ public class ResourceTarget {
/** Returns the target disk per node, in terms of the current allocation */
public double nodeDisk() { return disk; }
+ @Override
+ public String toString() {
+ return "target " +
+ (adjustForRedundancy ? "(with redundancy adjustment) " : "") +
+ "[vcpu " + cpu + ", memoryGb " + memory + ", diskGb " + disk + "]";
+ }
+
private static double nodeUsage(Resource resource, double load, AllocatableClusterResources current) {
return load * resource.valueFrom(current.realResources());
}
diff --git a/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/provisioning/EmptyProvisionServiceProvider.java b/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/provisioning/EmptyProvisionServiceProvider.java
index 9b2e63587b5..e9634906fb1 100644
--- a/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/provisioning/EmptyProvisionServiceProvider.java
+++ b/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/provisioning/EmptyProvisionServiceProvider.java
@@ -39,14 +39,15 @@ public class EmptyProvisionServiceProvider implements ProvisionServiceProvider {
}
@Override
- public NodeResources lowestRealResourcesAllocating(NodeResources advertisedResources, boolean exclusive) {
- return advertisedResources;
+ public NodeResources advertisedResourcesOf(Flavor flavor) {
+ return flavor.resources();
}
@Override
- public NodeResources advertisedResourcesOf(Flavor flavor) {
- return flavor.resources();
+ public NodeResources overheadAllocating(NodeResources resources, boolean exclusive) {
+ return resources.withVcpu(0).withMemoryGb(0).withDiskGb(0);
}
}
+
}
diff --git a/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/provisioning/HostResourcesCalculator.java b/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/provisioning/HostResourcesCalculator.java
index 8d2704e8572..d1b7da2e0b5 100644
--- a/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/provisioning/HostResourcesCalculator.java
+++ b/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/provisioning/HostResourcesCalculator.java
@@ -16,13 +16,20 @@ import com.yahoo.vespa.hosted.provision.NodeRepository;
*/
public interface HostResourcesCalculator {
- /** Nodes use advertised resources. This returns the real resources for the node. */
+ /** Returns the real resources available on a node */
NodeResources realResourcesOf(Node node, NodeRepository nodeRepository);
- /** Returns the lowest possible real resources we may get if we request the given resources */
- NodeResources lowestRealResourcesAllocating(NodeResources advertisedResources, boolean exclusive);
-
- /** Flavors use real resources. This returns the advertised resources of the flavor. */
+ /** Returns the advertised resources of a flavor */
NodeResources advertisedResourcesOf(Flavor flavor);
+ /**
+ * Returns the highest possible overhead (difference between advertised and real) which may result
+ * from requesting the given advertised resources
+ *
+ * @return a NodeResources containing the *difference* between the given advertised resources
+ * and the (worst case) real resources we'll observe. This is always compatible with the
+ * given resources.
+ */
+ NodeResources overheadAllocating(NodeResources resources, boolean exclusive);
+
}
diff --git a/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/autoscale/AutoscalingTest.java b/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/autoscale/AutoscalingTest.java
index 08e4237fe00..0f13ebd8f89 100644
--- a/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/autoscale/AutoscalingTest.java
+++ b/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/autoscale/AutoscalingTest.java
@@ -11,12 +11,16 @@ import com.yahoo.config.provision.NodeResources;
import com.yahoo.config.provision.RegionName;
import com.yahoo.config.provision.SystemName;
import com.yahoo.config.provision.Zone;
+import com.yahoo.vespa.hosted.provision.Node;
+import com.yahoo.vespa.hosted.provision.NodeRepository;
+import com.yahoo.vespa.hosted.provision.provisioning.HostResourcesCalculator;
import org.junit.Test;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
+import static com.yahoo.config.provision.NodeResources.StorageType.local;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
@@ -26,7 +30,7 @@ import static org.junit.Assert.assertTrue;
public class AutoscalingTest {
@Test
- public void testAutoscalingSingleContentGroup() {
+ public void test_autoscaling_single_content_group() {
NodeResources hostResources = new NodeResources(3, 100, 100, 1);
ClusterResources min = new ClusterResources( 2, 1,
new NodeResources(1, 1, 1, 1, NodeResources.DiskSpeed.any));
@@ -68,7 +72,7 @@ public class AutoscalingTest {
}
@Test
- public void testAutoscalingHandlesDiskSettingChanges() {
+ public void autoscaling_handles_disk_setting_changes() {
NodeResources hostResources = new NodeResources(3, 100, 100, 1, NodeResources.DiskSpeed.slow);
AutoscalingTester tester = new AutoscalingTester(hostResources);
@@ -98,7 +102,7 @@ public class AutoscalingTest {
/** We prefer fewer nodes for container clusters as (we assume) they all use the same disk and memory */
@Test
- public void testAutoscalingSingleContainerGroup() {
+ public void test_autoscaling_single_container_group() {
NodeResources resources = new NodeResources(3, 100, 100, 1);
ClusterResources min = new ClusterResources( 2, 1, new NodeResources(1, 1, 1, 1));
ClusterResources max = new ClusterResources(20, 1, new NodeResources(100, 1000, 1000, 1));
@@ -125,7 +129,7 @@ public class AutoscalingTest {
}
@Test
- public void testAutoscalingRespectsUpperLimit() {
+ public void autoscaling_respects_upper_limit() {
NodeResources hostResources = new NodeResources(3, 100, 100, 1);
ClusterResources min = new ClusterResources( 2, 1, new NodeResources(1, 1, 1, 1));
ClusterResources max = new ClusterResources( 6, 1, new NodeResources(2.4, 78, 79, 1));
@@ -146,7 +150,7 @@ public class AutoscalingTest {
}
@Test
- public void testAutoscalingRespectsLowerLimit() {
+ public void autoscaling_respects_lower_limit() {
NodeResources resources = new NodeResources(3, 100, 100, 1);
ClusterResources min = new ClusterResources( 4, 1, new NodeResources(1.8, 7.4, 8.5, 1));
ClusterResources max = new ClusterResources( 6, 1, new NodeResources(2.4, 78, 79, 1));
@@ -166,7 +170,7 @@ public class AutoscalingTest {
}
@Test
- public void testAutoscalingRespectsGroupLimit() {
+ public void autoscaling_respects_group_limit() {
NodeResources hostResources = new NodeResources(30.0, 100, 100, 1);
ClusterResources min = new ClusterResources( 2, 2, new NodeResources(1, 1, 1, 1));
ClusterResources max = new ClusterResources(18, 6, new NodeResources(100, 1000, 1000, 1));
@@ -184,7 +188,7 @@ public class AutoscalingTest {
}
@Test
- public void testAutoscalingLimitsWhenMinEqualsMax() {
+ public void test_autoscaling_limits_when_min_equals_xax() {
NodeResources resources = new NodeResources(3, 100, 100, 1);
ClusterResources min = new ClusterResources( 2, 1, new NodeResources(1, 1, 1, 1));
ClusterResources max = min;
@@ -200,7 +204,7 @@ public class AutoscalingTest {
}
@Test
- public void testSuggestionsIgnoresLimits() {
+ public void suggestions_ignores_limits() {
NodeResources resources = new NodeResources(3, 100, 100, 1);
ClusterResources min = new ClusterResources( 2, 1, new NodeResources(1, 1, 1, 1));
ClusterResources max = min;
@@ -218,7 +222,7 @@ public class AutoscalingTest {
}
@Test
- public void testAutoscalingGroupSize1() {
+ public void test_autoscaling_group_size_1() {
NodeResources resources = new NodeResources(3, 100, 100, 1);
ClusterResources min = new ClusterResources( 2, 2, new NodeResources(1, 1, 1, 1));
ClusterResources max = new ClusterResources(20, 20, new NodeResources(100, 1000, 1000, 1));
@@ -236,7 +240,7 @@ public class AutoscalingTest {
}
@Test
- public void testAutoscalingGroupSizeByCpu() {
+ public void test_autoscalinggroupsize_by_cpu() {
NodeResources resources = new NodeResources(3, 100, 100, 1);
ClusterResources min = new ClusterResources( 3, 1, new NodeResources(1, 1, 1, 1));
ClusterResources max = new ClusterResources(21, 7, new NodeResources(100, 1000, 1000, 1));
@@ -254,7 +258,7 @@ public class AutoscalingTest {
}
@Test
- public void testAutoscalingGroupSize() {
+ public void test_autoscaling_group_size() {
NodeResources hostResources = new NodeResources(100, 1000, 1000, 100);
ClusterResources min = new ClusterResources( 3, 2, new NodeResources(1, 1, 1, 1));
ClusterResources max = new ClusterResources(30, 30, new NodeResources(100, 100, 1000, 1));
@@ -272,7 +276,7 @@ public class AutoscalingTest {
}
@Test
- public void testAutoscalingAvoidsIllegalConfigurations() {
+ public void autoscaling_avoids_illegal_configurations() {
NodeResources resources = new NodeResources(3, 100, 100, 1);
ClusterResources min = new ClusterResources( 2, 1, new NodeResources(1, 1, 1, 1));
ClusterResources max = new ClusterResources(20, 1, new NodeResources(100, 1000, 1000, 1));
@@ -290,7 +294,46 @@ public class AutoscalingTest {
}
@Test
- public void testAutoscalingAws() {
+ public void real_resources_are_taken_into_account() {
+ NodeResources hostResources = new NodeResources(60, 100, 1000, 10);
+ ClusterResources min = new ClusterResources(2, 1, new NodeResources( 2, 20, 200, 1));
+ ClusterResources max = new ClusterResources(4, 1, new NodeResources(60, 100, 1000, 1));
+
+ { // No memory tax
+ System.out.println("------- No memory tax");
+ AutoscalingTester tester = new AutoscalingTester(hostResources, new OnlySubtractingWhenForecastingCalculator(0));
+
+ ApplicationId application1 = tester.applicationId("app1");
+ ClusterSpec cluster1 = tester.clusterSpec(ClusterSpec.Type.content, "cluster1");
+
+ tester.deploy(application1, cluster1, min);
+ tester.addMeasurements(Resource.memory, 1.0f, 1000, application1); // Need more memory, which can be achieved in two way
+ tester.addMeasurements(Resource.cpu, 1.0f, 1000, application1); // Pushes towards more nodes due to fixed cpu cost per node
+ tester.addMeasurements(Resource.disk, 0.7f, 1000, application1);
+ tester.assertResources("Scaling up",
+ 4, 1, 7.0, 20.0, 200.0,
+ tester.autoscale(application1, cluster1.id(), min, max));
+ }
+
+ { // 15 Gb memory tax
+ System.out.println("------- With 15 Gb memory tax");
+ AutoscalingTester tester = new AutoscalingTester(hostResources, new OnlySubtractingWhenForecastingCalculator(15));
+
+ ApplicationId application1 = tester.applicationId("app1");
+ ClusterSpec cluster1 = tester.clusterSpec(ClusterSpec.Type.content, "cluster1");
+
+ tester.deploy(application1, cluster1, min);
+ tester.addMeasurements(Resource.memory, 1.0f, 1000, application1); // Need more memory, which can be achieved in two way
+ tester.addMeasurements(Resource.cpu, 1.0f, 1000, application1); // Pushes towards more nodes due to fixed cpu cost per node
+ tester.addMeasurements(Resource.disk, 0.7f, 1000, application1);
+ tester.assertResources("Scaling up",
+ 4, 1, 7.0, 20.0, 200.0,
+ tester.autoscale(application1, cluster1.id(), min, max));
+ }
+ }
+
+ @Test
+ public void test_autoscaling_without_host_sharing() {
ClusterResources min = new ClusterResources( 2, 1, new NodeResources(1, 1, 1, 1));
ClusterResources max = new ClusterResources(20, 1, new NodeResources(100, 1000, 1000, 1));
List<Flavor> flavors = new ArrayList<>();
@@ -325,4 +368,35 @@ public class AutoscalingTest {
tester.autoscale(application1, cluster1.id(), min, max));
}
+ /**
+ * This calculator subtracts the memory tac when forecasting overhead, but not when actually
+ * returning information about nodes. This is allowed because the forecast is a *worst case*.
+ * It is useful here because it ensures that we end up with the same real (and therefore target)
+ * resources regardless of tax which makes it easier to compare behavior with different tax levels.
+ */
+ private static class OnlySubtractingWhenForecastingCalculator implements HostResourcesCalculator {
+
+ private final int memoryTaxGb;
+
+ public OnlySubtractingWhenForecastingCalculator(int memoryTaxGb) {
+ this.memoryTaxGb = memoryTaxGb;
+ }
+
+ @Override
+ public NodeResources realResourcesOf(Node node, NodeRepository nodeRepository) {
+ return node.flavor().resources();
+ }
+
+ @Override
+ public NodeResources advertisedResourcesOf(Flavor flavor) {
+ return flavor.resources();
+ }
+
+ @Override
+ public NodeResources overheadAllocating(NodeResources resources, boolean exclusive) {
+ return resources.withVcpu(0).withMemoryGb(memoryTaxGb).withDiskGb(0);
+ }
+
+ }
+
}
diff --git a/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/autoscale/AutoscalingTester.java b/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/autoscale/AutoscalingTester.java
index bdea21cc4d3..bcae145f1e6 100644
--- a/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/autoscale/AutoscalingTester.java
+++ b/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/autoscale/AutoscalingTester.java
@@ -44,15 +44,24 @@ class AutoscalingTester {
/** Creates an autoscaling tester with a single host type ready */
public AutoscalingTester(NodeResources hostResources) {
- this(new Zone(Environment.prod, RegionName.from("us-east")), List.of(new Flavor("hostFlavor", hostResources)));
+ this(hostResources, null);
+ }
+
+ public AutoscalingTester(NodeResources hostResources, HostResourcesCalculator resourcesCalculator) {
+ this(new Zone(Environment.prod, RegionName.from("us-east")), List.of(new Flavor("hostFlavor", hostResources)), resourcesCalculator);
provisioningTester.makeReadyNodes(20, "hostFlavor", NodeType.host, 8);
provisioningTester.deployZoneApp();
}
public AutoscalingTester(Zone zone, List<Flavor> flavors) {
+ this(zone, flavors, new MockHostResourcesCalculator(zone));
+ }
+
+ private AutoscalingTester(Zone zone, List<Flavor> flavors,
+ HostResourcesCalculator resourcesCalculator) {
provisioningTester = new ProvisioningTester.Builder().zone(zone)
.flavors(flavors)
- .resourcesCalculator(new MockHostResourcesCalculator(zone))
+ .resourcesCalculator(resourcesCalculator)
.hostProvisioner(new MockHostProvisioner(flavors))
.build();
@@ -203,14 +212,6 @@ class AutoscalingTester {
}
@Override
- public NodeResources lowestRealResourcesAllocating(NodeResources resources, boolean exclusive) {
- if (zone.getCloud().dynamicProvisioning())
- return resources.withMemoryGb(resources.memoryGb() - 3);
- else
- return resources;
- }
-
- @Override
public NodeResources advertisedResourcesOf(Flavor flavor) {
if (zone.getCloud().dynamicProvisioning())
return flavor.resources().withMemoryGb(flavor.resources().memoryGb() + 3);
@@ -218,6 +219,11 @@ class AutoscalingTester {
return flavor.resources();
}
+ @Override
+ public NodeResources overheadAllocating(NodeResources resources, boolean exclusive) {
+ return resources.withVcpu(0).withMemoryGb(zone.getCloud().dynamicProvisioning() ? 3 : 0).withDiskGb(0);
+ }
+
}
private class MockHostProvisioner implements HostProvisioner {
diff --git a/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/provisioning/DockerProvisioningTest.java b/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/provisioning/DockerProvisioningTest.java
index e4d464840ea..3c1cace3dac 100644
--- a/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/provisioning/DockerProvisioningTest.java
+++ b/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/provisioning/DockerProvisioningTest.java
@@ -39,8 +39,8 @@ import static org.junit.Assert.fail;
*/
public class DockerProvisioningTest {
- private static final NodeResources dockerFlavor = new NodeResources(1, 4, 100, 1,
- NodeResources.DiskSpeed.fast, NodeResources.StorageType.local);
+ private static final NodeResources dockerResources = new NodeResources(1, 4, 100, 1,
+ NodeResources.DiskSpeed.fast, NodeResources.StorageType.local);
@Test
public void docker_application_deployment() {
@@ -48,28 +48,28 @@ public class DockerProvisioningTest {
ApplicationId application1 = tester.makeApplicationId();
for (int i = 1; i < 10; i++)
- tester.makeReadyVirtualDockerNodes(1, dockerFlavor, "dockerHost" + i);
+ tester.makeReadyVirtualDockerNodes(1, dockerResources, "dockerHost" + i);
Version wantedVespaVersion = Version.fromString("6.39");
int nodeCount = 7;
List<HostSpec> hosts = tester.prepare(application1,
ClusterSpec.request(ClusterSpec.Type.content, ClusterSpec.Id.from("myContent")).vespaVersion(wantedVespaVersion).build(),
- nodeCount, 1, dockerFlavor);
+ nodeCount, 1, dockerResources);
tester.activate(application1, new HashSet<>(hosts));
NodeList nodes = tester.getNodes(application1, Node.State.active);
assertEquals(nodeCount, nodes.size());
- assertEquals(dockerFlavor, nodes.asList().get(0).flavor().resources());
+ assertEquals(dockerResources, nodes.asList().get(0).flavor().resources());
// Upgrade Vespa version on nodes
Version upgradedWantedVespaVersion = Version.fromString("6.40");
List<HostSpec> upgradedHosts = tester.prepare(application1,
ClusterSpec.request(ClusterSpec.Type.content, ClusterSpec.Id.from("myContent")).vespaVersion(upgradedWantedVespaVersion).build(),
- nodeCount, 1, dockerFlavor);
+ nodeCount, 1, dockerResources);
tester.activate(application1, new HashSet<>(upgradedHosts));
NodeList upgradedNodes = tester.getNodes(application1, Node.State.active);
assertEquals(nodeCount, upgradedNodes.size());
- assertEquals(dockerFlavor, upgradedNodes.asList().get(0).flavor().resources());
+ assertEquals(dockerResources, upgradedNodes.asList().get(0).flavor().resources());
assertEquals(hosts, upgradedHosts);
}
@@ -80,14 +80,14 @@ public class DockerProvisioningTest {
ApplicationId zoneApplication = tester.makeApplicationId();
List<Node> parents = tester.makeReadyNodes(10, new NodeResources(2, 4, 20, 2), NodeType.host, 1);
for (Node parent : parents)
- tester.makeReadyVirtualDockerNodes(1, dockerFlavor, parent.hostname());
+ tester.makeReadyVirtualDockerNodes(1, dockerResources, parent.hostname());
ApplicationId application1 = tester.makeApplicationId();
Version wantedVespaVersion = Version.fromString("6.39");
int nodeCount = 7;
List<HostSpec> nodes = tester.prepare(application1,
- ClusterSpec.request(ClusterSpec.Type.content, ClusterSpec.Id.from("myContent")).vespaVersion(wantedVespaVersion).build(),
- nodeCount, 1, dockerFlavor);
+ ClusterSpec.request(ClusterSpec.Type.content, ClusterSpec.Id.from("myContent")).vespaVersion(wantedVespaVersion).build(),
+ nodeCount, 1, dockerResources);
try {
tester.activate(application1, new HashSet<>(nodes));
fail("Expected the allocation to fail due to parent hosts not being active yet");
@@ -101,8 +101,8 @@ public class DockerProvisioningTest {
// Try allocating tenants again
nodes = tester.prepare(application1,
- ClusterSpec.request(ClusterSpec.Type.content, ClusterSpec.Id.from("myContent")).vespaVersion(wantedVespaVersion).build(),
- nodeCount, 1, dockerFlavor);
+ ClusterSpec.request(ClusterSpec.Type.content, ClusterSpec.Id.from("myContent")).vespaVersion(wantedVespaVersion).build(),
+ nodeCount, 1, dockerResources);
tester.activate(application1, new HashSet<>(nodes));
NodeList activeNodes = tester.getNodes(application1, Node.State.active);
@@ -153,13 +153,13 @@ public class DockerProvisioningTest {
public void docker_application_deployment_with_exclusive_app_first() {
ProvisioningTester tester = new ProvisioningTester.Builder().zone(new Zone(Environment.prod, RegionName.from("us-east"))).build();
for (int i = 1; i <= 4; i++)
- tester.makeReadyVirtualDockerNode(i, dockerFlavor, "host1");
+ tester.makeReadyVirtualDockerNode(i, dockerResources, "host1");
for (int i = 5; i <= 8; i++)
- tester.makeReadyVirtualDockerNode(i, dockerFlavor, "host2");
+ tester.makeReadyVirtualDockerNode(i, dockerResources, "host2");
for (int i = 9; i <= 12; i++)
- tester.makeReadyVirtualDockerNode(i, dockerFlavor, "host3");
+ tester.makeReadyVirtualDockerNode(i, dockerResources, "host3");
for (int i = 13; i <= 16; i++)
- tester.makeReadyVirtualDockerNode(i, dockerFlavor, "host4");
+ tester.makeReadyVirtualDockerNode(i, dockerResources, "host4");
ApplicationId application1 = tester.makeApplicationId();
prepareAndActivate(application1, 2, true, tester);
@@ -176,13 +176,13 @@ public class DockerProvisioningTest {
public void docker_application_deployment_with_exclusive_app_last() {
ProvisioningTester tester = new ProvisioningTester.Builder().zone(new Zone(Environment.prod, RegionName.from("us-east"))).build();
for (int i = 1; i <= 4; i++)
- tester.makeReadyVirtualDockerNode(i, dockerFlavor, "host1");
+ tester.makeReadyVirtualDockerNode(i, dockerResources, "host1");
for (int i = 5; i <= 8; i++)
- tester.makeReadyVirtualDockerNode(i, dockerFlavor, "host2");
+ tester.makeReadyVirtualDockerNode(i, dockerResources, "host2");
for (int i = 9; i <= 12; i++)
- tester.makeReadyVirtualDockerNode(i, dockerFlavor, "host3");
+ tester.makeReadyVirtualDockerNode(i, dockerResources, "host3");
for (int i = 13; i <= 16; i++)
- tester.makeReadyVirtualDockerNode(i, dockerFlavor, "host4");
+ tester.makeReadyVirtualDockerNode(i, dockerResources, "host4");
ApplicationId application1 = tester.makeApplicationId();
prepareAndActivate(application1, 2, false, tester);
@@ -199,13 +199,13 @@ public class DockerProvisioningTest {
public void docker_application_deployment_change_to_exclusive_and_back() {
ProvisioningTester tester = new ProvisioningTester.Builder().zone(new Zone(Environment.prod, RegionName.from("us-east"))).build();
for (int i = 1; i <= 4; i++)
- tester.makeReadyVirtualDockerNode(i, dockerFlavor, "host1");
+ tester.makeReadyVirtualDockerNode(i, dockerResources, "host1");
for (int i = 5; i <= 8; i++)
- tester.makeReadyVirtualDockerNode(i, dockerFlavor, "host2");
+ tester.makeReadyVirtualDockerNode(i, dockerResources, "host2");
for (int i = 9; i <= 12; i++)
- tester.makeReadyVirtualDockerNode(i, dockerFlavor, "host3");
+ tester.makeReadyVirtualDockerNode(i, dockerResources, "host3");
for (int i = 13; i <= 16; i++)
- tester.makeReadyVirtualDockerNode(i, dockerFlavor, "host4");
+ tester.makeReadyVirtualDockerNode(i, dockerResources, "host4");
ApplicationId application1 = tester.makeApplicationId();
prepareAndActivate(application1, 2, false, tester);
@@ -228,13 +228,13 @@ public class DockerProvisioningTest {
public void docker_application_deployment_with_exclusive_app_causing_allocation_failure() {
ProvisioningTester tester = new ProvisioningTester.Builder().zone(new Zone(Environment.prod, RegionName.from("us-east"))).build();
for (int i = 1; i <= 4; i++)
- tester.makeReadyVirtualDockerNode(i, dockerFlavor, "host1");
+ tester.makeReadyVirtualDockerNode(i, dockerResources, "host1");
for (int i = 5; i <= 8; i++)
- tester.makeReadyVirtualDockerNode(i, dockerFlavor, "host2");
+ tester.makeReadyVirtualDockerNode(i, dockerResources, "host2");
for (int i = 9; i <= 12; i++)
- tester.makeReadyVirtualDockerNode(i, dockerFlavor, "host3");
+ tester.makeReadyVirtualDockerNode(i, dockerResources, "host3");
for (int i = 13; i <= 16; i++)
- tester.makeReadyVirtualDockerNode(i, dockerFlavor, "host4");
+ tester.makeReadyVirtualDockerNode(i, dockerResources, "host4");
ApplicationId application1 = tester.makeApplicationId();
prepareAndActivate(application1, 2, true, tester);
@@ -266,11 +266,11 @@ public class DockerProvisioningTest {
public void get_specified_flavor_not_default_flavor_for_docker() {
ProvisioningTester tester = new ProvisioningTester.Builder().zone(new Zone(Environment.test, RegionName.from("corp-us-east-1"))).build();
ApplicationId application1 = tester.makeApplicationId();
- tester.makeReadyVirtualDockerNodes(1, dockerFlavor, "dockerHost");
+ tester.makeReadyVirtualDockerNodes(1, dockerResources, "dockerHost");
List<HostSpec> hosts = tester.prepare(application1,
ClusterSpec.request(ClusterSpec.Type.content, ClusterSpec.Id.from("myContent")).vespaVersion("6.42").build(),
- 1, 1, dockerFlavor);
+ 1, 1, dockerResources);
tester.activate(application1, new HashSet<>(hosts));
NodeList nodes = tester.getNodes(application1, Node.State.active);
@@ -284,13 +284,13 @@ public class DockerProvisioningTest {
ProvisioningTester tester = new ProvisioningTester.Builder()
.zone(new Zone(Environment.prod, RegionName.from("us-east-1"))).build();
ApplicationId application1 = tester.makeApplicationId("app1");
- tester.makeReadyVirtualDockerNodes(1, dockerFlavor, "dockerHost1");
- tester.makeReadyVirtualDockerNodes(1, dockerFlavor, "dockerHost2");
+ tester.makeReadyVirtualDockerNodes(1, dockerResources, "dockerHost1");
+ tester.makeReadyVirtualDockerNodes(1, dockerResources, "dockerHost2");
- List<HostSpec> hosts = tester.prepare(application1,
- ClusterSpec.request(ClusterSpec.Type.content, ClusterSpec.Id.from("myContent")).vespaVersion("6.42").build(),
- 2, 1,
- dockerFlavor.with(NodeResources.StorageType.remote));
+ tester.prepare(application1,
+ ClusterSpec.request(ClusterSpec.Type.content, ClusterSpec.Id.from("myContent")).vespaVersion("6.42").build(),
+ 2, 1,
+ dockerResources.with(NodeResources.StorageType.remote));
}
catch (OutOfCapacityException e) {
assertEquals("Could not satisfy request for 2 nodes with " +
@@ -308,7 +308,7 @@ public class DockerProvisioningTest {
private void prepareAndActivate(ApplicationId application, int nodeCount, boolean exclusive, ProvisioningTester tester) {
Set<HostSpec> hosts = new HashSet<>(tester.prepare(application,
ClusterSpec.request(ClusterSpec.Type.container, ClusterSpec.Id.from("myContainer")).vespaVersion("6.39").exclusive(exclusive).build(),
- Capacity.from(new ClusterResources(nodeCount, 1, dockerFlavor), false, true)));
+ Capacity.from(new ClusterResources(nodeCount, 1, dockerResources), false, true)));
tester.activate(application, hosts);
}
diff --git a/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/provisioning/DynamicDockerProvisionTest.java b/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/provisioning/DynamicDockerProvisionTest.java
index da2002bd488..1757efea51c 100644
--- a/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/provisioning/DynamicDockerProvisionTest.java
+++ b/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/provisioning/DynamicDockerProvisionTest.java
@@ -47,6 +47,7 @@ import static org.mockito.Mockito.verify;
/**
* @author freva
+ * @author bratseth
*/
public class DynamicDockerProvisionTest {
@@ -159,14 +160,14 @@ public class DynamicDockerProvisionTest {
}
@Test
- public void test_capacity_is_in_advertised_amounts_on_aws() {
+ public void test_capacity_is_in_advertised_amounts() {
int memoryTax = 3;
List<Flavor> flavors = List.of(new Flavor("2x",
new NodeResources(2, 17, 200, 10, fast, remote)));
ProvisioningTester tester = new ProvisioningTester.Builder().zone(zone)
.flavors(flavors)
- .hostProvisioner(new MockHostProvisioner(flavors, memoryTax, 0))
+ .hostProvisioner(new MockHostProvisioner(flavors, memoryTax))
.nameResolver(nameResolver)
.resourcesCalculator(new MockResourcesCalculator(memoryTax, 0))
.build();
@@ -204,7 +205,7 @@ public class DynamicDockerProvisionTest {
}
@Test
- public void test_changing_limits_on_aws() {
+ public void test_changing_limits() {
int memoryTax = 3;
List<Flavor> flavors = List.of(new Flavor("1x", new NodeResources(1, 10 - memoryTax, 100, 0.1, fast, remote)),
new Flavor("2x", new NodeResources(2, 20 - memoryTax, 200, 0.1, fast, remote)),
@@ -212,7 +213,7 @@ public class DynamicDockerProvisionTest {
ProvisioningTester tester = new ProvisioningTester.Builder().zone(zone)
.flavors(flavors)
- .hostProvisioner(new MockHostProvisioner(flavors, memoryTax, 0))
+ .hostProvisioner(new MockHostProvisioner(flavors, memoryTax))
.nameResolver(nameResolver)
.resourcesCalculator(new MockResourcesCalculator(memoryTax, 0))
.build();
@@ -278,7 +279,7 @@ public class DynamicDockerProvisionTest {
}
@Test
- public void test_changing_storage_type_on_aws() {
+ public void test_changing_storage_type() {
int memoryTax = 3;
List<Flavor> flavors = List.of(new Flavor("2x", new NodeResources(2, 20 - memoryTax, 200, 0.1, fast, remote)),
new Flavor("2xl", new NodeResources(2, 20 - memoryTax, 200, 0.1, fast, local)),
@@ -287,7 +288,7 @@ public class DynamicDockerProvisionTest {
ProvisioningTester tester = new ProvisioningTester.Builder().zone(zone)
.flavors(flavors)
- .hostProvisioner(new MockHostProvisioner(flavors, memoryTax, 0))
+ .hostProvisioner(new MockHostProvisioner(flavors, memoryTax))
.nameResolver(nameResolver)
.resourcesCalculator(new MockResourcesCalculator(memoryTax, 0))
.build();
@@ -322,7 +323,7 @@ public class DynamicDockerProvisionTest {
ProvisioningTester tester = new ProvisioningTester.Builder().zone(zone)
.flavors(flavors)
- .hostProvisioner(new MockHostProvisioner(flavors, memoryTax, localDiskTax))
+ .hostProvisioner(new MockHostProvisioner(flavors, memoryTax))
.nameResolver(nameResolver)
.resourcesCalculator(new MockResourcesCalculator(memoryTax, localDiskTax))
.build();
@@ -383,30 +384,29 @@ public class DynamicDockerProvisionTest {
}
@Override
- public NodeResources lowestRealResourcesAllocating(NodeResources resources, boolean exclusive) {
- return resources.withMemoryGb(resources.memoryGb() - memoryTaxGb)
- .withDiskGb(resources.diskGb() - ( resources.storageType() == local ? localDiskTax : 0));
- }
-
- @Override
public NodeResources advertisedResourcesOf(Flavor flavor) {
NodeResources resources = flavor.resources();
if ( ! flavor.isConfigured()) return resources;
return resources.withMemoryGb(resources.memoryGb() + memoryTaxGb);
}
+ @Override
+ public NodeResources overheadAllocating(NodeResources resources, boolean exclusive) {
+ return resources.withVcpu(0)
+ .withMemoryGb(memoryTaxGb)
+ .withDiskGb(resources.storageType() == local ? localDiskTax : 0);
+ }
+
}
private static class MockHostProvisioner implements HostProvisioner {
private final List<Flavor> hostFlavors;
private final int memoryTaxGb;
- private final int localDiskTaxGb;
- public MockHostProvisioner(List<Flavor> hostFlavors, int memoryTaxGb, int localDiskTaxGb) {
+ public MockHostProvisioner(List<Flavor> hostFlavors, int memoryTaxGb) {
this.hostFlavors = List.copyOf(hostFlavors);
this.memoryTaxGb = memoryTaxGb;
- this.localDiskTaxGb = localDiskTaxGb;
}
@Override
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 326af2fc60a..92e64e752a7 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
@@ -556,7 +556,8 @@ public class ProvisioningTester {
}
public Builder resourcesCalculator(HostResourcesCalculator resourcesCalculator) {
- this.resourcesCalculator = resourcesCalculator;
+ if (resourcesCalculator != null)
+ this.resourcesCalculator = resourcesCalculator;
return this;
}