Search in sources :

Example 66 with Node

use of com.yahoo.vespa.hosted.provision.Node in project vespa by vespa-engine.

the class ProvisioningTest method out_of_capacity_all_nodes_want_to_retire.

@Test
public void out_of_capacity_all_nodes_want_to_retire() {
    ProvisioningTester tester = new ProvisioningTester(new Zone(Environment.prod, RegionName.from("us-east")));
    ApplicationId application = tester.makeApplicationId();
    // Flag all nodes for retirement
    List<Node> readyNodes = tester.makeReadyNodes(5, "default");
    readyNodes.forEach(node -> tester.patchNode(node.with(node.status().withWantToRetire(true))));
    try {
        prepare(application, 2, 0, 2, 0, "default", tester);
        fail("Expected exception");
    } catch (OutOfCapacityException e) {
        assertTrue(e.getMessage().startsWith("Could not satisfy request"));
    }
}
Also used : Zone(com.yahoo.config.provision.Zone) Node(com.yahoo.vespa.hosted.provision.Node) OutOfCapacityException(com.yahoo.config.provision.OutOfCapacityException) ApplicationId(com.yahoo.config.provision.ApplicationId) Test(org.junit.Test)

Example 67 with Node

use of com.yahoo.vespa.hosted.provision.Node in project vespa by vespa-engine.

the class ProvisioningTest method application_deployment_extends_existing_reservations_on_deploy.

@Test
public void application_deployment_extends_existing_reservations_on_deploy() {
    ProvisioningTester tester = new ProvisioningTester(new Zone(Environment.prod, RegionName.from("us-east")));
    ApplicationId application = tester.makeApplicationId();
    tester.makeReadyNodes(2, "default");
    // Deploy fails with out of capacity
    try {
        prepare(application, 2, 0, 2, 0, "default", tester);
        fail("Expected exception");
    } catch (OutOfCapacityException ignored) {
    }
    assertEquals("Reserved a subset of required nodes", 2, tester.getNodes(application, Node.State.reserved).size());
    // Enough nodes become available
    tester.makeReadyNodes(2, "default");
    // Deploy is retried after a few minutes
    tester.clock().advance(Duration.ofMinutes(2));
    SystemState state = prepare(application, 2, 0, 2, 0, "default", tester);
    List<Node> reserved = tester.getNodes(application, Node.State.reserved).asList();
    assertEquals("Reserved required nodes", 4, reserved.size());
    assertTrue("Time of event is updated for all nodes", reserved.stream().allMatch(n -> n.history().event(History.Event.Type.reserved).get().at().equals(tester.clock().instant())));
    // Over 10 minutes pass since first reservation. First set of reserved nodes are not expired
    tester.clock().advance(Duration.ofMinutes(8).plus(Duration.ofSeconds(1)));
    ReservationExpirer expirer = new ReservationExpirer(tester.nodeRepository(), tester.clock(), Duration.ofMinutes(10), new JobControl(tester.nodeRepository().database()));
    expirer.run();
    assertEquals("Nodes remain reserved", 4, tester.getNodes(application, Node.State.reserved).size());
    tester.activate(application, state.allHosts);
    assertEquals(4, tester.getNodes(application, Node.State.active).size());
}
Also used : Capacity(com.yahoo.config.provision.Capacity) InstanceName(com.yahoo.config.provision.InstanceName) ApplicationName(com.yahoo.config.provision.ApplicationName) Version(com.yahoo.component.Version) ApplicationId(com.yahoo.config.provision.ApplicationId) ClusterMembership(com.yahoo.config.provision.ClusterMembership) ClusterSpec(com.yahoo.config.provision.ClusterSpec) Node(com.yahoo.vespa.hosted.provision.Node) ConfigserverConfig(com.yahoo.cloud.config.ConfigserverConfig) Function(java.util.function.Function) RegionName(com.yahoo.config.provision.RegionName) NameResolver(com.yahoo.vespa.hosted.provision.persistence.NameResolver) TenantName(com.yahoo.config.provision.TenantName) Curator(com.yahoo.vespa.curator.Curator) HashSet(java.util.HashSet) ReservationExpirer(com.yahoo.vespa.hosted.provision.maintenance.ReservationExpirer) History(com.yahoo.vespa.hosted.provision.node.History) NestedTransaction(com.yahoo.transaction.NestedTransaction) Duration(java.time.Duration) NodeList(com.yahoo.vespa.hosted.provision.NodeList) Assert.fail(org.junit.Assert.fail) NodeFlavors(com.yahoo.config.provision.NodeFlavors) Iterator(java.util.Iterator) Environment(com.yahoo.config.provision.Environment) Predicate(java.util.function.Predicate) OutOfCapacityException(com.yahoo.config.provision.OutOfCapacityException) JobControl(com.yahoo.vespa.hosted.provision.maintenance.JobControl) HostSpec(com.yahoo.config.provision.HostSpec) FlavorsConfig(com.yahoo.config.provisioning.FlavorsConfig) MockNameResolver(com.yahoo.vespa.hosted.provision.testutils.MockNameResolver) Set(java.util.Set) Assert.assertTrue(org.junit.Assert.assertTrue) Test(org.junit.Test) UUID(java.util.UUID) Collectors(java.util.stream.Collectors) HostFilter(com.yahoo.config.provision.HostFilter) List(java.util.List) Agent(com.yahoo.vespa.hosted.provision.node.Agent) Ignore(org.junit.Ignore) Flavor(com.yahoo.config.provision.Flavor) Assert.assertFalse(org.junit.Assert.assertFalse) Zone(com.yahoo.config.provision.Zone) Optional(java.util.Optional) MockCurator(com.yahoo.vespa.curator.mock.MockCurator) Collections(java.util.Collections) Assert.assertEquals(org.junit.Assert.assertEquals) Zone(com.yahoo.config.provision.Zone) Node(com.yahoo.vespa.hosted.provision.Node) OutOfCapacityException(com.yahoo.config.provision.OutOfCapacityException) JobControl(com.yahoo.vespa.hosted.provision.maintenance.JobControl) ReservationExpirer(com.yahoo.vespa.hosted.provision.maintenance.ReservationExpirer) ApplicationId(com.yahoo.config.provision.ApplicationId) Test(org.junit.Test)

