public static Optional<ServiceInstance> getStorageNodeAtHost(ApplicationInstance application, HostName hostName) { Set<ServiceInstance> storageNodesOnHost = application.serviceClusters().stream() .filter(VespaModelUtil::isStorage) .flatMap(cluster -> cluster.serviceInstances().stream()) .filter(service -> service.hostName().equals(hostName)) .collect(Collectors.toSet()); if (storageNodesOnHost.isEmpty()) { return Optional.empty(); } if (storageNodesOnHost.size() > 1) { throw new RuntimeException("Expected application " + application.applicationInstanceId() + " to have exactly one storage node service on host " + hostName + " but got " + storageNodesOnHost.size() + ": " + storageNodesOnHost); } return storageNodesOnHost.stream().findAny(); }
@Override public String toString() { return "StorageNodeImpl{" + "applicationInstance=" + applicationInstance.reference() + ", clusterId=" + clusterId + ", storageService=" + storageService + '}'; }
@Override public Host getHost(HostName hostName) throws HostNameNotFoundException { ApplicationInstance applicationInstance = getApplicationInstance(hostName); List<ServiceInstance> serviceInstances = applicationInstance .serviceClusters().stream() .flatMap(cluster -> cluster.serviceInstances().stream()) .filter(serviceInstance -> hostName.equals(serviceInstance.hostName())) .collect(Collectors.toList()); HostStatus hostStatus = getNodeStatus(applicationInstance.reference(), hostName); return new Host(hostName, hostStatus, applicationInstance.reference(), serviceInstances); }
public static Set<ServiceCluster> getClusterControllerServiceClusters(ApplicationInstance application) { return application.serviceClusters().stream() .filter(VespaModelUtil::isClusterController) .collect(Collectors.toSet()); }
/** * @return The node index of the storage node running on the host. * @throws java.lang.IllegalArgumentException if there is not exactly one storage node running on the host, * or if the index of that storage node could not be found. */ public static int getStorageNodeIndex(ApplicationInstance application, HostName hostName) { Optional<ServiceInstance> storageNode = getStorageNodeAtHost(application, hostName); if (!storageNode.isPresent()) { throw new IllegalArgumentException("Failed to find a storage node for application " + application.applicationInstanceId() + " at host " + hostName); } return getStorageNodeIndex(storageNode.get().configId()); }
@Override public Map<ApplicationInstanceReference, ApplicationInstance> getAllApplicationInstances() { // Convert apps information to the response payload to return Map<ApplicationInstanceReference, ApplicationInstance> status = new HashMap<>(); for (Map.Entry<ApplicationId, MockDeployer.ApplicationContext> app : apps.entrySet()) { Set<ServiceInstance> serviceInstances = new HashSet<>(); for (Node node : nodeRepository.getNodes(app.getValue().id(), Node.State.active)) { serviceInstances.add(new ServiceInstance(new ConfigId("configid"), new HostName(node.hostname()), getHostStatus(node.hostname()))); } Set<ServiceCluster> serviceClusters = new HashSet<>(); serviceClusters.add(new ServiceCluster(new ClusterId(app.getValue().clusterContexts().get(0).cluster().id().value()), new ServiceType("serviceType"), serviceInstances)); TenantId tenantId = new TenantId(app.getKey().tenant().value()); ApplicationInstanceId applicationInstanceId = new ApplicationInstanceId(app.getKey().application().value()); status.put(new ApplicationInstanceReference(tenantId, applicationInstanceId), new ApplicationInstance(tenantId, applicationInstanceId, serviceClusters)); } return status; }
public static Set<HostName> getHostsUsedByApplicationInstance(ApplicationInstance applicationInstance) { return applicationInstance.serviceClusters().stream() .flatMap(serviceCluster -> getHostsUsedByServiceCluster(serviceCluster).stream()) .collect(toSet()); }
/** * A content cluster consists of many content-related service clusters, like distributor and storagenode. * All of the service clusters within a content cluster have the same service cluster ID, * which is also called the content ID (specified in services.xml) and also cluster name * (terminology used in Cluster Controller). The cluster name is used when referring to * content cluster resources through the HTTP REST on the Cluster Controller. * * There may be many content clusters within an application. But only one content cluster may be * present on any single host, * * @return The cluster name managed by a Cluster Controller. * @throws IllegalArgumentException if there is not exactly one content cluster name. */ public static ClusterId getContentClusterName(ApplicationInstance application, HostName hostName) { Set<ClusterId> contentClusterIdsOnHost = application.serviceClusters().stream() .filter(VespaModelUtil::isContent) .filter(cluster -> clusterHasInstanceOnHost(cluster, hostName)) .map(ServiceCluster::clusterId) .collect(Collectors.toSet()); if (contentClusterIdsOnHost.size() != 1) { throw new IllegalArgumentException("Expected exactly one content cluster within application " + application.applicationInstanceId() + " and host " + hostName + ", but found " + contentClusterIdsOnHost.size() + ": " + contentClusterIdsOnHost + ", application: " + application); } return contentClusterIdsOnHost.iterator().next(); }
@Override public String toString() { return "NodeGroup{" + "application=" + application.reference() + ", hostNames=" + hostNames + '}'; }
private static boolean applicationInstanceUsesHost(ApplicationInstance applicationInstance, HostName hostName) { return applicationInstance.serviceClusters().stream() .anyMatch(serviceCluster -> serviceCluster.serviceInstances().stream() .anyMatch(serviceInstance -> serviceInstance.hostName().equals(hostName))); }
throws ApplicationStateChangeDeniedException, ApplicationIdNotFoundException { Set<ClusterId> contentClusterIds = application.serviceClusters().stream() .filter(VespaModelUtil::isContent) .map(ServiceCluster::clusterId) contentClusterIds,application.applicationInstanceId(),state)); for (ClusterId clusterId : contentClusterIds) { List<HostName> clusterControllers = VespaModelUtil.getClusterControllerInstancesInOrder(application, clusterId); if (!response.wasModified) { String msg = String.format("Fail to set application %s, cluster name %s to cluster state %s due to: %s", application.applicationInstanceId(), clusterId, state, response.reason); throw new ApplicationStateChangeDeniedException(msg);
public ApplicationInstanceReference getApplicationReference() { return application.reference(); }
private static Set<ServiceCluster> getServiceClustersInGroup(NodeGroup nodeGroup) { ApplicationInstance applicationInstance = nodeGroup.getApplication(); Set<ServiceCluster> serviceClustersInGroup = new HashSet<>(); for (ServiceCluster cluster : applicationInstance.serviceClusters()) { for (ServiceInstance instance : cluster.serviceInstances()) { if (nodeGroup.contains(instance.hostName())) { serviceClustersInGroup.add(cluster); break; } } } return serviceClustersInGroup; }
@Override public ApplicationId applicationId() { return OrchestratorUtil.toApplicationId(applicationInstance.reference()); }
@Override public HostStatus getNodeStatus(HostName hostName) throws HostNameNotFoundException { return getNodeStatus(getApplicationInstance(hostName).reference(), hostName); }
@Override public void setNodeStatus(HostName hostName, HostStatus status) throws OrchestrationException { ApplicationInstanceReference reference = getApplicationInstance(hostName).reference(); OrchestratorContext context = OrchestratorContext.createContextForSingleAppOp(clock); try (MutableStatusRegistry statusRegistry = statusService .lockApplicationInstance_forCurrentThreadOnly(context, reference)) { statusRegistry.setHostState(hostName, status); } }
@Override public void acquirePermissionToRemove(HostName hostName) throws OrchestrationException { ApplicationInstance appInstance = getApplicationInstance(hostName); NodeGroup nodeGroup = new NodeGroup(appInstance, hostName); OrchestratorContext context = OrchestratorContext.createContextForSingleAppOp(clock); try (MutableStatusRegistry statusRegistry = statusService .lockApplicationInstance_forCurrentThreadOnly(context, appInstance.reference())) { ApplicationApi applicationApi = new ApplicationApiImpl( nodeGroup, statusRegistry, clusterControllerClientFactory); policy.acquirePermissionToRemove(context.createSubcontextWithinLock(), applicationApi); } }
.lockApplicationInstance_forCurrentThreadOnly(context, appInstance.reference())) { final HostStatus currentHostState = statusRegistry.getHostStatus(hostName); ApplicationInstanceStatus appStatus = statusService.forApplicationInstance(appInstance.reference()).getApplicationInstanceStatus(); if (appStatus == ApplicationInstanceStatus.NO_REMARKS) { policy.releaseSuspensionGrant(context.createSubcontextWithinLock(), appInstance, hostName, statusRegistry);
"application " + applicationInstance.reference().asString() + ", host " + hostName() + ", cluster name " + clusterId + " has been set to " + wantedNodeState; logger.log(LogLevel.INFO, "Storage node " + nodeIndex + " in cluster " + clusterId + " application " + applicationInstance.reference().asString() + " on host " + hostName() + logSuffix);