Search in sources :

Example 1 with NodeGroup

use of com.yahoo.vespa.orchestrator.model.NodeGroup in project vespa by vespa-engine.

the class HostedVespaPolicy method grantSuspensionRequest.

// TODO: Remove later - currently used for backward compatibility testing
@Override
public void grantSuspensionRequest(ApplicationInstance applicationInstance, HostName hostName, MutableStatusRegistry hostStatusService) throws HostStateChangeDeniedException {
    NodeGroup nodeGroup = new NodeGroup(applicationInstance);
    nodeGroup.addNode(hostName);
    ApplicationApi applicationApi = new ApplicationApiImpl(nodeGroup, hostStatusService, clusterControllerClientFactory);
    grantSuspensionRequest(applicationApi);
}
Also used : ApplicationApi(com.yahoo.vespa.orchestrator.model.ApplicationApi) ApplicationApiImpl(com.yahoo.vespa.orchestrator.model.ApplicationApiImpl) NodeGroup(com.yahoo.vespa.orchestrator.model.NodeGroup)

Example 2 with NodeGroup

use of com.yahoo.vespa.orchestrator.model.NodeGroup in project vespa by vespa-engine.

the class OrchestratorImpl method suspend.

@Override
public void suspend(HostName hostName) throws HostStateChangeDeniedException, HostNameNotFoundException {
    ApplicationInstance appInstance = getApplicationInstance(hostName);
    NodeGroup nodeGroup = new NodeGroup(appInstance, hostName);
    suspendGroup(nodeGroup);
}
Also used : ApplicationInstance(com.yahoo.vespa.applicationmodel.ApplicationInstance) NodeGroup(com.yahoo.vespa.orchestrator.model.NodeGroup)

Example 3 with NodeGroup

use of com.yahoo.vespa.orchestrator.model.NodeGroup in project vespa by vespa-engine.

the class OrchestratorImpl method acquirePermissionToRemove.

@Override
public void acquirePermissionToRemove(HostName hostName) throws OrchestrationException {
    ApplicationInstance appInstance = getApplicationInstance(hostName);
    NodeGroup nodeGroup = new NodeGroup(appInstance, hostName);
    try (MutableStatusRegistry statusRegistry = statusService.lockApplicationInstance_forCurrentThreadOnly(appInstance.reference())) {
        ApplicationApi applicationApi = new ApplicationApiImpl(nodeGroup, statusRegistry, clusterControllerClientFactory);
        policy.acquirePermissionToRemove(applicationApi);
    }
}
Also used : ApplicationInstance(com.yahoo.vespa.applicationmodel.ApplicationInstance) ApplicationApi(com.yahoo.vespa.orchestrator.model.ApplicationApi) ApplicationApiImpl(com.yahoo.vespa.orchestrator.model.ApplicationApiImpl) MutableStatusRegistry(com.yahoo.vespa.orchestrator.status.MutableStatusRegistry) NodeGroup(com.yahoo.vespa.orchestrator.model.NodeGroup)

Example 4 with NodeGroup

use of com.yahoo.vespa.orchestrator.model.NodeGroup in project vespa by vespa-engine.

the class OrchestratorImpl method nodeGroupsOrderedForSuspend.

/**
 * PROBLEM
 * Take the example of 2 Docker hosts:
 *  - Docker host 1 has two nodes A1 and B1, belonging to the application with
 *    a globally unique ID A and B, respectively.
 *  - Similarly, Docker host 2 has two nodes running content nodes A2 and B2,
 *    and we assume both A1 and A2 (and B1 and B2) have services within the same service cluster.
 *
 * Suppose both Docker hosts wanting to reboot, and
 *  - Docker host 1 asks to suspend A1 and B1, while
 *  - Docker host 2 asks to suspend B2 and A2.
 *
 * The Orchestrator may allow suspend of A1 and B2, before requesting the suspension of B1 and A2.
 * None of these can be suspended (assuming max 1 suspended content node per content cluster),
 * and so both requests for suspension will fail.
 *
 * Note that it's not a deadlock - both client will fail immediately and resume both A1 and B2 before
 * responding to the client, and if host 1 asks later w/o host 2 asking at the same time,
 * it will be given permission to suspend. However if both hosts were to request in lock-step,
 * there would be starvation. And in general, it would fail requests for suspension more
 * than necessary.
 *
 * SOLUTION
 * The solution we're using is to order the hostnames by the globally unique application instance ID,
 * e.g. hosted-vespa:routing:dev:some-region:default. In the example above, it would guarantee
 * Docker host 2 would ensure ask to suspend B2 before A2. We take care of that ordering here.
 *
 * NodeGroups complicate the above picture a little:  Each A1, A2, B1, and B2 is a NodeGroup that may
 * contain several nodes (on the same Docker host).  But the argument still applies.
 */
