/** * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you 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. */ package org.apache.ambari.server.checks; import java.util.ArrayList; import java.util.Arrays; import java.util.LinkedHashMap; import java.util.List; import java.util.Map; import java.util.Set; import org.apache.ambari.server.AmbariException; import org.apache.ambari.server.controller.PrereqCheckRequest; import org.apache.ambari.server.state.Cluster; import org.apache.ambari.server.state.stack.PrereqCheckStatus; import org.apache.ambari.server.state.stack.PrerequisiteCheck; import org.apache.ambari.server.state.stack.UpgradePack.PrerequisiteCheckConfig; import org.apache.commons.lang.StringUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import com.google.inject.Singleton; /** * Checks if Atlas service is present. Upgrade to stack HDP 2.5 can't pursuit * with existed on the cluster Atlas service. */ @Singleton @UpgradeCheck(group = UpgradeCheckGroup.DEFAULT) public class ServicePresenceCheck extends AbstractCheckDescriptor{ private static final Logger LOG = LoggerFactory.getLogger(ServicePresenceCheck.class); static final String KEY_SERVICE_REPLACED = "service_replaced"; static final String KEY_SERVICE_REMOVED = "service_removed"; /* * List of services that do not support upgrade * services must be removed before the stack upgrade * */ static final String NO_UPGRADE_SUPPORT_SERVICES_PROPERTY_NAME = "no-upgrade-support-service-names"; /* * List of services removed from the new release * */ static final String REMOVED_SERVICES_PROPERTY_NAME = "removed-service-names"; /* * List of services replaced by other services in the new release * */ static final String REPLACED_SERVICES_PROPERTY_NAME = "replaced-service-names"; /* * Such as Spark to Spark2 */ static final String NEW_SERVICES_PROPERTY_NAME = "new-service-names"; public ServicePresenceCheck(){ super(CheckDescription.SERVICE_PRESENCE_CHECK); } @Override public void perform(PrerequisiteCheck prerequisiteCheck, PrereqCheckRequest request) throws AmbariException { final Cluster cluster = clustersProvider.get().getCluster(request.getClusterName()); Set<String> installedServices = cluster.getServices().keySet(); List<String> noUpgradeSupportServices = getNoUpgradeSupportServices(request); Map<String, String> replacedServices = getReplacedServices(request); List<String> removedServices = getRemovedServices(request); List<String> failReasons = new ArrayList<>(); String reason = getFailReason(prerequisiteCheck, request); for(String service: noUpgradeSupportServices){ if (installedServices.contains(service.toUpperCase())){ prerequisiteCheck.getFailedOn().add(service); String msg = String.format(reason, service, service); failReasons.add(msg); } } reason = getFailReason(KEY_SERVICE_REPLACED, prerequisiteCheck, request); for (Map.Entry<String, String> entry : replacedServices.entrySet()) { String removedService = entry.getKey(); if(installedServices.contains(removedService.toUpperCase())){ prerequisiteCheck.getFailedOn().add(removedService); String newService = entry.getValue(); String msg = String.format(reason, removedService, newService); failReasons.add(msg); } } reason = getFailReason(KEY_SERVICE_REMOVED, prerequisiteCheck, request); for(String service: removedServices){ if (installedServices.contains(service.toUpperCase())){ prerequisiteCheck.getFailedOn().add(service); String msg = String.format(reason, service); failReasons.add(msg); } } if(!failReasons.isEmpty()){ prerequisiteCheck.setStatus(PrereqCheckStatus.FAIL); prerequisiteCheck.setFailReason(StringUtils.join(failReasons, '\n')); } } /** * Obtain property value specified in the upgrade XML * @return service name * */ private String getPropertyValue(PrereqCheckRequest request, String propertyKey){ String value = null; PrerequisiteCheckConfig prerequisiteCheckConfig = request.getPrerequisiteCheckConfig(); Map<String, String> checkProperties = null; if(prerequisiteCheckConfig != null) { checkProperties = prerequisiteCheckConfig.getCheckProperties(this.getClass().getName()); } if(checkProperties != null && checkProperties.containsKey(propertyKey)) { value = checkProperties.get(propertyKey); } return value; } /** * @return service names * */ private List<String> getNoUpgradeSupportServices(PrereqCheckRequest request){ List<String> result = new ArrayList<>(); String value = getPropertyValue(request, NO_UPGRADE_SUPPORT_SERVICES_PROPERTY_NAME); if (null != value){ String[] services = value.split(","); for(String service: services){ service = service.trim(); if (!service.isEmpty()){ result.add(service); } } } return result; } /** + * @return service names + * */ private List<String> getRemovedServices(PrereqCheckRequest request){ List<String> result = new ArrayList<String>(); String value = getPropertyValue(request, REMOVED_SERVICES_PROPERTY_NAME); if (null != value){ String[] services = value.split(","); for(String service: services){ service = service.trim(); if (!service.isEmpty()){ result.add(service); } } } return result; } /** * @return service names and new service names map * */ private Map<String, String> getReplacedServices(PrereqCheckRequest request) throws AmbariException{ Map<String, String> result = new LinkedHashMap<>(); String value = getPropertyValue(request, REPLACED_SERVICES_PROPERTY_NAME); String newValue = getPropertyValue(request, NEW_SERVICES_PROPERTY_NAME); if(value == null && newValue == null){ return result; //no need to check removed services as they are not specified in the upgrade xml file. } else { if (value == null || newValue == null){ throw new AmbariException(String.format("Both %s and %s list must be specified in the upgrade XML file.", REPLACED_SERVICES_PROPERTY_NAME, NEW_SERVICES_PROPERTY_NAME)); } else { List<String> oldServices = Arrays.asList(value.split(",")); List<String> newServices = Arrays.asList(newValue.split(",")); if (oldServices.size() != newServices.size()){ throw new AmbariException(String.format("%s must have the same number of services as the %s list.", NEW_SERVICES_PROPERTY_NAME, REPLACED_SERVICES_PROPERTY_NAME)); } else { for (int i = 0; i < oldServices.size(); i++){ String oldService = oldServices.get(i).trim(); String newService = newServices.get(i).trim(); if (oldService.isEmpty() || newService.isEmpty()) { throw new AmbariException(String.format("Make sure both %s and %s list only contain comma separated list of services.", NEW_SERVICES_PROPERTY_NAME, REPLACED_SERVICES_PROPERTY_NAME)); } else { result.put(oldService, newService); } } } } } return result; } }