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(); }
/** * @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()); }
/** * 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(); }
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);