Example 68 with Node

use of com.yahoo.vespa.hosted.provision.Node in project vespa by vespa-engine.

the class ResourceCapacityTest method basic_capacity_and_compare_operations.

@Test
public void basic_capacity_and_compare_operations() {
    FlavorConfigBuilder b = new FlavorConfigBuilder();
    b.addFlavor("host-large", 6., 6., 6, Flavor.Type.BARE_METAL);
    b.addFlavor("host-small", 3., 3., 3, Flavor.Type.BARE_METAL);
    b.addFlavor("d-1", 1, 1., 1, Flavor.Type.DOCKER_CONTAINER);
    b.addFlavor("d-2", 2, 2., 2, Flavor.Type.DOCKER_CONTAINER);
    b.addFlavor("d-3", 3, 3., 3, Flavor.Type.DOCKER_CONTAINER);
    b.addFlavor("d-3-disk", 3, 3., 5, Flavor.Type.DOCKER_CONTAINER);
    b.addFlavor("d-3-mem", 3, 5., 3, Flavor.Type.DOCKER_CONTAINER);
    b.addFlavor("d-3-cpu", 5, 3., 3, Flavor.Type.DOCKER_CONTAINER);
    FlavorsConfig flavors = b.build();
    Flavor hostLargeFlavor = new Flavor(flavors.flavor(0));
    Flavor hostSmallFlavor = new Flavor(flavors.flavor(1));
    Flavor d1Flavor = new Flavor(flavors.flavor(2));
    Flavor d2Flavor = new Flavor(flavors.flavor(3));
    Flavor d3Flavor = new Flavor(flavors.flavor(4));
    Flavor d3DiskFlavor = new Flavor(flavors.flavor(5));
    Flavor d3MemFlavor = new Flavor(flavors.flavor(6));
    Flavor d3CPUFlavor = new Flavor(flavors.flavor(7));
    Node nodeHostSmall = node(hostSmallFlavor);
    ResourceCapacity capacityOfHostSmall = new ResourceCapacity(nodeHostSmall);
    // Assert initial capacities
    assertTrue(capacityOfHostSmall.hasCapacityFor(hostSmallFlavor));
    assertTrue(capacityOfHostSmall.hasCapacityFor(d1Flavor));
    assertTrue(capacityOfHostSmall.hasCapacityFor(d2Flavor));
    assertTrue(capacityOfHostSmall.hasCapacityFor(d3Flavor));
    assertFalse(capacityOfHostSmall.hasCapacityFor(hostLargeFlavor));
    // Also check that we are taking all three resources into accout
    assertFalse(capacityOfHostSmall.hasCapacityFor(d3DiskFlavor));
    assertFalse(capacityOfHostSmall.hasCapacityFor(d3MemFlavor));
    assertFalse(capacityOfHostSmall.hasCapacityFor(d3CPUFlavor));
    // Compare it to various flavors
    assertEquals(1, capacityOfHostSmall.compare(nodeCapacity(d1Flavor)));
    assertEquals(1, capacityOfHostSmall.compare(nodeCapacity(d2Flavor)));
    assertEquals(0, capacityOfHostSmall.compare(nodeCapacity(d3Flavor)));
    assertEquals(-1, capacityOfHostSmall.compare(nodeCapacity(d3DiskFlavor)));
    assertEquals(-1, capacityOfHostSmall.compare(nodeCapacity(d3CPUFlavor)));
    assertEquals(-1, capacityOfHostSmall.compare(nodeCapacity(d3MemFlavor)));
    // Change free capacity and assert on rest capacity
    capacityOfHostSmall.subtract(node(d1Flavor));
    assertEquals(0, capacityOfHostSmall.compare(nodeCapacity(d2Flavor)));
    // Assert on rest capacity
    assertTrue(capacityOfHostSmall.hasCapacityFor(d1Flavor));
    assertFalse(capacityOfHostSmall.hasCapacityFor(d3Flavor));
    // At last compare the disk and cpu and mem variations
    assertEquals(-1, nodeCapacity(d3Flavor).compare(nodeCapacity(d3DiskFlavor)));
    assertEquals(1, nodeCapacity(d3DiskFlavor).compare(nodeCapacity(d3CPUFlavor)));
    assertEquals(-1, nodeCapacity(d3CPUFlavor).compare(nodeCapacity(d3MemFlavor)));
    assertEquals(1, nodeCapacity(d3MemFlavor).compare(nodeCapacity(d3DiskFlavor)));
}
Also used : Node(com.yahoo.vespa.hosted.provision.Node) FlavorsConfig(com.yahoo.config.provisioning.FlavorsConfig) Flavor(com.yahoo.config.provision.Flavor) Test(org.junit.Test)

