diff options
author | Jon Bratseth <bratseth@oath.com> | 2020-05-11 23:08:04 +0200 |
---|---|---|
committer | GitHub <noreply@github.com> | 2020-05-11 23:08:04 +0200 |
commit | dfbe98d77704e4c598c28b90e739634dd33d2127 (patch) | |
tree | 7edbcc739029801250b81b2b19e95a9d73cf94ff | |
parent | 4b7df75c499b44b9dd1693dd959105cf78589ea0 (diff) | |
parent | e030cc94a1151029355b3241c415d23dd1c608c4 (diff) |
Merge pull request #13218 from vespa-engine/bratseth/exclusivity-on-app-level
Exclusivity on app level
3 files changed, 19 insertions, 14 deletions
diff --git a/config-provisioning/src/main/java/com/yahoo/config/provision/ClusterSpec.java b/config-provisioning/src/main/java/com/yahoo/config/provision/ClusterSpec.java index 3a230c89732..f7030535573 100644 --- a/config-provisioning/src/main/java/com/yahoo/config/provision/ClusterSpec.java +++ b/config-provisioning/src/main/java/com/yahoo/config/provision/ClusterSpec.java @@ -66,8 +66,7 @@ public final class ClusterSpec { /** * Returns whether the physical hosts running the nodes of this application can - * also run nodes of other applications. Using exclusive nodes for containers increases security - * and increases cost. + * also run nodes of other applications. Using exclusive nodes for containers increases security and cost. */ public boolean isExclusive() { return exclusive; } @@ -84,7 +83,7 @@ public final class ClusterSpec { return new Builder(type, id, false); } - /** Creates a ClusterSpec for an existing cluster, group id and vespa version needs to be set */ + /** Creates a ClusterSpec for an existing cluster, group id and Vespa version needs to be set */ public static Builder specification(Type type, Id id) { return new Builder(type, id, true); } 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 a67a5b8e3fb..71e8259665b 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 @@ -2,6 +2,7 @@ package com.yahoo.vespa.hosted.provision.provisioning; import com.yahoo.config.provision.ApplicationId; +import com.yahoo.config.provision.ApplicationName; import com.yahoo.config.provision.ClusterMembership; import com.yahoo.config.provision.ClusterSpec; import com.yahoo.config.provision.Flavor; @@ -116,7 +117,7 @@ class NodeAllocation { if (violatesParentHostPolicy(this.nodes, offered)) wantToRetireNode = true; if ( ! hasCompatibleFlavor(node)) wantToRetireNode = true; if (offered.status().wantToRetire()) wantToRetireNode = true; - if (requestedNodes.isExclusive() && ! hostsOnly(application.tenant(), offered.parentHostname())) + if (requestedNodes.isExclusive() && ! hostsOnly(application.tenant(), application.application(), offered.parentHostname())) wantToRetireNode = true; if ((! saturated() && hasCompatibleFlavor(node)) || acceptToRetire(node)) accepted.add(acceptNode(node, wantToRetireNode, node.isResizable)); @@ -130,11 +131,11 @@ class NodeAllocation { ++rejectedWithClashingParentHost; continue; } - if ( ! exclusiveTo(application.tenant(), offered.parentHostname())) { + if ( ! exclusiveTo(application.tenant(), application.application(), offered.parentHostname())) { ++rejectedDueToExclusivity; continue; } - if ( requestedNodes.isExclusive() && ! hostsOnly(application.tenant(), offered.parentHostname())) { + if ( requestedNodes.isExclusive() && ! hostsOnly(application.tenant(), application.application(), offered.parentHostname())) { ++rejectedDueToExclusivity; continue; } @@ -172,32 +173,37 @@ class NodeAllocation { } /** - * If a parent host is given, and it hosts another tenant with an application which requires exclusive access + * If a parent host is given, and it hosts another application which requires exclusive access * to the physical host, then we cannot host this application on it. */ - private boolean exclusiveTo(TenantName tenant, Optional<String> parentHostname) { + private boolean exclusiveTo(TenantName tenant, ApplicationName application, Optional<String> parentHostname) { if (parentHostname.isEmpty()) return true; for (Node nodeOnHost : allNodes.childrenOf(parentHostname.get())) { if (nodeOnHost.allocation().isEmpty()) continue; - if ( nodeOnHost.allocation().get().membership().cluster().isExclusive() && - ! nodeOnHost.allocation().get().owner().tenant().equals(tenant)) + ! allocatedTo(tenant, application, nodeOnHost)) return false; } return true; } - private boolean hostsOnly(TenantName tenant, Optional<String> parentHostname) { + /** Returns true if this host only hosts the given applicaton (in any instance) */ + private boolean hostsOnly(TenantName tenant, ApplicationName application, Optional<String> parentHostname) { if (parentHostname.isEmpty()) return true; // yes, as host is exclusive for (Node nodeOnHost : allNodes.childrenOf(parentHostname.get())) { if (nodeOnHost.allocation().isEmpty()) continue; - if ( ! nodeOnHost.allocation().get().owner().tenant().equals(tenant)) - return false; + if ( ! allocatedTo(tenant, application, nodeOnHost)) return false; } return true; } + private boolean allocatedTo(TenantName tenant, ApplicationName application, Node node) { + if (node.allocation().isEmpty()) return false; + ApplicationId owner = node.allocation().get().owner(); + return owner.tenant().equals(tenant) && owner.application().equals(application); + } + /** * Returns whether this node should be accepted into the cluster even if it is not currently desired * (already enough nodes, or wrong flavor). 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 d6d6d76e182..df35cabab36 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 @@ -101,9 +101,9 @@ public class NodeRepositoryProvisioner implements Provisioner { if ( requested.type() == NodeType.tenant) { ClusterResources target = decideTargetResources(application, cluster, requested); int nodeCount = capacityPolicies.decideSize(target.nodes(), requested, cluster, application); + groups = Math.min(target.groups(), nodeCount); // cannot have more groups than nodes resources = capacityPolicies.decideNodeResources(target.nodeResources(), requested, cluster); boolean exclusive = capacityPolicies.decideExclusivity(cluster.isExclusive()); - groups = Math.min(target.groups(), nodeCount); // cannot have more groups than nodes nodeSpec = NodeSpec.from(nodeCount, resources, exclusive, requested.canFail()); logIfDownscaled(target.nodes(), nodeCount, cluster, logger); } |