summaryrefslogtreecommitdiffstats
path: root/node-repository
diff options
context:
space:
mode:
authorjonmv <venstad@gmail.com>2023-10-12 19:29:56 +0200
committerjonmv <venstad@gmail.com>2023-10-12 19:29:56 +0200
commit29db2908a03d26478ca4e59454e057c0f0ca8bbf (patch)
treea3760d9ffcfdbb81452d8178df090dcabb8c6f69 /node-repository
parent0d1c470292b17ac405ffd854882f9ee1e84dd368 (diff)
Move violatesExclusivity to NodeCandidate
Diffstat (limited to 'node-repository')
-rw-r--r--node-repository/src/main/java/com/yahoo/vespa/hosted/provision/provisioning/NodeAllocation.java37
-rw-r--r--node-repository/src/main/java/com/yahoo/vespa/hosted/provision/provisioning/NodeCandidate.java31
2 files changed, 39 insertions, 29 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 87e3bea1af9..9f6d4f159f6 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
@@ -117,21 +117,21 @@ class NodeAllocation {
ClusterMembership membership = allocation.membership();
if ( ! allocation.owner().equals(application)) continue; // wrong application
if ( ! membership.cluster().satisfies(cluster)) continue; // wrong cluster id/type
- if ( candidate.state() == Node.State.active && allocation.removable()) continue; // don't accept; causes removal
- if ( candidate.state() == Node.State.active && candidate.wantToFail()) continue; // don't accept; causes failing
- if ( indexes.contains(membership.index())) continue; // duplicate index (just to be sure)
+ if (candidate.state() == Node.State.active && allocation.removable()) continue; // don't accept; causes removal
+ if (candidate.state() == Node.State.active && candidate.wantToFail()) continue; // don't accept; causes failing
+ if (indexes.contains(membership.index())) continue; // duplicate index (just to be sure)
if (nodeRepository.zone().cloud().allowEnclave() && candidate.parent.isPresent() && ! candidate.parent.get().cloudAccount().equals(requested.cloudAccount())) continue; // wrong account
boolean resizeable = requested.considerRetiring() && candidate.isResizable;
- if ((! saturated() && hasCompatibleResources(candidate) && requested.acceptable(candidate)) || acceptIncompatible(candidate)) {
+ if (( ! saturated() && hasCompatibleResources(candidate) && requested.acceptable(candidate)) || acceptIncompatible(candidate)) {
candidate = candidate.withNode();
if (candidate.isValid())
acceptNode(candidate, shouldRetire(candidate, candidates), resizeable);
}
}
- else if (! saturated() && hasCompatibleResources(candidate)) {
- if (! nodeRepository.nodeResourceLimits().isWithinRealLimits(candidate, application, cluster)) {
+ else if ( ! saturated() && hasCompatibleResources(candidate)) {
+ if ( ! nodeRepository.nodeResourceLimits().isWithinRealLimits(candidate, application, cluster)) {
++rejectedDueToInsufficientRealResources;
continue;
}
@@ -196,29 +196,8 @@ class NodeAllocation {
}
private boolean violatesExclusivity(NodeCandidate candidate) {
- if (candidate.parentHostname().isEmpty()) return false;
- if (requested.type() != NodeType.tenant) return false;
-
- // In zones which does not allow host sharing, exclusivity is violated if...
- if ( ! nodeRepository.zone().cloud().allowHostSharing()) {
- // TODO: Write this in a way that is simple to read
- // 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 the parent is dedicated to a different application
- ! candidate.parent.flatMap(Node::exclusiveToApplicationId).map(application::equals).orElse(true) ||
- // or this cluster requires exclusivity, but the host is not exclusive
- (nodeRepository.exclusiveAllocation(cluster) && candidate.parent.flatMap(Node::exclusiveToApplicationId).isEmpty());
- }
-
- // In zones with shared hosts 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
- for (Node nodeOnHost : allNodes.childrenOf(candidate.parentHostname().get())) {
- if (nodeOnHost.allocation().isEmpty()) continue;
- if (nodeRepository.exclusiveAllocation(cluster) || nodeOnHost.allocation().get().membership().cluster().isExclusive()) {
- if ( ! nodeOnHost.allocation().get().owner().equals(application)) return true;
- }
- }
- return false;
+ return candidate.violatesExclusivity(cluster, application, nodeRepository.exclusiveAllocation(cluster),
+ nodeRepository.zone().cloud().allowHostSharing(), allNodes);
}
/**
diff --git a/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/provisioning/NodeCandidate.java b/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/provisioning/NodeCandidate.java
index 1efc35b416d..5ab7e032dc5 100644
--- a/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/provisioning/NodeCandidate.java
+++ b/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/provisioning/NodeCandidate.java
@@ -4,11 +4,13 @@ package com.yahoo.vespa.hosted.provision.provisioning;
import com.yahoo.component.Version;
import com.yahoo.config.provision.ApplicationId;
import com.yahoo.config.provision.ClusterMembership;
+import com.yahoo.config.provision.ClusterSpec;
import com.yahoo.config.provision.Flavor;
import com.yahoo.config.provision.NodeResources;
import com.yahoo.config.provision.NodeType;
import com.yahoo.vespa.hosted.provision.LockedNodeList;
import com.yahoo.vespa.hosted.provision.Node;
+import com.yahoo.vespa.hosted.provision.NodeList;
import com.yahoo.vespa.hosted.provision.Nodelike;
import com.yahoo.vespa.hosted.provision.node.Allocation;
import com.yahoo.vespa.hosted.provision.node.IP;
@@ -20,6 +22,8 @@ import java.util.Objects;
import java.util.Optional;
import java.util.logging.Logger;
+import static com.yahoo.collections.Optionals.emptyOrEqual;
+
/**
* A node candidate containing the details required to prioritize it for allocation. This is immutable.
*
@@ -559,4 +563,31 @@ public abstract class NodeCandidate implements Nodelike, Comparable<NodeCandidat
}
+ public boolean violatesExclusivity(ClusterSpec cluster, ApplicationId application,
+ boolean exclusiveCluster, boolean hostSharing, NodeList allNodes) {
+ if (parentHostname().isEmpty()) return false;
+ if (type() != NodeType.tenant) return false;
+
+ // In zones which do not allow host sharing, exclusivity is violated if...
+ if ( ! hostSharing) {
+ // If either the parent is dedicated to a cluster type different from this cluster
+ return ! emptyOrEqual(parent.flatMap(Node::exclusiveToClusterType), cluster.type()) ||
+ // or the parent is dedicated to a different application
+ ! emptyOrEqual(parent.flatMap(Node::exclusiveToApplicationId), application) ||
+ // or this cluster requires exclusivity, but the host is not exclusive (to this, implicitly by the above).
+ exclusiveCluster && parent.flatMap(Node::exclusiveToApplicationId).isEmpty();
+ }
+
+ // In zones with shared hosts we require that if any node on the host requires exclusivity,
+ // then all the nodes on the host must have the same owner.
+ for (Node nodeOnHost : allNodes.childrenOf(parentHostname().get())) {
+ if (nodeOnHost.allocation().isEmpty()) continue;
+ if (exclusiveCluster || nodeOnHost.allocation().get().membership().cluster().isExclusive()) {
+ if ( ! nodeOnHost.allocation().get().owner().equals(application)) return true;
+ }
+ }
+ return false;
+
+ }
+
}