summaryrefslogtreecommitdiffstats
path: root/node-repository/src
diff options
context:
space:
mode:
authorValerij Fredriksen <valerij92@gmail.com>2021-07-27 10:41:57 +0200
committerValerij Fredriksen <valerijf@verizonmedia.com>2021-07-27 13:58:51 +0200
commit49593e10f8dc4e755335773070072c917768164d (patch)
tree5d6d3e6e950e5e342a103a2bbc890064eae19228 /node-repository/src
parent44b6365684c2d7d931d5d9f0c300a750648d875d (diff)
Add exclusiveToClusterType to Node
Diffstat (limited to 'node-repository/src')
-rw-r--r--node-repository/src/main/java/com/yahoo/vespa/hosted/provision/Node.java83
-rw-r--r--node-repository/src/main/java/com/yahoo/vespa/hosted/provision/maintenance/DynamicProvisioningMaintainer.java2
-rw-r--r--node-repository/src/main/java/com/yahoo/vespa/hosted/provision/persistence/CuratorDatabaseClient.java2
-rw-r--r--node-repository/src/main/java/com/yahoo/vespa/hosted/provision/persistence/NodeSerializer.java19
-rw-r--r--node-repository/src/main/java/com/yahoo/vespa/hosted/provision/provisioning/NodeAllocation.java2
-rw-r--r--node-repository/src/main/java/com/yahoo/vespa/hosted/provision/provisioning/NodePrioritizer.java4
-rw-r--r--node-repository/src/main/java/com/yahoo/vespa/hosted/provision/provisioning/NodeResourceLimits.java2
-rw-r--r--node-repository/src/main/java/com/yahoo/vespa/hosted/provision/provisioning/ProvisionedHost.java2
-rw-r--r--node-repository/src/main/java/com/yahoo/vespa/hosted/provision/restapi/NodePatcher.java2
-rw-r--r--node-repository/src/main/java/com/yahoo/vespa/hosted/provision/restapi/NodesResponse.java2
-rw-r--r--node-repository/src/main/java/com/yahoo/vespa/hosted/provision/restapi/NodesV2ApiHandler.java2
-rw-r--r--node-repository/src/test/java/com/yahoo/vespa/hosted/provision/persistence/NodeSerializerTest.java12
-rw-r--r--node-repository/src/test/java/com/yahoo/vespa/hosted/provision/provisioning/DynamicProvisioningTest.java2
13 files changed, 88 insertions, 48 deletions
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 3dbafdc2aba..240e041a504 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
@@ -4,6 +4,7 @@ package com.yahoo.vespa.hosted.provision;
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;
@@ -46,7 +47,8 @@ public final class Node implements Nodelike {
private final Reports reports;
private final Optional<String> modelName;
private final Optional<TenantName> reservedTo;
- private final Optional<ApplicationId> exclusiveTo;
+ private final Optional<ApplicationId> exclusiveToApplicationId;
+ private final Optional<ClusterSpec.Type> exclusiveToClusterType;
private final Optional<String> switchHostname;
/** Record of the last event of each type happening to this node */
@@ -76,7 +78,8 @@ public final class Node implements Nodelike {
public Node(String id, IP.Config ipConfig, String hostname, Optional<String> parentHostname,
Flavor flavor, Status status, State state, Optional<Allocation> allocation, History history, NodeType type,
Reports reports, Optional<String> modelName, Optional<TenantName> reservedTo,
- Optional<ApplicationId> exclusiveTo, Optional<String> switchHostname) {
+ Optional<ApplicationId> exclusiveToApplicationId, Optional<ClusterSpec.Type> exclusiveToClusterType,
+ Optional<String> switchHostname) {
this.id = Objects.requireNonNull(id, "A node must have an ID");
this.hostname = requireNonEmptyString(hostname, "A node must have a hostname");
this.ipConfig = Objects.requireNonNull(ipConfig, "A node must a have an IP config");
@@ -90,7 +93,8 @@ public final class Node implements Nodelike {
this.reports = Objects.requireNonNull(reports, "A null reports is not permitted");
this.modelName = Objects.requireNonNull(modelName, "A null modelName is not permitted");
this.reservedTo = Objects.requireNonNull(reservedTo, "reservedTo cannot be null");
- this.exclusiveTo = Objects.requireNonNull(exclusiveTo, "exclusiveTo cannot be null");
+ this.exclusiveToApplicationId = Objects.requireNonNull(exclusiveToApplicationId, "exclusiveToApplicationId cannot be null");
+ this.exclusiveToClusterType = Objects.requireNonNull(exclusiveToClusterType, "exclusiveToClusterType cannot be null");
this.switchHostname = requireNonEmptyString(switchHostname, "switchHostname cannot be null");
if (state == State.active)
@@ -110,8 +114,11 @@ public final class Node implements Nodelike {
if (type != NodeType.host && reservedTo.isPresent())
throw new IllegalArgumentException("Only tenant hosts can be reserved to a tenant");
- if (type != NodeType.host && exclusiveTo.isPresent())
+ if (type != NodeType.host && exclusiveToApplicationId.isPresent())
throw new IllegalArgumentException("Only tenant hosts can be exclusive to an application");
+
+ if (type != NodeType.host && exclusiveToClusterType.isPresent())
+ throw new IllegalArgumentException("Only tenant hosts can be exclusive to a cluster type");
}
/** Returns the IP config of this node */
@@ -182,11 +189,18 @@ public final class Node implements Nodelike {
public Optional<TenantName> reservedTo() { return reservedTo; }
/**
- * Returns the application this node is exclusive to, if any. Only hosts can be exclusive to an application.
+ * Returns the application this host is exclusive to, if any. Only tenant hosts can be exclusive to an application.
* If this is set, resources on this host cannot be allocated to any other application. This is set during
* provisioning and applies for the entire lifetime of the host
*/
- public Optional<ApplicationId> exclusiveTo() { return exclusiveTo; }
+ public Optional<ApplicationId> exclusiveToApplicationId() { return exclusiveToApplicationId; }
+
+ /**
+ * Returns the cluster type this host is exclusive to, if any. Only tenant hosts can be exclusive to a cluster type.
+ * If this is set, resources on this host cannot be allocated to any other cluster type. This is set during
+ * provisioning and applies for the entire lifetime of the host
+ */
+ public Optional<ClusterSpec.Type> exclusiveToClusterType() { return exclusiveToClusterType; }
/** Returns the hostname of the switch this node is connected to, if any */
public Optional<String> switchHostname() {
@@ -281,13 +295,13 @@ public final class Node implements Nodelike {
/** Returns a node with the status assigned to the given value */
public Node with(Status status) {
return new Node(id, ipConfig, hostname, parentHostname, flavor, status, state, allocation, history, type,
- reports, modelName, reservedTo, exclusiveTo, switchHostname);
+ reports, modelName, reservedTo, exclusiveToApplicationId, exclusiveToClusterType, switchHostname);
}
/** Returns a node with the type assigned to the given value */
public Node with(NodeType type) {
return new Node(id, ipConfig, hostname, parentHostname, flavor, status, state, allocation, history, type,
- reports, modelName, reservedTo, exclusiveTo, switchHostname);
+ reports, modelName, reservedTo, exclusiveToApplicationId, exclusiveToClusterType, switchHostname);
}
/** Returns a node with the flavor assigned to the given value */
@@ -295,31 +309,31 @@ public final class Node implements Nodelike {
if (flavor.equals(this.flavor)) return this;
History updateHistory = history.with(new History.Event(History.Event.Type.resized, agent, instant));
return new Node(id, ipConfig, hostname, parentHostname, flavor, status, state, allocation, updateHistory, type,
- reports, modelName, reservedTo, exclusiveTo, switchHostname);
+ reports, modelName, reservedTo, exclusiveToApplicationId, exclusiveToClusterType, switchHostname);
}
/** Returns a copy of this with the reboot generation set to generation */
public Node withReboot(Generation generation) {
return new Node(id, ipConfig, hostname, parentHostname, flavor, status.withReboot(generation), state,
- allocation, history, type, reports, modelName, reservedTo, exclusiveTo, switchHostname);
+ allocation, history, type, reports, modelName, reservedTo, exclusiveToApplicationId, exclusiveToClusterType, switchHostname);
}
/** Returns a copy of this with the openStackId set */
public Node withOpenStackId(String openStackId) {
return new Node(openStackId, ipConfig, hostname, parentHostname, flavor, status, state,
- allocation, history, type, reports, modelName, reservedTo, exclusiveTo, switchHostname);
+ allocation, history, type, reports, modelName, reservedTo, exclusiveToApplicationId, exclusiveToClusterType, switchHostname);
}
/** Returns a copy of this with model name set to given value */
public Node withModelName(String modelName) {
return new Node(id, ipConfig, hostname, parentHostname, flavor, status, state,
- allocation, history, type, reports, Optional.of(modelName), reservedTo, exclusiveTo, switchHostname);
+ allocation, history, type, reports, Optional.of(modelName), reservedTo, exclusiveToApplicationId, exclusiveToClusterType, switchHostname);
}
/** Returns a copy of this with model name cleared */
public Node withoutModelName() {
return new Node(id, ipConfig, hostname, parentHostname, flavor, status, state,
- allocation, history, type, reports, Optional.empty(), reservedTo, exclusiveTo, switchHostname);
+ allocation, history, type, reports, Optional.empty(), reservedTo, exclusiveToApplicationId, exclusiveToClusterType, switchHostname);
}
/** Returns a copy of this with a history record saying it was detected to be down at this instant */
@@ -350,50 +364,55 @@ public final class Node implements Nodelike {
*/
public Node with(Allocation allocation) {
return new Node(id, ipConfig, hostname, parentHostname, flavor, status, state,
- Optional.of(allocation), history, type, reports, modelName, reservedTo, exclusiveTo, switchHostname);
+ Optional.of(allocation), history, type, reports, modelName, reservedTo, exclusiveToApplicationId, exclusiveToClusterType, switchHostname);
}
/** Returns a new Node without an allocation. */
public Node withoutAllocation() {
return new Node(id, ipConfig, hostname, parentHostname, flavor, status, state,
- Optional.empty(), history, type, reports, modelName, reservedTo, exclusiveTo, switchHostname);
+ Optional.empty(), history, type, reports, modelName, reservedTo, exclusiveToApplicationId, exclusiveToClusterType, switchHostname);
}
/** Returns a copy of this node with IP config set to the given value. */
public Node with(IP.Config ipConfig) {
return new Node(id, ipConfig, hostname, parentHostname, flavor, status, state,
- allocation, history, type, reports, modelName, reservedTo, exclusiveTo, switchHostname);
+ allocation, history, type, reports, modelName, reservedTo, exclusiveToApplicationId, exclusiveToClusterType, switchHostname);
}
/** Returns a copy of this node with the parent hostname assigned to the given value. */
public Node withParentHostname(String parentHostname) {
return new Node(id, ipConfig, hostname, Optional.of(parentHostname), flavor, status, state,
- allocation, history, type, reports, modelName, reservedTo, exclusiveTo, switchHostname);
+ allocation, history, type, reports, modelName, reservedTo, exclusiveToApplicationId, exclusiveToClusterType, switchHostname);
}
public Node withReservedTo(TenantName tenant) {
if (type != NodeType.host)
throw new IllegalArgumentException("Only host nodes can be reserved, " + hostname + " has type " + type);
return new Node(id, ipConfig, hostname, parentHostname, flavor, status, state,
- allocation, history, type, reports, modelName, Optional.of(tenant), exclusiveTo, switchHostname);
+ allocation, history, type, reports, modelName, Optional.of(tenant), exclusiveToApplicationId, exclusiveToClusterType, switchHostname);
}
/** Returns a copy of this node which is not reserved to a tenant */
public Node withoutReservedTo() {
return new Node(id, ipConfig, hostname, parentHostname, flavor, status, state,
- allocation, history, type, reports, modelName, Optional.empty(), exclusiveTo, switchHostname);
+ allocation, history, type, reports, modelName, Optional.empty(), exclusiveToApplicationId, exclusiveToClusterType, switchHostname);
}
- public Node withExclusiveTo(ApplicationId exclusiveTo) {
+ public Node withExclusiveToApplicationId(ApplicationId exclusiveTo) {
return new Node(id, ipConfig, hostname, parentHostname, flavor, status, state,
- allocation, history, type, reports, modelName, reservedTo, Optional.ofNullable(exclusiveTo), switchHostname);
+ allocation, history, type, reports, modelName, reservedTo, Optional.ofNullable(exclusiveTo), exclusiveToClusterType, switchHostname);
+ }
+
+ public Node withExclusiveToClusterType(ClusterSpec.Type exclusiveTo) {
+ return new Node(id, ipConfig, hostname, parentHostname, flavor, status, state,
+ allocation, history, type, reports, modelName, reservedTo, exclusiveToApplicationId, Optional.ofNullable(exclusiveTo), switchHostname);
}
/** Returns a copy of this node with switch hostname set to given value */
public Node withSwitchHostname(String switchHostname) {
return new Node(id, ipConfig, hostname, parentHostname, flavor, status, state,
- allocation, history, type, reports, modelName, reservedTo, exclusiveTo, Optional.ofNullable(switchHostname));
+ allocation, history, type, reports, modelName, reservedTo, exclusiveToApplicationId, exclusiveToClusterType, Optional.ofNullable(switchHostname));
}
/** Returns a copy of this node with switch hostname unset */
@@ -431,12 +450,12 @@ public final class Node implements Nodelike {
/** Returns a copy of this node with the given history. */
public Node with(History history) {
return new Node(id, ipConfig, hostname, parentHostname, flavor, status, state,
- allocation, history, type, reports, modelName, reservedTo, exclusiveTo, switchHostname);
+ allocation, history, type, reports, modelName, reservedTo, exclusiveToApplicationId, exclusiveToClusterType, switchHostname);
}
public Node with(Reports reports) {
return new Node(id, ipConfig, hostname, parentHostname, flavor, status, state,
- allocation, history, type, reports, modelName, reservedTo, exclusiveTo, switchHostname);
+ allocation, history, type, reports, modelName, reservedTo, exclusiveToApplicationId, exclusiveToClusterType, switchHostname);
}
private static Optional<String> requireNonEmptyString(Optional<String> value, String message) {
@@ -567,7 +586,8 @@ public final class Node implements Nodelike {
private String parentHostname;
private String modelName;
private TenantName reservedTo;
- private ApplicationId exclusiveTo;
+ private ApplicationId exclusiveToApplicationId;
+ private ClusterSpec.Type exclusiveToClusterType;
private String switchHostname;
private Allocation allocation;
private IP.Config ipConfig;
@@ -598,8 +618,13 @@ public final class Node implements Nodelike {
return this;
}
- public Builder exclusiveTo(ApplicationId exclusiveTo) {
- this.exclusiveTo = exclusiveTo;
+ public Builder exclusiveToApplicationId(ApplicationId exclusiveTo) {
+ this.exclusiveToApplicationId = exclusiveTo;
+ return this;
+ }
+
+ public Builder exclusiveToClusterType(ClusterSpec.Type exclusiveTo) {
+ this.exclusiveToClusterType = exclusiveTo;
return this;
}
@@ -642,8 +667,8 @@ public final class Node implements Nodelike {
return new Node(id, Optional.ofNullable(ipConfig).orElse(IP.Config.EMPTY), hostname, Optional.ofNullable(parentHostname),
flavor, Optional.ofNullable(status).orElseGet(Status::initial), state, Optional.ofNullable(allocation),
Optional.ofNullable(history).orElseGet(History::empty), type, Optional.ofNullable(reports).orElseGet(Reports::new),
- Optional.ofNullable(modelName), Optional.ofNullable(reservedTo), Optional.ofNullable(exclusiveTo),
- Optional.ofNullable(switchHostname));
+ Optional.ofNullable(modelName), Optional.ofNullable(reservedTo), Optional.ofNullable(exclusiveToApplicationId),
+ Optional.ofNullable(exclusiveToClusterType), Optional.ofNullable(switchHostname));
}
}
diff --git a/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/maintenance/DynamicProvisioningMaintainer.java b/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/maintenance/DynamicProvisioningMaintainer.java
index 0eb2038e233..cbe951dccd4 100644
--- a/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/maintenance/DynamicProvisioningMaintainer.java
+++ b/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/maintenance/DynamicProvisioningMaintainer.java
@@ -206,7 +206,7 @@ public class DynamicProvisioningMaintainer extends NodeRepositoryMaintainer {
return nodeList.stream()
.filter(node -> Nodes.canAllocateTenantNodeTo(node, true))
.filter(node -> node.reservedTo().isEmpty())
- .filter(node -> node.exclusiveTo().isEmpty())
+ .filter(node -> node.exclusiveToApplicationId().isEmpty())
.collect(Collectors.toMap(Node::hostname, Function.identity()));
}
diff --git a/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/persistence/CuratorDatabaseClient.java b/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/persistence/CuratorDatabaseClient.java
index da4ab528630..d5a4c459ef3 100644
--- a/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/persistence/CuratorDatabaseClient.java
+++ b/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/persistence/CuratorDatabaseClient.java
@@ -210,7 +210,7 @@ public class CuratorDatabaseClient {
toState.isAllocated() ? node.allocation() : Optional.empty(),
node.history().recordStateTransition(node.state(), toState, agent, clock.instant()),
node.type(), node.reports(), node.modelName(), node.reservedTo(),
- node.exclusiveTo(), node.switchHostname());
+ node.exclusiveToApplicationId(), node.exclusiveToClusterType(), node.switchHostname());
writeNode(toState, curatorTransaction, node, newNode);
writtenNodes.add(newNode);
}
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 dff4a66bd42..19bbe92eff6 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
@@ -10,6 +10,7 @@ import com.yahoo.component.Version;
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.DockerImage;
import com.yahoo.config.provision.Flavor;
import com.yahoo.config.provision.InstanceName;
@@ -91,7 +92,8 @@ public class NodeSerializer {
private static final String reportsKey = "reports";
private static final String modelNameKey = "modelName";
private static final String reservedToKey = "reservedTo";
- private static final String exclusiveToKey = "exclusiveTo";
+ private static final String exclusiveToApplicationIdKey = "exclusiveTo";
+ private static final String exclusiveToClusterTypeKey = "exclusiveToClusterType";
private static final String switchHostnameKey = "switchHostname";
// Node resource fields
@@ -178,7 +180,8 @@ public class NodeSerializer {
node.reports().toSlime(object, reportsKey);
node.modelName().ifPresent(modelName -> object.setString(modelNameKey, modelName));
node.reservedTo().ifPresent(tenant -> object.setString(reservedToKey, tenant.value()));
- node.exclusiveTo().ifPresent(applicationId -> object.setString(exclusiveToKey, applicationId.serializedForm()));
+ node.exclusiveToApplicationId().ifPresent(applicationId -> object.setString(exclusiveToApplicationIdKey, applicationId.serializedForm()));
+ node.exclusiveToClusterType().ifPresent(clusterType -> object.setString(exclusiveToClusterTypeKey, clusterType.name()));
}
private void toSlime(Flavor flavor, Cursor object) {
@@ -264,7 +267,8 @@ public class NodeSerializer {
Reports.fromSlime(object.field(reportsKey)),
modelNameFromSlime(object),
reservedToFromSlime(object.field(reservedToKey)),
- exclusiveToFromSlime(object.field(exclusiveToKey)),
+ exclusiveToApplicationIdFromSlime(object.field(exclusiveToApplicationIdKey)),
+ exclusiveToClusterTypeFromSlime(object.field(exclusiveToClusterTypeKey)),
switchHostnameFromSlime(object.field(switchHostnameKey)));
}
@@ -401,13 +405,20 @@ public class NodeSerializer {
return Optional.of(TenantName.from(object.asString()));
}
- private Optional<ApplicationId> exclusiveToFromSlime(Inspector object) {
+ private Optional<ApplicationId> exclusiveToApplicationIdFromSlime(Inspector object) {
if (! object.valid()) return Optional.empty();
if (object.type() != Type.STRING)
throw new IllegalArgumentException("Expected 'exclusiveTo' to be a string but is " + object);
return Optional.of(ApplicationId.fromSerializedForm(object.asString()));
}
+ private Optional<ClusterSpec.Type> exclusiveToClusterTypeFromSlime(Inspector object) {
+ if (! object.valid()) return Optional.empty();
+ if (object.type() != Type.STRING)
+ throw new IllegalArgumentException("Expected 'exclusiveToClusterType' to be a string but is " + object);
+ return Optional.of(ClusterSpec.Type.from(object.asString()));
+ }
+
// ----------------- Enum <-> string mappings ----------------------------------------
/** Returns the event type, or null if this event type should be ignored */
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 b5579451a0e..2efca58fe26 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
@@ -192,7 +192,7 @@ class NodeAllocation {
// 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::exclusiveTo).map(application::equals).orElse(false);
+ ! 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 5fe10f09f8a..98219e678d4 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
@@ -136,7 +136,7 @@ public class NodePrioritizer {
if ( ! Nodes.canAllocateTenantNodeTo(host, dynamicProvisioning)) continue;
if (host.reservedTo().isPresent() && !host.reservedTo().get().equals(application.tenant())) continue;
if (host.reservedTo().isPresent() && application.instance().isTester()) continue;
- if (host.exclusiveTo().isPresent()) continue; // Never allocate new nodes to exclusive hosts
+ if (host.exclusiveToApplicationId().isPresent()) continue; // Never allocate new nodes to exclusive hosts
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;
@@ -183,7 +183,7 @@ public class NodePrioritizer {
spareHosts.contains(parent.get()),
isSurplus,
false,
- parent.get().exclusiveTo().isEmpty()
+ parent.get().exclusiveToApplicationId().isEmpty()
&& requestedNodes.canResize(node.resources(),
capacity.freeCapacityOf(parent.get(), false),
topologyChange,
diff --git a/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/provisioning/NodeResourceLimits.java b/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/provisioning/NodeResourceLimits.java
index 2b64cc86c9a..0b007bf4a41 100644
--- a/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/provisioning/NodeResourceLimits.java
+++ b/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/provisioning/NodeResourceLimits.java
@@ -43,7 +43,7 @@ public class NodeResourceLimits {
if (candidateNode.type() != NodeType.tenant) return true; // Resource limits only apply to tenant nodes
// This node is allocated exclusively if that has been explicitly requested, or if the host of the node was
// provisioned exclusively
- boolean exclusive = cluster.isExclusive() || candidateNode.parent.flatMap(Node::exclusiveTo).isPresent();
+ boolean exclusive = cluster.isExclusive() || candidateNode.parent.flatMap(Node::exclusiveToApplicationId).isPresent();
return isWithinRealLimits(nodeRepository.resourcesCalculator().realResourcesOf(candidateNode, nodeRepository, exclusive),
cluster.type());
}
diff --git a/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/provisioning/ProvisionedHost.java b/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/provisioning/ProvisionedHost.java
index caaea1167b5..f00707de439 100644
--- a/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/provisioning/ProvisionedHost.java
+++ b/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/provisioning/ProvisionedHost.java
@@ -59,7 +59,7 @@ public class ProvisionedHost {
Node.Builder builder = Node
.create(id, IP.Config.of(Set.of(), Set.of(), nodeAddresses), hostHostname, hostFlavor, hostType)
.status(Status.initial().withOsVersion(OsVersion.EMPTY.withCurrent(Optional.of(osVersion))));
- exclusiveTo.ifPresent(builder::exclusiveTo);
+ exclusiveTo.ifPresent(builder::exclusiveToApplicationId);
return builder.build();
}
diff --git a/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/restapi/NodePatcher.java b/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/restapi/NodePatcher.java
index 1bea7056790..fbb8f854160 100644
--- a/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/restapi/NodePatcher.java
+++ b/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/restapi/NodePatcher.java
@@ -179,7 +179,7 @@ public class NodePatcher implements AutoCloseable {
case "reservedTo":
return value.type() == Type.NIX ? node.withoutReservedTo() : node.withReservedTo(TenantName.from(value.asString()));
case "exclusiveTo":
- return node.withExclusiveTo(SlimeUtils.optionalString(value).map(ApplicationId::fromSerializedForm).orElse(null));
+ return node.withExclusiveToApplicationId(SlimeUtils.optionalString(value).map(ApplicationId::fromSerializedForm).orElse(null));
case "switchHostname":
return value.type() == Type.NIX ? node.withoutSwitchHostname() : node.withSwitchHostname(value.asString());
default :
diff --git a/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/restapi/NodesResponse.java b/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/restapi/NodesResponse.java
index 1b3b2f81f11..fbbc73a2c22 100644
--- a/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/restapi/NodesResponse.java
+++ b/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/restapi/NodesResponse.java
@@ -129,7 +129,7 @@ class NodesResponse extends SlimeJsonResponse {
object.setString("openStackId", node.id());
object.setString("flavor", node.flavor().name());
node.reservedTo().ifPresent(reservedTo -> object.setString("reservedTo", reservedTo.value()));
- node.exclusiveTo().ifPresent(exclusiveTo -> object.setString("exclusiveTo", exclusiveTo.serializedForm()));
+ node.exclusiveToApplicationId().ifPresent(exclusiveTo -> object.setString("exclusiveTo", exclusiveTo.serializedForm()));
if (node.flavor().isConfigured())
object.setDouble("cpuCores", node.flavor().resources().vcpu());
NodeResourcesSerializer.toSlime(node.flavor().resources(), object.setObject("resources"));
diff --git a/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/restapi/NodesV2ApiHandler.java b/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/restapi/NodesV2ApiHandler.java
index 24e297de179..c35d6b89090 100644
--- a/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/restapi/NodesV2ApiHandler.java
+++ b/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/restapi/NodesV2ApiHandler.java
@@ -283,7 +283,7 @@ public class NodesV2ApiHandler extends LoggingRequestHandler {
optionalString(inspector.field("parentHostname")).ifPresent(builder::parentHostname);
optionalString(inspector.field("modelName")).ifPresent(builder::modelName);
optionalString(inspector.field("reservedTo")).map(TenantName::from).ifPresent(builder::reservedTo);
- optionalString(inspector.field("exclusiveTo")).map(ApplicationId::fromSerializedForm).ifPresent(builder::exclusiveTo);
+ optionalString(inspector.field("exclusiveTo")).map(ApplicationId::fromSerializedForm).ifPresent(builder::exclusiveToApplicationId);
optionalString(inspector.field("switchHostname")).ifPresent(builder::switchHostname);
return builder.build();
}
diff --git a/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/persistence/NodeSerializerTest.java b/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/persistence/NodeSerializerTest.java
index 523ceeb94ce..158a1d6e5ac 100644
--- a/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/persistence/NodeSerializerTest.java
+++ b/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/persistence/NodeSerializerTest.java
@@ -7,6 +7,7 @@ import com.yahoo.component.Vtag;
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.InstanceName;
import com.yahoo.config.provision.NetworkPorts;
import com.yahoo.config.provision.NodeFlavors;
@@ -450,12 +451,15 @@ public class NodeSerializerTest {
Node.Builder builder = Node.create("myId", IP.Config.EMPTY, "myHostname",
nodeFlavors.getFlavorOrThrow("default"), NodeType.host);
Node node = nodeSerializer.fromJson(State.provisioned, nodeSerializer.toJson(builder.build()));
- assertFalse(node.exclusiveTo().isPresent());
+ assertFalse(node.exclusiveToApplicationId().isPresent());
+ assertFalse(node.exclusiveToClusterType().isPresent());
- ApplicationId exclusiveTo = ApplicationId.from("tenant1", "app1", "instance1");
- node = builder.exclusiveTo(exclusiveTo).build();
+ ApplicationId exclusiveToApp = ApplicationId.from("tenant1", "app1", "instance1");
+ ClusterSpec.Type exclusiveToCluster = ClusterSpec.Type.admin;
+ node = builder.exclusiveToApplicationId(exclusiveToApp).exclusiveToClusterType(exclusiveToCluster).build();
node = nodeSerializer.fromJson(State.provisioned, nodeSerializer.toJson(node));
- assertEquals(exclusiveTo, node.exclusiveTo().get());
+ assertEquals(exclusiveToApp, node.exclusiveToApplicationId().get());
+ assertEquals(exclusiveToCluster, node.exclusiveToClusterType().get());
}
private byte[] createNodeJson(String hostname, String... ipAddress) {
diff --git a/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/provisioning/DynamicProvisioningTest.java b/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/provisioning/DynamicProvisioningTest.java
index 0b7b9f2fa13..cb50b886d16 100644
--- a/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/provisioning/DynamicProvisioningTest.java
+++ b/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/provisioning/DynamicProvisioningTest.java
@@ -468,7 +468,7 @@ public class DynamicProvisioningTest {
}).collect(Collectors.toSet());
Node parent = Node.create(hostHostname, new IP.Config(Set.of(hostIp), pool), hostHostname, hostFlavor, NodeType.host)
- .exclusiveTo(exclusiveTo).build();
+ .exclusiveToApplicationId(exclusiveTo).build();
Node child = Node.reserve(Set.of("::" + hostIndex + ":1"), hostHostname + "-1", hostHostname, nodeResources, NodeType.tenant).build();
ProvisionedHost provisionedHost = mock(ProvisionedHost.class);
when(provisionedHost.generateHost()).thenReturn(parent);