package com.thinkbiganalytics.servicemonitor.check; /*- * #%L * thinkbig-service-monitor-cloudera * %% * Copyright (C) 2017 ThinkBig Analytics * %% * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * #L% */ import com.cloudera.api.model.ApiCluster; import com.cloudera.api.model.ApiClusterList; import com.cloudera.api.model.ApiHealthCheck; import com.cloudera.api.model.ApiHealthSummary; import com.cloudera.api.model.ApiRole; import com.cloudera.api.model.ApiRoleState; import com.cloudera.api.model.ApiService; import com.thinkbiganalytics.servicemonitor.model.DefaultServiceAlert; import com.thinkbiganalytics.servicemonitor.model.DefaultServiceComponent; import com.thinkbiganalytics.servicemonitor.model.DefaultServiceStatusResponse; import com.thinkbiganalytics.servicemonitor.model.ServiceAlert; import com.thinkbiganalytics.servicemonitor.model.ServiceComponent; import com.thinkbiganalytics.servicemonitor.model.ServiceStatusResponse; import com.thinkbiganalytics.servicemonitor.rest.client.cdh.ClouderaClient; import com.thinkbiganalytics.servicemonitor.rest.client.cdh.ClouderaRootResource; import com.thinkbiganalytics.servicemonitor.support.ServiceMonitorCheckUtil; import org.springframework.beans.factory.annotation.Value; import java.util.ArrayList; import java.util.List; import java.util.Map; import javax.inject.Inject; /** * Checks for Hadoop services status using Cloudera API. */ public class ClouderaServicesStatusCheck implements ServicesStatusCheck { @Value("${cloudera.services.status:#{null}}") private String services; @Inject private ClouderaClient clouderaClient; private ServiceComponent.STATE apiRoleStateToServiceComponentState(ApiRoleState roleState) { ServiceComponent.STATE state; if (ApiRoleState.STARTED.equals(roleState)) { state = ServiceComponent.STATE.UP; } else if (ApiRoleState.STARTING.equals(roleState)) { state = ServiceComponent.STATE.STARTING; } else if (ApiRoleState.STOPPING.equals(roleState)) { state = ServiceComponent.STATE.DOWN; } else if (ApiRoleState.STOPPED.equals(roleState)) { state = ServiceComponent.STATE.DOWN; } else if (ApiRoleState.BUSY.equals(roleState)) { state = ServiceComponent.STATE.UP; } else { state = ServiceComponent.STATE.UNKNOWN; } return state; } private ServiceAlert.STATE apiHealthSummaryAlertState(ApiHealthSummary healthSummary) { ServiceAlert.STATE state = ServiceAlert.STATE.UNKNOWN; if (ApiHealthSummary.HISTORY_NOT_AVAILABLE.equals(healthSummary) || ApiHealthSummary.NOT_AVAILABLE.equals(healthSummary)) { state = ServiceAlert.STATE.UNKNOWN; } else if (ApiHealthSummary.DISABLED.equals(healthSummary) || ApiHealthSummary.GOOD.equals(healthSummary)) { state = ServiceAlert.STATE.OK; } else if (ApiHealthSummary.BAD.equals(healthSummary)) { state = ServiceAlert.STATE.CRITICAL; } else if (ApiHealthSummary.CONCERNING.equals(healthSummary)) { state = ServiceAlert.STATE.WARNING; } return state; } private ServiceAlert apiHealthCheckToServiceAlert(String componentName, ApiHealthCheck healthCheck) { ServiceAlert alert = new DefaultServiceAlert(); alert.setComponentName(componentName); alert.setLabel(healthCheck.getName()); alert.setMessage(healthCheck.getSummary().name()); alert.setState(apiHealthSummaryAlertState(healthCheck.getSummary())); return alert; } @Override public List<ServiceStatusResponse> healthCheck() { List<ServiceStatusResponse> serviceStatusResponseList = new ArrayList<>(); //Get the Map of Services and optional Components we are tracking Map<String, List<String>> definedServiceComponentMap = ServiceMonitorCheckUtil.getMapOfServiceAndComponents(services); if (definedServiceComponentMap != null && !definedServiceComponentMap.isEmpty()) { ClouderaRootResource rootResource; try { rootResource = clouderaClient.getClouderaResource(); if (rootResource == null) { throw new Exception("The Cloudera Resource is null... It may still be trying to initialize the Rest Client."); } ApiClusterList clusters = rootResource.getPopulatedClusterList(); for (ApiCluster cluster : clusters.getClusters()) { String clusterName = cluster.getName(); List<ApiService> services = cluster.getServices(); for (ApiService service : services) { List<ServiceComponent> serviceComponents = new ArrayList<>(); List<ServiceAlert> alerts = new ArrayList<>(); String serviceName = service.getType(); if (definedServiceComponentMap.containsKey(serviceName)) { service.getHealthSummary(); List<ApiHealthCheck> healthChecks = service.getHealthChecks(); for (ApiHealthCheck healthCheck : healthChecks) { alerts.add(apiHealthCheckToServiceAlert(null, healthCheck)); } List<ApiRole> roles = service.getRoles(); for (ApiRole role : roles) { String roleName = role.getType(); role.getHealthSummary(); List<ApiHealthCheck> roleHealthChecks = role.getHealthChecks(); ServiceComponent.STATE roleState = apiRoleStateToServiceComponentState(role.getRoleState()); List<ServiceAlert> componentAlerts = new ArrayList<>(); for (ApiHealthCheck healthCheck : roleHealthChecks) { ServiceAlert alert = apiHealthCheckToServiceAlert(roleName, healthCheck); alerts.add(alert); componentAlerts.add(alert); } ServiceComponent component = new DefaultServiceComponent.Builder(roleName, roleState).clusterName(clusterName) .message(role.getRoleState().name()).alerts(componentAlerts).build(); if (definedServiceComponentMap.containsKey(serviceName) && (definedServiceComponentMap.get(serviceName).contains( ServiceMonitorCheckUtil.ALL_COMPONENTS) || definedServiceComponentMap.get(serviceName) .contains(component.getName()))) { serviceComponents.add(component); } } ServiceStatusResponse serviceStatusResponse = new DefaultServiceStatusResponse(serviceName, serviceComponents, alerts); serviceStatusResponseList.add(serviceStatusResponse); } } } } catch (Exception e) { Throwable cause; if (e.getCause() != null) { cause = e.getCause(); } else { cause = e; } ServiceComponent clouderaServiceComponent = new DefaultServiceComponent.Builder("Cloudera REST_CLIENT", ServiceComponent.STATE.DOWN).serviceName("Cloudera") .clusterName("UNKNOWN").exception(cause).build(); List<ServiceComponent> clouderaComponents = new ArrayList<>(); clouderaComponents.add(clouderaServiceComponent); ServiceStatusResponse serviceStatusResponse = new DefaultServiceStatusResponse(clouderaServiceComponent.getServiceName(), clouderaComponents); serviceStatusResponseList.add(serviceStatusResponse); //add the other services as being Warnings addClouderaServiceErrors(cause.getMessage(), serviceStatusResponseList, definedServiceComponentMap); } } return serviceStatusResponseList; } private void addClouderaServiceErrors(String exceptionMessage, List<ServiceStatusResponse> list, Map<String, List<String>> definedServiceComponentMap) { if (definedServiceComponentMap != null && !definedServiceComponentMap.isEmpty()) { String message = "Status Unknown. Unable to check service. Cloudera connection error: " + exceptionMessage; for (Map.Entry<String, List<String>> entry : definedServiceComponentMap.entrySet()) { String serviceName = entry.getKey(); List<String> componentNames = entry.getValue(); List<ServiceComponent> components = new ArrayList<>(); if (componentNames != null && !componentNames.isEmpty()) { for (String componentName : componentNames) { if (ServiceMonitorCheckUtil.ALL_COMPONENTS.equals(componentName)) { componentName = serviceName; } ServiceComponent serviceComponent = new DefaultServiceComponent.Builder(componentName, ServiceComponent.STATE.UNKNOWN).clusterName("UNKNOWN") .message(message).build(); components.add(serviceComponent); } } else { //add the component based uppon the Service Name ServiceComponent serviceComponent = new DefaultServiceComponent.Builder(serviceName, ServiceComponent.STATE.UNKNOWN).clusterName("UNKNOWN") .message(message).build(); components.add(serviceComponent); } ServiceStatusResponse serviceStatusResponse = new DefaultServiceStatusResponse(serviceName, components); list.add(serviceStatusResponse); } } } }