From aa086b71fef26b5d238be1401669e44c514db73d Mon Sep 17 00:00:00 2001 From: Jon Bratseth Date: Fri, 2 Oct 2020 14:10:11 +0200 Subject: Don't reactivate on retired hosts --- .../hosted/provision/provisioning/Activator.java | 3 - .../provision/provisioning/NodePrioritizer.java | 14 ++ .../provisioning/DockerProvisioningTest.java | 148 +++++++++------------ .../provisioning/LoadBalancerProvisionerTest.java | 35 +++-- .../provisioning/VirtualNodeProvisioningTest.java | 122 +++++------------ 5 files changed, 125 insertions(+), 197 deletions(-) diff --git a/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/provisioning/Activator.java b/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/provisioning/Activator.java index 7158ccc57e3..e36d5fa4075 100644 --- a/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/provisioning/Activator.java +++ b/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/provisioning/Activator.java @@ -20,7 +20,6 @@ import java.util.HashSet; import java.util.List; import java.util.Optional; import java.util.Set; -import java.util.logging.Logger; import java.util.stream.Collectors; /** @@ -30,8 +29,6 @@ import java.util.stream.Collectors; */ class Activator { - private static final Logger logger = Logger.getLogger(Activator.class.getName()); - private final NodeRepository nodeRepository; private final Optional loadBalancerProvisioner; 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 9925ba65324..85c268c911d 100644 --- a/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/provisioning/NodePrioritizer.java +++ b/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/provisioning/NodePrioritizer.java @@ -136,6 +136,7 @@ public class NodePrioritizer { .filter(node -> legalStates.contains(node.state())) .filter(node -> node.allocation().isPresent()) .filter(node -> node.allocation().get().owner().equals(application)) + .filter(node -> node.state() == Node.State.active || canStillAllocateToParentOf(node)) .map(node -> candidateFrom(node, false)) .forEach(candidate -> nodes.add(candidate)); } @@ -177,6 +178,19 @@ public class NodePrioritizer { return requestedNodes.fulfilledBy(nofNodesInCluster - nodeFailedNodes); } + /** + * Even though a node is allocated to a parent, we may regret it and not offer it to the application + * now, if the node is currently not active. E.g if we want to retire the host. + * + * @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; + Optional parent = node.parentHostname().flatMap(nodeRepository::getNode); + if (parent.isEmpty()) return false; + return nodeRepository.canAllocateTenantNodeTo(parent.get()); + } + private static NodeResources resources(NodeSpec requestedNodes) { if ( ! (requestedNodes instanceof NodeSpec.CountNodeSpec)) return null; return requestedNodes.resources().get(); 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 d2a5e06469a..5abe7134aa0 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 @@ -46,10 +46,8 @@ public class DockerProvisioningTest { @Test public void docker_application_deployment() { ProvisioningTester tester = new ProvisioningTester.Builder().zone(new Zone(Environment.prod, RegionName.from("us-east"))).build(); - ApplicationId application1 = ProvisioningTester.makeApplicationId(); - - for (int i = 1; i < 10; i++) - tester.makeReadyVirtualDockerNodes(1, dockerResources, "dockerHost" + i); + tester.makeReadyHosts(10, dockerResources).activateTenantHosts(); + ApplicationId application1 = ProvisioningTester.makeApplicationId("app1"); Version wantedVespaVersion = Version.fromString("6.39"); int nodeCount = 7; @@ -86,13 +84,12 @@ public class DockerProvisioningTest { ApplicationId application1 = ProvisioningTester.makeApplicationId(); Version wantedVespaVersion = Version.fromString("6.39"); int nodeCount = 7; - List nodes = tester.prepare(application1, - ClusterSpec.request(ClusterSpec.Type.content, ClusterSpec.Id.from("myContent")).vespaVersion(wantedVespaVersion).build(), - nodeCount, 1, dockerResources); try { - tester.activate(application1, new HashSet<>(nodes)); + List nodes = tester.prepare(application1, + ClusterSpec.request(ClusterSpec.Type.content, ClusterSpec.Id.from("myContent")).vespaVersion(wantedVespaVersion).build(), + nodeCount, 1, dockerResources); fail("Expected the allocation to fail due to parent hosts not being active yet"); - } catch (ParentHostUnavailableException ignored) { } + } catch (OutOfCapacityException expected) { } // Activate the zone-app, thereby allocating the parents List hosts = tester.prepare(zoneApplication, @@ -101,9 +98,9 @@ public class DockerProvisioningTest { tester.activate(zoneApplication, hosts); // Try allocating tenants again - nodes = tester.prepare(application1, - ClusterSpec.request(ClusterSpec.Type.content, ClusterSpec.Id.from("myContent")).vespaVersion(wantedVespaVersion).build(), - nodeCount, 1, dockerResources); + List nodes = tester.prepare(application1, + ClusterSpec.request(ClusterSpec.Type.content, ClusterSpec.Id.from("myContent")).vespaVersion(wantedVespaVersion).build(), + nodeCount, 1, dockerResources); tester.activate(application1, new HashSet<>(nodes)); NodeList activeNodes = tester.getNodes(application1, Node.State.active); @@ -152,53 +149,49 @@ public class DockerProvisioningTest { /** Exclusive app first, then non-exclusive: Should give the same result as below */ @Test public void docker_application_deployment_with_exclusive_app_first() { + NodeResources hostResources = new NodeResources(10, 40, 1000, 10); + NodeResources nodeResources = new NodeResources(1, 4, 100, 1); ProvisioningTester tester = new ProvisioningTester.Builder().zone(new Zone(Environment.prod, RegionName.from("us-east"))).build(); - for (int i = 1; i <= 4; i++) - tester.makeReadyVirtualDockerNode(i, dockerResources, "host1"); - for (int i = 5; i <= 8; i++) - tester.makeReadyVirtualDockerNode(i, dockerResources, "host2"); - for (int i = 9; i <= 12; i++) - tester.makeReadyVirtualDockerNode(i, dockerResources, "host3"); - for (int i = 13; i <= 16; i++) - tester.makeReadyVirtualDockerNode(i, dockerResources, "host4"); - - ApplicationId application1 = ProvisioningTester.makeApplicationId(); - prepareAndActivate(application1, 2, true, tester); - assertEquals(Set.of("host1", "host2"), hostsOf(tester.getNodes(application1, Node.State.active))); - - ApplicationId application2 = ProvisioningTester.makeApplicationId(); - prepareAndActivate(application2, 2, false, tester); + tester.makeReadyHosts(4, hostResources).activateTenantHosts(); + ApplicationId application1 = ProvisioningTester.makeApplicationId("app1"); + prepareAndActivate(application1, 2, true, nodeResources, tester); + assertEquals(Set.of("host-1.yahoo.com", "host-2.yahoo.com"), + hostsOf(tester.getNodes(application1, Node.State.active))); + + ApplicationId application2 = ProvisioningTester.makeApplicationId("app2"); + prepareAndActivate(application2, 2, false, nodeResources, tester); assertEquals("Application is assigned to separate hosts", - Set.of("host3", "host4"), hostsOf(tester.getNodes(application2, Node.State.active))); + Set.of("host-3.yahoo.com", "host-4.yahoo.com"), + hostsOf(tester.getNodes(application2, Node.State.active))); } /** Non-exclusive app first, then an exclusive: Should give the same result as above */ @Test public void docker_application_deployment_with_exclusive_app_last() { + NodeResources hostResources = new NodeResources(10, 40, 1000, 10); + NodeResources nodeResources = new NodeResources(1, 4, 100, 1); ProvisioningTester tester = new ProvisioningTester.Builder().zone(new Zone(Environment.prod, RegionName.from("us-east"))).build(); - for (int i = 1; i <= 4; i++) - tester.makeReadyVirtualDockerNode(i, dockerResources, "host1"); - for (int i = 5; i <= 8; i++) - tester.makeReadyVirtualDockerNode(i, dockerResources, "host2"); - for (int i = 9; i <= 12; i++) - tester.makeReadyVirtualDockerNode(i, dockerResources, "host3"); - for (int i = 13; i <= 16; i++) - tester.makeReadyVirtualDockerNode(i, dockerResources, "host4"); - - ApplicationId application1 = ProvisioningTester.makeApplicationId(); - prepareAndActivate(application1, 2, false, tester); - assertEquals(Set.of("host1", "host2"), hostsOf(tester.getNodes(application1, Node.State.active))); - - ApplicationId application2 = ProvisioningTester.makeApplicationId(); - prepareAndActivate(application2, 2, true, tester); + tester.makeReadyHosts(4, hostResources).activateTenantHosts(); + ApplicationId application1 = ProvisioningTester.makeApplicationId("app1"); + prepareAndActivate(application1, 2, false, nodeResources, tester); + assertEquals(Set.of("host-1.yahoo.com", "host-2.yahoo.com"), + hostsOf(tester.getNodes(application1, Node.State.active))); + + ApplicationId application2 = ProvisioningTester.makeApplicationId("app2"); + prepareAndActivate(application2, 2, true, nodeResources, tester); assertEquals("Application is assigned to separate hosts", - Set.of("host3", "host4"), hostsOf(tester.getNodes(application2, Node.State.active))); + Set.of("host-3.yahoo.com", "host-4.yahoo.com"), + hostsOf(tester.getNodes(application2, Node.State.active))); } /** Test making an application exclusive */ @Test public void docker_application_deployment_change_to_exclusive_and_back() { + NodeResources hostResources = new NodeResources(10, 40, 1000, 10); + NodeResources nodeResources = new NodeResources(1, 4, 100, 1); ProvisioningTester tester = new ProvisioningTester.Builder().zone(new Zone(Environment.prod, RegionName.from("us-east"))).build(); + tester.makeReadyHosts(4, hostResources).activateTenantHosts(); + /* for (int i = 1; i <= 4; i++) tester.makeReadyVirtualDockerNode(i, dockerResources, "host1"); for (int i = 5; i <= 8; i++) @@ -207,19 +200,20 @@ public class DockerProvisioningTest { tester.makeReadyVirtualDockerNode(i, dockerResources, "host3"); for (int i = 13; i <= 16; i++) tester.makeReadyVirtualDockerNode(i, dockerResources, "host4"); + */ ApplicationId application1 = ProvisioningTester.makeApplicationId(); - prepareAndActivate(application1, 2, false, tester); + prepareAndActivate(application1, 2, false, nodeResources, tester); for (Node node : tester.getNodes(application1, Node.State.active)) assertFalse(node.allocation().get().membership().cluster().isExclusive()); - prepareAndActivate(application1, 2, true, tester); - assertEquals(Set.of("host1", "host2"), hostsOf(tester.getNodes(application1, Node.State.active))); + prepareAndActivate(application1, 2, true, nodeResources, tester); + assertEquals(Set.of("host-1.yahoo.com", "host-2.yahoo.com"), hostsOf(tester.getNodes(application1, Node.State.active))); for (Node node : tester.getNodes(application1, Node.State.active)) assertTrue(node.allocation().get().membership().cluster().isExclusive()); - prepareAndActivate(application1, 2, false, tester); - assertEquals(Set.of("host1", "host2"), hostsOf(tester.getNodes(application1, Node.State.active))); + prepareAndActivate(application1, 2, false, nodeResources, tester); + assertEquals(Set.of("host-1.yahoo.com", "host-2.yahoo.com"), hostsOf(tester.getNodes(application1, Node.State.active))); for (Node node : tester.getNodes(application1, Node.State.active)) assertFalse(node.allocation().get().membership().cluster().isExclusive()); } @@ -227,56 +221,34 @@ public class DockerProvisioningTest { /** Non-exclusive app first, then an exclusive: Should give the same result as above */ @Test public void docker_application_deployment_with_exclusive_app_causing_allocation_failure() { + ApplicationId application1 = ApplicationId.from("tenant1", "app1", "default"); + ApplicationId application2 = ApplicationId.from("tenant2", "app2", "default"); + ApplicationId application3 = ApplicationId.from("tenant1", "app3", "default"); + NodeResources hostResources = new NodeResources(10, 40, 1000, 10); + NodeResources nodeResources = new NodeResources(1, 4, 100, 1); ProvisioningTester tester = new ProvisioningTester.Builder().zone(new Zone(Environment.prod, RegionName.from("us-east"))).build(); - for (int i = 1; i <= 4; i++) - tester.makeReadyVirtualDockerNode(i, dockerResources, "host1"); - for (int i = 5; i <= 8; i++) - tester.makeReadyVirtualDockerNode(i, dockerResources, "host2"); - for (int i = 9; i <= 12; i++) - tester.makeReadyVirtualDockerNode(i, dockerResources, "host3"); - for (int i = 13; i <= 16; i++) - tester.makeReadyVirtualDockerNode(i, dockerResources, "host4"); + tester.makeReadyHosts(4, hostResources).activateTenantHosts(); - ApplicationId application1 = ProvisioningTester.makeApplicationId(); - prepareAndActivate(application1, 2, true, tester); - assertEquals(Set.of("host1", "host2"), hostsOf(tester.getNodes(application1, Node.State.active))); + prepareAndActivate(application1, 2, true, nodeResources, tester); + assertEquals(Set.of("host-1.yahoo.com", "host-2.yahoo.com"), + hostsOf(tester.getNodes(application1, Node.State.active))); try { - ApplicationId application2 = ApplicationId.from("tenant1", "app1", "default"); - prepareAndActivate(application2, 3, false, tester); + prepareAndActivate(application2, 3, false, nodeResources, tester); fail("Expected allocation failure"); } catch (Exception e) { assertEquals("No room for 3 nodes as 2 of 4 hosts are exclusive", "Could not satisfy request for 3 nodes with " + - "[vcpu: 1.0, memory: 4.0 Gb, disk 100.0 Gb, bandwidth: 1.0 Gbps, storage type: local] " + - "in tenant1.app1 container cluster 'myContainer' 6.39: " + + "[vcpu: 1.0, memory: 4.0 Gb, disk 100.0 Gb, bandwidth: 1.0 Gbps] " + + "in tenant2.app2 container cluster 'myContainer' 6.39: " + "Out of capacity on group 0: " + - "Not enough nodes available due to host exclusivity constraints, " + - "insufficient nodes available on separate physical hosts", + "Not enough nodes available due to host exclusivity constraints", e.getMessage()); } // Adding 3 nodes of another application for the same tenant works - ApplicationId application3 = ApplicationId.from(application1.tenant(), ApplicationName.from("app3"), InstanceName.from("default")); - prepareAndActivate(application3, 2, true, tester); - } - - // In dev, test and staging you get nodes with default flavor, but we should get specified flavor for docker nodes - @Test - public void get_specified_flavor_not_default_flavor_for_docker() { - ProvisioningTester tester = new ProvisioningTester.Builder().zone(new Zone(Environment.test, RegionName.from("corp-us-east-1"))).build(); - ApplicationId application1 = ProvisioningTester.makeApplicationId(); - tester.makeReadyVirtualDockerNodes(1, dockerResources, "dockerHost"); - - List hosts = tester.prepare(application1, - ClusterSpec.request(ClusterSpec.Type.content, ClusterSpec.Id.from("myContent")).vespaVersion("6.42").build(), - 1, 1, dockerResources); - tester.activate(application1, new HashSet<>(hosts)); - - NodeList nodes = tester.getNodes(application1, Node.State.active); - assertEquals(1, nodes.size()); - assertEquals("[vcpu: 1.0, memory: 4.0 Gb, disk 100.0 Gb, bandwidth: 1.0 Gbps, storage type: local]", nodes.asList().get(0).flavor().name()); + prepareAndActivate(application3, 2, true, nodeResources, tester); } @Test @@ -442,9 +414,13 @@ public class DockerProvisioningTest { } private void prepareAndActivate(ApplicationId application, int nodeCount, boolean exclusive, ProvisioningTester tester) { + prepareAndActivate(application, nodeCount, exclusive, dockerResources, tester); + } + + private void prepareAndActivate(ApplicationId application, int nodeCount, boolean exclusive, NodeResources resources, ProvisioningTester tester) { Set hosts = new HashSet<>(tester.prepare(application, ClusterSpec.request(ClusterSpec.Type.container, ClusterSpec.Id.from("myContainer")).vespaVersion("6.39").exclusive(exclusive).build(), - Capacity.from(new ClusterResources(nodeCount, 1, dockerResources), false, true))); + Capacity.from(new ClusterResources(nodeCount, 1, resources), false, true))); tester.activate(application, hosts); } diff --git a/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/provisioning/LoadBalancerProvisionerTest.java b/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/provisioning/LoadBalancerProvisionerTest.java index 88f5d41a4f0..3d784c403f3 100644 --- a/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/provisioning/LoadBalancerProvisionerTest.java +++ b/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/provisioning/LoadBalancerProvisionerTest.java @@ -6,6 +6,7 @@ import com.yahoo.config.provision.ApplicationId; import com.yahoo.config.provision.Capacity; import com.yahoo.config.provision.ClusterResources; import com.yahoo.config.provision.ClusterSpec; +import com.yahoo.config.provision.Flavor; import com.yahoo.config.provision.HostName; import com.yahoo.config.provision.HostSpec; import com.yahoo.config.provision.NodeResources; @@ -158,9 +159,10 @@ public class LoadBalancerProvisionerTest { @Test public void provision_load_balancers_with_dynamic_node_provisioning() { - var nodes = prepare(app1, Capacity.from(new ClusterResources(2, 1, new NodeResources(1, 4, 10, 0.3)), false, true), - true, - clusterRequest(ClusterSpec.Type.container, ClusterSpec.Id.from("qrs"))); + NodeResources resources = new NodeResources(1, 4, 10, 0.3); + tester.makeReadyHosts(2, resources); + tester.activateTenantHosts(); + var nodes = tester.prepare(app1, clusterRequest(ClusterSpec.Type.container, ClusterSpec.Id.from("qrs")), 2 , 1, resources); Supplier lb = () -> tester.nodeRepository().loadBalancers(app1).asList().get(0); assertTrue("Load balancer provisioned with empty reals", tester.loadBalancerService().instances().get(lb.get().id()).reals().isEmpty()); assignIps(tester.nodeRepository().getNodes(app1)); @@ -171,14 +173,12 @@ public class LoadBalancerProvisionerTest { NestedTransaction removeTransaction = new NestedTransaction(); tester.provisioner().remove(removeTransaction, app1); removeTransaction.commit(); - tester.nodeRepository().database().removeNodes(tester.nodeRepository().getNodes()); - assertTrue("Nodes are deleted", tester.nodeRepository().getNodes().isEmpty()); + tester.nodeRepository().database().removeNodes(tester.nodeRepository().getNodes(NodeType.tenant)); + assertTrue("Nodes are deleted", tester.nodeRepository().getNodes(NodeType.tenant).isEmpty()); assertSame("Load balancer is deactivated", LoadBalancer.State.inactive, lb.get().state()); // Application is redeployed - nodes = prepare(app1, Capacity.from(new ClusterResources(2, 1, new NodeResources(1, 4, 10, 0.3)), false, true), - true, - clusterRequest(ClusterSpec.Type.container, ClusterSpec.Id.from("qrs"))); + nodes = tester.prepare(app1, clusterRequest(ClusterSpec.Type.container, ClusterSpec.Id.from("qrs")), 2 , 1, resources); assertTrue("Load balancer is reconfigured with empty reals", tester.loadBalancerService().instances().get(lb.get().id()).reals().isEmpty()); assignIps(tester.nodeRepository().getNodes(app1)); tester.activate(app1, nodes); @@ -188,7 +188,6 @@ public class LoadBalancerProvisionerTest { @Test public void does_not_provision_load_balancers_for_non_tenant_node_type() { tester.activate(infraApp1, prepare(infraApp1, Capacity.fromRequiredNodeType(NodeType.host), - false, clusterRequest(ClusterSpec.Type.container, ClusterSpec.Id.from("tenant-host")))); assertTrue("No load balancer provisioned", tester.loadBalancerService().instances().isEmpty()); @@ -220,7 +219,7 @@ public class LoadBalancerProvisionerTest { ApplicationId configServerApp = ApplicationId.from("hosted-vespa", "zone-config-servers", "default"); Supplier> lbs = () -> tester.nodeRepository().loadBalancers(configServerApp).asList(); var cluster = ClusterSpec.Id.from("zone-config-servers"); - var nodes = prepare(configServerApp, Capacity.fromRequiredNodeType(NodeType.config), false, + var nodes = prepare(configServerApp, Capacity.fromRequiredNodeType(NodeType.config), clusterRequest(ClusterSpec.Type.admin, cluster)); assertEquals(1, lbs.get().size()); assertEquals("Prepare provisions load balancer with reserved nodes", 2, lbs.get().get(0).instance().reals().size()); @@ -235,7 +234,7 @@ public class LoadBalancerProvisionerTest { ApplicationId controllerApp = ApplicationId.from("hosted-vespa", "controller", "default"); Supplier> lbs = () -> tester.nodeRepository().loadBalancers(controllerApp).asList(); var cluster = ClusterSpec.Id.from("zone-config-servers"); - var nodes = prepare(controllerApp, Capacity.fromRequiredNodeType(NodeType.controller), false, + var nodes = prepare(controllerApp, Capacity.fromRequiredNodeType(NodeType.controller), clusterRequest(ClusterSpec.Type.container, cluster)); assertEquals(1, lbs.get().size()); assertEquals("Prepare provisions load balancer with reserved nodes", 2, lbs.get().get(0).instance().reals().size()); @@ -249,15 +248,11 @@ public class LoadBalancerProvisionerTest { } private Set prepare(ApplicationId application, ClusterSpec... specs) { - return prepare(application, Capacity.from(new ClusterResources(2, 1, new NodeResources(1, 4, 10, 0.3)), false, true), false, specs); + return prepare(application, Capacity.from(new ClusterResources(2, 1, new NodeResources(1, 4, 10, 0.3)), false, true), specs); } - private Set prepare(ApplicationId application, Capacity capacity, boolean dynamicDockerNodes, ClusterSpec... specs) { - if (dynamicDockerNodes) { - makeDynamicDockerNodes(specs.length * 2, capacity.type()); - } else { - tester.makeReadyNodes(specs.length * 2, new NodeResources(1, 4, 10, 0.3), capacity.type()); - } + private Set prepare(ApplicationId application, Capacity capacity, ClusterSpec... specs) { + tester.makeReadyNodes(specs.length * 2, new NodeResources(1, 4, 10, 0.3), capacity.type()); Set allNodes = new LinkedHashSet<>(); for (ClusterSpec spec : specs) { allNodes.addAll(tester.prepare(application, spec, capacity)); @@ -266,9 +261,11 @@ public class LoadBalancerProvisionerTest { } private void makeDynamicDockerNodes(int n, NodeType nodeType) { + tester.makeReadyHosts(n, new NodeResources(1, 4, 10, 0.3)); List nodes = new ArrayList<>(n); for (int i = 1; i <= n; i++) { - var node = Node.createDockerNode(Set.of(), "node" + i, "parent" + i, + var node = Node.createDockerNode(Set.of(), "vnode" + i, + tester.nodeRepository().getNodes(NodeType.host).get(n - 1).hostname(), new NodeResources(1, 4, 10, 0.3), nodeType); nodes.add(node); 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 b5e31e7cbdb..d1446cd8bc1 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 @@ -34,40 +34,37 @@ import static org.junit.Assert.assertNotNull; // to remove these tests public class VirtualNodeProvisioningTest { - private static final NodeResources flavor = new NodeResources(4, 8, 100, 1); + private static final NodeResources resources = new NodeResources(4, 8, 100, 1); private static final ClusterSpec contentClusterSpec = ClusterSpec.request(ClusterSpec.Type.content, ClusterSpec.Id.from("myContent")).vespaVersion("6.42").build(); private static final ClusterSpec containerClusterSpec = ClusterSpec.request(ClusterSpec.Type.container, ClusterSpec.Id.from("myContainer")).vespaVersion("6.42").build(); private ProvisioningTester tester = new ProvisioningTester.Builder().build(); - private ApplicationId applicationId = ProvisioningTester.makeApplicationId(); + private ApplicationId applicationId = ProvisioningTester.makeApplicationId("test"); @Test public void distinct_parent_host_for_each_node_in_a_cluster() { - tester.makeReadyVirtualDockerNodes(2, flavor, "parentHost1"); - tester.makeReadyVirtualDockerNodes(2, flavor, "parentHost2"); - tester.makeReadyVirtualDockerNodes(2, flavor, "parentHost3"); - tester.makeReadyVirtualDockerNodes(1, flavor, "parentHost4"); - - final int containerNodeCount = 4; - final int contentNodeCount = 3; - final int groups = 1; - List containerHosts = prepare(containerClusterSpec, containerNodeCount, groups); - List contentHosts = prepare(contentClusterSpec, contentNodeCount, groups); + tester.makeReadyHosts(4, new NodeResources(8, 16, 200, 2)) + .activateTenantHosts(); + int containerNodeCount = 4; + int contentNodeCount = 3; + int groups = 1; + List containerHosts = tester.prepare(applicationId, containerClusterSpec, containerNodeCount, groups, resources); + List contentHosts = tester.prepare(applicationId, contentClusterSpec, contentNodeCount, groups, resources); activate(containerHosts, contentHosts); - final List nodes = getNodes(applicationId); + List nodes = getNodes(applicationId); assertEquals(contentNodeCount + containerNodeCount, nodes.size()); assertDistinctParentHosts(nodes, ClusterSpec.Type.container, containerNodeCount); assertDistinctParentHosts(nodes, ClusterSpec.Type.content, contentNodeCount); // Go down to 3 nodes in container cluster - List containerHosts2 = prepare(containerClusterSpec, containerNodeCount - 1, groups); + List containerHosts2 = tester.prepare(applicationId, containerClusterSpec, containerNodeCount - 1, groups, resources); activate(containerHosts2); List nodes2 = getNodes(applicationId); assertDistinctParentHosts(nodes2, ClusterSpec.Type.container, containerNodeCount - 1); // Go up to 4 nodes again in container cluster - List containerHosts3 = prepare(containerClusterSpec, containerNodeCount, groups); + List containerHosts3 = tester.prepare(applicationId, containerClusterSpec, containerNodeCount, groups, resources); activate(containerHosts3); List nodes3 = getNodes(applicationId); assertDistinctParentHosts(nodes3, ClusterSpec.Type.container, containerNodeCount); @@ -97,7 +94,7 @@ public class VirtualNodeProvisioningTest { // Allowed to use same parent host for several nodes in same cluster in CD (even if prod env) { tester = new ProvisioningTester.Builder().zone(new Zone(SystemName.cd, Environment.prod, RegionName.from("us-east"))).build(); - tester.makeReadyNodes(4, flavor, NodeType.host, 1); + tester.makeReadyNodes(4, resources, NodeType.host, 1); tester.prepareAndActivateInfraApplication(ProvisioningTester.makeApplicationId(), NodeType.host); List containerHosts = prepare(containerClusterSpec, containerNodeCount, groups); @@ -110,19 +107,13 @@ public class VirtualNodeProvisioningTest { @Test public void will_retire_clashing_active() { - tester.makeReadyVirtualDockerNodes(1, flavor, "parentHost1"); - tester.makeReadyVirtualDockerNodes(1, flavor, "parentHost2"); - tester.makeReadyVirtualDockerNodes(1, flavor, "parentHost3"); - tester.makeReadyVirtualDockerNodes(1, flavor, "parentHost4"); - tester.makeReadyVirtualDockerNodes(1, flavor, "parentHost5"); - tester.makeReadyVirtualDockerNodes(1, flavor, "parentHost6"); - + tester.makeReadyHosts(4, resources).activateTenantHosts(); int containerNodeCount = 2; int contentNodeCount = 2; int groups = 1; - List containerHosts = prepare(containerClusterSpec, containerNodeCount, groups); - List contentHosts = prepare(contentClusterSpec, contentNodeCount, groups); - activate(containerHosts, contentHosts); + List containerNodes = tester.prepare(applicationId, containerClusterSpec, containerNodeCount, groups, resources); + List contentNodes = tester.prepare(applicationId, contentClusterSpec, contentNodeCount, groups, resources); + activate(containerNodes, contentNodes); List nodes = getNodes(applicationId); assertEquals(4, nodes.size()); @@ -130,48 +121,19 @@ public class VirtualNodeProvisioningTest { assertDistinctParentHosts(nodes, ClusterSpec.Type.content, contentNodeCount); tester.patchNodes(nodes, (n) -> n.withParentHostname("clashing")); - containerHosts = prepare(containerClusterSpec, containerNodeCount, groups); - contentHosts = prepare(contentClusterSpec, contentNodeCount, groups); - activate(containerHosts, contentHosts); + containerNodes = prepare(containerClusterSpec, containerNodeCount, groups); + contentNodes = prepare(contentClusterSpec, contentNodeCount, groups); + activate(containerNodes, contentNodes); nodes = getNodes(applicationId); assertEquals(6, nodes.size()); assertEquals(2, nodes.stream().filter(n -> n.allocation().get().membership().retired()).count()); } - @Test - public void fail_when_all_hosts_become_clashing() { - tester.makeReadyVirtualDockerNodes(1, flavor, "parentHost1"); - tester.makeReadyVirtualDockerNodes(1, flavor, "parentHost2"); - tester.makeReadyVirtualDockerNodes(1, flavor, "parentHost3"); - tester.makeReadyVirtualDockerNodes(1, flavor, "parentHost4"); - - int containerNodeCount = 2; - int contentNodeCount = 2; - int groups = 1; - List containerHosts = prepare(containerClusterSpec, containerNodeCount, groups); - List contentHosts = prepare(contentClusterSpec, contentNodeCount, groups); - activate(containerHosts, contentHosts); - - List nodes = getNodes(applicationId); - assertEquals(4, nodes.size()); - assertDistinctParentHosts(nodes, ClusterSpec.Type.container, containerNodeCount); - assertDistinctParentHosts(nodes, ClusterSpec.Type.content, contentNodeCount); - - tester.patchNodes(nodes, (n) -> n.withParentHostname("clashing")); - OutOfCapacityException expected = null; - try { - containerHosts = prepare(containerClusterSpec, containerNodeCount, groups); - } catch (OutOfCapacityException e) { - expected = e; - } - assertNotNull(expected); - } - @Test(expected = OutOfCapacityException.class) public void fail_when_too_few_distinct_parent_hosts() { - tester.makeReadyVirtualDockerNodes(2, flavor, "parentHost1"); - tester.makeReadyVirtualDockerNodes(1, flavor, "parentHost2"); + tester.makeReadyVirtualDockerNodes(2, resources, "parentHost1"); + tester.makeReadyVirtualDockerNodes(1, resources, "parentHost2"); int contentNodeCount = 3; List hosts = prepare(contentClusterSpec, contentNodeCount, 1); @@ -181,27 +143,9 @@ public class VirtualNodeProvisioningTest { assertDistinctParentHosts(nodes, ClusterSpec.Type.content, contentNodeCount); } - @Test - public void incomplete_parent_hosts_has_distinct_distribution() { - tester.makeReadyVirtualDockerNode(1, flavor, "parentHost1"); - tester.makeReadyVirtualDockerNode(1, flavor, "parentHost2"); - tester.makeReadyVirtualNodes(1, flavor); - - final int contentNodeCount = 3; - final int groups = 1; - final List contentHosts = prepare(contentClusterSpec, contentNodeCount, groups); - activate(contentHosts); - assertEquals(3, getNodes(applicationId).size()); - - tester.makeReadyVirtualDockerNode(2, flavor, "parentHost1"); - tester.makeReadyVirtualDockerNode(2, flavor, "parentHost2"); - - assertEquals(contentHosts, prepare(contentClusterSpec, contentNodeCount, groups)); - } - @Test public void indistinct_distribution_with_known_ready_nodes() { - tester.makeReadyVirtualNodes(3, flavor); + tester.makeReadyVirtualNodes(3, resources); final int contentNodeCount = 3; final int groups = 1; @@ -218,8 +162,8 @@ public class VirtualNodeProvisioningTest { nodes = getNodes(applicationId); assertEquals(3, nodes.stream().filter(n -> n.parentHostname().isPresent()).count()); - tester.makeReadyVirtualDockerNodes(1, flavor, "parentHost1"); - tester.makeReadyVirtualDockerNodes(2, flavor, "parentHost2"); + tester.makeReadyVirtualDockerNodes(1, resources, "parentHost1"); + tester.makeReadyVirtualDockerNodes(2, resources, "parentHost2"); OutOfCapacityException expectedException = null; try { @@ -232,7 +176,7 @@ public class VirtualNodeProvisioningTest { @Test public void unknown_distribution_with_known_ready_nodes() { - tester.makeReadyVirtualNodes(3, flavor); + tester.makeReadyVirtualNodes(3, resources); final int contentNodeCount = 3; final int groups = 1; @@ -240,15 +184,15 @@ public class VirtualNodeProvisioningTest { activate(contentHosts); assertEquals(3, getNodes(applicationId).size()); - tester.makeReadyVirtualDockerNodes(1, flavor, "parentHost1"); - tester.makeReadyVirtualDockerNodes(1, flavor, "parentHost2"); - tester.makeReadyVirtualDockerNodes(1, flavor, "parentHost3"); + tester.makeReadyVirtualDockerNodes(1, resources, "parentHost1"); + tester.makeReadyVirtualDockerNodes(1, resources, "parentHost2"); + tester.makeReadyVirtualDockerNodes(1, resources, "parentHost3"); assertEquals(contentHosts, prepare(contentClusterSpec, contentNodeCount, groups)); } @Test public void unknown_distribution_with_known_and_unknown_ready_nodes() { - tester.makeReadyVirtualNodes(3, flavor); + tester.makeReadyVirtualNodes(3, resources); int contentNodeCount = 3; int groups = 1; @@ -256,8 +200,8 @@ public class VirtualNodeProvisioningTest { activate(contentHosts); assertEquals(3, getNodes(applicationId).size()); - tester.makeReadyVirtualDockerNodes(1, flavor, "parentHost1"); - tester.makeReadyVirtualNodes(1, flavor); + tester.makeReadyVirtualDockerNodes(1, resources, "parentHost1"); + tester.makeReadyVirtualNodes(1, resources); assertEquals(contentHosts, prepare(contentClusterSpec, contentNodeCount, groups)); } @@ -289,7 +233,7 @@ public class VirtualNodeProvisioningTest { } private List prepare(ClusterSpec clusterSpec, int nodeCount, int groups) { - return tester.prepare(applicationId, clusterSpec, nodeCount, groups, flavor); + return tester.prepare(applicationId, clusterSpec, nodeCount, groups, resources); } private List prepare(ClusterSpec clusterSpec, int nodeCount, int groups, NodeResources flavor) { -- cgit v1.2.3