aboutsummaryrefslogtreecommitdiffstats
path: root/node-repository
diff options
context:
space:
mode:
authorValerij Fredriksen <valerij92@gmail.com>2021-07-27 11:53:32 +0200
committerValerij Fredriksen <valerijf@verizonmedia.com>2021-07-27 13:58:51 +0200
commitf816421a481f6a1c0778a6be2139b8bbe5892f9f (patch)
treeb84e8ef471a39479dff7b790d2d156bfbf9a40a1 /node-repository
parent502fe327240c47220f6066132d3948eb6b07bc8f (diff)
Make sure exclusiveToClusterType is respected in allocation code
Diffstat (limited to 'node-repository')
-rw-r--r--node-repository/src/main/java/com/yahoo/vespa/hosted/provision/provisioning/NodeAllocation.java11
-rw-r--r--node-repository/src/main/java/com/yahoo/vespa/hosted/provision/provisioning/NodePrioritizer.java1
-rw-r--r--node-repository/src/test/java/com/yahoo/vespa/hosted/provision/provisioning/VirtualNodeProvisioningTest.java28
3 files changed, 36 insertions, 4 deletions
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 2efca58fe26..bdb7cb4b64d 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
@@ -189,10 +189,13 @@ class NodeAllocation {
private boolean violatesExclusivity(NodeCandidate candidate) {
if (candidate.parentHostname().isEmpty()) return false;
- // In dynamic provisioned zones a node requiring exclusivity must be on a host that has exclusiveTo equal to its owner
- if (nodeRepository.zone().getCloud().dynamicProvisioning())
- return requestedNodes.isExclusive() &&
- ! candidate.parent.flatMap(Node::exclusiveToApplicationId).map(application::equals).orElse(false);
+ // In dynamic provisioned zones, exclusivity is violated if...
+ if (nodeRepository.zone().getCloud().dynamicProvisioning()) {
+ // If either the parent is dedicated to a cluster type different from this cluster
+ return ! candidate.parent.flatMap(Node::exclusiveToClusterType).map(cluster.type()::equals).orElse(true) ||
+ // or this cluster is requiring exclusivity, but the host is exclusive to a different owner
+ (requestedNodes.isExclusive() && !candidate.parent.flatMap(Node::exclusiveToApplicationId).map(application::equals).orElse(false));
+ }
// In non-dynamic provisioned zones we require that if either of the nodes on the host requires exclusivity,
// then all the nodes on the host must have the same owner
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 98219e678d4..6568046991b 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
@@ -137,6 +137,7 @@ public class NodePrioritizer {
if (host.reservedTo().isPresent() && !host.reservedTo().get().equals(application.tenant())) continue;
if (host.reservedTo().isPresent() && application.instance().isTester()) continue;
if (host.exclusiveToApplicationId().isPresent()) continue; // Never allocate new nodes to exclusive hosts
+ if ( ! host.exclusiveToClusterType().map(clusterSpec.type()::equals).orElse(true)) continue;
if (spareHosts.contains(host) && !canAllocateToSpareHosts) continue;
if ( ! capacity.hasCapacity(host, requestedNodes.resources().get())) continue;
if ( ! allNodes.childrenOf(host).owner(application).cluster(clusterSpec.id()).isEmpty()) continue;
diff --git a/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/provisioning/VirtualNodeProvisioningTest.java b/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/provisioning/VirtualNodeProvisioningTest.java
index 18fcb56d87f..fdef4135c16 100644
--- a/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/provisioning/VirtualNodeProvisioningTest.java
+++ b/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/provisioning/VirtualNodeProvisioningTest.java
@@ -333,6 +333,34 @@ public class VirtualNodeProvisioningTest {
assertNodeParentReservation(tester.getNodes(application1_1).asList(), Optional.empty(), tester); // Reservation is cleared after activation
}
+ @Test
+ public void respects_exclusive_to_cluster_type() {
+ NodeResources resources = new NodeResources(10, 10, 100, 10);
+ ProvisioningTester tester = new ProvisioningTester.Builder().zone(new Zone(Environment.prod, RegionName.from("us-east"))).build();
+
+ tester.makeReadyNodes(10, resources, Optional.empty(), NodeType.host, 1);
+ tester.activateTenantHosts();
+ // All hosts are exclusive to content nodes
+ tester.patchNodes(tester.nodeRepository().nodes().list().asList(), node -> node.withExclusiveToClusterType(ClusterSpec.Type.content));
+
+ Version wantedVespaVersion = Version.fromString("6.39");
+ try {
+ // No capacity for 'container' nodes
+ tester.prepare(applicationId,
+ ClusterSpec.request(ClusterSpec.Type.container, ClusterSpec.Id.from("myContent")).vespaVersion(wantedVespaVersion).build(),
+ 6, 1, resources);
+ fail("Expected to fail due to out of capacity");
+ } catch (OutOfCapacityException ignored) { }
+
+ // Same cluster, but content type is now 'content'
+ List<HostSpec> nodes = tester.prepare(applicationId,
+ ClusterSpec.request(ClusterSpec.Type.content, ClusterSpec.Id.from("myContent")).vespaVersion(wantedVespaVersion).build(),
+ 6, 1, resources);
+ tester.activate(applicationId, nodes);
+
+ assertEquals(6, tester.nodeRepository().nodes().list(Node.State.active).owner(applicationId).size());
+ }
+
/** Exclusive app first, then non-exclusive: Should give the same result as below */
@Test
public void application_deployment_with_exclusive_app_first() {