/**
* 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.controller.internal;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.apache.ambari.server.AmbariException;
import org.apache.ambari.server.ParentObjectNotFoundException;
import org.apache.ambari.server.StaticallyInject;
import org.apache.ambari.server.checks.AbstractCheckDescriptor;
import org.apache.ambari.server.checks.UpgradeCheckRegistry;
import org.apache.ambari.server.controller.AmbariManagementController;
import org.apache.ambari.server.controller.PrereqCheckRequest;
import org.apache.ambari.server.controller.spi.NoSuchParentResourceException;
import org.apache.ambari.server.controller.spi.NoSuchResourceException;
import org.apache.ambari.server.controller.spi.Predicate;
import org.apache.ambari.server.controller.spi.Request;
import org.apache.ambari.server.controller.spi.Resource;
import org.apache.ambari.server.controller.spi.Resource.Type;
import org.apache.ambari.server.controller.spi.SystemException;
import org.apache.ambari.server.controller.spi.UnsupportedPropertyException;
import org.apache.ambari.server.controller.utilities.PropertyHelper;
import org.apache.ambari.server.orm.dao.RepositoryVersionDAO;
import org.apache.ambari.server.orm.entities.RepositoryVersionEntity;
import org.apache.ambari.server.state.CheckHelper;
import org.apache.ambari.server.state.Cluster;
import org.apache.ambari.server.state.Clusters;
import org.apache.ambari.server.state.ServiceInfo;
import org.apache.ambari.server.state.UpgradeHelper;
import org.apache.ambari.server.state.stack.PrerequisiteCheck;
import org.apache.ambari.server.state.stack.UpgradePack;
import org.apache.ambari.server.state.stack.upgrade.Direction;
import org.apache.ambari.server.state.stack.upgrade.UpgradeType;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.google.common.collect.Sets;
import com.google.inject.Inject;
import com.google.inject.Provider;
/**
* Resource provider for pre-upgrade checks.
*/
@StaticallyInject
public class PreUpgradeCheckResourceProvider extends ReadOnlyResourceProvider {
private static Logger LOG = LoggerFactory.getLogger(PreUpgradeCheckResourceProvider.class);
//----- Property ID constants ---------------------------------------------
public static final String UPGRADE_CHECK_ID_PROPERTY_ID = PropertyHelper.getPropertyId("UpgradeChecks", "id");
public static final String UPGRADE_CHECK_CHECK_PROPERTY_ID = PropertyHelper.getPropertyId("UpgradeChecks", "check");
public static final String UPGRADE_CHECK_STATUS_PROPERTY_ID = PropertyHelper.getPropertyId("UpgradeChecks", "status");
public static final String UPGRADE_CHECK_REASON_PROPERTY_ID = PropertyHelper.getPropertyId("UpgradeChecks", "reason");
public static final String UPGRADE_CHECK_FAILED_ON_PROPERTY_ID = PropertyHelper.getPropertyId("UpgradeChecks", "failed_on");
public static final String UPGRADE_CHECK_FAILED_DETAIL_PROPERTY_ID = PropertyHelper.getPropertyId("UpgradeChecks", "failed_detail");
public static final String UPGRADE_CHECK_CHECK_TYPE_PROPERTY_ID = PropertyHelper.getPropertyId("UpgradeChecks", "check_type");
public static final String UPGRADE_CHECK_CLUSTER_NAME_PROPERTY_ID = PropertyHelper.getPropertyId("UpgradeChecks", "cluster_name");
public static final String UPGRADE_CHECK_UPGRADE_TYPE_PROPERTY_ID = PropertyHelper.getPropertyId("UpgradeChecks", "upgrade_type");
/**
* Optional parameter to specify the preferred Upgrade Pack to use.
*/
public static final String UPGRADE_CHECK_UPGRADE_PACK_PROPERTY_ID = PropertyHelper.getPropertyId("UpgradeChecks", "upgrade_pack");
public static final String UPGRADE_CHECK_REPOSITORY_VERSION_PROPERTY_ID = PropertyHelper.getPropertyId("UpgradeChecks", "repository_version");
@Inject
private static Provider<Clusters> clustersProvider;
@Inject
private static RepositoryVersionDAO repositoryVersionDAO;
@Inject
private static UpgradeCheckRegistry upgradeCheckRegistry;
@Inject
private static Provider<UpgradeHelper> upgradeHelper;
@Inject
private static CheckHelper checkHelper;
private static Set<String> pkPropertyIds = Collections.singleton(UPGRADE_CHECK_ID_PROPERTY_ID);
public static Set<String> propertyIds = Sets.newHashSet(
UPGRADE_CHECK_ID_PROPERTY_ID,
UPGRADE_CHECK_CHECK_PROPERTY_ID,
UPGRADE_CHECK_STATUS_PROPERTY_ID,
UPGRADE_CHECK_REASON_PROPERTY_ID,
UPGRADE_CHECK_FAILED_ON_PROPERTY_ID,
UPGRADE_CHECK_FAILED_DETAIL_PROPERTY_ID,
UPGRADE_CHECK_CHECK_TYPE_PROPERTY_ID,
UPGRADE_CHECK_CLUSTER_NAME_PROPERTY_ID,
UPGRADE_CHECK_UPGRADE_TYPE_PROPERTY_ID,
UPGRADE_CHECK_UPGRADE_PACK_PROPERTY_ID,
UPGRADE_CHECK_REPOSITORY_VERSION_PROPERTY_ID);
@SuppressWarnings("serial")
public static Map<Type, String> keyPropertyIds = new HashMap<Type, String>() {
{
put(Type.PreUpgradeCheck, UPGRADE_CHECK_ID_PROPERTY_ID);
put(Type.Cluster, UPGRADE_CHECK_CLUSTER_NAME_PROPERTY_ID);
}
};
/**
* Constructor.
*
* @param managementController management controller
*/
public PreUpgradeCheckResourceProvider(AmbariManagementController managementController) {
super(propertyIds, keyPropertyIds, managementController);
}
public Set<Resource> getResources(Request request, Predicate predicate) throws SystemException, UnsupportedPropertyException,
NoSuchResourceException, NoSuchParentResourceException {
final Set<Resource> resources = new HashSet<>();
final Set<String> requestedIds = getRequestPropertyIds(request, predicate);
final Set<Map<String, Object>> propertyMaps = getPropertyMaps(predicate);
for (Map<String, Object> propertyMap: propertyMaps) {
final String clusterName = propertyMap.get(UPGRADE_CHECK_CLUSTER_NAME_PROPERTY_ID).toString();
UpgradeType upgradeType = UpgradeType.ROLLING;
if (propertyMap.containsKey(UPGRADE_CHECK_UPGRADE_TYPE_PROPERTY_ID)) {
try {
upgradeType = UpgradeType.valueOf(propertyMap.get(UPGRADE_CHECK_UPGRADE_TYPE_PROPERTY_ID).toString());
} catch(Exception e){
throw new SystemException(String.format("Property %s has an incorrect value of %s.", UPGRADE_CHECK_UPGRADE_TYPE_PROPERTY_ID, propertyMap.get(UPGRADE_CHECK_UPGRADE_TYPE_PROPERTY_ID)));
}
}
final Cluster cluster;
try {
cluster = clustersProvider.get().getCluster(clusterName);
} catch (AmbariException ambariException) {
throw new NoSuchResourceException(ambariException.getMessage());
}
String stackName = cluster.getCurrentStackVersion().getStackName();
String sourceStackVersion = cluster.getCurrentStackVersion().getStackVersion();
final PrereqCheckRequest upgradeCheckRequest = new PrereqCheckRequest(clusterName, upgradeType);
upgradeCheckRequest.setSourceStackId(cluster.getCurrentStackVersion());
if (propertyMap.containsKey(UPGRADE_CHECK_REPOSITORY_VERSION_PROPERTY_ID)) {
String repositoryVersionId = propertyMap.get(UPGRADE_CHECK_REPOSITORY_VERSION_PROPERTY_ID).toString();
RepositoryVersionEntity repositoryVersionEntity = repositoryVersionDAO.findByStackNameAndVersion(stackName, repositoryVersionId);
// set some required properties on the check request
upgradeCheckRequest.setRepositoryVersion(repositoryVersionId);
upgradeCheckRequest.setTargetStackId(repositoryVersionEntity.getStackId());
}
//ambariMetaInfo.getStack(stackName, cluster.getCurrentStackVersion().getStackVersion()).getUpgradePacks()
// TODO AMBARI-12698, filter the upgrade checks to run based on the stack and upgrade type, or the upgrade pack.
UpgradePack upgradePack = null;
String preferredUpgradePackName = propertyMap.containsKey(UPGRADE_CHECK_UPGRADE_PACK_PROPERTY_ID) ?
(String) propertyMap.get(UPGRADE_CHECK_UPGRADE_PACK_PROPERTY_ID) : null;
try{
// Hint: PreChecks currently executing only before UPGRADE direction
upgradePack = upgradeHelper.get().suggestUpgradePack(clusterName, sourceStackVersion,
upgradeCheckRequest.getRepositoryVersion(), Direction.UPGRADE, upgradeType, preferredUpgradePackName);
} catch (AmbariException e) {
throw new SystemException(e.getMessage(), e);
}
if (upgradePack == null) {
throw new SystemException(String.format("Upgrade pack not found for the target repository version %s",
upgradeCheckRequest.getRepositoryVersion()));
}
// ToDo: properly handle exceptions, i.e. create fake check with error description
List<AbstractCheckDescriptor> upgradeChecksToRun = upgradeCheckRegistry.getFilteredUpgradeChecks(upgradePack);
upgradeCheckRequest.setPrerequisiteCheckConfig(upgradePack.getPrerequisiteCheckConfig());
try {
// Register all the custom prechecks from the services
Map<String, ServiceInfo> services = getManagementController().getAmbariMetaInfo().getServices(stackName, sourceStackVersion);
List<AbstractCheckDescriptor> serviceLevelUpgradeChecksToRun = upgradeCheckRegistry.getServiceLevelUpgradeChecks(upgradePack, services);
upgradeChecksToRun.addAll(serviceLevelUpgradeChecksToRun);
} catch (ParentObjectNotFoundException parentNotFoundException) {
LOG.error("Invalid stack version: " + stackName + "-" + sourceStackVersion, parentNotFoundException);
} catch (AmbariException ambariException) {
LOG.error("Unable to register all the custom prechecks from the services", ambariException);
} catch (Exception e) {
LOG.error("Failed to register custom prechecks for the services", e);
}
for (PrerequisiteCheck prerequisiteCheck : checkHelper.performChecks(upgradeCheckRequest, upgradeChecksToRun)) {
final Resource resource = new ResourceImpl(Resource.Type.PreUpgradeCheck);
setResourceProperty(resource, UPGRADE_CHECK_ID_PROPERTY_ID, prerequisiteCheck.getId(), requestedIds);
setResourceProperty(resource, UPGRADE_CHECK_CHECK_PROPERTY_ID, prerequisiteCheck.getDescription(), requestedIds);
setResourceProperty(resource, UPGRADE_CHECK_STATUS_PROPERTY_ID, prerequisiteCheck.getStatus(), requestedIds);
setResourceProperty(resource, UPGRADE_CHECK_REASON_PROPERTY_ID, prerequisiteCheck.getFailReason(), requestedIds);
setResourceProperty(resource, UPGRADE_CHECK_FAILED_ON_PROPERTY_ID, prerequisiteCheck.getFailedOn(), requestedIds);
setResourceProperty(resource, UPGRADE_CHECK_FAILED_DETAIL_PROPERTY_ID,prerequisiteCheck.getFailedDetail(), requestedIds);
setResourceProperty(resource, UPGRADE_CHECK_CHECK_TYPE_PROPERTY_ID, prerequisiteCheck.getType(), requestedIds);
setResourceProperty(resource, UPGRADE_CHECK_CLUSTER_NAME_PROPERTY_ID, prerequisiteCheck.getClusterName(), requestedIds);
setResourceProperty(resource, UPGRADE_CHECK_UPGRADE_TYPE_PROPERTY_ID, upgradeType, requestedIds);
if (upgradeCheckRequest.getRepositoryVersion() != null) {
setResourceProperty(resource, UPGRADE_CHECK_REPOSITORY_VERSION_PROPERTY_ID, upgradeCheckRequest.getRepositoryVersion(), requestedIds);
}
resources.add(resource);
}
}
return resources;
}
@Override
protected Set<String> getPKPropertyIds() {
return pkPropertyIds;
}
}