Example 69 with Node

use of com.yahoo.vespa.hosted.provision.Node in project vespa by vespa-engine.

the class MultigroupProvisioningTest method deploy.

private void deploy(ApplicationId application, Capacity capacity, int wantedGroups, ProvisioningTester tester) {
    int nodeCount = capacity.nodeCount();
    String flavor = capacity.flavor().get();
    int previousActiveNodeCount = tester.getNodes(application, Node.State.active).flavor(flavor).size();
    tester.activate(application, prepare(application, capacity, wantedGroups, tester));
    assertEquals("Superfluous nodes are retired, but no others - went from " + previousActiveNodeCount + " to " + nodeCount + " nodes", Math.max(0, previousActiveNodeCount - capacity.nodeCount()), tester.getNodes(application, Node.State.active).retired().flavor(flavor).size());
    assertEquals("Other flavors are retired", 0, tester.getNodes(application, Node.State.active).nonretired().notFlavor(capacity.flavor().get()).size());
    // Check invariants for all nodes
    Set<Integer> allIndexes = new HashSet<>();
    for (Node node : tester.getNodes(application, Node.State.active).asList()) {
        // Node indexes must be unique
        int index = node.allocation().get().membership().index();
        assertFalse("Node indexes are unique", allIndexes.contains(index));
        allIndexes.add(index);
        assertTrue(node.allocation().get().membership().cluster().group().isPresent());
    }
    // Count unretired nodes and groups of the requested flavor
    Set<Integer> indexes = new HashSet<>();
    Map<ClusterSpec.Group, Integer> nonretiredGroups = new HashMap<>();
    for (Node node : tester.getNodes(application, Node.State.active).nonretired().flavor(flavor).asList()) {
        indexes.add(node.allocation().get().membership().index());
        ClusterSpec.Group group = node.allocation().get().membership().cluster().group().get();
        nonretiredGroups.put(group, nonretiredGroups.getOrDefault(group, 0) + 1);
        if (wantedGroups > 1)
            assertTrue("Group indexes are always in [0, wantedGroups>", group.index() < wantedGroups);
    }
    assertEquals("Total nonretired nodes", nodeCount, indexes.size());
    assertEquals("Total nonretired groups", wantedGroups, nonretiredGroups.size());
    for (Integer groupSize : nonretiredGroups.values()) assertEquals("Group size", (long) nodeCount / wantedGroups, (long) groupSize);
    Map<ClusterSpec.Group, Integer> allGroups = new HashMap<>();
    for (Node node : tester.getNodes(application, Node.State.active).flavor(flavor).asList()) {
        ClusterSpec.Group group = node.allocation().get().membership().cluster().group().get();
        allGroups.put(group, nonretiredGroups.getOrDefault(group, 0) + 1);
    }
    assertEquals("No additional groups are retained containing retired nodes", wantedGroups, allGroups.size());
}
Also used : HashMap(java.util.HashMap) Node(com.yahoo.vespa.hosted.provision.Node) ClusterSpec(com.yahoo.config.provision.ClusterSpec) HashSet(java.util.HashSet)