private List<NodeGroup> nodeGroupsOrderedForSuspend(List<HostName> hostNames) throws HostNameNotFoundException {
    Map<ApplicationInstanceReference, NodeGroup> nodeGroupMap = new HashMap<>(hostNames.size());
    for (HostName hostName : hostNames) {
        ApplicationInstance application = getApplicationInstance(hostName);
        NodeGroup nodeGroup = nodeGroupMap.get(application.reference());
        if (nodeGroup == null) {
            nodeGroup = new NodeGroup(application);
            nodeGroupMap.put(application.reference(), nodeGroup);
        }
        nodeGroup.addNode(hostName);
    }
    return nodeGroupMap.values().stream().sorted(OrchestratorImpl::compareNodeGroupsForSuspend).collect(Collectors.toList());
}
Also used : ApplicationInstance(com.yahoo.vespa.applicationmodel.ApplicationInstance) HashMap(java.util.HashMap) ApplicationInstanceReference(com.yahoo.vespa.applicationmodel.ApplicationInstanceReference) HostName(com.yahoo.vespa.applicationmodel.HostName) NodeGroup(com.yahoo.vespa.orchestrator.model.NodeGroup)

Example 5 with NodeGroup

use of com.yahoo.vespa.orchestrator.model.NodeGroup in project vespa by vespa-engine.

the class HostedVespaClusterPolicyTest method verifyGroupGoingDownIsFine.

private void verifyGroupGoingDownIsFine(boolean noServicesOutsideGroupIsDown, boolean noServicesInGroupIsUp, int percentageOfServicesDownIfGroupIsAllowedToBeDown, boolean expectSuccess) {
    when(clusterApi.noServicesOutsideGroupIsDown()).thenReturn(noServicesOutsideGroupIsDown);
    when(clusterApi.noServicesInGroupIsUp()).thenReturn(noServicesInGroupIsUp);
    when(clusterApi.percentageOfServicesDownIfGroupIsAllowedToBeDown()).thenReturn(20);
    doReturn(ConcurrentSuspensionLimitForCluster.TEN_PERCENT).when(policy).getConcurrentSuspensionLimit(clusterApi);
    when(clusterApi.serviceType()).thenReturn(new ServiceType("service-type"));
    when(clusterApi.percentageOfServicesDown()).thenReturn(5);
    when(clusterApi.percentageOfServicesDownIfGroupIsAllowedToBeDown()).thenReturn(percentageOfServicesDownIfGroupIsAllowedToBeDown);
    when(clusterApi.servicesDownAndNotInGroupDescription()).thenReturn("services-down-and-not-in-group");
    when(clusterApi.nodesAllowedToBeDownNotInGroupDescription()).thenReturn("allowed-to-be-down");
    NodeGroup nodeGroup = mock(NodeGroup.class);
    when(clusterApi.getNodeGroup()).thenReturn(nodeGroup);
    when(nodeGroup.toCommaSeparatedString()).thenReturn("node-group");
    when(clusterApi.noServicesInGroupIsUp()).thenReturn(false);
    try {
        policy.verifyGroupGoingDownIsFine(clusterApi);
        if (!expectSuccess) {
            fail();
        }
    } catch (HostStateChangeDeniedException e) {
        if (!expectSuccess) {
            assertEquals("Changing the state of node-group would violate enough-services-up: " + "Suspension percentage for service type service-type would increase from " + "5% to 13%, over the limit of 10%. These instances may be down: " + "services-down-and-not-in-group and these hosts are allowed to be down: " + "allowed-to-be-down", e.getMessage());
            assertEquals("enough-services-up", e.getConstraintName());
        }
    }
}
Also used : ServiceType(com.yahoo.vespa.applicationmodel.ServiceType) NodeGroup(com.yahoo.vespa.orchestrator.model.NodeGroup)

Aggregations

NodeGroup (com.yahoo.vespa.orchestrator.model.NodeGroup)6 ApplicationInstance (com.yahoo.vespa.applicationmodel.ApplicationInstance)3 ApplicationApi (com.yahoo.vespa.orchestrator.model.ApplicationApi)3 ApplicationApiImpl (com.yahoo.vespa.orchestrator.model.ApplicationApiImpl)3 ApplicationInstanceReference (com.yahoo.vespa.applicationmodel.ApplicationInstanceReference)1 HostName (com.yahoo.vespa.applicationmodel.HostName)1 ServiceType (com.yahoo.vespa.applicationmodel.ServiceType)1 MutableStatusRegistry (com.yahoo.vespa.orchestrator.status.MutableStatusRegistry)1 HashMap (java.util.HashMap)1