summaryrefslogtreecommitdiffstats
path: root/node-repository
diff options
context:
space:
mode:
authorMartin Polden <mpolden@mpolden.no>2020-09-22 14:26:25 +0200
committerGitHub <noreply@github.com>2020-09-22 14:26:25 +0200
commit8cae83209c036e5d3bac4ef5aca05a78666c0111 (patch)
tree393713384d6c771b3341625057c67acedad367e1 /node-repository
parenta2291b556e31f07be9d207511a2ae5f7dc4946ec (diff)
parent14c1f947b2906e8cfa38d98ec48ea44bf5fe9e22 (diff)
Merge pull request #14452 from vespa-engine/mpolden/exclusive-switch
Add switch field to nodes API
Diffstat (limited to 'node-repository')
-rw-r--r--node-repository/src/main/java/com/yahoo/vespa/hosted/provision/Node.java64
-rw-r--r--node-repository/src/main/java/com/yahoo/vespa/hosted/provision/NodeRepository.java2
-rw-r--r--node-repository/src/main/java/com/yahoo/vespa/hosted/provision/persistence/CuratorDatabaseClient.java3
-rw-r--r--node-repository/src/main/java/com/yahoo/vespa/hosted/provision/persistence/NodeSerializer.java10
-rw-r--r--node-repository/src/main/java/com/yahoo/vespa/hosted/provision/provisioning/GroupPreparer.java14
-rw-r--r--node-repository/src/main/java/com/yahoo/vespa/hosted/provision/provisioning/NodeAllocation.java136
-rw-r--r--node-repository/src/main/java/com/yahoo/vespa/hosted/provision/provisioning/NodeCandidate.java (renamed from node-repository/src/main/java/com/yahoo/vespa/hosted/provision/provisioning/PrioritizableNode.java)28
-rw-r--r--node-repository/src/main/java/com/yahoo/vespa/hosted/provision/provisioning/NodePrioritizer.java38
-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.java1
-rw-r--r--node-repository/src/main/java/com/yahoo/vespa/hosted/provision/restapi/NodesV2ApiHandler.java9
-rw-r--r--node-repository/src/test/java/com/yahoo/vespa/hosted/provision/autoscale/AutoscalingTester.java7
-rw-r--r--node-repository/src/test/java/com/yahoo/vespa/hosted/provision/autoscale/NodeMetricsDbTest.java10
-rw-r--r--node-repository/src/test/java/com/yahoo/vespa/hosted/provision/autoscale/NodeMetricsFetcherTest.java3
-rw-r--r--node-repository/src/test/java/com/yahoo/vespa/hosted/provision/maintenance/AutoscalingMaintainerTest.java2
-rw-r--r--node-repository/src/test/java/com/yahoo/vespa/hosted/provision/maintenance/DynamicProvisioningMaintainerTest.java5
-rw-r--r--node-repository/src/test/java/com/yahoo/vespa/hosted/provision/maintenance/InactiveAndFailedExpirerTest.java6
-rw-r--r--node-repository/src/test/java/com/yahoo/vespa/hosted/provision/maintenance/MetricsReporterTest.java2
-rw-r--r--node-repository/src/test/java/com/yahoo/vespa/hosted/provision/maintenance/OsUpgradeActivatorTest.java8
-rw-r--r--node-repository/src/test/java/com/yahoo/vespa/hosted/provision/maintenance/RebalancerTest.java10
-rw-r--r--node-repository/src/test/java/com/yahoo/vespa/hosted/provision/maintenance/ScalingSuggestionsMaintainerTest.java2
-rw-r--r--node-repository/src/test/java/com/yahoo/vespa/hosted/provision/node/IPTest.java2
-rw-r--r--node-repository/src/test/java/com/yahoo/vespa/hosted/provision/os/OsVersionsTest.java17
-rw-r--r--node-repository/src/test/java/com/yahoo/vespa/hosted/provision/persistence/NodeSerializerTest.java29
-rw-r--r--node-repository/src/test/java/com/yahoo/vespa/hosted/provision/provisioning/AclProvisioningTest.java2
-rw-r--r--node-repository/src/test/java/com/yahoo/vespa/hosted/provision/provisioning/AllocationSimulator.java3
-rw-r--r--node-repository/src/test/java/com/yahoo/vespa/hosted/provision/provisioning/DockerImagesTest.java2
-rw-r--r--node-repository/src/test/java/com/yahoo/vespa/hosted/provision/provisioning/DockerProvisioningCompleteHostCalculatorTest.java2
-rw-r--r--node-repository/src/test/java/com/yahoo/vespa/hosted/provision/provisioning/DockerProvisioningTest.java13
-rw-r--r--node-repository/src/test/java/com/yahoo/vespa/hosted/provision/provisioning/DynamicDockerAllocationTest.java28
-rw-r--r--node-repository/src/test/java/com/yahoo/vespa/hosted/provision/provisioning/DynamicDockerProvisionTest.java17
-rw-r--r--node-repository/src/test/java/com/yahoo/vespa/hosted/provision/provisioning/HostCapacityTest.java8
-rw-r--r--node-repository/src/test/java/com/yahoo/vespa/hosted/provision/provisioning/MultigroupProvisioningTest.java6
-rw-r--r--node-repository/src/test/java/com/yahoo/vespa/hosted/provision/provisioning/NodeCandidateTest.java (renamed from node-repository/src/test/java/com/yahoo/vespa/hosted/provision/provisioning/PrioritizableNodeTest.java)58
-rw-r--r--node-repository/src/test/java/com/yahoo/vespa/hosted/provision/provisioning/ProvisioningTest.java64
-rw-r--r--node-repository/src/test/java/com/yahoo/vespa/hosted/provision/provisioning/ProvisioningTester.java22
-rw-r--r--node-repository/src/test/java/com/yahoo/vespa/hosted/provision/provisioning/VirtualNodeProvisioningTest.java14
-rw-r--r--node-repository/src/test/java/com/yahoo/vespa/hosted/provision/restapi/NodesV2ApiTest.java37
39 files changed, 379 insertions, 309 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 b08dc6bbaf2..3b3711d1081 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
@@ -43,6 +43,7 @@ public final class Node {
private final Reports reports;
private final Optional<String> modelName;
private final Optional<TenantName> reservedTo;
+ private final Optional<String> switchHostname;
/** Record of the last event of each type happening to this node */
private final History history;
@@ -54,20 +55,21 @@ public final class Node {
public static Node createDockerNode(Set<String> ipAddresses, String hostname, String parentHostname, NodeResources resources, NodeType type) {
return new Node("fake-" + hostname, new IP.Config(ipAddresses, Set.of()), hostname, Optional.of(parentHostname),
new Flavor(resources), Status.initial(), State.reserved,
- Optional.empty(), History.empty(), type, new Reports(), Optional.empty(), Optional.empty());
+ Optional.empty(), History.empty(), type, new Reports(), Optional.empty(), Optional.empty(),
+ Optional.empty());
}
/** Creates a node in the initial state (provisioned) */
public static Node create(String openStackId, IP.Config ipConfig, String hostname, Optional<String> parentHostname,
- Optional<String> modelName, Flavor flavor, Optional<TenantName> reservedTo, NodeType type) {
+ Optional<String> modelName, Flavor flavor, Optional<TenantName> reservedTo, NodeType type, Optional<String> switchHostname) {
return new Node(openStackId, ipConfig, hostname, parentHostname, flavor, Status.initial(), State.provisioned,
- Optional.empty(), History.empty(), type, new Reports(), modelName, reservedTo);
+ Optional.empty(), History.empty(), type, new Reports(), modelName, reservedTo, switchHostname);
}
/** Creates a node. See also the {@code create} helper methods. */
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) {
+ Reports reports, Optional<String> modelName, Optional<TenantName> reservedTo, 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");
@@ -81,6 +83,7 @@ public final class Node {
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.switchHostname = requireNonEmptyString(switchHostname, "switchHostname cannot be null");
if (state == State.active)
requireNonEmpty(ipConfig.primary(), "Active node " + hostname + " must have at least one valid IP address");
@@ -88,6 +91,7 @@ public final class Node {
if (parentHostname.isPresent()) {
if (!ipConfig.pool().asSet().isEmpty()) throw new IllegalArgumentException("A child node cannot have an IP address pool");
if (modelName.isPresent()) throw new IllegalArgumentException("A child node cannot have model name set");
+ if (switchHostname.isPresent()) throw new IllegalArgumentException("A child node cannot have switch hostname set");
}
if (type != NodeType.host && reservedTo.isPresent())
@@ -151,7 +155,7 @@ public final class Node {
/** Returns all the reports on this node. */
public Reports reports() { return reports; }
- /** Returns the hardware model of this node */
+ /** Returns the hardware model of this node, if any */
public Optional<String> modelName() { return modelName; }
/**
@@ -160,6 +164,11 @@ public final class Node {
*/
public Optional<TenantName> reservedTo() { return reservedTo; }
+ /** Returns the hostname of the switch this node is connected to, if any */
+ public Optional<String> switchHostname() {
+ return switchHostname;
+ }
+
/**
* Returns a copy of this node with wantToRetire and wantToDeprovision set to the given values and updated history.
*
@@ -217,42 +226,44 @@ public final class Node {
/** 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);
+ return new Node(id, ipConfig, hostname, parentHostname, flavor, status, state, allocation, history, type,
+ reports, modelName, reservedTo, 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);
+ return new Node(id, ipConfig, hostname, parentHostname, flavor, status, state, allocation, history, type,
+ reports, modelName, reservedTo, switchHostname);
}
/** Returns a node with the flavor assigned to the given value */
public Node with(Flavor flavor) {
- return new Node(id, ipConfig, hostname, parentHostname, flavor, status, state,
- allocation, history, type, reports, modelName, reservedTo);
+ return new Node(id, ipConfig, hostname, parentHostname, flavor, status, state, allocation, history, type,
+ reports, modelName, reservedTo, 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);
+ allocation, history, type, reports, modelName, reservedTo, 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);
+ allocation, history, type, reports, modelName, reservedTo, 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);
+ allocation, history, type, reports, Optional.of(modelName), reservedTo, 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);
+ allocation, history, type, reports, Optional.empty(), reservedTo, switchHostname);
}
/** Returns a copy of this with a history record saying it was detected to be down at this instant */
@@ -278,39 +289,50 @@ public final class Node {
*/
public Node with(Allocation allocation) {
return new Node(id, ipConfig, hostname, parentHostname, flavor, status, state,
- Optional.of(allocation), history, type, reports, modelName, reservedTo);
+ Optional.of(allocation), history, type, reports, modelName, reservedTo, 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);
+ Optional.empty(), history, type, reports, modelName, reservedTo, 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);
+ allocation, history, type, reports, modelName, reservedTo, 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);
+ allocation, history, type, reports, modelName, reservedTo, 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));
+ allocation, history, type, reports, modelName, Optional.of(tenant), 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());
+ allocation, history, type, reports, modelName, Optional.empty(), 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, Optional.ofNullable(switchHostname));
+ }
+
+ /** Returns a copy of this node with switch hostname unset */
+ public Node withoutSwitchHostname() {
+ return withSwitchHostname(null);
}
/** Returns a copy of this node with the current reboot generation set to the given number at the given instant */
@@ -343,12 +365,12 @@ public final class Node {
/** 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);
+ allocation, history, type, reports, modelName, reservedTo, switchHostname);
}
public Node with(Reports reports) {
return new Node(id, ipConfig, hostname, parentHostname, flavor, status, state,
- allocation, history, type, reports, modelName, reservedTo);
+ allocation, history, type, reports, modelName, reservedTo, switchHostname);
}
private static Optional<String> requireNonEmptyString(Optional<String> value, String message) {
diff --git a/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/NodeRepository.java b/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/NodeRepository.java
index 4ec7ddd04c4..8523db7a970 100644
--- a/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/NodeRepository.java
+++ b/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/NodeRepository.java
@@ -407,7 +407,7 @@ public class NodeRepository extends AbstractComponent {
Flavor flavor, Optional<TenantName> reservedTo, NodeType type) {
if (ipConfig.primary().isEmpty()) // TODO: Remove this. Only test code hits this path
ipConfig = ipConfig.with(nameResolver.getAllByNameOrThrow(hostname));
- return Node.create(openStackId, ipConfig, hostname, parentHostname, Optional.empty(), flavor, reservedTo, type);
+ return Node.create(openStackId, ipConfig, hostname, parentHostname, Optional.empty(), flavor, reservedTo, type, Optional.empty());
}
public Node createNode(String openStackId, String hostname, Optional<String> parentHostname, Flavor flavor, NodeType type) {
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 cc62ae67e84..504854108b6 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
@@ -216,7 +216,8 @@ public class CuratorDatabaseClient {
toState,
toState.isAllocated() ? node.allocation() : Optional.empty(),
node.history().recordStateTransition(node.state(), toState, agent, clock.instant()),
- node.type(), node.reports(), node.modelName(), node.reservedTo());
+ node.type(), node.reports(), node.modelName(), node.reservedTo(),
+ 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 5a3584b6ff4..0ce81e49bda 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
@@ -79,6 +79,7 @@ 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 switchHostnameKey = "switchHostname";
// Node resource fields
private static final String flavorKey = "flavor";
@@ -143,6 +144,7 @@ public class NodeSerializer {
node.status().osVersion().current().ifPresent(version -> object.setString(osVersionKey, version.toString()));
node.status().osVersion().wanted().ifPresent(version -> object.setString(wantedOsVersionKey, version.toFullString()));
node.status().firmwareVerifiedAt().ifPresent(instant -> object.setLong(firmwareCheckKey, instant.toEpochMilli()));
+ node.switchHostname().ifPresent(switchHostname -> object.setString(switchHostnameKey, switchHostname));
node.reports().toSlime(object, reportsKey);
node.modelName().ifPresent(modelName -> object.setString(modelNameKey, modelName));
node.reservedTo().ifPresent(tenant -> object.setString(reservedToKey, tenant.value()));
@@ -212,7 +214,8 @@ public class NodeSerializer {
nodeTypeFromString(object.field(nodeTypeKey).asString()),
Reports.fromSlime(object.field(reportsKey)),
modelNameFromSlime(object),
- reservedToFromSlime(object.field(reservedToKey)));
+ reservedToFromSlime(object.field(reservedToKey)),
+ switchHostnameFromSlime(object.field(switchHostnameKey)));
}
private Status statusFromSlime(Inspector object) {
@@ -227,6 +230,11 @@ public class NodeSerializer {
instantFromSlime(object.field(firmwareCheckKey)));
}
+ private Optional<String> switchHostnameFromSlime(Inspector field) {
+ if (!field.valid()) return Optional.empty();
+ return Optional.of(field.asString());
+ }
+
private Flavor flavorFromSlime(Inspector object) {
Inspector resources = object.field(resourcesKey);
diff --git a/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/provisioning/GroupPreparer.java b/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/provisioning/GroupPreparer.java
index d3faa4d80f5..75f3c892571 100644
--- a/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/provisioning/GroupPreparer.java
+++ b/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/provisioning/GroupPreparer.java
@@ -99,13 +99,13 @@ public class GroupPreparer {
nodeRepository.addNodes(hosts, Agent.application);
// Offer the nodes on the newly provisioned hosts, this should be enough to cover the deficit
- List<PrioritizableNode> nodes = provisionedHosts.stream()
- .map(provisionedHost -> new PrioritizableNode.Builder(provisionedHost.generateNode())
- .parent(provisionedHost.generateHost())
- .newNode(true)
- .build())
- .collect(Collectors.toList());
- allocation.offer(nodes);
+ List<NodeCandidate> candidates = provisionedHosts.stream()
+ .map(provisionedHost -> new NodeCandidate.Builder(provisionedHost.generateNode())
+ .parent(provisionedHost.generateHost())
+ .newNode(true)
+ .build())
+ .collect(Collectors.toList());
+ allocation.offer(candidates);
}
if (! allocation.fulfilled() && requestedNodes.canFail())
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 a37da10f5f0..b07ce786685 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
@@ -21,8 +21,9 @@ import java.util.Collection;
import java.util.Comparator;
import java.util.EnumSet;
import java.util.HashSet;
-import java.util.LinkedHashSet;
+import java.util.LinkedHashMap;
import java.util.List;
+import java.util.Map;
import java.util.Optional;
import java.util.Set;
import java.util.function.Predicate;
@@ -48,8 +49,8 @@ class NodeAllocation {
/** The requested nodes of this list */
private final NodeSpec requestedNodes;
- /** The nodes this has accepted so far */
- private final Set<PrioritizableNode> nodes = new LinkedHashSet<>();
+ /** The node candidates this has accepted so far, keyed on hostname */
+ private final Map<String, NodeCandidate> nodes = new LinkedHashMap<>();
/** The number of already allocated nodes accepted and not retired */
private int accepted = 0;
@@ -98,36 +99,36 @@ class NodeAllocation {
* @param nodesPrioritized the nodes which are potentially on offer. These may belong to a different application etc.
* @return the subset of offeredNodes which was accepted, with the correct allocation assigned
*/
- List<Node> offer(List<PrioritizableNode> nodesPrioritized) {
+ List<Node> offer(List<NodeCandidate> nodesPrioritized) {
List<Node> accepted = new ArrayList<>();
- for (PrioritizableNode node : nodesPrioritized) {
- Node offered = node.node;
+ for (NodeCandidate candidate : nodesPrioritized) {
+ Node offered = candidate.node;
if (offered.allocation().isPresent()) {
Allocation allocation = offered.allocation().get();
ClusterMembership membership = allocation.membership();
if ( ! allocation.owner().equals(application)) continue; // wrong application
if ( ! membership.cluster().satisfies(cluster)) continue; // wrong cluster id/type
- if ((! node.isSurplusNode || saturated()) && ! membership.cluster().group().equals(cluster.group())) continue; // wrong group and we can't or have no reason to change it
+ if ((! candidate.isSurplusNode || saturated()) && ! membership.cluster().group().equals(cluster.group())) continue; // wrong group and we can't or have no reason to change it
if ( offered.state() == Node.State.active && allocation.isRemovable()) continue; // don't accept; causes removal
if ( indexes.contains(membership.index())) continue; // duplicate index (just to be sure)
boolean resizeable = false;
boolean acceptToRetire = false;
if (requestedNodes.considerRetiring()) {
- resizeable = node.isResizable;
- acceptToRetire = acceptToRetire(node);
+ resizeable = candidate.isResizable;
+ acceptToRetire = acceptToRetire(candidate);
}
- if ((! saturated() && hasCompatibleFlavor(node) && requestedNodes.acceptable(offered)) || acceptToRetire)
- accepted.add(acceptNode(node, shouldRetire(node), resizeable));
+ if ((! saturated() && hasCompatibleFlavor(candidate) && requestedNodes.acceptable(offered)) || acceptToRetire)
+ accepted.add(acceptNode(candidate, shouldRetire(candidate), resizeable));
}
- else if (! saturated() && hasCompatibleFlavor(node)) {
+ else if (! saturated() && hasCompatibleFlavor(candidate)) {
if ( ! nodeResourceLimits.isWithinRealLimits(offered, cluster)) {
++rejectedDueToInsufficientRealResources;
continue;
}
- if ( violatesParentHostPolicy(this.nodes, offered)) {
+ if ( violatesParentHostPolicy(offered)) {
++rejectedDueToClashingParentHost;
continue;
}
@@ -142,29 +143,29 @@ class NodeAllocation {
if (offered.status().wantToRetire()) {
continue;
}
- node.node = offered.allocate(application,
- ClusterMembership.from(cluster, highestIndex.add(1)),
- requestedNodes.resources().orElse(node.node.resources()),
- nodeRepository.clock().instant());
- accepted.add(acceptNode(node, false, false));
+ candidate = candidate.withNode(offered.allocate(application,
+ ClusterMembership.from(cluster, highestIndex.add(1)),
+ requestedNodes.resources().orElse(candidate.node.resources()),
+ nodeRepository.clock().instant()));
+ accepted.add(acceptNode(candidate, false, false));
}
}
return accepted;
}
- private boolean shouldRetire(PrioritizableNode node) {
+ private boolean shouldRetire(NodeCandidate candidate) {
if ( ! requestedNodes.considerRetiring()) return false;
- if ( ! nodeResourceLimits.isWithinRealLimits(node.node, cluster)) return true;
- if (violatesParentHostPolicy(this.nodes, node.node)) return true;
- if ( ! hasCompatibleFlavor(node)) return true;
- if (node.node.status().wantToRetire()) return true;
- if (requestedNodes.isExclusive() && ! hostsOnly(application, node.node.parentHostname())) return true;
+ if ( ! nodeResourceLimits.isWithinRealLimits(candidate.node, cluster)) return true;
+ if (violatesParentHostPolicy(candidate.node)) return true;
+ if ( ! hasCompatibleFlavor(candidate)) return true;
+ if (candidate.node.status().wantToRetire()) return true;
+ if (requestedNodes.isExclusive() && ! hostsOnly(application, candidate.node.parentHostname())) return true;
return false;
}
- private boolean violatesParentHostPolicy(Collection<PrioritizableNode> accepted, Node offered) {
- return checkForClashingParentHost() && offeredNodeHasParentHostnameAlreadyAccepted(accepted, offered);
+ private boolean violatesParentHostPolicy(Node offered) {
+ return checkForClashingParentHost() && offeredNodeHasParentHostnameAlreadyAccepted(offered);
}
private boolean checkForClashingParentHost() {
@@ -173,8 +174,8 @@ class NodeAllocation {
! application.instance().isTester();
}
- private boolean offeredNodeHasParentHostnameAlreadyAccepted(Collection<PrioritizableNode> accepted, Node offered) {
- for (PrioritizableNode acceptedNode : accepted) {
+ private boolean offeredNodeHasParentHostnameAlreadyAccepted(Node offered) {
+ for (NodeCandidate acceptedNode : nodes.values()) {
if (acceptedNode.node.parentHostname().isPresent() && offered.parentHostname().isPresent() &&
acceptedNode.node.parentHostname().get().equals(offered.parentHostname().get())) {
return true;
@@ -230,21 +231,21 @@ class NodeAllocation {
* initialized. (In the other case, where a container node is not desired because we have enough nodes we
* do want to remove it immediately to get immediate feedback on how the size reduction works out.)
*/
- private boolean acceptToRetire(PrioritizableNode node) {
- if (node.node.state() != Node.State.active) return false;
- if (! node.node.allocation().get().membership().cluster().group().equals(cluster.group())) return false;
- if (node.node.allocation().get().membership().retired()) return true; // don't second-guess if already retired
+ private boolean acceptToRetire(NodeCandidate candidate) {
+ if (candidate.node.state() != Node.State.active) return false;
+ if (! candidate.node.allocation().get().membership().cluster().group().equals(cluster.group())) return false;
+ if (candidate.node.allocation().get().membership().retired()) return true; // don't second-guess if already retired
return cluster.type().isContent() ||
- (cluster.type() == ClusterSpec.Type.container && !hasCompatibleFlavor(node));
+ (cluster.type() == ClusterSpec.Type.container && !hasCompatibleFlavor(candidate));
}
- private boolean hasCompatibleFlavor(PrioritizableNode node) {
- return requestedNodes.isCompatible(node.node.flavor(), nodeRepository.flavors()) || node.isResizable;
+ private boolean hasCompatibleFlavor(NodeCandidate candidate) {
+ return requestedNodes.isCompatible(candidate.node.flavor(), nodeRepository.flavors()) || candidate.isResizable;
}
- private Node acceptNode(PrioritizableNode prioritizableNode, boolean wantToRetire, boolean resizeable) {
- Node node = prioritizableNode.node;
+ private Node acceptNode(NodeCandidate candidate, boolean wantToRetire, boolean resizeable) {
+ Node node = candidate.node;
if (node.allocation().isPresent()) // Record the currently requested resources
node = node.with(node.allocation().get().withRequestedResources(requestedNodes.resources().orElse(node.resources())));
@@ -271,13 +272,17 @@ class NodeAllocation {
// group may be different
node = setCluster(cluster, node);
}
- prioritizableNode.node = node;
+ candidate = candidate.withNode(node);
indexes.add(node.allocation().get().membership().index());
highestIndex.set(Math.max(highestIndex.get(), node.allocation().get().membership().index()));
- nodes.add(prioritizableNode);
+ put(candidate);
return node;
}
+ private void put(NodeCandidate candidate) {
+ nodes.put(candidate.node.hostname(), candidate);
+ }
+
private Node resize(Node node) {
NodeResources hostResources = allNodes.parentOf(node).get().flavor().resources();
return node.with(new Flavor(requestedNodes.resources().get()
@@ -323,36 +328,39 @@ class NodeAllocation {
* @return the final list of nodes
*/
List<Node> finalNodes() {
- int currentRetiredCount = (int) nodes.stream().filter(node -> node.node.allocation().get().membership().retired()).count();
+ int currentRetiredCount = (int) nodes.values().stream().filter(node -> node.node.allocation().get().membership().retired()).count();
int deltaRetiredCount = requestedNodes.idealRetiredCount(nodes.size(), currentRetiredCount) - currentRetiredCount;
if (deltaRetiredCount > 0) { // retire until deltaRetiredCount is 0
- for (PrioritizableNode node : byRetiringPriority(nodes)) {
- if ( ! node.node.allocation().get().membership().retired() && node.node.state() == Node.State.active) {
- node.node = node.node.retire(Agent.application, nodeRepository.clock().instant());
+ for (NodeCandidate candidate : byRetiringPriority(nodes.values())) {
+ if ( ! candidate.node.allocation().get().membership().retired() && candidate.node.state() == Node.State.active) {
+ candidate = candidate.withNode(candidate.node.retire(Agent.application, nodeRepository.clock().instant()));
+ put(candidate);
if (--deltaRetiredCount == 0) break;
}
}
}
else if (deltaRetiredCount < 0) { // unretire until deltaRetiredCount is 0
- for (PrioritizableNode node : byUnretiringPriority(nodes)) {
- if ( node.node.allocation().get().membership().retired() && hasCompatibleFlavor(node) ) {
- if (node.isResizable)
- node.node = resize(node.node);
- node.node = node.node.unretire();
+ for (NodeCandidate candidate : byUnretiringPriority(nodes.values())) {
+ if ( candidate.node.allocation().get().membership().retired() && hasCompatibleFlavor(candidate) ) {
+ if (candidate.isResizable)
+ candidate = candidate.withNode(resize(candidate.node));
+ candidate = candidate.withNode(candidate.node.unretire());
+ put(candidate);
if (++deltaRetiredCount == 0) break;
}
}
}
- for (PrioritizableNode node : nodes) {
+ for (NodeCandidate candidate : nodes.values()) {
// Set whether the node is exclusive
- Allocation allocation = node.node.allocation().get();
- node.node = node.node.with(allocation.with(allocation.membership()
- .with(allocation.membership().cluster().exclusive(requestedNodes.isExclusive()))));
+ Allocation allocation = candidate.node.allocation().get();
+ candidate = candidate.withNode(candidate.node.with(allocation.with(allocation.membership()
+ .with(allocation.membership().cluster().exclusive(requestedNodes.isExclusive())))));
+ put(candidate);
}
- return nodes.stream().map(n -> n.node).collect(Collectors.toList());
+ return nodes.values().stream().map(n -> n.node).collect(Collectors.toList());
}
List<Node> reservableNodes() {
@@ -361,32 +369,28 @@ class NodeAllocation {
return nodesFilter(n -> !n.isNewNode && reservableStates.contains(n.node.state()));
}
- List<Node> surplusNodes() {
- return nodesFilter(n -> n.isSurplusNode);
- }
-
List<Node> newNodes() {
return nodesFilter(n -> n.isNewNode);
}
- private List<Node> nodesFilter(Predicate<PrioritizableNode> predicate) {
- return nodes.stream()
+ private List<Node> nodesFilter(Predicate<NodeCandidate> predicate) {
+ return nodes.values().stream()
.filter(predicate)
.map(n -> n.node)
.collect(Collectors.toList());
}
/** Prefer to retire nodes we want the least */
- private List<PrioritizableNode> byRetiringPriority(Set<PrioritizableNode> nodes) {
- return nodes.stream().sorted(Comparator.reverseOrder()).collect(Collectors.toList());
+ private List<NodeCandidate> byRetiringPriority(Collection<NodeCandidate> candidates) {
+ return candidates.stream().sorted(Comparator.reverseOrder()).collect(Collectors.toList());
}
/** Prefer to unretire nodes we don't want to retire, and otherwise those with lower index */
- private List<PrioritizableNode> byUnretiringPriority(Set<PrioritizableNode> nodes) {
- return nodes.stream()
- .sorted(Comparator.comparing((PrioritizableNode n) -> n.node.status().wantToRetire())
- .thenComparing(n -> n.node.allocation().get().membership().index()))
- .collect(Collectors.toList());
+ private List<NodeCandidate> byUnretiringPriority(Collection<NodeCandidate> candidates) {
+ return candidates.stream()
+ .sorted(Comparator.comparing((NodeCandidate n) -> n.node.status().wantToRetire())
+ .thenComparing(n -> n.node.allocation().get().membership().index()))
+ .collect(Collectors.toList());
}
public String outOfCapacityDetails() {
diff --git a/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/provisioning/PrioritizableNode.java b/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/provisioning/NodeCandidate.java
index 9955d75a742..651ab9b1e09 100644
--- a/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/provisioning/PrioritizableNode.java
+++ b/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/provisioning/NodeCandidate.java
@@ -8,11 +8,11 @@ import java.util.List;
import java.util.Optional;
/**
- * A node with additional information required to prioritize it for allocation.
+ * A node candidate containing the details required to prioritize it for allocation. This is immutable.
*
* @author smorgrav
*/
-class PrioritizableNode implements Comparable<PrioritizableNode> {
+class NodeCandidate implements Comparable<NodeCandidate> {
/** List of host states ordered by preference (ascending) */
private static final List<Node.State> HOST_STATE_PRIORITY =
@@ -21,8 +21,7 @@ class PrioritizableNode implements Comparable<PrioritizableNode> {
private static final NodeResources zeroResources =
new NodeResources(0, 0, 0, 0, NodeResources.DiskSpeed.any, NodeResources.StorageType.any);
- // TODO: Make immutable
- Node node;
+ final Node node;
/** The free capacity on the parent of this node, before adding this node to it */
private final NodeResources freeParentCapacity;
@@ -42,7 +41,7 @@ class PrioritizableNode implements Comparable<PrioritizableNode> {
/** This node can be resized to the new NodeResources */
final boolean isResizable;
- PrioritizableNode(Node node, NodeResources freeParentCapacity, Optional<Node> parent, boolean violatesSpares, boolean isSurplusNode, boolean isNewNode, boolean isResizeable) {
+ NodeCandidate(Node node, NodeResources freeParentCapacity, Optional<Node> parent, boolean violatesSpares, boolean isSurplusNode, boolean isNewNode, boolean isResizeable) {
if (isResizeable && isNewNode)
throw new IllegalArgumentException("A new node cannot be resizable");
@@ -56,12 +55,12 @@ class PrioritizableNode implements Comparable<PrioritizableNode> {
}
/**
- * Compares two prioritizable nodes
+ * Compare this candidate to another
*
* @return negative if first priority is higher than second node
*/
@Override
- public int compareTo(PrioritizableNode other) {
+ public int compareTo(NodeCandidate other) {
// First always pick nodes without violation above nodes with violations
if (!this.violatesSpares && other.violatesSpares) return -1;
if (!other.violatesSpares && this.violatesSpares) return 1;
@@ -138,7 +137,12 @@ class PrioritizableNode implements Comparable<PrioritizableNode> {
/** Returns the allocation skew of the parent of this after adding this node to it */
double skewWithThis() { return skewWith(node.resources()); }
- private boolean lessThanHalfTheHost(PrioritizableNode node) {
+ /** Returns a copy of this with node set to given value */
+ NodeCandidate withNode(Node node) {
+ return new NodeCandidate(node, freeParentCapacity, parent, violatesSpares, isSurplusNode, isNewNode, isResizable);
+ }
+
+ private boolean lessThanHalfTheHost(NodeCandidate node) {
var n = node.node.resources();
var h = node.parent.get().resources();
if (h.vcpu() < n.vcpu() * 2) return false;
@@ -172,8 +176,8 @@ class PrioritizableNode implements Comparable<PrioritizableNode> {
@Override
public boolean equals(Object other) {
if (other == this) return true;
- if ( ! (other instanceof PrioritizableNode)) return false;
- return this.node.equals(((PrioritizableNode)other).node);
+ if ( ! (other instanceof NodeCandidate)) return false;
+ return this.node.equals(((NodeCandidate)other).node);
}
static class Builder {
@@ -222,8 +226,8 @@ class PrioritizableNode implements Comparable<PrioritizableNode> {
return this;
}
- PrioritizableNode build() {
- return new PrioritizableNode(node, freeParentCapacity, parent, violatesSpares, isSurplusNode, isNewNode, isResizable);
+ NodeCandidate build() {
+ return new NodeCandidate(node, freeParentCapacity, parent, violatesSpares, isSurplusNode, isNewNode, isResizable);
}
}
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 3dc7eefa277..226079e43fe 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
@@ -5,29 +5,28 @@ import com.yahoo.config.provision.ApplicationId;
import com.yahoo.config.provision.ClusterSpec;
import com.yahoo.config.provision.NodeResources;
import com.yahoo.config.provision.NodeType;
-
-import java.util.ArrayList;
-import java.util.logging.Level;
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.NodeRepository;
import com.yahoo.vespa.hosted.provision.node.IP;
+import java.util.ArrayList;
import java.util.EnumSet;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.Set;
+import java.util.logging.Level;
import java.util.logging.Logger;
import java.util.stream.Collectors;
/**
* Builds up data structures necessary for node prioritization. It wraps each node
- * up in a PrioritizableNode object with attributes used in sorting.
+ * up in a {@link NodeCandidate} object with attributes used in sorting.
*
- * The actual sorting/prioritization is implemented in the PrioritizableNode class as a compare method.
+ * The prioritization logic is implemented by {@link NodeCandidate}.
*
* @author smorgrav
*/
@@ -35,7 +34,7 @@ public class NodePrioritizer {
private final static Logger log = Logger.getLogger(NodePrioritizer.class.getName());
- private final Map<Node, PrioritizableNode> nodes = new HashMap<>();
+ private final Map<Node, NodeCandidate> nodes = new HashMap<>();
private final LockedNodeList allNodes;
private final HostCapacity capacity;
private final NodeSpec requestedNodes;
@@ -81,8 +80,8 @@ public class NodePrioritizer {
this.isDocker = resources(requestedNodes) != null;
}
- /** Returns the list of nodes sorted by PrioritizableNode::compare */
- List<PrioritizableNode> prioritize() {
+ /** Returns the list of nodes sorted by {@link NodeCandidate#compareTo(NodeCandidate)} */
+ List<NodeCandidate> prioritize() {
return nodes.values().stream().sorted().collect(Collectors.toList());
}
@@ -92,7 +91,7 @@ public class NodePrioritizer {
*/
void addSurplusNodes(List<Node> surplusNodes) {
for (Node node : surplusNodes) {
- PrioritizableNode nodePri = toPrioritizable(node, true, false);
+ NodeCandidate nodePri = candidateFrom(node, true, false);
if (!nodePri.violatesSpares || isAllocatingForReplacement) {
nodes.put(node, nodePri);
}
@@ -143,7 +142,7 @@ public class NodePrioritizer {
resources(requestedNodes).with(host.flavor().resources().diskSpeed())
.with(host.flavor().resources().storageType()),
NodeType.tenant);
- PrioritizableNode nodePri = toPrioritizable(newNode, false, true);
+ NodeCandidate nodePri = candidateFrom(newNode, false, true);
if ( ! nodePri.violatesSpares || isAllocatingForReplacement) {
log.log(Level.FINE, "Adding new Docker node " + newNode);
nodes.put(newNode, nodePri);
@@ -159,7 +158,7 @@ public class NodePrioritizer {
.filter(node -> legalStates.contains(node.state()))
.filter(node -> node.allocation().isPresent())
.filter(node -> node.allocation().get().owner().equals(application))
- .map(node -> toPrioritizable(node, false, false))
+ .map(node -> candidateFrom(node, false, false))
.forEach(prioritizableNode -> nodes.put(prioritizableNode.node, prioritizableNode));
}
@@ -168,20 +167,17 @@ public class NodePrioritizer {
allNodes.asList().stream()
.filter(node -> node.type() == requestedNodes.type())
.filter(node -> node.state() == Node.State.ready)
- .map(node -> toPrioritizable(node, false, false))
+ .map(node -> candidateFrom(node, false, false))
.filter(n -> !n.violatesSpares || isAllocatingForReplacement)
- .forEach(prioritizableNode -> nodes.put(prioritizableNode.node, prioritizableNode));
+ .forEach(candidate -> nodes.put(candidate.node, candidate));
}
- public List<PrioritizableNode> nodes() { return new ArrayList<>(nodes.values()); }
+ public List<NodeCandidate> nodes() { return new ArrayList<>(nodes.values()); }
- /**
- * Convert a list of nodes to a list of node priorities. This includes finding, calculating
- * parameters to the priority sorting procedure.
- */
- private PrioritizableNode toPrioritizable(Node node, boolean isSurplusNode, boolean isNewNode) {
- PrioritizableNode.Builder builder = new PrioritizableNode.Builder(node).surplusNode(isSurplusNode)
- .newNode(isNewNode);
+ /** Create a candidate from given node */
+ private NodeCandidate candidateFrom(Node node, boolean isSurplusNode, boolean isNewNode) {
+ NodeCandidate.Builder builder = new NodeCandidate.Builder(node).surplusNode(isSurplusNode)
+ .newNode(isNewNode);
allNodes.parentOf(node).ifPresent(parent -> {
NodeResources parentCapacity = capacity.freeCapacityOf(parent, false);
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 151fcb4233f..298404a4cb4 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
@@ -38,7 +38,7 @@ public class ProvisionedHost {
/** Generate {@link Node} instance representing the provisioned physical host */
public Node generateHost() {
- var node = Node.create(id, IP.Config.EMPTY, hostHostname, Optional.empty(), Optional.empty(), hostFlavor, Optional.empty(), NodeType.host);
+ var node = Node.create(id, IP.Config.EMPTY, hostHostname, Optional.empty(), Optional.empty(), hostFlavor, Optional.empty(), NodeType.host, Optional.empty());
return node.with(node.status().withOsVersion(OsVersion.EMPTY.withCurrent(Optional.of(osVersion))));
}
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 19276a81ef8..834bed00bd0 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
@@ -149,6 +149,8 @@ public class NodePatcher {
return patchRequiredDiskSpeed(node, asString(value));
case "reservedTo":
return value.type() == Type.NIX ? node.withoutReservedTo() : node.withReservedTo(TenantName.from(value.asString()));
+ case "switchHostname":
+ return value.type() == Type.NIX ? node.withoutSwitchHostname() : node.withSwitchHostname(value.asString());
default :
throw new IllegalArgumentException("Could not apply field '" + name + "' on a node: No such modifiable field");
}
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 8e3ae6358df..0137bee5fbd 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
@@ -189,6 +189,7 @@ class NodesResponse extends HttpResponse {
ipAddressesToSlime(node.ipConfig().pool().asSet(), object.setArray("additionalIpAddresses"));
node.reports().toSlime(object, "reports");
node.modelName().ifPresent(modelName -> object.setString("modelName", modelName));
+ node.switchHostname().ifPresent(switchHostname -> object.setString("switchHostname", switchHostname));
}
private void toSlime(ApplicationId id, Cursor object) {
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 5080dafe2a5..1891b9d2f82 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
@@ -261,8 +261,13 @@ public class NodesV2ApiHandler extends LoggingRequestHandler {
modelName,
flavorFromSlime(inspector),
reservedToFromSlime(inspector.field("reservedTo")),
- nodeTypeFromSlime(inspector.field("type"))
- );
+ nodeTypeFromSlime(inspector.field("type")),
+ switchHostnameFromSlime(inspector.field("switchHostname")));
+ }
+
+ private Optional<String> switchHostnameFromSlime(Inspector field) {
+ if (!field.valid()) return Optional.empty();
+ return Optional.of(field.asString());
}
private Flavor flavorFromSlime(Inspector inspector) {
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 0a127eacae1..cc755c01405 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
@@ -32,7 +32,6 @@ import java.util.List;
import java.util.Optional;
import java.util.Set;
-import static com.yahoo.config.provision.NodeResources.StorageType.local;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
@@ -51,7 +50,7 @@ class AutoscalingTester {
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();
+ provisioningTester.activateTenantHosts();
}
public AutoscalingTester(Zone zone, List<Flavor> flavors) {
@@ -87,14 +86,14 @@ class AutoscalingTester {
List<HostSpec> hosts = provisioningTester.prepare(application, cluster, Capacity.from(new ClusterResources(nodes, groups, resources)));
for (HostSpec host : hosts)
makeReady(host.hostname());
- provisioningTester.deployZoneApp();
+ provisioningTester.activateTenantHosts();
provisioningTester.activate(application, hosts);
return hosts;
}
public void makeReady(String hostname) {
Node node = nodeRepository().getNode(hostname).get();
- nodeRepository().write(node.with(new IP.Config(Set.of("::" + 0 + ":0"), Set.of())), nodeRepository().lock(node));
+ provisioningTester.patchNode(node, (n) -> n.with(new IP.Config(Set.of("::" + 0 + ":0"), Set.of())));
Node host = nodeRepository().getNode(node.parentHostname().get()).get();
host = host.with(new IP.Config(Set.of("::" + 0 + ":0"), Set.of("::" + 0 + ":2")));
if (host.state() == Node.State.provisioned)
diff --git a/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/autoscale/NodeMetricsDbTest.java b/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/autoscale/NodeMetricsDbTest.java
index 976aeb2346a..eaad4526591 100644
--- a/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/autoscale/NodeMetricsDbTest.java
+++ b/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/autoscale/NodeMetricsDbTest.java
@@ -6,10 +6,7 @@ import com.yahoo.config.provision.Capacity;
import com.yahoo.config.provision.ClusterResources;
import com.yahoo.config.provision.ClusterSpec;
import com.yahoo.config.provision.NodeResources;
-import com.yahoo.config.provision.NodeType;
import com.yahoo.test.ManualClock;
-import com.yahoo.vespa.hosted.provision.NodeRepository;
-import com.yahoo.vespa.hosted.provision.NodeRepositoryTester;
import com.yahoo.vespa.hosted.provision.provisioning.ProvisioningTester;
import org.junit.Test;
@@ -19,14 +16,17 @@ import java.util.List;
import static org.junit.Assert.assertEquals;
+/**
+ * @author bratseth
+ */
public class NodeMetricsDbTest {
@Test
public void testNodeMetricsDb() {
ProvisioningTester tester = new ProvisioningTester.Builder().build();
- tester.makeReadyHosts(10, new NodeResources(10, 100, 1000, 10)).deployZoneApp();
+ tester.makeReadyHosts(10, new NodeResources(10, 100, 1000, 10))
+ .activateTenantHosts();
ApplicationId app1 = tester.makeApplicationId("app1");
- tester.deployZoneApp();
var hosts =
tester.activate(app1,
ClusterSpec.request(ClusterSpec.Type.container, ClusterSpec.Id.from("test")).vespaVersion("7.0").build(),
diff --git a/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/autoscale/NodeMetricsFetcherTest.java b/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/autoscale/NodeMetricsFetcherTest.java
index d418d818ef3..fea3e8da70a 100644
--- a/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/autoscale/NodeMetricsFetcherTest.java
+++ b/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/autoscale/NodeMetricsFetcherTest.java
@@ -5,7 +5,6 @@ import com.yahoo.config.provision.ApplicationId;
import com.yahoo.config.provision.Capacity;
import com.yahoo.config.provision.ClusterResources;
import com.yahoo.config.provision.NodeResources;
-import com.yahoo.vdslib.state.NodeState;
import com.yahoo.vespa.hosted.provision.Node;
import com.yahoo.vespa.hosted.provision.provisioning.ProvisioningTester;
import com.yahoo.vespa.hosted.provision.testutils.OrchestratorMock;
@@ -29,7 +28,7 @@ public class NodeMetricsFetcherTest {
NodeMetricsFetcher fetcher = new NodeMetricsFetcher(tester.nodeRepository(), orchestrator, httpClient);
tester.makeReadyNodes(4, resources); // Creates (in order) host-1.yahoo.com, host-2.yahoo.com, host-3.yahoo.com, host-4.yahoo.com
- tester.deployZoneApp();
+ tester.activateTenantHosts();
ApplicationId application1 = tester.makeApplicationId();
ApplicationId application2 = tester.makeApplicationId();
diff --git a/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/maintenance/AutoscalingMaintainerTest.java b/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/maintenance/AutoscalingMaintainerTest.java
index 88195cf0ed9..833daebc37a 100644
--- a/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/maintenance/AutoscalingMaintainerTest.java
+++ b/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/maintenance/AutoscalingMaintainerTest.java
@@ -65,7 +65,7 @@ public class AutoscalingMaintainerTest {
assertTrue(deployer.lastDeployTime(app2).isEmpty());
tester.makeReadyNodes(20, "flt", NodeType.host, 8);
- tester.deployZoneApp();
+ tester.activateTenantHosts();
tester.deploy(app1, cluster1, Capacity.from(new ClusterResources(5, 1, new NodeResources(4, 4, 10, 0.1)),
new ClusterResources(5, 1, new NodeResources(4, 4, 10, 0.1)),
diff --git a/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/maintenance/DynamicProvisioningMaintainerTest.java b/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/maintenance/DynamicProvisioningMaintainerTest.java
index 45da1f1d3ee..9978f37e835 100644
--- a/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/maintenance/DynamicProvisioningMaintainerTest.java
+++ b/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/maintenance/DynamicProvisioningMaintainerTest.java
@@ -179,7 +179,7 @@ public class DynamicProvisioningMaintainerTest {
tester.maintainer.maintain(); // Resume provisioning of new hosts
List<Node> provisioned = tester.nodeRepository.list().state(Node.State.provisioned).asList();
tester.nodeRepository.setReady(provisioned, Agent.system, this.getClass().getSimpleName());
- tester.provisioningTester.deployZoneApp();
+ tester.provisioningTester.activateTenantHosts();
// Allocating nodes to a host does not result in provisioning of additional capacity
ApplicationId application = tester.provisioningTester.makeApplicationId();
@@ -273,7 +273,8 @@ public class DynamicProvisioningMaintainerTest {
false));
var ipConfig = new IP.Config(state == Node.State.active ? Set.of("::1") : Set.of(), Set.of());
return new Node("fake-id-" + hostname, ipConfig, hostname, parentHostname, flavor, Status.initial(),
- state, allocation, History.empty(), nodeType, new Reports(), Optional.empty(), Optional.empty());
+ state, allocation, History.empty(), nodeType, new Reports(), Optional.empty(), Optional.empty(),
+ Optional.empty());
}
private long provisionedHostsMatching(NodeResources resources) {
diff --git a/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/maintenance/InactiveAndFailedExpirerTest.java b/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/maintenance/InactiveAndFailedExpirerTest.java
index 3d17cbf0217..056fe041377 100644
--- a/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/maintenance/InactiveAndFailedExpirerTest.java
+++ b/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/maintenance/InactiveAndFailedExpirerTest.java
@@ -133,7 +133,7 @@ public class InactiveAndFailedExpirerTest {
// Flag one node for retirement and redeploy
{
Node toRetire = tester.getNodes(applicationId, Node.State.active).asList().get(0);
- tester.patchNode(toRetire.withWantToRetire(true, Agent.operator, tester.clock().instant()));
+ tester.patchNode(toRetire, (node) -> node.withWantToRetire(true, Agent.operator, tester.clock().instant()));
List<HostSpec> hostSpecs = tester.prepare(applicationId, cluster, Capacity.from(new ClusterResources(2, 1, nodeResources)));
tester.activate(applicationId, new HashSet<>(hostSpecs));
}
@@ -203,9 +203,7 @@ public class InactiveAndFailedExpirerTest {
assertEquals(2, inactiveNodes.size());
// Nodes marked for deprovisioning are moved to parked
- tester.nodeRepository().write(inactiveNodes.stream()
- .map(node -> node.withWantToRetire(true, true, Agent.system, tester.clock().instant()))
- .collect(Collectors.toList()), () -> {});
+ tester.patchNodes(inactiveNodes, (node) -> node.withWantToRetire(true, true, Agent.system, tester.clock().instant()));
tester.advanceTime(Duration.ofMinutes(11));
new InactiveExpirer(tester.nodeRepository(), tester.clock(), Duration.ofMinutes(10), new TestMetric()).run();
assertEquals(2, tester.nodeRepository().getNodes(Node.State.parked).size());
diff --git a/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/maintenance/MetricsReporterTest.java b/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/maintenance/MetricsReporterTest.java
index 20c9d24d1b6..6897a293525 100644
--- a/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/maintenance/MetricsReporterTest.java
+++ b/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/maintenance/MetricsReporterTest.java
@@ -163,7 +163,7 @@ public class MetricsReporterTest {
Set<String> ipAddressPool = Set.of("::2", "::3", "::4", "::5");
Node dockerHost = Node.create("openStackId1", new IP.Config(Set.of("::1"), ipAddressPool), "dockerHost",
- Optional.empty(), Optional.empty(), nodeFlavors.getFlavorOrThrow("host"), Optional.empty(), NodeType.host);
+ Optional.empty(), Optional.empty(), nodeFlavors.getFlavorOrThrow("host"), Optional.empty(), NodeType.host, Optional.empty());
nodeRepository.addNodes(List.of(dockerHost), Agent.system);
nodeRepository.dirtyRecursively("dockerHost", Agent.system, getClass().getSimpleName());
nodeRepository.setReady("dockerHost", Agent.system, getClass().getSimpleName());
diff --git a/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/maintenance/OsUpgradeActivatorTest.java b/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/maintenance/OsUpgradeActivatorTest.java
index 218812f9a3d..f795dbaaa1c 100644
--- a/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/maintenance/OsUpgradeActivatorTest.java
+++ b/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/maintenance/OsUpgradeActivatorTest.java
@@ -97,13 +97,7 @@ public class OsUpgradeActivatorTest {
}
private void completeUpgradeOf(List<Node> nodes) {
- for (var node : nodes) {
- try (var lock = tester.nodeRepository().lock(node)) {
- node = tester.nodeRepository().getNode(node.hostname()).get();
- node = node.with(node.status().withVespaVersion(node.allocation().get().membership().cluster().vespaVersion()));
- tester.nodeRepository().write(node, lock);
- }
- }
+ tester.patchNodes(nodes, (node) -> node.with(node.status().withVespaVersion(node.allocation().get().membership().cluster().vespaVersion())));
}
private Stream<Node> streamUpdatedNodes(List<Node> nodes) {
diff --git a/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/maintenance/RebalancerTest.java b/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/maintenance/RebalancerTest.java
index 05e5b4829e9..65b79c2df04 100644
--- a/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/maintenance/RebalancerTest.java
+++ b/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/maintenance/RebalancerTest.java
@@ -54,7 +54,7 @@ public class RebalancerTest {
// --- Making a more suitable node configuration available causes rebalancing
Node newCpuHost = tester.makeReadyNode("cpu");
- tester.deployZoneApp();
+ tester.activateTenantHosts();
tester.maintain();
assertTrue("Rebalancer retired the node we wanted to move away from", tester.isNodeRetired(cpuSkewedNode));
@@ -74,7 +74,7 @@ public class RebalancerTest {
// --- Adding a more suitable node reconfiguration causes no action as the system is not stable
Node memSkewedNode = tester.getNode(memoryApp);
Node newMemHost = tester.makeReadyNode("mem");
- tester.deployZoneApp();
+ tester.activateTenantHosts();
tester.maintain();
assertFalse("No rebalancing happens because cpuSkewedNode is still retired", tester.isNodeRetired(memSkewedNode));
@@ -117,7 +117,7 @@ public class RebalancerTest {
// --- Making a more suitable node configuration available causes rebalancing
Node newCpuHost = tester.makeReadyNode("cpu");
- tester.deployZoneApp();
+ tester.activateTenantHosts();
tester.deployApp(cpuApp, false /* skip advancing clock after deployment */);
tester.maintain();
@@ -152,7 +152,7 @@ public class RebalancerTest {
deployer = new MockDeployer(tester.provisioner(), tester.clock(), apps);
rebalancer = new Rebalancer(deployer, tester.nodeRepository(), metric, tester.clock(), Duration.ofMinutes(1));
tester.makeReadyNodes(3, "flat", NodeType.host, 8);
- tester.deployZoneApp();
+ tester.activateTenantHosts();
}
void maintain() { rebalancer.maintain(); }
@@ -163,7 +163,7 @@ public class RebalancerTest {
NodeRepository nodeRepository() { return tester.nodeRepository(); }
- void deployZoneApp() { tester.deployZoneApp(); }
+ void activateTenantHosts() { tester.activateTenantHosts(); }
void deployApp(ApplicationId id) { deployApp(id, true); }
diff --git a/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/maintenance/ScalingSuggestionsMaintainerTest.java b/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/maintenance/ScalingSuggestionsMaintainerTest.java
index 31a9fcb8999..bd2afb5d1c8 100644
--- a/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/maintenance/ScalingSuggestionsMaintainerTest.java
+++ b/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/maintenance/ScalingSuggestionsMaintainerTest.java
@@ -47,7 +47,7 @@ public class ScalingSuggestionsMaintainerTest {
NodeMetricsDb nodeMetricsDb = new NodeMetricsDb(tester.nodeRepository());
tester.makeReadyNodes(20, "flt", NodeType.host, 8);
- tester.deployZoneApp();
+ tester.activateTenantHosts();
tester.deploy(app1, cluster1, Capacity.from(new ClusterResources(5, 1, new NodeResources(4, 4, 10, 0.1)),
new ClusterResources(5, 1, new NodeResources(4, 4, 10, 0.1)),
diff --git a/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/node/IPTest.java b/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/node/IPTest.java
index fcf2ab5a52d..4602a8f3560 100644
--- a/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/node/IPTest.java
+++ b/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/node/IPTest.java
@@ -179,7 +179,7 @@ public class IPTest {
private static Node createNode(Set<String> ipAddresses) {
return Node.create("id1", new IP.Config(Set.of("127.0.0.1"), ipAddresses),
"host1", Optional.empty(), Optional.empty(), nodeFlavors.getFlavorOrThrow("default"),
- Optional.empty(), NodeType.host);
+ Optional.empty(), NodeType.host, Optional.empty());
}
}
diff --git a/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/os/OsVersionsTest.java b/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/os/OsVersionsTest.java
index 6a41e766ace..715ecdb5949 100644
--- a/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/os/OsVersionsTest.java
+++ b/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/os/OsVersionsTest.java
@@ -21,7 +21,6 @@ import java.util.List;
import java.util.Optional;
import java.util.function.Function;
import java.util.function.Supplier;
-import java.util.function.UnaryOperator;
import java.util.stream.Collectors;
import static org.junit.Assert.assertEquals;
@@ -273,20 +272,11 @@ public class OsVersionsTest {
}
private void setWantedVersion(List<Node> nodes, Version wantedVersion) {
- writeNode(nodes, node -> node.with(node.status().withOsVersion(node.status().osVersion().withWanted(Optional.of(wantedVersion)))));
+ tester.patchNodes(nodes, node -> node.with(node.status().withOsVersion(node.status().osVersion().withWanted(Optional.of(wantedVersion)))));
}
private void setCurrentVersion(List<Node> nodes, Version currentVersion) {
- writeNode(nodes, node -> node.with(node.status().withOsVersion(node.status().osVersion().withCurrent(Optional.of(currentVersion)))));
- }
-
- private void writeNode(List<Node> nodes, UnaryOperator<Node> updateFunc) {
- for (var node : nodes) {
- try (var lock = tester.nodeRepository().lock(node)) {
- node = tester.nodeRepository().getNode(node.hostname()).get();
- tester.nodeRepository().write(updateFunc.apply(node), lock);
- }
- }
+ tester.patchNodes(nodes, node -> node.with(node.status().withOsVersion(node.status().osVersion().withCurrent(Optional.of(currentVersion)))));
}
private void completeUpgradeOf(List<Node> nodes) {
@@ -294,7 +284,8 @@ public class OsVersionsTest {
}
private void completeUpgradeOf(List<Node> nodes, NodeType nodeType) {
- writeNode(nodes, (node) -> {
+ // Complete upgrade by deprovisioning stale hosts and provisioning new ones
+ tester.patchNodes(nodes, (node) -> {
Optional<Version> wantedOsVersion = node.status().osVersion().wanted();
if (node.status().wantToDeprovision()) {
// Complete upgrade by deprovisioning stale hosts and provisioning new ones
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 dbbad0b8982..97c9bef0dd0 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
@@ -57,7 +57,7 @@ public class NodeSerializerTest {
private final ManualClock clock = new ManualClock();
@Test
- public void testProvisionedNodeSerialization() {
+ public void provisioned_node_serialization() {
Node node = createNode();
Node copy = nodeSerializer.fromJson(Node.State.provisioned, nodeSerializer.toJson(node));
@@ -69,7 +69,7 @@ public class NodeSerializerTest {
}
@Test
- public void testReservedNodeSerialization() {
+ public void reserved_node_serialization() {
Node node = createNode();
NodeResources requestedResources = new NodeResources(1.2, 3.4, 5.6, 7.8, NodeResources.DiskSpeed.any);
@@ -110,7 +110,7 @@ public class NodeSerializerTest {
}
@Test
- public void testRebootAndRestartAndTypeNoCurrentValuesSerialization() {
+ public void reboot_and_restart_and_type_no_current_values_serialization() {
String nodeData =
"{\n" +
" \"type\" : \"tenant\",\n" +
@@ -158,7 +158,7 @@ public class NodeSerializerTest {
}
@Test
- public void testRetiredNodeSerialization() {
+ public void retired_node_serialization() {
Node node = createNode();
clock.advance(Duration.ofMinutes(3));
@@ -185,7 +185,7 @@ public class NodeSerializerTest {
}
@Test
- public void testAssimilatedDeserialization() {
+ public void assimilated_node_deserialization() {
Node node = nodeSerializer.fromJson(Node.State.active, ("{\n" +
" \"type\": \"tenant\",\n" +
" \"hostname\": \"assimilate2.vespahosted.yahoo.tld\",\n" +
@@ -211,7 +211,7 @@ public class NodeSerializerTest {
}
@Test
- public void testSetFailCount() {
+ public void fail_count() {
Node node = createNode();
node = node.allocate(ApplicationId.from(TenantName.from("myTenant"),
ApplicationName.from("myApplication"),
@@ -229,7 +229,7 @@ public class NodeSerializerTest {
@Test
public void serialize_parentHostname() {
final String parentHostname = "parent.yahoo.com";
- Node node = Node.create("myId", new IP.Config(Set.of("127.0.0.1"), Set.of()), "myHostname", Optional.of(parentHostname), Optional.empty(), nodeFlavors.getFlavorOrThrow("default"), Optional.empty(), NodeType.tenant);
+ Node node = Node.create("myId", new IP.Config(Set.of("127.0.0.1"), Set.of()), "myHostname", Optional.of(parentHostname), Optional.empty(), nodeFlavors.getFlavorOrThrow("default"), Optional.empty(), NodeType.tenant, Optional.empty());
Node deserializedNode = nodeSerializer.fromJson(State.provisioned, nodeSerializer.toJson(node));
assertEquals(parentHostname, deserializedNode.parentHostname().get());
@@ -392,7 +392,7 @@ public class NodeSerializerTest {
}
@Test
- public void testNodeWithNetworkPorts() {
+ public void network_ports_serialization() {
Node node = createNode();
List<NetworkPorts.Allocation> list = new ArrayList<>();
list.add(new NetworkPorts.Allocation(8080, "container", "default/0", "http"));
@@ -416,6 +416,15 @@ public class NodeSerializerTest {
assertEquals(list, listCopy);
}
+ @Test
+ public void switch_hostname_serialization() {
+ Node node = nodeSerializer.fromJson(State.active, nodeSerializer.toJson(createNode()));
+ assertFalse(node.switchHostname().isPresent());
+ String switchHostname = "switch0.example.com";
+ node = node.withSwitchHostname(switchHostname);
+ node = nodeSerializer.fromJson(State.active, nodeSerializer.toJson(node));
+ assertEquals(switchHostname, node.switchHostname().get());
+ }
private byte[] createNodeJson(String hostname, String... ipAddress) {
String ipAddressJsonPart = "";
@@ -441,8 +450,8 @@ public class NodeSerializerTest {
Optional.empty(),
Optional.empty(),
nodeFlavors.getFlavorOrThrow("default"),
- Optional.empty(), NodeType.tenant
- );
+ Optional.empty(), NodeType.tenant,
+ Optional.empty());
}
}
diff --git a/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/provisioning/AclProvisioningTest.java b/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/provisioning/AclProvisioningTest.java
index d165f865432..505e53c9195 100644
--- a/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/provisioning/AclProvisioningTest.java
+++ b/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/provisioning/AclProvisioningTest.java
@@ -165,7 +165,7 @@ public class AclProvisioningTest {
public void trusted_nodes_for_application_with_load_balancer() {
// Provision hosts and containers
var hosts = tester.makeReadyNodes(2, "default", NodeType.host);
- tester.deployZoneApp();
+ tester.activateTenantHosts();
for (var host : hosts) {
tester.makeReadyVirtualDockerNodes(2, new NodeResources(2, 8, 50, 1),
host.hostname());
diff --git a/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/provisioning/AllocationSimulator.java b/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/provisioning/AllocationSimulator.java
index b113c281289..051420d694d 100644
--- a/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/provisioning/AllocationSimulator.java
+++ b/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/provisioning/AllocationSimulator.java
@@ -80,7 +80,8 @@ public class AllocationSimulator {
var ipConfig = new IP.Config(Set.of("127.0.0.1"), parent.isPresent() ? Set.of() : getAdditionalIP());
return new Node("fake", ipConfig, hostname, parent, flavor, Status.initial(),
parent.isPresent() ? Node.State.ready : Node.State.active, allocation(tenant, flavor), History.empty(),
- parent.isPresent() ? NodeType.tenant : NodeType.host, new Reports(), Optional.empty(), Optional.empty());
+ parent.isPresent() ? NodeType.tenant : NodeType.host, new Reports(), Optional.empty(), Optional.empty(),
+ Optional.empty());
}
private Set<String> getAdditionalIP() {
diff --git a/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/provisioning/DockerImagesTest.java b/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/provisioning/DockerImagesTest.java
index cd6ae587b04..d5437296620 100644
--- a/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/provisioning/DockerImagesTest.java
+++ b/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/provisioning/DockerImagesTest.java
@@ -27,7 +27,7 @@ public class DockerImagesTest {
// Host uses tenant default image (for preload purposes)
var defaultImage = DockerImage.fromString("docker-registry.domain.tld:8080/dist/vespa");
var hosts = tester.makeReadyNodes(2, "default", NodeType.host);
- tester.deployZoneApp();
+ tester.activateTenantHosts();
for (var host : hosts) {
assertEquals(defaultImage, tester.nodeRepository().dockerImages().dockerImageFor(host.type()));
}
diff --git a/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/provisioning/DockerProvisioningCompleteHostCalculatorTest.java b/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/provisioning/DockerProvisioningCompleteHostCalculatorTest.java
index 24cdc5c8fd0..2588818a9d3 100644
--- a/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/provisioning/DockerProvisioningCompleteHostCalculatorTest.java
+++ b/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/provisioning/DockerProvisioningCompleteHostCalculatorTest.java
@@ -30,7 +30,7 @@ public class DockerProvisioningCompleteHostCalculatorTest {
.resourcesCalculator(new CompleteResourcesCalculator(hostFlavor))
.flavors(List.of(hostFlavor))
.build();
- tester.makeReadyHosts(9, hostFlavor.resources()).deployZoneApp();
+ tester.makeReadyHosts(9, hostFlavor.resources()).activateTenantHosts();
ApplicationId app1 = tester.makeApplicationId("app1");
ClusterSpec cluster1 = ClusterSpec.request(ClusterSpec.Type.content, new ClusterSpec.Id("cluster1")).vespaVersion("7").build();
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 e566172b524..6ae78f9019c 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
@@ -20,7 +20,6 @@ import com.yahoo.config.provision.TenantName;
import com.yahoo.config.provision.Zone;
import com.yahoo.vespa.hosted.provision.Node;
import com.yahoo.vespa.hosted.provision.NodeList;
-import com.yahoo.vespa.hosted.provision.NodeRepository;
import org.junit.Test;
import java.util.HashSet;
@@ -123,7 +122,7 @@ public class DockerProvisioningTest {
tester.makeReadyNodes(10, resources, Optional.of(tenant1), NodeType.host, 1);
tester.makeReadyNodes(10, resources, Optional.empty(), NodeType.host, 1);
- tester.deployZoneApp();
+ tester.activateTenantHosts();
Version wantedVespaVersion = Version.fromString("6.39");
List<HostSpec> nodes = tester.prepare(application2_1,
@@ -310,7 +309,7 @@ public class DockerProvisioningTest {
.resourcesCalculator(3, 0)
.flavors(List.of(hostFlavor))
.build();
- tester.makeReadyHosts(2, hostFlavor.resources()).deployZoneApp();
+ tester.makeReadyHosts(2, hostFlavor.resources()).activateTenantHosts();
ApplicationId app1 = tester.makeApplicationId("app1");
ClusterSpec cluster1 = ClusterSpec.request(ClusterSpec.Type.content, new ClusterSpec.Id("cluster1")).vespaVersion("7").build();
@@ -330,7 +329,7 @@ public class DockerProvisioningTest {
.resourcesCalculator(3, 0)
.flavors(List.of(hostFlavor))
.build();
- tester.makeReadyHosts(9, hostFlavor.resources()).deployZoneApp();
+ tester.makeReadyHosts(9, hostFlavor.resources()).activateTenantHosts();
ApplicationId app1 = tester.makeApplicationId("app1");
ClusterSpec cluster1 = ClusterSpec.request(ClusterSpec.Type.content, new ClusterSpec.Id("cluster1")).vespaVersion("7").build();
@@ -365,7 +364,7 @@ public class DockerProvisioningTest {
.resourcesCalculator(3, 0)
.flavors(List.of(hostFlavor))
.build();
- tester.makeReadyHosts(2, hostFlavor.resources()).deployZoneApp();
+ tester.makeReadyHosts(2, hostFlavor.resources()).activateTenantHosts();
ApplicationId app1 = tester.makeApplicationId("app1");
ClusterSpec cluster1 = ClusterSpec.request(ClusterSpec.Type.content, new ClusterSpec.Id("cluster1")).vespaVersion("7").build();
@@ -387,7 +386,7 @@ public class DockerProvisioningTest {
ProvisioningTester tester = new ProvisioningTester.Builder().zone(new Zone(Environment.prod, RegionName.from("us-east")))
.flavors(List.of(new Flavor(r)))
.build();
- tester.makeReadyHosts(5, r).deployZoneApp();
+ tester.makeReadyHosts(5, r).activateTenantHosts();
ApplicationId app1 = tester.makeApplicationId("app1");
ClusterSpec cluster1 = ClusterSpec.request(ClusterSpec.Type.container, new ClusterSpec.Id("cluster1")).vespaVersion("7").build();
@@ -420,7 +419,7 @@ public class DockerProvisioningTest {
ProvisioningTester tester = new ProvisioningTester.Builder().zone(new Zone(Environment.prod, RegionName.from("us-east")))
.flavors(List.of(new Flavor(r)))
.build();
- tester.makeReadyHosts(4, r).deployZoneApp();
+ tester.makeReadyHosts(4, r).activateTenantHosts();
ApplicationId app1 = tester.makeApplicationId("app1");
ClusterSpec cluster1 = ClusterSpec.request(clusterType, new ClusterSpec.Id("cluster1")).vespaVersion("7").build();
diff --git a/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/provisioning/DynamicDockerAllocationTest.java b/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/provisioning/DynamicDockerAllocationTest.java
index 29e371dd937..7e416bfc397 100644
--- a/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/provisioning/DynamicDockerAllocationTest.java
+++ b/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/provisioning/DynamicDockerAllocationTest.java
@@ -66,7 +66,7 @@ public class DynamicDockerAllocationTest {
.spareCount(spareCount)
.build();
tester.makeReadyNodes(4, "host-small", NodeType.host, 32);
- tester.deployZoneApp();
+ tester.activateTenantHosts();
List<Node> dockerHosts = tester.nodeRepository().getNodes(NodeType.host, Node.State.active);
NodeResources flavor = new NodeResources(1, 4, 100, 1);
@@ -109,7 +109,7 @@ public class DynamicDockerAllocationTest {
public void relocate_failed_nodes() {
ProvisioningTester tester = new ProvisioningTester.Builder().zone(new Zone(Environment.prod, RegionName.from("us-east"))).flavorsConfig(flavorsConfig()).build();
tester.makeReadyNodes(5, "host-small", NodeType.host, 32);
- tester.deployZoneApp();
+ tester.activateTenantHosts();
List<Node> dockerHosts = tester.nodeRepository().getNodes(NodeType.host, Node.State.active);
NodeResources resources = new NodeResources(1, 4, 100, 0.3);
@@ -158,7 +158,7 @@ public class DynamicDockerAllocationTest {
tester.makeReadyNodes(3, "flt", NodeType.host, 8); // cpu: 30, mem: 30
tester.makeReadyNodes(3, "cpu", NodeType.host, 8); // cpu: 40, mem: 20
tester.makeReadyNodes(3, "mem", NodeType.host, 8); // cpu: 20, mem: 40
- tester.deployZoneApp();
+ tester.activateTenantHosts();
NodeResources fltResources = new NodeResources(6, 6, 10, 0.1);
NodeResources cpuResources = new NodeResources(8, 4, 10, 0.1);
NodeResources memResources = new NodeResources(4, 8, 10, 0.1);
@@ -201,7 +201,7 @@ public class DynamicDockerAllocationTest {
public void do_not_relocate_nodes_from_spare_if_no_where_to_relocate_them() {
ProvisioningTester tester = new ProvisioningTester.Builder().zone(new Zone(Environment.prod, RegionName.from("us-east"))).flavorsConfig(flavorsConfig()).build();
tester.makeReadyNodes(2, "host-small", NodeType.host, 32);
- tester.deployZoneApp();
+ tester.activateTenantHosts();
List<Node> dockerHosts = tester.nodeRepository().getNodes(NodeType.host, Node.State.active);
NodeResources flavor = new NodeResources(1, 4, 100, 1);
@@ -228,7 +228,7 @@ public class DynamicDockerAllocationTest {
public void multiple_groups_are_on_separate_parent_hosts() {
ProvisioningTester tester = new ProvisioningTester.Builder().zone(new Zone(Environment.prod, RegionName.from("us-east"))).flavorsConfig(flavorsConfig()).build();
tester.makeReadyNodes(5, "host-small", NodeType.host, 32);
- tester.deployZoneApp();
+ tester.activateTenantHosts();
//Deploy an application having 6 nodes (3 nodes in 2 groups). We only have 5 docker hosts available
ApplicationId application1 = tester.makeApplicationId();
@@ -249,7 +249,7 @@ public class DynamicDockerAllocationTest {
// Setup test
ApplicationId application1 = tester.makeApplicationId();
tester.makeReadyNodes(5, "host-small", NodeType.host, 32);
- tester.deployZoneApp();
+ tester.activateTenantHosts();
NodeResources flavor = new NodeResources(1, 4, 100, 1);
// Deploy initial state (can max deploy 3 nodes due to redundancy requirements)
@@ -278,7 +278,7 @@ public class DynamicDockerAllocationTest {
public void non_prod_zones_do_not_have_spares() {
ProvisioningTester tester = new ProvisioningTester.Builder().zone(new Zone(Environment.perf, RegionName.from("us-east"))).flavorsConfig(flavorsConfig()).build();
tester.makeReadyNodes(3, "host-small", NodeType.host, 32);
- tester.deployZoneApp();
+ tester.activateTenantHosts();
ApplicationId application1 = tester.makeApplicationId();
List<HostSpec> hosts = tester.prepare(application1, clusterSpec("myContent.t1.a1"), 3, 1, new NodeResources(1, 4, 100, 1));
tester.activate(application1, ImmutableSet.copyOf(hosts));
@@ -291,7 +291,7 @@ public class DynamicDockerAllocationTest {
public void cd_uses_slow_disk_nodes_for_docker_hosts() {
ProvisioningTester tester = new ProvisioningTester.Builder().zone(new Zone(SystemName.cd, Environment.test, RegionName.from("us-east"))).flavorsConfig(flavorsConfig()).build();
tester.makeReadyNodes(4, new Flavor(new NodeResources(1, 8, 120, 1, NodeResources.DiskSpeed.slow)), NodeType.host, 10, true);
- tester.deployZoneApp();
+ tester.activateTenantHosts();
ApplicationId application1 = tester.makeApplicationId();
List<HostSpec> hosts = tester.prepare(application1, clusterSpec("myContent.t1.a1"), 3, 1, new NodeResources(1, 4, 100, 1));
tester.activate(application1, ImmutableSet.copyOf(hosts));
@@ -311,7 +311,7 @@ public class DynamicDockerAllocationTest {
public void provision_dual_stack_containers() {
ProvisioningTester tester = new ProvisioningTester.Builder().zone(new Zone(Environment.prod, RegionName.from("us-east"))).flavorsConfig(flavorsConfig()).build();
tester.makeReadyNodes(2, "host-large", NodeType.host, 10, true);
- tester.deployZoneApp();
+ tester.activateTenantHosts();
ApplicationId application = tester.makeApplicationId();
List<HostSpec> hosts = tester.prepare(application, clusterSpec("myContent.t1.a1"), 2, 1, new NodeResources(1, 4, 100, 1));
@@ -342,7 +342,7 @@ public class DynamicDockerAllocationTest {
ProvisioningTester tester = new ProvisioningTester.Builder().zone(new Zone(Environment.prod, RegionName.from("us-east"))).flavorsConfig(flavorsConfig()).build();
tester.makeReadyNodes(2, new Flavor(new NodeResources(1, 8, 120, 1, NodeResources.DiskSpeed.fast)), NodeType.host, 10, true);
tester.makeReadyNodes(2, new Flavor(new NodeResources(1, 8, 120, 1, NodeResources.DiskSpeed.slow)), NodeType.host, 10, true);
- tester.deployZoneApp();
+ tester.activateTenantHosts();
ApplicationId application = tester.makeApplicationId();
ClusterSpec cluster = ClusterSpec.request(ClusterSpec.Type.container, ClusterSpec.Id.from("test")).vespaVersion("1").build();
@@ -359,7 +359,7 @@ public class DynamicDockerAllocationTest {
ProvisioningTester tester = new ProvisioningTester.Builder().zone(new Zone(Environment.prod, RegionName.from("us-east"))).flavorsConfig(flavorsConfig()).build();
tester.makeReadyNodes(2, new Flavor(new NodeResources(1, 8, 120, 1, NodeResources.DiskSpeed.fast)), NodeType.host, 10, true);
tester.makeReadyNodes(2, new Flavor(new NodeResources(1, 8, 120, 1, NodeResources.DiskSpeed.slow)), NodeType.host, 10, true);
- tester.deployZoneApp();
+ tester.activateTenantHosts();
ApplicationId application = tester.makeApplicationId();
ClusterSpec cluster = ClusterSpec.request(ClusterSpec.Type.container, ClusterSpec.Id.from("test")).vespaVersion("1").build();
@@ -381,7 +381,7 @@ public class DynamicDockerAllocationTest {
ProvisioningTester tester = new ProvisioningTester.Builder().zone(new Zone(Environment.dev, RegionName.from("us-east"))).flavorsConfig(flavorsConfig()).build();
tester.makeReadyNodes(2, new Flavor(new NodeResources(1, 8, 120, 1, NodeResources.DiskSpeed.fast)), NodeType.host, 10, true);
tester.makeReadyNodes(2, new Flavor(new NodeResources(1, 8, 120, 1, NodeResources.DiskSpeed.slow)), NodeType.host, 10, true);
- tester.deployZoneApp();
+ tester.activateTenantHosts();
ApplicationId application = tester.makeApplicationId();
ClusterSpec cluster = ClusterSpec.request(ClusterSpec.Type.container, ClusterSpec.Id.from("test")).vespaVersion("1").build();
@@ -399,7 +399,7 @@ public class DynamicDockerAllocationTest {
public void testSwitchingFromLegacyFlavorSyntaxToResourcesDoesNotCauseReallocation() {
ProvisioningTester tester = new ProvisioningTester.Builder().zone(new Zone(Environment.prod, RegionName.from("us-east"))).flavorsConfig(flavorsConfig()).build();
tester.makeReadyNodes(2, new Flavor(new NodeResources(5, 20, 1400, 3)), NodeType.host, 10, true);
- tester.deployZoneApp();
+ tester.activateTenantHosts();
ApplicationId application = tester.makeApplicationId();
ClusterSpec cluster = ClusterSpec.request(ClusterSpec.Type.container, ClusterSpec.Id.from("test")).vespaVersion("1").build();
@@ -425,7 +425,7 @@ public class DynamicDockerAllocationTest {
private void addAndAssignNode(ApplicationId id, String hostname, String parentHostname, ClusterSpec clusterSpec, NodeResources flavor, int index, ProvisioningTester tester) {
Node node1a = Node.create("open1", new IP.Config(Set.of("127.0.233." + index), Set.of()), hostname,
- Optional.of(parentHostname), Optional.empty(), new Flavor(flavor), Optional.empty(), NodeType.tenant
+ Optional.of(parentHostname), Optional.empty(), new Flavor(flavor), Optional.empty(), NodeType.tenant, Optional.empty()
);
ClusterMembership clusterMembership1 = ClusterMembership.from(
clusterSpec.with(Optional.of(ClusterSpec.Group.from(0))), index); // Need to add group here so that group is serialized in node allocation
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 db6d75d724e..57c7c46c2d9 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
@@ -81,7 +81,7 @@ public class DynamicDockerProvisionTest {
@Test
public void does_not_allocate_to_available_empty_hosts() {
tester.makeReadyNodes(3, "small", NodeType.host, 10);
- tester.deployZoneApp();
+ tester.activateTenantHosts();
ApplicationId application = tester.makeApplicationId();
NodeResources flavor = new NodeResources(1, 4, 10, 1);
@@ -109,7 +109,7 @@ public class DynamicDockerProvisionTest {
tester.nodeRepository().setReady(List.of(host), Agent.system, getClass().getSimpleName());
nameResolver.addRecord(hostname + "-2", "::" + i + ":2");
}
- tester.deployZoneApp();
+ tester.activateTenantHosts();
mockHostProvisioner(hostProvisioner, tester.nodeRepository().flavors().getFlavorOrThrow("small"));
tester.prepare(application, clusterSpec("another-id"), 2, 1, flavor);
@@ -128,15 +128,14 @@ public class DynamicDockerProvisionTest {
NodeResources resources = new NodeResources(10, 10, 10, 10);
ApplicationId app = tester.makeApplicationId();
- Function<Node, Node> retireNode = node ->
- tester.nodeRepository().write(node.withWantToRetire(true, Agent.system, Instant.now()), () -> {});
+ Function<Node, Node> retireNode = node -> tester.patchNode(node, (n) -> n.withWantToRetire(true, Agent.system, Instant.now()));
Function<Integer, Node> getNodeInGroup = group -> tester.nodeRepository().getNodes(app).stream()
.filter(node -> node.allocation().get().membership().cluster().group().get().index() == group)
.findAny().orElseThrow();
// Allocate 10 hosts
tester.makeReadyNodes(10, resources, NodeType.host, 1);
- tester.deployZoneApp();
+ tester.activateTenantHosts();
// Prepare & activate an application with 8 nodes and 2 groups
tester.activate(app, tester.prepare(app, clusterSpec("content"), 8, 2, resources));
@@ -170,7 +169,7 @@ public class DynamicDockerProvisionTest {
.resourcesCalculator(memoryTax, 0)
.build();
- tester.deployZoneApp();
+ tester.activateTenantHosts();
ApplicationId app1 = tester.makeApplicationId("app1");
ClusterSpec cluster1 = ClusterSpec.request(ClusterSpec.Type.content, new ClusterSpec.Id("cluster1")).vespaVersion("7").build();
@@ -216,7 +215,7 @@ public class DynamicDockerProvisionTest {
.resourcesCalculator(memoryTax, 0)
.build();
- tester.deployZoneApp();
+ tester.activateTenantHosts();
ApplicationId app1 = tester.makeApplicationId("app1");
ClusterSpec cluster1 = ClusterSpec.request(ClusterSpec.Type.content, new ClusterSpec.Id("cluster1")).vespaVersion("7").build();
@@ -291,7 +290,7 @@ public class DynamicDockerProvisionTest {
.resourcesCalculator(memoryTax, 0)
.build();
- tester.deployZoneApp();
+ tester.activateTenantHosts();
ApplicationId app1 = tester.makeApplicationId("app1");
ClusterSpec cluster1 = ClusterSpec.request(ClusterSpec.Type.content, new ClusterSpec.Id("cluster1")).vespaVersion("7").build();
@@ -326,7 +325,7 @@ public class DynamicDockerProvisionTest {
.resourcesCalculator(memoryTax, localDiskTax)
.build();
- tester.deployZoneApp();
+ tester.activateTenantHosts();
ApplicationId app1 = tester.makeApplicationId("app1");
ClusterSpec cluster1 = ClusterSpec.request(ClusterSpec.Type.content, new ClusterSpec.Id("cluster1")).vespaVersion("7").build();
diff --git a/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/provisioning/HostCapacityTest.java b/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/provisioning/HostCapacityTest.java
index da78aff493e..f831f2d501b 100644
--- a/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/provisioning/HostCapacityTest.java
+++ b/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/provisioning/HostCapacityTest.java
@@ -44,9 +44,9 @@ public class HostCapacityTest {
NodeFlavors nodeFlavors = FlavorConfigBuilder.createDummies("host", "docker", "docker2");
// Create three docker hosts
- host1 = Node.create("host1", new IP.Config(Set.of("::1"), generateIPs(2, 4)), "host1", Optional.empty(), Optional.empty(), nodeFlavors.getFlavorOrThrow("host"), Optional.empty(), NodeType.host);
- host2 = Node.create("host2", new IP.Config(Set.of("::11"), generateIPs(12, 3)), "host2", Optional.empty(), Optional.empty(), nodeFlavors.getFlavorOrThrow("host"), Optional.empty(), NodeType.host);
- host3 = Node.create("host3", new IP.Config(Set.of("::21"), generateIPs(22, 1)), "host3", Optional.empty(), Optional.empty(), nodeFlavors.getFlavorOrThrow("host"), Optional.empty(), NodeType.host);
+ host1 = Node.create("host1", new IP.Config(Set.of("::1"), generateIPs(2, 4)), "host1", Optional.empty(), Optional.empty(), nodeFlavors.getFlavorOrThrow("host"), Optional.empty(), NodeType.host, Optional.empty());
+ host2 = Node.create("host2", new IP.Config(Set.of("::11"), generateIPs(12, 3)), "host2", Optional.empty(), Optional.empty(), nodeFlavors.getFlavorOrThrow("host"), Optional.empty(), NodeType.host, Optional.empty());
+ host3 = Node.create("host3", new IP.Config(Set.of("::21"), generateIPs(22, 1)), "host3", Optional.empty(), Optional.empty(), nodeFlavors.getFlavorOrThrow("host"), Optional.empty(), NodeType.host, Optional.empty());
// Add two containers to host1
var nodeA = Node.createDockerNode(Set.of("::2"), "nodeA", "host1", resources1, NodeType.tenant);
@@ -111,7 +111,7 @@ public class HostCapacityTest {
// Dev host can assign both configserver and tenant containers.
var nodeFlavors = FlavorConfigBuilder.createDummies("devhost", "container");
- var devHost = Node.create("devhost", new IP.Config(Set.of("::1"), generateIPs(2, 10)), "devhost", Optional.empty(), Optional.empty(), nodeFlavors.getFlavorOrThrow("devhost"), Optional.empty(), NodeType.devhost);
+ var devHost = Node.create("devhost", new IP.Config(Set.of("::1"), generateIPs(2, 10)), "devhost", Optional.empty(), Optional.empty(), nodeFlavors.getFlavorOrThrow("devhost"), Optional.empty(), NodeType.devhost, Optional.empty());
var cfg = Node.createDockerNode(Set.of("::2"), "cfg", "devhost", resources1, NodeType.config);
diff --git a/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/provisioning/MultigroupProvisioningTest.java b/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/provisioning/MultigroupProvisioningTest.java
index 6e609d13d3b..09d1600e1d7 100644
--- a/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/provisioning/MultigroupProvisioningTest.java
+++ b/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/provisioning/MultigroupProvisioningTest.java
@@ -134,7 +134,7 @@ public class MultigroupProvisioningTest {
ProvisioningTester tester = new ProvisioningTester.Builder().zone(new Zone(Environment.prod, RegionName.from("us-east")))
.flavors(List.of(hostFlavor))
.build();
- tester.makeReadyHosts(6, hostFlavor.resources()).deployZoneApp();
+ tester.makeReadyHosts(6, hostFlavor.resources()).activateTenantHosts();
ApplicationId app1 = tester.makeApplicationId("app1");
ClusterSpec cluster1 = ClusterSpec.request(ClusterSpec.Type.content, new ClusterSpec.Id("cluster1")).vespaVersion("7").build();
@@ -160,7 +160,7 @@ public class MultigroupProvisioningTest {
ProvisioningTester tester = new ProvisioningTester.Builder().zone(new Zone(Environment.prod, RegionName.from("us-east")))
.flavors(List.of(hostFlavor))
.build();
- tester.makeReadyHosts(6, hostFlavor.resources()).deployZoneApp();
+ tester.makeReadyHosts(6, hostFlavor.resources()).activateTenantHosts();
ApplicationId app1 = tester.makeApplicationId("app1");
ClusterSpec cluster1 = ClusterSpec.request(ClusterSpec.Type.content, new ClusterSpec.Id("cluster1")).vespaVersion("7").build();
@@ -190,7 +190,7 @@ public class MultigroupProvisioningTest {
ProvisioningTester tester = new ProvisioningTester.Builder().zone(new Zone(Environment.prod, RegionName.from("us-east")))
.flavors(List.of(hostFlavor))
.build();
- tester.makeReadyHosts(12, hostFlavor.resources()).deployZoneApp();
+ tester.makeReadyHosts(12, hostFlavor.resources()).activateTenantHosts();
ApplicationId app1 = tester.makeApplicationId("app1");
ClusterSpec cluster1 = ClusterSpec.request(ClusterSpec.Type.content, new ClusterSpec.Id("cluster1")).vespaVersion("7").build();
diff --git a/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/provisioning/PrioritizableNodeTest.java b/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/provisioning/NodeCandidateTest.java
index 3865baa51c1..ec001556f58 100644
--- a/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/provisioning/PrioritizableNodeTest.java
+++ b/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/provisioning/NodeCandidateTest.java
@@ -22,29 +22,29 @@ import static org.junit.Assert.assertEquals;
/**
* @author bratseth
*/
-public class PrioritizableNodeTest {
+public class NodeCandidateTest {
@Test
public void test_order() {
- List<PrioritizableNode> expected = List.of(
- new PrioritizableNode(node("01", Node.State.ready), new NodeResources(2, 2, 2, 2), Optional.empty(), false, true, false, false),
- new PrioritizableNode(node("02", Node.State.active), new NodeResources(2, 2, 2, 2), Optional.empty(), true, false, false, false),
- new PrioritizableNode(node("04", Node.State.reserved), new NodeResources(2, 2, 2, 2), Optional.empty(), true, false, false, false),
- new PrioritizableNode(node("03", Node.State.inactive), new NodeResources(2, 2, 2, 2), Optional.empty(), true, false, false, false),
- new PrioritizableNode(node("05", Node.State.ready), new NodeResources(2, 2, 2, 2), Optional.of(node("host1", Node.State.active)), true, false, true, false),
- new PrioritizableNode(node("06", Node.State.ready), new NodeResources(2, 2, 2, 2), Optional.of(node("host1", Node.State.ready)), true, false, true, false),
- new PrioritizableNode(node("07", Node.State.ready), new NodeResources(2, 2, 2, 2), Optional.of(node("host1", Node.State.provisioned)), true, false, true, false),
- new PrioritizableNode(node("08", Node.State.ready), new NodeResources(2, 2, 2, 2), Optional.of(node("host1", Node.State.failed)), true, false, true, false),
- new PrioritizableNode(node("09", Node.State.ready), new NodeResources(1, 1, 1, 1), Optional.empty(), true, false, true, false),
- new PrioritizableNode(node("10", Node.State.ready), new NodeResources(2, 2, 2, 2), Optional.empty(), true, false, true, false),
- new PrioritizableNode(node("11", Node.State.ready), new NodeResources(2, 2, 2, 2), Optional.empty(), true, false, true, false)
+ List<NodeCandidate> expected = List.of(
+ new NodeCandidate(node("01", Node.State.ready), new NodeResources(2, 2, 2, 2), Optional.empty(), false, true, false, false),
+ new NodeCandidate(node("02", Node.State.active), new NodeResources(2, 2, 2, 2), Optional.empty(), true, false, false, false),
+ new NodeCandidate(node("04", Node.State.reserved), new NodeResources(2, 2, 2, 2), Optional.empty(), true, false, false, false),
+ new NodeCandidate(node("03", Node.State.inactive), new NodeResources(2, 2, 2, 2), Optional.empty(), true, false, false, false),
+ new NodeCandidate(node("05", Node.State.ready), new NodeResources(2, 2, 2, 2), Optional.of(node("host1", Node.State.active)), true, false, true, false),
+ new NodeCandidate(node("06", Node.State.ready), new NodeResources(2, 2, 2, 2), Optional.of(node("host1", Node.State.ready)), true, false, true, false),
+ new NodeCandidate(node("07", Node.State.ready), new NodeResources(2, 2, 2, 2), Optional.of(node("host1", Node.State.provisioned)), true, false, true, false),
+ new NodeCandidate(node("08", Node.State.ready), new NodeResources(2, 2, 2, 2), Optional.of(node("host1", Node.State.failed)), true, false, true, false),
+ new NodeCandidate(node("09", Node.State.ready), new NodeResources(1, 1, 1, 1), Optional.empty(), true, false, true, false),
+ new NodeCandidate(node("10", Node.State.ready), new NodeResources(2, 2, 2, 2), Optional.empty(), true, false, true, false),
+ new NodeCandidate(node("11", Node.State.ready), new NodeResources(2, 2, 2, 2), Optional.empty(), true, false, true, false)
);
assertOrder(expected);
}
@Test
public void testOrderingByAllocationSkew1() {
- List<PrioritizableNode> expected = List.of(
+ List<NodeCandidate> expected = List.of(
node("1", node(4, 4), host(20, 20), host(40, 40)),
node("2", node(4, 4), host(21, 20), host(40, 40)),
node("3", node(4, 4), host(22, 20), host(40, 40)),
@@ -59,7 +59,7 @@ public class PrioritizableNodeTest {
// The same as testOrderingByAllocationSkew1, but deviating from mean (20) in the other direction.
// Since we don't choose the node with the lowest skew, but with the largest skew *reduction*
// this causes the opposite order.
- List<PrioritizableNode> expected = List.of(
+ List<NodeCandidate> expected = List.of(
node("4", node(4, 4), host(19, 18), host(40, 40)),
node("3", node(4, 4), host(18, 20), host(40, 40)),
node("2", node(4, 4), host(19, 20), host(40, 40)),
@@ -72,7 +72,7 @@ public class PrioritizableNodeTest {
@Test
public void testOrderingByAllocationSkew3() {
// The same as testOrderingByAllocationSkew1, but allocating skewed towards cpu
- List<PrioritizableNode> expected = List.of(
+ List<NodeCandidate> expected = List.of(
node("1", node(4, 2), host(20, 20), host(40, 40)),
node("2", node(4, 2), host(21, 20), host(40, 40)),
node("4", node(4, 2), host(21, 22), host(40, 40)),
@@ -85,7 +85,7 @@ public class PrioritizableNodeTest {
@Test
public void testOrderingByAllocationSkew4() {
// The same as testOrderingByAllocationSkew1, but allocating skewed towards memory
- List<PrioritizableNode> expected = List.of(
+ List<NodeCandidate> expected = List.of(
node("5", node(2, 10), host(21, 21), host(40, 80)),
node("3", node(2, 10), host(22, 20), host(40, 40)),
node("2", node(2, 10), host(21, 20), host(40, 40)),
@@ -99,7 +99,7 @@ public class PrioritizableNodeTest {
public void testOrderingByAllocationSkew5() {
// node1 is skewed towards cpu (without this allocation), allocation is skewed towards memory, therefore
// node 1 is preferred (even though it is still most skewed)
- List<PrioritizableNode> expected = List.of(
+ List<NodeCandidate> expected = List.of(
node("1", node(1, 5), host(21, 10), host(40, 40)),
node("2", node(1, 5), host(21, 20), host(40, 40)),
node("3", node(1, 5), host(20, 20), host(40, 40)),
@@ -108,8 +108,8 @@ public class PrioritizableNodeTest {
assertOrder(expected);
}
- private void assertOrder(List<PrioritizableNode> expected) {
- List<PrioritizableNode> copy = new ArrayList<>(expected);
+ private void assertOrder(List<NodeCandidate> expected) {
+ List<NodeCandidate> copy = new ArrayList<>(expected);
Collections.shuffle(copy);
Collections.sort(copy);
assertEquals(expected, copy);
@@ -127,23 +127,23 @@ public class PrioritizableNodeTest {
return new Node(hostname, new IP.Config(Set.of("::1"), Set.of()), hostname, Optional.empty(),
new Flavor(new NodeResources(2, 2, 2, 2)),
Status.initial(), state, Optional.empty(), History.empty(), NodeType.tenant, new Reports(),
- Optional.empty(), Optional.empty());
+ Optional.empty(), Optional.empty(), Optional.empty());
}
- private static PrioritizableNode node(String hostname,
- NodeResources nodeResources,
- NodeResources allocatedHostResources, // allocated before adding nodeResources
- NodeResources totalHostResources) {
+ private static NodeCandidate node(String hostname,
+ NodeResources nodeResources,
+ NodeResources allocatedHostResources, // allocated before adding nodeResources
+ NodeResources totalHostResources) {
Node node = new Node(hostname, new IP.Config(Set.of("::1"), Set.of()), hostname, Optional.of(hostname + "parent"),
new Flavor(nodeResources),
Status.initial(), Node.State.ready, Optional.empty(), History.empty(), NodeType.tenant,
- new Reports(), Optional.empty(), Optional.empty());
+ new Reports(), Optional.empty(), Optional.empty(), Optional.empty());
Node parent = new Node(hostname + "parent", new IP.Config(Set.of("::1"), Set.of()), hostname, Optional.empty(),
new Flavor(totalHostResources),
Status.initial(), Node.State.ready, Optional.empty(), History.empty(), NodeType.host,
- new Reports(), Optional.empty(), Optional.empty());
- return new PrioritizableNode(node, totalHostResources.subtract(allocatedHostResources), Optional.of(parent),
- false, false, true, false);
+ new Reports(), Optional.empty(), Optional.empty(), Optional.empty());
+ return new NodeCandidate(node, totalHostResources.subtract(allocatedHostResources), Optional.of(parent),
+ false, false, true, false);
}
}
diff --git a/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/provisioning/ProvisioningTest.java b/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/provisioning/ProvisioningTest.java
index ff2f0ffca96..6cf5a2c8342 100644
--- a/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/provisioning/ProvisioningTest.java
+++ b/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/provisioning/ProvisioningTest.java
@@ -62,7 +62,7 @@ public class ProvisioningTest {
ApplicationId application1 = tester.makeApplicationId();
ApplicationId application2 = tester.makeApplicationId();
- tester.makeReadyHosts(21, defaultResources).deployZoneApp();
+ tester.makeReadyHosts(21, defaultResources).activateTenantHosts();
// deploy
SystemState state1 = prepare(application1, 2, 2, 3, 3, defaultResources, tester);
@@ -196,7 +196,7 @@ public class ProvisioningTest {
ApplicationId application1 = tester.makeApplicationId();
tester.makeReadyHosts(24, defaultResources);
- tester.deployZoneApp();
+ tester.activateTenantHosts();
// deploy
SystemState state1 = prepare(application1, 2, 2, 3, 3, defaultResources, tester);
@@ -267,7 +267,7 @@ public class ProvisioningTest {
ApplicationId application1 = tester.makeApplicationId();
tester.makeReadyHosts(12, small);
- tester.deployZoneApp();
+ tester.activateTenantHosts();
// deploy
SystemState state1 = prepare(application1, 2, 2, 4, 4, small, tester);
@@ -278,7 +278,7 @@ public class ProvisioningTest {
tester.activate(application1, state2.allHosts);
tester.makeReadyHosts(16, large);
- tester.deployZoneApp();
+ tester.activateTenantHosts();
// redeploy with increased sizes and new flavor
SystemState state3 = prepare(application1, 3, 4, 4, 5, large, tester);
@@ -303,7 +303,7 @@ public class ProvisioningTest {
tester.makeReadyHosts(12, small);
tester.makeReadyHosts(12, large);
- tester.deployZoneApp();
+ tester.activateTenantHosts();
// deploy
SystemState state1 = prepare(application1, 2, 2, 4, 4, small, tester);
@@ -319,7 +319,7 @@ public class ProvisioningTest {
ApplicationId application1 = tester.makeApplicationId();
- tester.makeReadyHosts(5, defaultResources).deployZoneApp();
+ tester.makeReadyHosts(5, defaultResources).activateTenantHosts();
// deploy
SystemState state1 = prepare(application1, 2, 0, 3, 0, defaultResources, tester);
@@ -354,7 +354,7 @@ public class ProvisioningTest {
@Test
public void requested_resources_info_is_retained() {
ProvisioningTester tester = new ProvisioningTester.Builder().zone(new Zone(Environment.prod, RegionName.from("us-east"))).build();
- tester.makeReadyHosts(13, defaultResources).deployZoneApp();
+ tester.makeReadyHosts(13, defaultResources).activateTenantHosts();
tester.prepareAndActivateInfraApplication(tester.makeApplicationId(), NodeType.host);
ApplicationId application = tester.makeApplicationId();
@@ -398,7 +398,7 @@ public class ProvisioningTest {
public void deploy_specific_vespa_version() {
ProvisioningTester tester = new ProvisioningTester.Builder().zone(new Zone(Environment.dev, RegionName.from("us-east"))).build();
- tester.makeReadyHosts(4, defaultResources).deployZoneApp();
+ tester.makeReadyHosts(4, defaultResources).activateTenantHosts();
tester.prepareAndActivateInfraApplication(tester.makeApplicationId(), NodeType.host);
ApplicationId application = tester.makeApplicationId();
@@ -411,7 +411,7 @@ public class ProvisioningTest {
public void deploy_specific_vespa_version_and_docker_image() {
ProvisioningTester tester = new ProvisioningTester.Builder().zone(new Zone(Environment.dev, RegionName.from("us-east"))).build();
- tester.makeReadyHosts(4, defaultResources).deployZoneApp();
+ tester.makeReadyHosts(4, defaultResources).activateTenantHosts();
tester.prepareAndActivateInfraApplication(tester.makeApplicationId(), NodeType.host);
ApplicationId application = tester.makeApplicationId();
@@ -426,7 +426,7 @@ public class ProvisioningTest {
ProvisioningTester tester = new ProvisioningTester.Builder().zone(new Zone(Environment.test, RegionName.from("us-east"))).build();
ApplicationId application = tester.makeApplicationId();
- tester.makeReadyHosts(4, defaultResources).deployZoneApp();
+ tester.makeReadyHosts(4, defaultResources).activateTenantHosts();
SystemState state = prepare(application, 2, 2, 3, 3, defaultResources, tester);
assertEquals(4, state.allHosts.size());
tester.activate(application, state.allHosts);
@@ -438,7 +438,7 @@ public class ProvisioningTest {
ProvisioningTester tester = new ProvisioningTester.Builder().zone(new Zone(Environment.prod, RegionName.from("us-east")))
.flavors(List.of(hostFlavor))
.build();
- tester.makeReadyHosts(4, hostFlavor.resources()).deployZoneApp();
+ tester.makeReadyHosts(4, hostFlavor.resources()).activateTenantHosts();
ApplicationId app1 = tester.makeApplicationId("app1");
ClusterSpec cluster1 = ClusterSpec.request(ClusterSpec.Type.content, new ClusterSpec.Id("cluster1")).vespaVersion("7").build();
@@ -456,7 +456,7 @@ public class ProvisioningTest {
ProvisioningTester tester = new ProvisioningTester.Builder().zone(new Zone(Environment.prod, RegionName.from("us-east")))
.flavors(List.of(hostFlavor))
.build();
- tester.makeReadyHosts(31, hostFlavor.resources()).deployZoneApp();
+ tester.makeReadyHosts(31, hostFlavor.resources()).activateTenantHosts();
ApplicationId app1 = tester.makeApplicationId("app1");
ClusterSpec cluster1 = ClusterSpec.request(ClusterSpec.Type.content, new ClusterSpec.Id("cluster1")).vespaVersion("7").build();
@@ -516,7 +516,7 @@ public class ProvisioningTest {
ProvisioningTester tester = new ProvisioningTester.Builder().zone(new Zone(Environment.prod, RegionName.from("us-east"))).build();
ApplicationId application = tester.makeApplicationId();
- tester.makeReadyHosts(10, defaultResources).deployZoneApp();
+ tester.makeReadyHosts(10, defaultResources).activateTenantHosts();
prepare(application, 1, 2, 3, 3, defaultResources, tester);
}
@@ -525,7 +525,7 @@ public class ProvisioningTest {
ProvisioningTester tester = new ProvisioningTester.Builder().zone(new Zone(Environment.prod, RegionName.from("us-east"))).build();
ApplicationId application = tester.makeApplicationId();
- tester.makeReadyHosts(10, defaultResources).deployZoneApp();
+ tester.makeReadyHosts(10, defaultResources).activateTenantHosts();
try {
prepare(application, 2, 2, 3, 3,
new NodeResources(2, 2, 10, 2), tester);
@@ -540,7 +540,7 @@ public class ProvisioningTest {
ProvisioningTester tester = new ProvisioningTester.Builder().zone(new Zone(Environment.prod, RegionName.from("us-east"))).build();
ApplicationId application = tester.makeApplicationId();
- tester.makeReadyHosts(10, defaultResources).deployZoneApp();
+ tester.makeReadyHosts(10, defaultResources).activateTenantHosts();
try {
prepare(application, 2, 2, 3, 3,
new NodeResources(0.4, 4, 10, 2), tester);
@@ -573,7 +573,7 @@ public class ProvisioningTest {
ProvisioningTester tester = new ProvisioningTester.Builder().zone(new Zone(Environment.test, RegionName.from("us-east"))).build();
ApplicationId application = tester.makeApplicationId();
- tester.makeReadyHosts(4, large).deployZoneApp();
+ tester.makeReadyHosts(4, large).activateTenantHosts();
SystemState state = prepare(application, 2, 2, 3, 3, large, tester);
assertEquals(4, state.allHosts.size());
tester.activate(application, state.allHosts);
@@ -584,7 +584,7 @@ public class ProvisioningTest {
ProvisioningTester tester = new ProvisioningTester.Builder().zone(new Zone(Environment.staging, RegionName.from("us-east"))).build();
ApplicationId application = tester.makeApplicationId();
- tester.makeReadyHosts(14, defaultResources).deployZoneApp();
+ tester.makeReadyHosts(14, defaultResources).activateTenantHosts();
SystemState state = prepare(application, 1, 1, 1, 64, defaultResources, tester); // becomes 1, 1, 1, 1, 6
assertEquals(9, state.allHosts.size());
tester.activate(application, state.allHosts);
@@ -594,7 +594,7 @@ public class ProvisioningTest {
public void activate_after_reservation_timeout() {
ProvisioningTester tester = new ProvisioningTester.Builder().zone(new Zone(Environment.prod, RegionName.from("us-east"))).build();
- tester.makeReadyHosts(10, defaultResources).deployZoneApp();
+ tester.makeReadyHosts(10, defaultResources).activateTenantHosts();
ApplicationId application = tester.makeApplicationId();
SystemState state = prepare(application, 2, 2, 3, 3, defaultResources, tester);
@@ -616,7 +616,7 @@ public class ProvisioningTest {
public void out_of_capacity() {
ProvisioningTester tester = new ProvisioningTester.Builder().zone(new Zone(Environment.prod, RegionName.from("us-east"))).build();
- tester.makeReadyHosts(9, defaultResources).deployZoneApp(); // need 2+2+3+3=10
+ tester.makeReadyHosts(9, defaultResources).activateTenantHosts(); // need 2+2+3+3=10
ApplicationId application = tester.makeApplicationId();
try {
prepare(application, 2, 2, 3, 3, defaultResources, tester);
@@ -633,7 +633,7 @@ public class ProvisioningTest {
Environment.prod,
RegionName.from("us-east"))).build();
- tester.makeReadyHosts(13, defaultResources).deployZoneApp();
+ tester.makeReadyHosts(13, defaultResources).activateTenantHosts();
ApplicationId application = tester.makeApplicationId();
try {
prepare(application, 2, 2, 6, 3, defaultResources, tester);
@@ -651,7 +651,7 @@ public class ProvisioningTest {
Environment.prod,
RegionName.from("us-east"))).build();
- tester.makeReadyHosts(13, defaultResources).deployZoneApp();
+ tester.makeReadyHosts(13, defaultResources).activateTenantHosts();
ApplicationId application = tester.makeApplicationId();
prepare(application, 2, 2, 6, 3, defaultResources, tester);
}
@@ -659,7 +659,7 @@ public class ProvisioningTest {
@Test
public void out_of_capacity_but_cannot_fail() {
ProvisioningTester tester = new ProvisioningTester.Builder().zone(new Zone(Environment.prod, RegionName.from("us-east"))).build();
- tester.makeReadyHosts(4, defaultResources).deployZoneApp();
+ tester.makeReadyHosts(4, defaultResources).activateTenantHosts();
ApplicationId application = tester.makeApplicationId();
ClusterSpec cluster = ClusterSpec.request(ClusterSpec.Type.content, ClusterSpec.Id.from("music")).vespaVersion("4.5.6").build();
tester.prepare(application, cluster, Capacity.from(new ClusterResources(5, 1, NodeResources.unspecified()), false, false));
@@ -673,7 +673,7 @@ public class ProvisioningTest {
ApplicationId application = tester.makeApplicationId();
// Flag all nodes for retirement
List<Node> readyNodes = tester.makeReadyNodes(5, defaultResources);
- readyNodes.forEach(node -> tester.patchNode(node.withWantToRetire(true, Agent.system, tester.clock().instant())));
+ tester.patchNodes(readyNodes, (node) -> node.withWantToRetire(true, Agent.system, tester.clock().instant()));
try {
prepare(application, 2, 0, 2, 0, defaultResources, tester);
@@ -693,7 +693,7 @@ public class ProvisioningTest {
ApplicationId application = tester.makeApplicationId();
// Create 10 nodes
- tester.makeReadyHosts(10, defaultResources).deployZoneApp();
+ tester.makeReadyHosts(10, defaultResources).activateTenantHosts();
// Allocate 5 nodes
ClusterSpec cluster = ClusterSpec.request(ClusterSpec.Type.content, ClusterSpec.Id.from("music")).vespaVersion("4.5.6").build();
tester.activate(application, tester.prepare(application, cluster, capacity));
@@ -701,7 +701,7 @@ public class ProvisioningTest {
assertEquals(0, NodeList.copyOf(tester.nodeRepository().getNodes(application, Node.State.active)).retired().size());
// Mark the nodes as want to retire
- tester.nodeRepository().getNodes(application, Node.State.active).forEach(node -> tester.patchNode(node.withWantToRetire(true, Agent.system, tester.clock().instant())));
+ tester.nodeRepository().getNodes(application, Node.State.active).forEach(node -> tester.patchNode(node, (n) -> n.withWantToRetire(true, Agent.system, tester.clock().instant())));
// redeploy without allow failing
tester.activate(application, tester.prepare(application, cluster, capacityFORCED));
@@ -724,7 +724,7 @@ public class ProvisioningTest {
ApplicationId application1 = tester.makeApplicationId();
- tester.makeReadyHosts(14, defaultResources).deployZoneApp();
+ tester.makeReadyHosts(14, defaultResources).activateTenantHosts();
// deploy
SystemState state1 = prepare(application1, 3, 3, 4, 4, defaultResources, tester);
@@ -751,7 +751,7 @@ public class ProvisioningTest {
public void node_on_spare_host_retired_first() {
ProvisioningTester tester = new ProvisioningTester.Builder().zone(new Zone(Environment.prod, RegionName.from("us-east")))
.spareCount(1).build();
- tester.makeReadyHosts(7, defaultResources).deployZoneApp();
+ tester.makeReadyHosts(7, defaultResources).activateTenantHosts();
ApplicationId application = tester.makeApplicationId();
ClusterSpec spec = ClusterSpec.request(ClusterSpec.Type.content, ClusterSpec.Id.from("content1")).vespaVersion("7.1.2").build();
@@ -774,7 +774,7 @@ public class ProvisioningTest {
ProvisioningTester tester = new ProvisioningTester.Builder().zone(new Zone(Environment.prod, RegionName.from("us-east"))).build();
ApplicationId application = tester.makeApplicationId();
- tester.makeReadyHosts(10, defaultResources).deployZoneApp();
+ tester.makeReadyHosts(10, defaultResources).activateTenantHosts();
// Deploy application
{
@@ -786,7 +786,7 @@ public class ProvisioningTest {
// Retire some nodes and redeploy
{
List<Node> nodesToRetire = tester.getNodes(application, Node.State.active).asList().subList(0, 2);
- nodesToRetire.forEach(node -> tester.patchNode(node.withWantToRetire(true, Agent.system, tester.clock().instant())));
+ tester.patchNodes(nodesToRetire, (node) -> node.withWantToRetire(true, Agent.system, tester.clock().instant()));
SystemState state = prepare(application, 2, 0, 2, 0, defaultResources, tester);
tester.activate(application, state.allHosts);
@@ -802,7 +802,7 @@ public class ProvisioningTest {
ProvisioningTester tester = new ProvisioningTester.Builder().zone(new Zone(Environment.prod, RegionName.from("us-east"))).build();
ApplicationId application = tester.makeApplicationId();
- tester.makeReadyHosts(2, defaultResources).deployZoneApp();
+ tester.makeReadyHosts(2, defaultResources).activateTenantHosts();
// Deploy fails with out of capacity
try {
@@ -813,7 +813,7 @@ public class ProvisioningTest {
tester.getNodes(application, Node.State.reserved).size());
// Enough nodes become available
- tester.makeReadyHosts(2, defaultResources).deployZoneApp();
+ tester.makeReadyHosts(2, defaultResources).activateTenantHosts();
// Deploy is retried after a few minutes
tester.clock().advance(Duration.ofMinutes(2));
@@ -883,7 +883,7 @@ public class ProvisioningTest {
var tester = new ProvisioningTester.Builder().zone(new Zone(Environment.prod, RegionName.from("us-east"))).build();
var application = tester.makeApplicationId();
- tester.makeReadyHosts(4, defaultResources).deployZoneApp();
+ tester.makeReadyHosts(4, defaultResources).activateTenantHosts();
// Application allocates two content nodes initially, with cluster type content
ClusterSpec cluster = ClusterSpec.request(ClusterSpec.Type.content, ClusterSpec.Id.from("music")).vespaVersion("1.2.3").build();
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 d56cae799b2..4c8d5caad43 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
@@ -53,6 +53,7 @@ import java.util.Optional;
import java.util.Set;
import java.util.UUID;
import java.util.function.Function;
+import java.util.function.UnaryOperator;
import java.util.logging.Level;
import java.util.stream.Collectors;
@@ -139,7 +140,22 @@ public class ProvisioningTester {
public CapacityPolicies capacityPolicies() { return capacityPolicies; }
public NodeList getNodes(ApplicationId id, Node.State ... inState) { return NodeList.copyOf(nodeRepository.getNodes(id, inState)); }
- public void patchNode(Node node) { nodeRepository.write(node, () -> {}); }
+ public Node patchNode(Node node, UnaryOperator<Node> patcher) {
+ return patchNodes(List.of(node), patcher).get(0);
+ }
+
+ public List<Node> patchNodes(List<Node> nodes, UnaryOperator<Node> patcher) {
+ List<Node> updated = new ArrayList<>();
+ for (var node : nodes) {
+ try (var lock = nodeRepository.lock(node)) {
+ node = nodeRepository.getNode(node.hostname()).get();
+ node = patcher.apply(node);
+ nodeRepository.write(node, lock);
+ updated.add(node);
+ }
+ }
+ return updated;
+ }
public List<HostSpec> prepare(ApplicationId application, ClusterSpec cluster, int nodeCount, int groups, NodeResources resources) {
return prepare(application, cluster, nodeCount, groups, false, resources);
@@ -320,7 +336,7 @@ public class ProvisioningTester {
return makeReadyNodes(n, flavor, NodeType.tenant);
}
- /** Call deployZoneApp() after this before deploying applications */
+ /** Call {@link this#activateTenantHosts()} after this before deploying applications */
public ProvisioningTester makeReadyHosts(int n, NodeResources resources) {
makeReadyNodes(n, resources, NodeType.host, 5);
return this;
@@ -494,7 +510,7 @@ public class ProvisioningTester {
return nodes;
}
- public void deployZoneApp() {
+ public void activateTenantHosts() {
ApplicationId applicationId = makeApplicationId();
List<HostSpec> list = prepare(applicationId,
ClusterSpec.request(ClusterSpec.Type.container, ClusterSpec.Id.from("node-admin")).vespaVersion("6.42").build(),
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 51261c29a71..0ef7071b095 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
@@ -129,9 +129,7 @@ public class VirtualNodeProvisioningTest {
assertDistinctParentHosts(nodes, ClusterSpec.Type.container, containerNodeCount);
assertDistinctParentHosts(nodes, ClusterSpec.Type.content, contentNodeCount);
- for (Node n : nodes) {
- tester.patchNode(n.withParentHostname("clashing"));
- }
+ tester.patchNodes(nodes, (n) -> n.withParentHostname("clashing"));
containerHosts = prepare(containerClusterSpec, containerNodeCount, groups);
contentHosts = prepare(contentClusterSpec, contentNodeCount, groups);
activate(containerHosts, contentHosts);
@@ -160,9 +158,7 @@ public class VirtualNodeProvisioningTest {
assertDistinctParentHosts(nodes, ClusterSpec.Type.container, containerNodeCount);
assertDistinctParentHosts(nodes, ClusterSpec.Type.content, contentNodeCount);
- for (Node n : nodes) {
- tester.patchNode(n.withParentHostname("clashing"));
- }
+ tester.patchNodes(nodes, (n) -> n.withParentHostname("clashing"));
OutOfCapacityException expected = null;
try {
containerHosts = prepare(containerClusterSpec, containerNodeCount, groups);
@@ -216,9 +212,9 @@ public class VirtualNodeProvisioningTest {
assertEquals(3, nodes.size());
// Set indistinct parents
- tester.patchNode(nodes.get(0).withParentHostname("parentHost1"));
- tester.patchNode(nodes.get(1).withParentHostname("parentHost1"));
- tester.patchNode(nodes.get(2).withParentHostname("parentHost2"));
+ tester.patchNode(nodes.get(0), (n) -> n.withParentHostname("parentHost1"));
+ tester.patchNode(nodes.get(1), (n) -> n.withParentHostname("parentHost1"));
+ tester.patchNode(nodes.get(2), (n) -> n.withParentHostname("parentHost2"));
nodes = getNodes(applicationId);
assertEquals(3, nodes.stream().filter(n -> n.parentHostname().isPresent()).count());
diff --git a/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/restapi/NodesV2ApiTest.java b/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/restapi/NodesV2ApiTest.java
index 2cd2fe1fc28..1a354686ae4 100644
--- a/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/restapi/NodesV2ApiTest.java
+++ b/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/restapi/NodesV2ApiTest.java
@@ -333,7 +333,7 @@ public class NodesV2ApiTest {
// Node types running a single container can share their IP address with child node
tester.assertResponse(new Request("http://localhost:8080/nodes/v2/node",
- "[" + asNodeJson("cfghost42.yahoo.com", NodeType.confighost, "default", Optional.empty(), "127.0.42.1") + "]",
+ "[" + asNodeJson("cfghost42.yahoo.com", NodeType.confighost, "default", Optional.empty(), Optional.empty(), "127.0.42.1") + "]",
Request.Method.POST), 200,
"{\"message\":\"Added 1 nodes to the provisioned state\"}");
tester.assertResponse(new Request("http://localhost:8080/nodes/v2/node",
@@ -349,7 +349,7 @@ public class NodesV2ApiTest {
// ... nor with child node on different host
tester.assertResponse(new Request("http://localhost:8080/nodes/v2/node",
- "[" + asNodeJson("cfghost43.yahoo.com", NodeType.confighost, "default", Optional.empty(), "127.0.43.1") + "]",
+ "[" + asNodeJson("cfghost43.yahoo.com", NodeType.confighost, "default", Optional.empty(), Optional.empty(), "127.0.43.1") + "]",
Request.Method.POST), 200,
"{\"message\":\"Added 1 nodes to the provisioned state\"}");
tester.assertResponse(new Request("http://localhost:8080/nodes/v2/node/cfg42.yahoo.com",
@@ -939,6 +939,30 @@ public class NodesV2ApiTest {
"\"resources\":{\"vcpu\":56.0,\"memoryGb\":34.0,\"diskGb\":12.0,\"bandwidthGbps\":78.0,\"diskSpeed\":\"fast\",\"storageType\":\"remote\"}");
}
+ @Test
+ public void test_node_switch_hostname() throws Exception {
+ String hostname = "host42.yahoo.com";
+ // Add host with switch hostname
+ String json = asNodeJson(hostname, NodeType.host, "default", Optional.empty(), Optional.of("switch0"), "127.0.42.1", "::42:1");
+ assertResponse(new Request("http://localhost:8080/nodes/v2/node",
+ ("[" + json + "]").getBytes(StandardCharsets.UTF_8),
+ Request.Method.POST),
+ "{\"message\":\"Added 1 nodes to the provisioned state\"}");
+ tester.assertResponseContains(new Request("http://localhost:8080/nodes/v2/node/" + hostname), "\"switchHostname\":\"switch0\"");
+
+ // Update switch hostname
+ json = "{\"switchHostname\":\"switch1\"}";
+ assertResponse(new Request("http://localhost:8080/nodes/v2/node/" + hostname, json.getBytes(StandardCharsets.UTF_8), Request.Method.PATCH),
+ "{\"message\":\"Updated host42.yahoo.com\"}");
+ tester.assertResponseContains(new Request("http://localhost:8080/nodes/v2/node/" + hostname), "\"switchHostname\":\"switch1\"");
+
+ // Clear switch hostname
+ json = "{\"switchHostname\":null}";
+ assertResponse(new Request("http://localhost:8080/nodes/v2/node/" + hostname, json.getBytes(StandardCharsets.UTF_8), Request.Method.PATCH),
+ "{\"message\":\"Updated host42.yahoo.com\"}");
+ tester.assertPartialResponse(new Request("http://localhost:8080/nodes/v2/node/" + hostname), "switchHostname", false);
+ }
+
private static String asDockerNodeJson(String hostname, String parentHostname, String... ipAddress) {
return asDockerNodeJson(hostname, NodeType.tenant, parentHostname, ipAddress);
}
@@ -958,14 +982,15 @@ public class NodesV2ApiTest {
}
private static String asHostJson(String hostname, String flavor, Optional<TenantName> reservedTo, String... ipAddress) {
- return asNodeJson(hostname, NodeType.host, flavor, reservedTo, ipAddress);
+ return asNodeJson(hostname, NodeType.host, flavor, reservedTo, Optional.empty(), ipAddress);
}
- private static String asNodeJson(String hostname, NodeType nodeType, String flavor, Optional<TenantName> reservedTo, String... ipAddress) {
+ private static String asNodeJson(String hostname, NodeType nodeType, String flavor, Optional<TenantName> reservedTo, Optional<String> switchHostname, String... ipAddress) {
return "{\"hostname\":\"" + hostname + "\", \"openStackId\":\"" + hostname + "\"," +
createIpAddresses(ipAddress) +
"\"flavor\":\"" + flavor + "\"" +
(reservedTo.isPresent() ? ", \"reservedTo\":\"" + reservedTo.get().value() + "\"" : "") +
+ (switchHostname.isPresent() ? ", \"switchHostname\":\"" + switchHostname.get() + "\"" : "") +
", \"type\":\"" + nodeType + "\"}";
}
@@ -989,8 +1014,8 @@ public class NodesV2ApiTest {
tester.assertFile(request, file);
}
- private void assertResponse(Request request, String file) throws IOException {
- tester.assertResponse(request, file);
+ private void assertResponse(Request request, String response) throws IOException {
+ tester.assertResponse(request, response);
}
}