package com.sequenceiq.cloudbreak.service.cluster.flow.status;
import java.util.ArrayList;
import java.util.EnumSet;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.TreeSet;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
import com.sequenceiq.ambari.client.AmbariClient;
@Component
public class AmbariClusterStatusFactory {
private static final Logger LOGGER = LoggerFactory.getLogger(AmbariClusterStatusFactory.class);
private EnumSet<ClusterStatus> partialStatuses = EnumSet.of(ClusterStatus.INSTALLING, ClusterStatus.INSTALL_FAILED, ClusterStatus.STARTING,
ClusterStatus.STOPPING);
private EnumSet<ClusterStatus> fullStatuses = EnumSet.of(ClusterStatus.INSTALLED, ClusterStatus.STARTED);
public ClusterStatus createClusterStatus(AmbariClient ambariClient, String blueprint) {
ClusterStatus clusterStatus;
if (!isAmbariServerRunning(ambariClient)) {
clusterStatus = ClusterStatus.AMBARISERVER_NOT_RUNNING;
} else if (blueprint != null) {
clusterStatus = determineClusterStatus(ambariClient);
} else {
clusterStatus = ClusterStatus.AMBARISERVER_RUNNING;
}
return clusterStatus;
}
private boolean isAmbariServerRunning(AmbariClient ambariClient) {
boolean result;
try {
result = "RUNNING".equals(ambariClient.healthCheck());
} catch (Exception ex) {
result = false;
}
return result;
}
private ClusterStatus determineClusterStatus(AmbariClient ambariClient) {
ClusterStatus clusterStatus;
try {
Map<String, List<Integer>> ambariOperations = ambariClient.getRequests("IN_PROGRESS", "PENDING");
if (!ambariOperations.isEmpty()) {
clusterStatus = ClusterStatus.PENDING;
} else {
Set<ClusterStatus> orderedPartialStatuses = new TreeSet<>();
Set<ClusterStatus> orderedFullStatuses = new TreeSet<>();
Set<String> unsupportedStatuses = new HashSet<>();
Map<String, Map<String, String>> hostComponentsStates = ambariClient.getHostComponentsStates();
Set<String> componentNames = new HashSet<>();
hostComponentsStates.entrySet().forEach(e -> componentNames.addAll(e.getValue().keySet()));
Map<String, String> componentsCategory = ambariClient.getComponentsCategory(new ArrayList<>(componentNames));
for (Map.Entry<String, Map<String, String>> hostComponentsEntry : hostComponentsStates.entrySet()) {
Map<String, String> componentStateMap = hostComponentsEntry.getValue();
for (Map.Entry<String, String> componentStateEntry : componentStateMap.entrySet()) {
String category = componentsCategory.get(componentStateEntry.getKey());
if (!"CLIENT".equals(category)) {
putComponentState(componentStateEntry.getValue(), orderedPartialStatuses, orderedFullStatuses, unsupportedStatuses);
}
}
}
clusterStatus = determineClusterStatus(orderedPartialStatuses, orderedFullStatuses);
}
} catch (Exception ex) {
LOGGER.warn("An error occurred while trying to reach Ambari.", ex);
clusterStatus = ClusterStatus.UNKNOWN;
}
return clusterStatus;
}
private ClusterStatus determineClusterStatus(Set<ClusterStatus> orderedPartialStatuses, Set<ClusterStatus> orderedFullStatuses) {
ClusterStatus clusterStatus;
if (!orderedPartialStatuses.isEmpty()) {
clusterStatus = orderedPartialStatuses.iterator().next();
} else if (orderedFullStatuses.size() == 1) {
clusterStatus = orderedFullStatuses.iterator().next();
} else {
clusterStatus = ClusterStatus.AMBIGUOUS;
}
return clusterStatus;
}
private void putComponentState(String componentStateStr, Set<ClusterStatus> orderedPartialStatuses, Set<ClusterStatus> orderedFullStatuses,
Set<String> unsupportedStatuses) {
try {
ClusterStatus componentStatus = ClusterStatus.valueOf(componentStateStr);
if (partialStatuses.contains(componentStatus)) {
orderedPartialStatuses.add(componentStatus);
} else if (fullStatuses.contains(componentStatus)) {
orderedFullStatuses.add(componentStatus);
} else {
unsupportedStatuses.add(componentStateStr);
}
} catch (RuntimeException ex) {
unsupportedStatuses.add(componentStateStr);
}
}
}