Example 70 with Node

use of com.yahoo.vespa.hosted.provision.Node in project vespa by vespa-engine.

the class NodeTypeProvisioningTest method retire_multiple_proxy_simultaneously.

@Test
public void retire_multiple_proxy_simultaneously() {
    MockDeployer deployer = new MockDeployer(tester.provisioner(), Collections.singletonMap(application, new MockDeployer.ApplicationContext(application, clusterSpec, capacity, 1)));
    RetiredExpirer retiredExpirer = new RetiredExpirer(tester.nodeRepository(), tester.orchestrator(), deployer, tester.clock(), Duration.ofDays(30), Duration.ofMinutes(10), new JobControl(tester.nodeRepository().database()));
    final int numNodesToRetire = 5;
    {
        // Deploy
        List<HostSpec> hosts = deployProxies(application, tester);
        assertEquals("Reserved all proxies", 11, hosts.size());
        tester.activate(application, new HashSet<>(hosts));
        List<Node> nodes = tester.nodeRepository().getNodes(NodeType.proxy, Node.State.active);
        assertEquals("Activated all proxies", 11, nodes.size());
    }
    List<Node> nodesToRetire = tester.nodeRepository().getNodes(NodeType.proxy, Node.State.active).subList(3, 3 + numNodesToRetire);
    String currentyRetiringHostname;
    {
        nodesToRetire.forEach(nodeToRetire -> tester.nodeRepository().write(nodeToRetire.with(nodeToRetire.status().withWantToRetire(true))));
        List<HostSpec> hosts = deployProxies(application, tester);
        assertEquals(11, hosts.size());
        tester.activate(application, new HashSet<>(hosts));
        List<Node> nodes = tester.nodeRepository().getNodes(NodeType.proxy, Node.State.active);
        assertEquals(11, nodes.size());
        // Verify that wantToRetire has been propagated
        List<Node> nodesCurrentlyRetiring = nodes.stream().filter(node -> node.allocation().get().membership().retired()).collect(Collectors.toList());
        assertEquals(1, nodesCurrentlyRetiring.size());
        // The retiring node should be one of the nodes we marked for retirement
        currentyRetiringHostname = nodesCurrentlyRetiring.get(0).hostname();
        assertTrue(nodesToRetire.stream().map(Node::hostname).filter(hostname -> hostname.equals(currentyRetiringHostname)).count() == 1);
    }
    {
        // Redeploying while the node is still retiring has no effect
        List<HostSpec> hosts = deployProxies(application, tester);
        assertEquals(11, hosts.size());
        tester.activate(application, new HashSet<>(hosts));
        List<Node> nodes = tester.nodeRepository().getNodes(NodeType.proxy, Node.State.active);
        assertEquals(11, nodes.size());
        // Verify that wantToRetire has been propagated
        List<Node> nodesCurrentlyRetiring = nodes.stream().filter(node -> node.allocation().get().membership().retired()).collect(Collectors.toList());
        assertEquals(1, nodesCurrentlyRetiring.size());
        // The node that started retiring is still the only one retiring
        assertEquals(currentyRetiringHostname, nodesCurrentlyRetiring.get(0).hostname());
    }
    {
        tester.advanceTime(Duration.ofMinutes(11));
        retiredExpirer.run();
        List<HostSpec> hosts = deployProxies(application, tester);
        assertEquals(10, hosts.size());
        tester.activate(application, new HashSet<>(hosts));
        List<Node> nodes = tester.nodeRepository().getNodes(NodeType.proxy, Node.State.active);
        assertEquals(10, nodes.size());
        // Verify the node we previously set to retire has finished retiring
        assertEquals(Node.State.inactive, tester.nodeRepository().getNode(currentyRetiringHostname).orElseThrow(RuntimeException::new).state());
        // Verify that a node is currently retiring
        List<Node> nodesCurrentlyRetiring = nodes.stream().filter(node -> node.allocation().get().membership().retired()).collect(Collectors.toList());
        assertEquals(1, nodesCurrentlyRetiring.size());
        // This node is different from the one that was retiring previously
        String newRetiringHostname = nodesCurrentlyRetiring.get(0).hostname();
        assertNotEquals(currentyRetiringHostname, newRetiringHostname);
        // ... but is one of the nodes that were put to wantToRetire earlier
        assertTrue(nodesToRetire.stream().map(Node::hostname).filter(hostname -> hostname.equals(newRetiringHostname)).count() == 1);
    }
    for (int i = 0; i < 10; i++) {
        tester.advanceTime(Duration.ofMinutes(11));
        retiredExpirer.run();
        List<HostSpec> hosts = deployProxies(application, tester);
        tester.activate(application, new HashSet<>(hosts));
    }
    // After a long time, all currently active proxy nodes are not marked with wantToRetire or as retired
    long numRetiredActiveProxyNodes = tester.nodeRepository().getNodes(NodeType.proxy, Node.State.active).stream().filter(node -> !node.status().wantToRetire()).filter(node -> !node.allocation().get().membership().retired()).count();
    assertEquals(11 - numNodesToRetire, numRetiredActiveProxyNodes);
    // All the nodes that were marked with wantToRetire earlier are now inactive
    assertEquals(nodesToRetire.stream().map(Node::hostname).collect(Collectors.toSet()), tester.nodeRepository().getNodes(Node.State.inactive).stream().map(Node::hostname).collect(Collectors.toSet()));
}
Also used : Capacity(com.yahoo.config.provision.Capacity) Version(com.yahoo.component.Version) ApplicationId(com.yahoo.config.provision.ApplicationId) Environment(com.yahoo.config.provision.Environment) NodeType(com.yahoo.config.provision.NodeType) JobControl(com.yahoo.vespa.hosted.provision.maintenance.JobControl) ClusterSpec(com.yahoo.config.provision.ClusterSpec) HostSpec(com.yahoo.config.provision.HostSpec) Assert.assertTrue(org.junit.Assert.assertTrue) Test(org.junit.Test) Node(com.yahoo.vespa.hosted.provision.Node) Collectors(java.util.stream.Collectors) RegionName(com.yahoo.config.provision.RegionName) Assert.assertNotEquals(org.junit.Assert.assertNotEquals) MockDeployer(com.yahoo.vespa.hosted.provision.testutils.MockDeployer) HashSet(java.util.HashSet) RetiredExpirer(com.yahoo.vespa.hosted.provision.maintenance.RetiredExpirer) List(java.util.List) Agent(com.yahoo.vespa.hosted.provision.node.Agent) Duration(java.time.Duration) Zone(com.yahoo.config.provision.Zone) Collections(java.util.Collections) Assert.assertEquals(org.junit.Assert.assertEquals) Before(org.junit.Before) Node(com.yahoo.vespa.hosted.provision.Node) JobControl(com.yahoo.vespa.hosted.provision.maintenance.JobControl) RetiredExpirer(com.yahoo.vespa.hosted.provision.maintenance.RetiredExpirer) HostSpec(com.yahoo.config.provision.HostSpec) List(java.util.List) MockDeployer(com.yahoo.vespa.hosted.provision.testutils.MockDeployer) HashSet(java.util.HashSet) Test(org.junit.Test)

Aggregations

Node (com.yahoo.vespa.hosted.provision.Node)121 Test (org.junit.Test)67 ApplicationId (com.yahoo.config.provision.ApplicationId)40 ClusterSpec (com.yahoo.config.provision.ClusterSpec)33 List (java.util.List)26 ArrayList (java.util.ArrayList)23 Zone (com.yahoo.config.provision.Zone)22 Flavor (com.yahoo.config.provision.Flavor)21 HashSet (java.util.HashSet)19 Collectors (java.util.stream.Collectors)19 Optional (java.util.Optional)18 NodeRepository (com.yahoo.vespa.hosted.provision.NodeRepository)16 Duration (java.time.Duration)16 HostSpec (com.yahoo.config.provision.HostSpec)15 NodeType (com.yahoo.config.provision.NodeType)15 Agent (com.yahoo.vespa.hosted.provision.node.Agent)13 Map (java.util.Map)13 HashMap (java.util.HashMap)12 Collections (java.util.Collections)11 Set (java.util.Set)11