Search in sources :

Example 11 with ApplicationInstanceReference

use of com.yahoo.vespa.applicationmodel.ApplicationInstanceReference in project vespa by vespa-engine.

the class OrchestratorUtilTest method applicationid_conversion_are_symmetric.

/**
 * Here we don't care how the internal of the different application
 * id/reference look like as long as we get back to exactly where we
 * started from a round trip. I.e I'm not testing validity of the
 * different representations.
 */
@Test
public void applicationid_conversion_are_symmetric() throws Exception {
    // From appId to appRef and back
    ApplicationInstanceReference appRef = OrchestratorUtil.toApplicationInstanceReference(APPID_1, new DummyInstanceLookupService());
    ApplicationId appIdRoundTrip = OrchestratorUtil.toApplicationId(appRef);
    Assert.assertEquals(APPID_1, appIdRoundTrip);
    // From appRef to appId and back
    ApplicationId appId = OrchestratorUtil.toApplicationId(APPREF_1);
    ApplicationInstanceReference appRefRoundTrip = OrchestratorUtil.toApplicationInstanceReference(appId, new DummyInstanceLookupService());
    Assert.assertEquals(APPREF_1, appRefRoundTrip);
}
Also used : ApplicationInstanceReference(com.yahoo.vespa.applicationmodel.ApplicationInstanceReference) ApplicationId(com.yahoo.config.provision.ApplicationId) Test(org.junit.Test)

Example 12 with ApplicationInstanceReference

use of com.yahoo.vespa.applicationmodel.ApplicationInstanceReference in project vespa by vespa-engine.

the class OrchestratorImpl method suspendGroup.

// Public for testing purposes
@Override
public void suspendGroup(NodeGroup nodeGroup) throws HostStateChangeDeniedException, HostNameNotFoundException {
    ApplicationInstanceReference applicationReference = nodeGroup.getApplicationReference();
    try (MutableStatusRegistry hostStatusRegistry = statusService.lockApplicationInstance_forCurrentThreadOnly(applicationReference)) {
        ApplicationInstanceStatus appStatus = statusService.forApplicationInstance(applicationReference).getApplicationInstanceStatus();
        if (appStatus == ApplicationInstanceStatus.ALLOWED_TO_BE_DOWN) {
            return;
        }
        ApplicationApi applicationApi = new ApplicationApiImpl(nodeGroup, hostStatusRegistry, clusterControllerClientFactory);
        policy.grantSuspensionRequest(applicationApi);
    }
}
Also used : ApplicationApi(com.yahoo.vespa.orchestrator.model.ApplicationApi) ApplicationApiImpl(com.yahoo.vespa.orchestrator.model.ApplicationApiImpl) MutableStatusRegistry(com.yahoo.vespa.orchestrator.status.MutableStatusRegistry) ApplicationInstanceStatus(com.yahoo.vespa.orchestrator.status.ApplicationInstanceStatus) ApplicationInstanceReference(com.yahoo.vespa.applicationmodel.ApplicationInstanceReference)

Example 13 with ApplicationInstanceReference

use of com.yahoo.vespa.applicationmodel.ApplicationInstanceReference in project vespa by vespa-engine.

the class OrchestratorImpl method compareNodeGroupsForSuspend.

private static int compareNodeGroupsForSuspend(NodeGroup leftNodeGroup, NodeGroup rightNodeGroup) {
    ApplicationInstanceReference leftApplicationReference = leftNodeGroup.getApplicationReference();
    ApplicationInstanceReference rightApplicationReference = rightNodeGroup.getApplicationReference();
    // ApplicationInstanceReference.toString() is e.g. "hosted-vespa:routing:dev:some-region:default"
    return leftApplicationReference.asString().compareTo(rightApplicationReference.asString());
}
Also used : ApplicationInstanceReference(com.yahoo.vespa.applicationmodel.ApplicationInstanceReference)

Example 14 with ApplicationInstanceReference

use of com.yahoo.vespa.applicationmodel.ApplicationInstanceReference in project vespa by vespa-engine.

the class OrchestratorImpl method setApplicationStatus.

private void setApplicationStatus(ApplicationId appId, ApplicationInstanceStatus status) throws ApplicationStateChangeDeniedException, ApplicationIdNotFoundException {
    ApplicationInstanceReference appRef = OrchestratorUtil.toApplicationInstanceReference(appId, instanceLookupService);
    try (MutableStatusRegistry statusRegistry = statusService.lockApplicationInstance_forCurrentThreadOnly(appRef)) {
        // Short-circuit if already in wanted state
        if (status == statusRegistry.getApplicationInstanceStatus())
            return;
        // Set content clusters for this application in maintenance on suspend
        if (status == ApplicationInstanceStatus.ALLOWED_TO_BE_DOWN) {
            ApplicationInstance application = getApplicationInstance(appRef);
            // Mark it allowed to be down before we manipulate the clustercontroller
            OrchestratorUtil.getHostsUsedByApplicationInstance(application).forEach(h -> statusRegistry.setHostState(h, HostStatus.ALLOWED_TO_BE_DOWN));
            // If the clustercontroller throws an error the nodes will be marked as allowed to be down
            // and be set back up on next resume invocation.
            setClusterStateInController(application, ClusterControllerNodeState.MAINTENANCE);
        }
        statusRegistry.setApplicationInstanceStatus(status);
    }
}
Also used : ApplicationInstance(com.yahoo.vespa.applicationmodel.ApplicationInstance) MutableStatusRegistry(com.yahoo.vespa.orchestrator.status.MutableStatusRegistry) ApplicationInstanceReference(com.yahoo.vespa.applicationmodel.ApplicationInstanceReference)

Example 15 with ApplicationInstanceReference

use of com.yahoo.vespa.applicationmodel.ApplicationInstanceReference 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)

Aggregations

ApplicationInstanceReference (com.yahoo.vespa.applicationmodel.ApplicationInstanceReference)17 ApplicationInstance (com.yahoo.vespa.applicationmodel.ApplicationInstance)10 HostName (com.yahoo.vespa.applicationmodel.HostName)6 ClusterId (com.yahoo.vespa.applicationmodel.ClusterId)5 ConfigId (com.yahoo.vespa.applicationmodel.ConfigId)5 ServiceType (com.yahoo.vespa.applicationmodel.ServiceType)5 Test (org.junit.Test)5 ApplicationId (com.yahoo.config.provision.ApplicationId)4 ApplicationInstanceId (com.yahoo.vespa.applicationmodel.ApplicationInstanceId)4 TenantId (com.yahoo.vespa.applicationmodel.TenantId)4 ServiceCluster (com.yahoo.vespa.applicationmodel.ServiceCluster)3 ServiceInstance (com.yahoo.vespa.applicationmodel.ServiceInstance)3 ServiceModel (com.yahoo.vespa.service.monitor.ServiceModel)3 HashMap (java.util.HashMap)3 GET (javax.ws.rs.GET)3 Path (javax.ws.rs.Path)3 Produces (javax.ws.rs.Produces)3 SuperModel (com.yahoo.config.model.api.SuperModel)2 Zone (com.yahoo.config.provision.Zone)2 OrchestratorUtil.getHostsUsedByApplicationInstance (com.yahoo.vespa.orchestrator.OrchestratorUtil.getHostsUsedByApplicationInstance)2