summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorHÃ¥kon Hallingstad <hakon@verizonmedia.com>2021-03-03 15:20:48 +0100
committerGitHub <noreply@github.com>2021-03-03 15:20:48 +0100
commitf4ce7be8026913554f81737b059ddee90e4f8ab7 (patch)
treea354ae12d3491256601b50e4ba5335bdba5fe922
parentb9a60a5a2901cdd103ba904f50c7fee4a5adb588 (diff)
parent9490d21634b322a2f2842b3cd7400af537de998d (diff)
Merge pull request #16765 from vespa-engine/mpolden/respect-exclusive
Respect exclusive request when allocating by type
-rw-r--r--node-repository/src/main/java/com/yahoo/vespa/hosted/provision/provisioning/NodeAllocation.java4
-rw-r--r--node-repository/src/main/java/com/yahoo/vespa/hosted/provision/provisioning/NodeRepositoryProvisioner.java3
-rw-r--r--node-repository/src/main/java/com/yahoo/vespa/hosted/provision/provisioning/NodeSpec.java10
-rw-r--r--node-repository/src/main/java/com/yahoo/vespa/hosted/provision/testutils/MockHostProvisioner.java6
-rw-r--r--node-repository/src/test/java/com/yahoo/vespa/hosted/provision/maintenance/DynamicProvisioningMaintainerTest.java11
-rw-r--r--node-repository/src/test/java/com/yahoo/vespa/hosted/provision/provisioning/ProvisioningTester.java1
6 files changed, 25 insertions, 10 deletions
diff --git a/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/provisioning/NodeAllocation.java b/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/provisioning/NodeAllocation.java
index f6e0ede4e7d..b5943cedb9c 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
@@ -436,9 +436,9 @@ class NodeAllocation {
}
private static Integer parseIndex(String hostname) {
- // Node index is the first number appearing in the hostname, before the first dot
+ // Node index is the first number appearing in the hostname
try {
- return Integer.parseInt(hostname.replaceFirst("^\\D+(\\d+)\\..*", "$1"));
+ return Integer.parseInt(hostname.replaceFirst("^\\D+(\\d+).*", "$1"));
} catch (NumberFormatException e) {
throw new IllegalArgumentException("Could not parse index from hostname '" + hostname + "'", e);
}
diff --git a/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/provisioning/NodeRepositoryProvisioner.java b/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/provisioning/NodeRepositoryProvisioner.java
index 22242e526f9..ec5444bfc98 100644
--- a/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/provisioning/NodeRepositoryProvisioner.java
+++ b/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/provisioning/NodeRepositoryProvisioner.java
@@ -19,7 +19,6 @@ import com.yahoo.config.provision.Zone;
import com.yahoo.transaction.Mutex;
import com.yahoo.vespa.flags.FlagSource;
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.applications.Application;
import com.yahoo.vespa.hosted.provision.autoscale.AllocatableClusterResources;
@@ -105,7 +104,7 @@ public class NodeRepositoryProvisioner implements Provisioner {
else {
groups = 1; // type request with multiple groups is not supported
resources = requested.minResources().nodeResources();
- nodeSpec = NodeSpec.from(requested.type());
+ nodeSpec = NodeSpec.from(requested.type(), cluster.isExclusive());
}
return asSortedHosts(preparer.prepare(application, cluster, nodeSpec, groups), resources);
}
diff --git a/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/provisioning/NodeSpec.java b/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/provisioning/NodeSpec.java
index c3cb805499c..9a111deeac3 100644
--- a/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/provisioning/NodeSpec.java
+++ b/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/provisioning/NodeSpec.java
@@ -77,8 +77,8 @@ public interface NodeSpec {
return new CountNodeSpec(nodeCount, resources, exclusive, canFail);
}
- static NodeSpec from(NodeType type) {
- return new TypeNodeSpec(type);
+ static NodeSpec from(NodeType type, boolean exclusive) {
+ return new TypeNodeSpec(type, exclusive);
}
/** A node spec specifying a node count and a flavor */
@@ -174,16 +174,18 @@ public interface NodeSpec {
private static final Map<NodeType, Integer> WANTED_NODE_COUNT = Map.of(NodeType.config, 3);
private final NodeType type;
+ private final boolean exclusive;
- public TypeNodeSpec(NodeType type) {
+ public TypeNodeSpec(NodeType type, boolean exclusive) {
this.type = type;
+ this.exclusive = exclusive;
}
@Override
public NodeType type() { return type; }
@Override
- public boolean isExclusive() { return false; }
+ public boolean isExclusive() { return exclusive; }
@Override
public boolean isCompatible(Flavor flavor, NodeFlavors flavors) { return true; }
diff --git a/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/testutils/MockHostProvisioner.java b/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/testutils/MockHostProvisioner.java
index 25e74df677b..a7a0848e1c1 100644
--- a/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/testutils/MockHostProvisioner.java
+++ b/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/testutils/MockHostProvisioner.java
@@ -58,6 +58,10 @@ public class MockHostProvisioner implements HostProvisioner {
Flavor hostFlavor = this.hostFlavor.orElseGet(() -> flavors.stream().filter(f -> compatible(f, resources))
.findFirst()
.orElseThrow(() -> new OutOfCapacityException("No host flavor matches " + resources)));
+ Optional<ApplicationId> exclusiveTo = Optional.empty();
+ if (sharing == HostSharing.exclusive) {
+ exclusiveTo = Optional.of(applicationId);
+ }
List<ProvisionedHost> hosts = new ArrayList<>();
for (int index : provisionIndices) {
String hostHostname = hostType == NodeType.host ? "hostname" + index : hostType.name() + index;
@@ -65,7 +69,7 @@ public class MockHostProvisioner implements HostProvisioner {
hostHostname,
hostFlavor,
hostType,
- Optional.empty(),
+ exclusiveTo,
createAddressesForHost(hostType, hostFlavor, index),
resources,
osVersion));
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 4a1b3df0514..dea7e50d641 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
@@ -428,13 +428,18 @@ public class DynamicProvisioningMaintainerTest {
// Initial config server hosts are provisioned manually
ApplicationId hostApp = ApplicationId.from("hosted-vespa", "configserver-host", "default");
+ ApplicationId configSrvApp = ApplicationId.from("hosted-vespa", "zone-config-servers", "default");
List<Node> provisionedHosts = tester.makeReadyNodes(3, "default", NodeType.confighost).stream()
.sorted(Comparator.comparing(Node::hostname))
.collect(Collectors.toList());
tester.prepareAndActivateInfraApplication(hostApp, NodeType.confighost);
+ tester.patchNodes(provisionedHosts, (node) -> node.withExclusiveTo(configSrvApp));
+ assertTrue("All hosts are exclusive", tester.nodeRepository().nodes().list()
+ .nodeType(NodeType.confighost)
+ .stream()
+ .allMatch(node -> node.allocation().get().membership().cluster().isExclusive()));
// Provision config servers
- ApplicationId configSrvApp = ApplicationId.from("hosted-vespa", "zone-config-servers", "default");
for (int i = 0; i < provisionedHosts.size(); i++) {
tester.makeReadyChildren(1, i + 1, NodeResources.unspecified(), NodeType.config,
provisionedHosts.get(i).hostname(), (nodeIndex) -> "cfg" + nodeIndex);
@@ -498,6 +503,10 @@ public class DynamicProvisioningMaintainerTest {
newNode = tester.nodeRepository().nodes().node(newNode.hostname()).get();
assertSame(Node.State.active, newNode.state());
assertEquals("Removed index is reused", removedIndex, newNode.allocation().get().membership().index());
+ assertTrue("All nodes are exclusive", tester.nodeRepository().nodes().list()
+ .nodeType(NodeType.config)
+ .stream()
+ .allMatch(node -> node.allocation().get().membership().cluster().isExclusive()));
// Next redeployment does nothing
NodeList nodesBefore = tester.nodeRepository().nodes().list().nodeType(NodeType.config);
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 eefbd03ce4e..df348fc1c48 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
@@ -230,6 +230,7 @@ public class ProvisioningTester {
ClusterSpec cluster = ClusterSpec.request(ClusterSpec.Type.container, ClusterSpec.Id.from(nodeType.toString()))
.vespaVersion(version)
.stateful(nodeType == NodeType.config || nodeType == NodeType.controller)
+ .exclusive(nodeType != NodeType.tenant)
.build();
Capacity capacity = Capacity.fromRequiredNodeType(nodeType);
List<HostSpec> hostSpecs = prepare(application, cluster, capacity);