diff options
author | Valerij Fredriksen <valerijf@verizonmedia.com> | 2020-10-29 16:21:31 +0100 |
---|---|---|
committer | Valerij Fredriksen <valerijf@verizonmedia.com> | 2020-10-29 16:22:50 +0100 |
commit | 61eb803ca7cbd26652c0b956e715bad6299fb917 (patch) | |
tree | 18718ba56ab212f89abc7420389a551d07ebf79b /node-repository | |
parent | e32b268ab273699a912c095af280e6c1f45e40af (diff) |
Allocate existing reserved application nodes for infra apps
Diffstat (limited to 'node-repository')
2 files changed, 41 insertions, 4 deletions
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 7ddb5fec3ed..4f5b2fd086e 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 @@ -132,7 +132,7 @@ public class NodePrioritizer { if ( !canAllocateNew) return; for (Node host : allNodes) { - if (host.type() == NodeType.host && !nodeRepository.canAllocateTenantNodeTo(host)) continue; + if ( ! nodeRepository.canAllocateTenantNodeTo(host)) continue; if (host.reservedTo().isPresent() && !host.reservedTo().get().equals(application.tenant())) continue; if (host.exclusiveTo().isPresent()) continue; // Never allocate new nodes to exclusive hosts if ( spareHosts.contains(host) && !canAllocateToSpareHosts) continue; @@ -156,7 +156,7 @@ public class NodePrioritizer { .filter(node -> node.allocation().isPresent()) .filter(node -> node.allocation().get().owner().equals(application)) .filter(node -> node.allocation().get().membership().cluster().id().equals(clusterSpec.id())) - .filter(node -> node.state() == Node.State.active || canStillAllocateToParentOf(node)) + .filter(node -> node.state() == Node.State.active || canStillAllocate(node)) .map(node -> candidateFrom(node, false)) .forEach(nodes::add); } @@ -204,8 +204,8 @@ public class NodePrioritizer { * * @return true if we still want to allocate the given node to its parent */ - private boolean canStillAllocateToParentOf(Node node) { - if (node.parentHostname().isEmpty()) return true; + private boolean canStillAllocate(Node node) { + if (node.type() != NodeType.tenant || node.parentHostname().isEmpty()) return true; Optional<Node> parent = allNodes.parentOf(node); if (parent.isEmpty()) return false; return nodeRepository.canAllocateTenantNodeTo(parent.get()); 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 f22ddfb81c9..9c1ced856cc 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 @@ -15,6 +15,7 @@ import com.yahoo.config.provision.HostSpec; import com.yahoo.config.provision.NodeResources; import com.yahoo.config.provision.NodeType; import com.yahoo.config.provision.OutOfCapacityException; +import com.yahoo.config.provision.ParentHostUnavailableException; import com.yahoo.config.provision.RegionName; import com.yahoo.config.provision.SystemName; import com.yahoo.config.provision.Zone; @@ -24,9 +25,14 @@ import com.yahoo.vespa.hosted.provision.maintenance.ReservationExpirer; import com.yahoo.vespa.hosted.provision.maintenance.TestMetric; import com.yahoo.vespa.hosted.provision.node.Agent; import com.yahoo.vespa.hosted.provision.node.History; +import com.yahoo.vespa.hosted.provision.node.IP; +import com.yahoo.vespa.service.duper.ConfigServerApplication; +import com.yahoo.vespa.service.duper.ConfigServerHostApplication; +import com.yahoo.vespa.service.duper.InfraApplication; import org.junit.Test; import java.time.Duration; +import java.util.Collection; import java.util.Collections; import java.util.HashSet; import java.util.Iterator; @@ -879,6 +885,37 @@ public class ProvisioningTest { } @Test + public void allocates_reserved_nodes_for_type_spec_deployment() { + ProvisioningTester tester = new ProvisioningTester.Builder().build(); + Function<InfraApplication, Collection<HostSpec>> prepareAndActivate = app -> tester.activate(app.getApplicationId(), + tester.prepare(app.getApplicationId(), app.getClusterSpecWithVersion(Version.fromString("1.2.3")), app.getCapacity())); + + // Add 2 config server hosts and 2 config servers + Flavor flavor = tester.nodeRepository().flavors().getFlavorOrThrow("default"); + List<Node> nodes = List.of( + Node.create("cfghost1", new IP.Config(Set.of("::1:0"), Set.of("::1:1")), "cfghost1", flavor, NodeType.confighost).build(), + Node.create("cfghost2", new IP.Config(Set.of("::2:0"), Set.of("::2:1")), "cfghost2", flavor, NodeType.confighost).ipConfig(Set.of("::2:0"), Set.of("::2:1")).build(), + Node.create("cfg1", new IP.Config(Set.of("::1:1"), Set.of()), "cfg1", flavor, NodeType.config).parentHostname("cfghost1").build(), + Node.create("cfg2", new IP.Config(Set.of("::2:1"), Set.of()), "cfg2", flavor, NodeType.config).parentHostname("cfghost2").build()); + tester.nodeRepository().setReady(tester.nodeRepository().addNodes(nodes, Agent.system), Agent.system, ProvisioningTest.class.getSimpleName()); + + InfraApplication cfgHostApp = new ConfigServerHostApplication(); + InfraApplication cfgApp = new ConfigServerApplication(); + + // Attempt to prepare & activate cfg, this should fail as cfg hosts are not active + try { + prepareAndActivate.apply(cfgApp); + } catch (ParentHostUnavailableException ignored) { } + assertEquals(2, tester.nodeRepository().list(cfgApp.getApplicationId()).state(Node.State.reserved).size()); + + prepareAndActivate.apply(cfgHostApp); + + // After activating cfg hosts, we can activate cfgs and all 4 should become active + prepareAndActivate.apply(cfgApp); + assertEquals(4, tester.nodeRepository().list().state(Node.State.active).size()); + } + + @Test public void cluster_spec_update_for_already_reserved_nodes() { ProvisioningTester tester = new ProvisioningTester.Builder().zone(new Zone(Environment.dev, RegionName.from("us-east"))).build(); ApplicationId application = ProvisioningTester.makeApplicationId(); |