Repository: ambari Updated Branches: refs/heads/trunk e65bad149 -> f4725228e
AMBARI-10976 - HDP-2.2 To HDP-2.3 Upgrade Pre-Upgrade Checks (jonathanhurley) Project: http://git-wip-us.apache.org/repos/asf/ambari/repo Commit: http://git-wip-us.apache.org/repos/asf/ambari/commit/f4725228 Tree: http://git-wip-us.apache.org/repos/asf/ambari/tree/f4725228 Diff: http://git-wip-us.apache.org/repos/asf/ambari/diff/f4725228 Branch: refs/heads/trunk Commit: f4725228e79416712986d0c2de1cb251c47e80b0 Parents: e65bad1 Author: Jonathan Hurley <[email protected]> Authored: Wed May 6 20:47:46 2015 -0400 Committer: Jonathan Hurley <[email protected]> Committed: Thu May 7 08:12:02 2015 -0400 ---------------------------------------------------------------------- .../server/checks/AbstractCheckDescriptor.java | 37 ++++- .../ambari/server/checks/CheckDescription.java | 38 ++++- .../server/checks/ClientRetryPropertyCheck.java | 116 +++++++++++++ .../server/checks/ConfigurationMergeCheck.java | 3 + .../HiveDynamicServiceDiscoveryCheck.java | 102 ++++++++++++ .../server/checks/HostsHeartbeatCheck.java | 4 + .../checks/HostsMasterMaintenanceCheck.java | 4 + .../checks/HostsRepositoryVersionCheck.java | 4 + .../checks/SecondaryNamenodeDeletedCheck.java | 3 + .../checks/ServicesDecommissionCheck.java | 3 + .../checks/ServicesMaintenanceModeCheck.java | 4 + .../ServicesMapReduceDistributedCacheCheck.java | 4 + .../ServicesNamenodeHighAvailabilityCheck.java | 4 + .../ServicesTezDistributedCacheCheck.java | 4 + .../ambari/server/checks/ServicesUpCheck.java | 4 + .../checks/ServicesYarnWorkPreservingCheck.java | 26 +-- .../ambari/server/checks/UpgradeCheck.java | 58 +++++++ .../ambari/server/checks/UpgradeCheckGroup.java | 83 ++++++++++ .../server/checks/UpgradeCheckRegistry.java | 113 +++++++++++++ .../checks/YarnRMHighAvailabilityCheck.java | 80 +++++++++ .../YarnTimelineServerStatePreservingCheck.java | 94 +++++++++++ .../server/controller/ControllerModule.java | 54 +++++- .../PreUpgradeCheckResourceProvider.java | 74 +-------- .../apache/ambari/server/state/CheckHelper.java | 31 ++-- .../checks/ClientRetryPropertyCheckTest.java | 164 +++++++++++++++++++ .../server/checks/UpgradeCheckOrderTest.java | 103 ++++++++++++ ...nTimelineServerStatePreservingCheckTest.java | 127 ++++++++++++++ .../ambari/server/state/CheckHelperTest.java | 15 +- 28 files changed, 1246 insertions(+), 110 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/ambari/blob/f4725228/ambari-server/src/main/java/org/apache/ambari/server/checks/AbstractCheckDescriptor.java ---------------------------------------------------------------------- diff --git a/ambari-server/src/main/java/org/apache/ambari/server/checks/AbstractCheckDescriptor.java b/ambari-server/src/main/java/org/apache/ambari/server/checks/AbstractCheckDescriptor.java index 1816ce8..8cabf29 100644 --- a/ambari-server/src/main/java/org/apache/ambari/server/checks/AbstractCheckDescriptor.java +++ b/ambari-server/src/main/java/org/apache/ambari/server/checks/AbstractCheckDescriptor.java @@ -28,6 +28,8 @@ import org.apache.ambari.server.orm.dao.HostVersionDAO; import org.apache.ambari.server.orm.dao.RepositoryVersionDAO; import org.apache.ambari.server.state.Cluster; import org.apache.ambari.server.state.Clusters; +import org.apache.ambari.server.state.Config; +import org.apache.ambari.server.state.DesiredConfig; import org.apache.ambari.server.state.ServiceInfo; import org.apache.ambari.server.state.StackId; import org.apache.ambari.server.state.stack.PrereqCheckType; @@ -46,8 +48,8 @@ import com.google.inject.Provider; public abstract class AbstractCheckDescriptor { private static final Logger LOG = LoggerFactory.getLogger(AbstractCheckDescriptor.class); - private static final StackId STACK_HDP_22 = new StackId("HDP", "2.2"); - private static final StackId STACK_HDP_23 = new StackId("HDP", "2.3"); + protected static final StackId STACK_HDP_22 = new StackId("HDP", "2.2"); + protected static final StackId STACK_HDP_23 = new StackId("HDP", "2.3"); protected static final String DEFAULT = "default"; @@ -178,6 +180,37 @@ public abstract class AbstractCheckDescriptor { } /** + * Gets a cluster configuration property if it exists, or {@code null} + * otherwise. + * + * @param request + * the request (not {@code null}). + * @param configType + * the configuration type, such as {@code hdfs-site} (not + * {@code null}). + * @param propertyName + * the name of the property (not {@code null}). + * @return the property value or {@code null} if not found. + * @throws AmbariException + */ + protected String getProperty(PrereqCheckRequest request, String configType, String propertyName) + throws AmbariException { + final String clusterName = request.getClusterName(); + final Cluster cluster = clustersProvider.get().getCluster(clusterName); + final Map<String, DesiredConfig> desiredConfigs = cluster.getDesiredConfigs(); + final DesiredConfig desiredConfig = desiredConfigs.get(configType); + + if (null == desiredConfig) { + return null; + } + + final Config config = cluster.getConfig(configType, desiredConfig.getTag()); + + Map<String, String> properties = config.getProperties(); + return properties.get(propertyName); + } + + /** * Gets the fail reason * @param key the failure text key * @param prerequisiteCheck the check being performed http://git-wip-us.apache.org/repos/asf/ambari/blob/f4725228/ambari-server/src/main/java/org/apache/ambari/server/checks/CheckDescription.java ---------------------------------------------------------------------- diff --git a/ambari-server/src/main/java/org/apache/ambari/server/checks/CheckDescription.java b/ambari-server/src/main/java/org/apache/ambari/server/checks/CheckDescription.java index b00d6fb..7103566 100644 --- a/ambari-server/src/main/java/org/apache/ambari/server/checks/CheckDescription.java +++ b/ambari-server/src/main/java/org/apache/ambari/server/checks/CheckDescription.java @@ -28,6 +28,17 @@ import org.apache.ambari.server.state.stack.PrereqCheckType; */ public enum CheckDescription { + CLIENT_RETRY(PrereqCheckType.SERVICE, + "Client Retry Properties", + new HashMap<String, String>() {{ + put(ClientRetryPropertyCheck.HDFS_CLIENT_RETRY_MISSING_KEY, + "The hdfs-site.xml property dfs.client.retry.policy.enabled should be set to true."); + put(ClientRetryPropertyCheck.HIVE_CLIENT_RETRY_MISSING_KEY, + "The hive-site.xml property hive.metastore.failure.retries should be set to a positive value."); + put(ClientRetryPropertyCheck.OOZIE_CLIENT_RETRY_MISSING_KEY, + "The oozie-env.sh script must contain a retry count such as export OOZIE_CLIENT_OPTS=\"${OOZIE_CLIENT_OPTS} -Doozie.connection.retry.count=5\""); + }}), + HOSTS_HEARTBEAT(PrereqCheckType.HOST, "All hosts must be heartbeating with the Ambari Server unless they are in Maintenance Mode", new HashMap<String, String>() {{ @@ -87,7 +98,7 @@ public enum CheckDescription { }}), SERVICES_NAMENODE_HA(PrereqCheckType.SERVICE, - "NameNode High Availability must be enabled", + "NameNode High Availability must be enabled", new HashMap<String, String>() {{ put(AbstractCheckDescriptor.DEFAULT, "NameNode High Availability is not enabled. Verify that dfs.nameservices property is present in hdfs-site.xml."); @@ -123,6 +134,31 @@ public enum CheckDescription { "YARN should have work preserving restart enabled. The yarn-site.xml property yarn.resourcemanager.work-preserving-recovery.enabled property should be set to true."); }}), + SERVICES_YARN_RM_HA(PrereqCheckType.SERVICE, + "YARN ResourceManager HA should be enabled to prevent a disruption in service during the upgrade", + new HashMap<String, String>() {{ + put(AbstractCheckDescriptor.DEFAULT, + "YARN ResourceManager High Availability is not enabled. Verify that dfs.nameservices property is present in hdfs-site.xml."); + }}), + + SERVICES_YARN_TIMELINE_ST(PrereqCheckType.SERVICE, + "YARN Timeline state preserving restart should be enabled", + new HashMap<String, String>() {{ + put(AbstractCheckDescriptor.DEFAULT, + "YARN should have state preserving restart enabled for the Timeline server. The yarn-site.xml property yarn.timeline-service.recovery.enabled should be set to true."); + }}), + + SERVICES_HIVE_DYNAMIC_SERVICE_DISCOVERY(PrereqCheckType.SERVICE, + "Hive Dynamic Service Discovery", + new HashMap<String, String>() {{ + put(HiveDynamicServiceDiscoveryCheck.HIVE_DYNAMIC_SERVICE_DISCOVERY_ENABLED_KEY, + "The hive-site.xml property hive.server2.support.dynamic.service.discovery should be set to true."); + put(HiveDynamicServiceDiscoveryCheck.HIVE_DYNAMIC_SERVICE_ZK_QUORUM_KEY, + "The hive-site.xml property hive.zookeeper.quorum should be set to a comma-separate list of ZooKeeper hosts:port pairs."); + put(HiveDynamicServiceDiscoveryCheck.HIVE_DYNAMIC_SERVICE_ZK_NAMESPACE_KEY, + "The hive-site.xml property hive.server2.zookeeper.namespace should be set to the value for the root namespace on ZooKeeper."); + }}), + CONFIG_MERGE(PrereqCheckType.CLUSTER, "Configuration Merge Check", new HashMap<String, String>() {{ http://git-wip-us.apache.org/repos/asf/ambari/blob/f4725228/ambari-server/src/main/java/org/apache/ambari/server/checks/ClientRetryPropertyCheck.java ---------------------------------------------------------------------- diff --git a/ambari-server/src/main/java/org/apache/ambari/server/checks/ClientRetryPropertyCheck.java b/ambari-server/src/main/java/org/apache/ambari/server/checks/ClientRetryPropertyCheck.java new file mode 100644 index 0000000..5fbb5e4 --- /dev/null +++ b/ambari-server/src/main/java/org/apache/ambari/server/checks/ClientRetryPropertyCheck.java @@ -0,0 +1,116 @@ +/* + * 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.List; +import java.util.Map; + +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.Service; +import org.apache.ambari.server.state.stack.PrereqCheckStatus; +import org.apache.ambari.server.state.stack.PrerequisiteCheck; +import org.apache.commons.lang.StringUtils; + +import com.google.inject.Singleton; + +/** + * The {@link ClientRetryPropertyCheck} class is used to check that the + * client retry properties for HDFS, HIVE, and OOZIE are set. + */ +@Singleton +@UpgradeCheck(group = UpgradeCheckGroup.CLIENT_RETRY_PROPERTY) +public class ClientRetryPropertyCheck extends AbstractCheckDescriptor { + + static final String HDFS_CLIENT_RETRY_MISSING_KEY = "hdfs.client.retry.missing.key"; + static final String HIVE_CLIENT_RETRY_MISSING_KEY = "hive.client.retry.missing.key"; + static final String OOZIE_CLIENT_RETRY_MISSING_KEY = "oozie.client.retry.missing.key"; + + /** + * Constructor. + */ + public ClientRetryPropertyCheck() { + super(CheckDescription.CLIENT_RETRY); + } + + /** + * {@inheritDoc} + */ + @Override + public boolean isApplicable(PrereqCheckRequest request) throws AmbariException { + if (!super.isApplicable(request)) { + return false; + } + + final Cluster cluster = clustersProvider.get().getCluster(request.getClusterName()); + Map<String, Service> services = cluster.getServices(); + + if (services.containsKey("HDFS") || services.containsKey("HIVE") + || services.containsKey("OOZIE")) { + return true; + } + + return false; + } + + /** + * {@inheritDoc} + */ + @Override + public void perform(PrerequisiteCheck prerequisiteCheck, PrereqCheckRequest request) throws AmbariException { + final Cluster cluster = clustersProvider.get().getCluster(request.getClusterName()); + Map<String, Service> services = cluster.getServices(); + + List<String> errorMessages = new ArrayList<String>(); + + // check hdfs client property + if (services.containsKey("HDFS")) { + String hdfsClientRetry = getProperty(request, "hdfs-site", "dfs.client.retry.policy.enabled"); + if (null == hdfsClientRetry || !Boolean.parseBoolean(hdfsClientRetry)) { + errorMessages.add(getFailReason(HDFS_CLIENT_RETRY_MISSING_KEY, prerequisiteCheck, request)); + prerequisiteCheck.getFailedOn().add("HDFS"); + } + } + + // check hive client properties + if (services.containsKey("HIVE")) { + String hiveClientRetryCount = getProperty(request, "hive-site", + "hive.metastore.failure.retries"); + + if (null != hiveClientRetryCount && Integer.parseInt(hiveClientRetryCount) <= 0) { + errorMessages.add(getFailReason(HIVE_CLIENT_RETRY_MISSING_KEY, prerequisiteCheck, request)); + prerequisiteCheck.getFailedOn().add("HIVE"); + } + } + + if (services.containsKey("OOZIE")) { + String oozieClientRetry = getProperty(request, "oozie-env", "template"); + if (null == oozieClientRetry || !oozieClientRetry.contains("-Doozie.connection.retry.count")) { + errorMessages.add(getFailReason(OOZIE_CLIENT_RETRY_MISSING_KEY, prerequisiteCheck, request)); + prerequisiteCheck.getFailedOn().add("OOZIE"); + } + } + + if (!errorMessages.isEmpty()) { + prerequisiteCheck.setFailReason(StringUtils.join(errorMessages, " ")); + prerequisiteCheck.setStatus(PrereqCheckStatus.FAIL); + } + } +} http://git-wip-us.apache.org/repos/asf/ambari/blob/f4725228/ambari-server/src/main/java/org/apache/ambari/server/checks/ConfigurationMergeCheck.java ---------------------------------------------------------------------- diff --git a/ambari-server/src/main/java/org/apache/ambari/server/checks/ConfigurationMergeCheck.java b/ambari-server/src/main/java/org/apache/ambari/server/checks/ConfigurationMergeCheck.java index e4dd0e6..095ecd5 100644 --- a/ambari-server/src/main/java/org/apache/ambari/server/checks/ConfigurationMergeCheck.java +++ b/ambari-server/src/main/java/org/apache/ambari/server/checks/ConfigurationMergeCheck.java @@ -33,10 +33,13 @@ import org.apache.ambari.server.state.stack.PrerequisiteCheck; import org.apache.commons.lang.StringUtils; import com.google.inject.Inject; +import com.google.inject.Singleton; /** * Checks for configuration merge conflicts. */ +@Singleton +@UpgradeCheck(order = 99.0f) public class ConfigurationMergeCheck extends AbstractCheckDescriptor { @Inject http://git-wip-us.apache.org/repos/asf/ambari/blob/f4725228/ambari-server/src/main/java/org/apache/ambari/server/checks/HiveDynamicServiceDiscoveryCheck.java ---------------------------------------------------------------------- diff --git a/ambari-server/src/main/java/org/apache/ambari/server/checks/HiveDynamicServiceDiscoveryCheck.java b/ambari-server/src/main/java/org/apache/ambari/server/checks/HiveDynamicServiceDiscoveryCheck.java new file mode 100644 index 0000000..74bed8a --- /dev/null +++ b/ambari-server/src/main/java/org/apache/ambari/server/checks/HiveDynamicServiceDiscoveryCheck.java @@ -0,0 +1,102 @@ +/* + * 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.List; +import java.util.Map; + +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.Service; +import org.apache.ambari.server.state.stack.PrereqCheckStatus; +import org.apache.ambari.server.state.stack.PrerequisiteCheck; +import org.apache.commons.lang.StringUtils; + +import com.google.inject.Singleton; + +/** + * The {@link HiveDynamicServiceDiscoveryCheck} class is used to check that HIVE + * is properly configured for dynamic discovery. + */ +@Singleton +@UpgradeCheck(group = UpgradeCheckGroup.DEFAULT, order = 1.0f) +public class HiveDynamicServiceDiscoveryCheck extends AbstractCheckDescriptor { + + static final String HIVE_DYNAMIC_SERVICE_DISCOVERY_ENABLED_KEY = "hive.dynamic-service.discovery.enabled.key"; + static final String HIVE_DYNAMIC_SERVICE_ZK_QUORUM_KEY = "hive.dynamic-service.discovery.zk-quorum.key"; + static final String HIVE_DYNAMIC_SERVICE_ZK_NAMESPACE_KEY = "hive.dynamic-service.zk-namespace.key"; + + /** + * Constructor. + */ + public HiveDynamicServiceDiscoveryCheck() { + super(CheckDescription.SERVICES_HIVE_DYNAMIC_SERVICE_DISCOVERY); + } + + /** + * {@inheritDoc} + */ + @Override + public boolean isApplicable(PrereqCheckRequest request) throws AmbariException { + if (!super.isApplicable(request)) { + return false; + } + + final Cluster cluster = clustersProvider.get().getCluster(request.getClusterName()); + Map<String, Service> services = cluster.getServices(); + if (services.containsKey("HIVE")) { + return true; + } + + return false; + } + + /** + * {@inheritDoc} + */ + @Override + public void perform(PrerequisiteCheck prerequisiteCheck, PrereqCheckRequest request) throws AmbariException { + List<String> errorMessages = new ArrayList<String>(); + + String dynamicServiceDiscoveryEnabled = getProperty(request, "hive-site", "hive.server2.support.dynamic.service.discovery"); + String zookeeperQuorum = getProperty(request, "hive-site", "hive.zookeeper.quorum"); + String zookeeperNamespace = getProperty(request, "hive-site", "hive.server2.zookeeper.namespace"); + + if (null == dynamicServiceDiscoveryEnabled || !Boolean.parseBoolean(dynamicServiceDiscoveryEnabled)) { + errorMessages.add(getFailReason(HIVE_DYNAMIC_SERVICE_DISCOVERY_ENABLED_KEY, prerequisiteCheck, request)); + } + + if (StringUtils.isBlank(zookeeperQuorum)) { + errorMessages.add(getFailReason(HIVE_DYNAMIC_SERVICE_ZK_QUORUM_KEY, prerequisiteCheck, + request)); + } + + if (StringUtils.isBlank(zookeeperNamespace)) { + errorMessages.add(getFailReason(HIVE_DYNAMIC_SERVICE_ZK_NAMESPACE_KEY, prerequisiteCheck, + request)); + } + + if (!errorMessages.isEmpty()) { + prerequisiteCheck.setFailReason(StringUtils.join(errorMessages, " ")); + prerequisiteCheck.getFailedOn().add("HIVE"); + prerequisiteCheck.setStatus(PrereqCheckStatus.FAIL); + } + } +} http://git-wip-us.apache.org/repos/asf/ambari/blob/f4725228/ambari-server/src/main/java/org/apache/ambari/server/checks/HostsHeartbeatCheck.java ---------------------------------------------------------------------- diff --git a/ambari-server/src/main/java/org/apache/ambari/server/checks/HostsHeartbeatCheck.java b/ambari-server/src/main/java/org/apache/ambari/server/checks/HostsHeartbeatCheck.java index cf9e4ae..6076a32 100644 --- a/ambari-server/src/main/java/org/apache/ambari/server/checks/HostsHeartbeatCheck.java +++ b/ambari-server/src/main/java/org/apache/ambari/server/checks/HostsHeartbeatCheck.java @@ -28,9 +28,13 @@ import org.apache.ambari.server.state.MaintenanceState; import org.apache.ambari.server.state.stack.PrereqCheckStatus; import org.apache.ambari.server.state.stack.PrerequisiteCheck; +import com.google.inject.Singleton; + /** * Checks that all hosts are either in maintenance mode or heartbeating with the server. */ +@Singleton +@UpgradeCheck(group = UpgradeCheckGroup.LIVELINESS, order = 1.0f) public class HostsHeartbeatCheck extends AbstractCheckDescriptor { /** http://git-wip-us.apache.org/repos/asf/ambari/blob/f4725228/ambari-server/src/main/java/org/apache/ambari/server/checks/HostsMasterMaintenanceCheck.java ---------------------------------------------------------------------- diff --git a/ambari-server/src/main/java/org/apache/ambari/server/checks/HostsMasterMaintenanceCheck.java b/ambari-server/src/main/java/org/apache/ambari/server/checks/HostsMasterMaintenanceCheck.java index 2c5ff28..ef93337 100644 --- a/ambari-server/src/main/java/org/apache/ambari/server/checks/HostsMasterMaintenanceCheck.java +++ b/ambari-server/src/main/java/org/apache/ambari/server/checks/HostsMasterMaintenanceCheck.java @@ -34,9 +34,13 @@ import org.apache.ambari.server.state.stack.PrerequisiteCheck; import org.apache.ambari.server.state.stack.UpgradePack; import org.apache.ambari.server.state.stack.UpgradePack.ProcessingComponent; +import com.google.inject.Singleton; + /** * Checks that all hosts in maintenance state do not have master components. */ +@Singleton +@UpgradeCheck(group = UpgradeCheckGroup.MAINTENANCE_MODE, order = 1.0f) public class HostsMasterMaintenanceCheck extends AbstractCheckDescriptor { static final String KEY_NO_UPGRADE_NAME = "no_upgrade_name"; http://git-wip-us.apache.org/repos/asf/ambari/blob/f4725228/ambari-server/src/main/java/org/apache/ambari/server/checks/HostsRepositoryVersionCheck.java ---------------------------------------------------------------------- diff --git a/ambari-server/src/main/java/org/apache/ambari/server/checks/HostsRepositoryVersionCheck.java b/ambari-server/src/main/java/org/apache/ambari/server/checks/HostsRepositoryVersionCheck.java index 0ea5d08..6ebf8e1 100644 --- a/ambari-server/src/main/java/org/apache/ambari/server/checks/HostsRepositoryVersionCheck.java +++ b/ambari-server/src/main/java/org/apache/ambari/server/checks/HostsRepositoryVersionCheck.java @@ -32,9 +32,13 @@ import org.apache.ambari.server.state.StackId; import org.apache.ambari.server.state.stack.PrereqCheckStatus; import org.apache.ambari.server.state.stack.PrerequisiteCheck; +import com.google.inject.Singleton; + /** * Checks that all hosts have particular repository version. */ +@Singleton +@UpgradeCheck(group = UpgradeCheckGroup.REPOSITORY_VERSION) public class HostsRepositoryVersionCheck extends AbstractCheckDescriptor { static final String KEY_NO_REPO_VERSION = "no_repo_version"; http://git-wip-us.apache.org/repos/asf/ambari/blob/f4725228/ambari-server/src/main/java/org/apache/ambari/server/checks/SecondaryNamenodeDeletedCheck.java ---------------------------------------------------------------------- diff --git a/ambari-server/src/main/java/org/apache/ambari/server/checks/SecondaryNamenodeDeletedCheck.java b/ambari-server/src/main/java/org/apache/ambari/server/checks/SecondaryNamenodeDeletedCheck.java index 14ec2c1..493042f 100644 --- a/ambari-server/src/main/java/org/apache/ambari/server/checks/SecondaryNamenodeDeletedCheck.java +++ b/ambari-server/src/main/java/org/apache/ambari/server/checks/SecondaryNamenodeDeletedCheck.java @@ -34,10 +34,13 @@ import org.apache.ambari.server.state.stack.PrereqCheckStatus; import org.apache.ambari.server.state.stack.PrerequisiteCheck; import com.google.inject.Inject; +import com.google.inject.Singleton; /** * Checks that the Secondary NameNode is not present on any of the hosts. */ +@Singleton +@UpgradeCheck(group = UpgradeCheckGroup.NAMENODE_HA, order = 2.0f) public class SecondaryNamenodeDeletedCheck extends AbstractCheckDescriptor { @Inject HostComponentStateDAO hostComponentStateDao; http://git-wip-us.apache.org/repos/asf/ambari/blob/f4725228/ambari-server/src/main/java/org/apache/ambari/server/checks/ServicesDecommissionCheck.java ---------------------------------------------------------------------- diff --git a/ambari-server/src/main/java/org/apache/ambari/server/checks/ServicesDecommissionCheck.java b/ambari-server/src/main/java/org/apache/ambari/server/checks/ServicesDecommissionCheck.java index 7497c2f..6ebfd1f 100644 --- a/ambari-server/src/main/java/org/apache/ambari/server/checks/ServicesDecommissionCheck.java +++ b/ambari-server/src/main/java/org/apache/ambari/server/checks/ServicesDecommissionCheck.java @@ -29,9 +29,12 @@ import org.apache.ambari.server.state.ServiceComponentHost; import org.apache.ambari.server.state.stack.PrereqCheckStatus; import org.apache.ambari.server.state.stack.PrerequisiteCheck; +import com.google.inject.Singleton; + /** * Checks that there are no services in decommission state. */ +@Singleton public class ServicesDecommissionCheck extends AbstractCheckDescriptor { /** http://git-wip-us.apache.org/repos/asf/ambari/blob/f4725228/ambari-server/src/main/java/org/apache/ambari/server/checks/ServicesMaintenanceModeCheck.java ---------------------------------------------------------------------- diff --git a/ambari-server/src/main/java/org/apache/ambari/server/checks/ServicesMaintenanceModeCheck.java b/ambari-server/src/main/java/org/apache/ambari/server/checks/ServicesMaintenanceModeCheck.java index 0ae5c46..2b5ff49 100644 --- a/ambari-server/src/main/java/org/apache/ambari/server/checks/ServicesMaintenanceModeCheck.java +++ b/ambari-server/src/main/java/org/apache/ambari/server/checks/ServicesMaintenanceModeCheck.java @@ -28,9 +28,13 @@ import org.apache.ambari.server.state.State; import org.apache.ambari.server.state.stack.PrereqCheckStatus; import org.apache.ambari.server.state.stack.PrerequisiteCheck; +import com.google.inject.Singleton; + /** * Checks that services are in the maintenance mode. */ +@Singleton +@UpgradeCheck(group = UpgradeCheckGroup.MAINTENANCE_MODE, order = 2.0f) public class ServicesMaintenanceModeCheck extends AbstractCheckDescriptor { /** http://git-wip-us.apache.org/repos/asf/ambari/blob/f4725228/ambari-server/src/main/java/org/apache/ambari/server/checks/ServicesMapReduceDistributedCacheCheck.java ---------------------------------------------------------------------- diff --git a/ambari-server/src/main/java/org/apache/ambari/server/checks/ServicesMapReduceDistributedCacheCheck.java b/ambari-server/src/main/java/org/apache/ambari/server/checks/ServicesMapReduceDistributedCacheCheck.java index 36526e3..be5d11a 100644 --- a/ambari-server/src/main/java/org/apache/ambari/server/checks/ServicesMapReduceDistributedCacheCheck.java +++ b/ambari-server/src/main/java/org/apache/ambari/server/checks/ServicesMapReduceDistributedCacheCheck.java @@ -31,9 +31,13 @@ import org.apache.ambari.server.state.stack.PrereqCheckStatus; import org.apache.ambari.server.state.stack.PrerequisiteCheck; import org.apache.commons.lang.StringUtils; +import com.google.inject.Singleton; + /** * Checks that MR jobs reference hadoop libraries from the distributed cache. */ +@Singleton +@UpgradeCheck(group = UpgradeCheckGroup.NAMENODE_HA, order = 3.0f) public class ServicesMapReduceDistributedCacheCheck extends AbstractCheckDescriptor { static final String KEY_APP_CLASSPATH = "app_classpath"; http://git-wip-us.apache.org/repos/asf/ambari/blob/f4725228/ambari-server/src/main/java/org/apache/ambari/server/checks/ServicesNamenodeHighAvailabilityCheck.java ---------------------------------------------------------------------- diff --git a/ambari-server/src/main/java/org/apache/ambari/server/checks/ServicesNamenodeHighAvailabilityCheck.java b/ambari-server/src/main/java/org/apache/ambari/server/checks/ServicesNamenodeHighAvailabilityCheck.java index e43e4fb..d92f12d 100644 --- a/ambari-server/src/main/java/org/apache/ambari/server/checks/ServicesNamenodeHighAvailabilityCheck.java +++ b/ambari-server/src/main/java/org/apache/ambari/server/checks/ServicesNamenodeHighAvailabilityCheck.java @@ -28,9 +28,13 @@ import org.apache.ambari.server.state.DesiredConfig; import org.apache.ambari.server.state.stack.PrereqCheckStatus; import org.apache.ambari.server.state.stack.PrerequisiteCheck; +import com.google.inject.Singleton; + /** * Checks that namenode high availability is enabled. */ +@Singleton +@UpgradeCheck(group = UpgradeCheckGroup.NAMENODE_HA, order = 1.0f) public class ServicesNamenodeHighAvailabilityCheck extends AbstractCheckDescriptor { /** http://git-wip-us.apache.org/repos/asf/ambari/blob/f4725228/ambari-server/src/main/java/org/apache/ambari/server/checks/ServicesTezDistributedCacheCheck.java ---------------------------------------------------------------------- diff --git a/ambari-server/src/main/java/org/apache/ambari/server/checks/ServicesTezDistributedCacheCheck.java b/ambari-server/src/main/java/org/apache/ambari/server/checks/ServicesTezDistributedCacheCheck.java index 41735b4..68a7103 100644 --- a/ambari-server/src/main/java/org/apache/ambari/server/checks/ServicesTezDistributedCacheCheck.java +++ b/ambari-server/src/main/java/org/apache/ambari/server/checks/ServicesTezDistributedCacheCheck.java @@ -31,9 +31,13 @@ import org.apache.ambari.server.state.stack.PrereqCheckStatus; import org.apache.ambari.server.state.stack.PrerequisiteCheck; import org.apache.commons.lang.StringUtils; +import com.google.inject.Singleton; + /** * Checks that Tez jobs reference hadoop libraries from the distributed cache. */ +@Singleton +@UpgradeCheck(group = UpgradeCheckGroup.NAMENODE_HA, order = 4.0f) public class ServicesTezDistributedCacheCheck extends AbstractCheckDescriptor { static final String KEY_LIB_URI_MISSING = "tez_lib_uri_missing"; http://git-wip-us.apache.org/repos/asf/ambari/blob/f4725228/ambari-server/src/main/java/org/apache/ambari/server/checks/ServicesUpCheck.java ---------------------------------------------------------------------- diff --git a/ambari-server/src/main/java/org/apache/ambari/server/checks/ServicesUpCheck.java b/ambari-server/src/main/java/org/apache/ambari/server/checks/ServicesUpCheck.java index e0696fa..243b26d 100644 --- a/ambari-server/src/main/java/org/apache/ambari/server/checks/ServicesUpCheck.java +++ b/ambari-server/src/main/java/org/apache/ambari/server/checks/ServicesUpCheck.java @@ -27,9 +27,13 @@ import org.apache.ambari.server.state.State; import org.apache.ambari.server.state.stack.PrereqCheckStatus; import org.apache.ambari.server.state.stack.PrerequisiteCheck; +import com.google.inject.Singleton; + /** * Checks that services are up. */ +@Singleton +@UpgradeCheck(group = UpgradeCheckGroup.LIVELINESS, order = 2.0f) public class ServicesUpCheck extends AbstractCheckDescriptor { /** http://git-wip-us.apache.org/repos/asf/ambari/blob/f4725228/ambari-server/src/main/java/org/apache/ambari/server/checks/ServicesYarnWorkPreservingCheck.java ---------------------------------------------------------------------- diff --git a/ambari-server/src/main/java/org/apache/ambari/server/checks/ServicesYarnWorkPreservingCheck.java b/ambari-server/src/main/java/org/apache/ambari/server/checks/ServicesYarnWorkPreservingCheck.java index a56f35d..a0b2b59 100644 --- a/ambari-server/src/main/java/org/apache/ambari/server/checks/ServicesYarnWorkPreservingCheck.java +++ b/ambari-server/src/main/java/org/apache/ambari/server/checks/ServicesYarnWorkPreservingCheck.java @@ -17,21 +17,21 @@ */ package org.apache.ambari.server.checks; -import java.util.Map; - import org.apache.ambari.server.AmbariException; import org.apache.ambari.server.ServiceNotFoundException; import org.apache.ambari.server.controller.PrereqCheckRequest; import org.apache.ambari.server.state.Cluster; -import org.apache.ambari.server.state.Config; -import org.apache.ambari.server.state.DesiredConfig; import org.apache.ambari.server.state.stack.PrereqCheckStatus; import org.apache.ambari.server.state.stack.PrerequisiteCheck; import org.apache.commons.lang.BooleanUtils; +import com.google.inject.Singleton; + /** * Checks that YARN has work-preserving restart enabled. */ +@Singleton +@UpgradeCheck(group = UpgradeCheckGroup.DEFAULT, order = 1.0f) public class ServicesYarnWorkPreservingCheck extends AbstractCheckDescriptor { /** @@ -41,6 +41,9 @@ public class ServicesYarnWorkPreservingCheck extends AbstractCheckDescriptor { super(CheckDescription.SERVICES_YARN_WP); } + /** + * {@inheritDoc} + */ @Override public boolean isApplicable(PrereqCheckRequest request) throws AmbariException { if (!super.isApplicable(request)) { @@ -56,16 +59,15 @@ public class ServicesYarnWorkPreservingCheck extends AbstractCheckDescriptor { return true; } + /** + * {@inheritDoc} + */ @Override public void perform(PrerequisiteCheck prerequisiteCheck, PrereqCheckRequest request) throws AmbariException { - final String clusterName = request.getClusterName(); - final Cluster cluster = clustersProvider.get().getCluster(clusterName); - final String configType = "yarn-site"; - final Map<String, DesiredConfig> desiredConfigs = cluster.getDesiredConfigs(); - final DesiredConfig desiredConfig = desiredConfigs.get(configType); - final Config config = cluster.getConfig(configType, desiredConfig.getTag()); - if (!config.getProperties().containsKey("yarn.resourcemanager.work-preserving-recovery.enabled") || - !BooleanUtils.toBoolean(config.getProperties().get("yarn.resourcemanager.work-preserving-recovery.enabled"))) { + String propertyValue = getProperty(request, "yarn-site", + "yarn.resourcemanager.work-preserving-recovery.enabled"); + + if (null == propertyValue || !BooleanUtils.toBoolean(propertyValue)) { prerequisiteCheck.getFailedOn().add("YARN"); prerequisiteCheck.setStatus(PrereqCheckStatus.FAIL); prerequisiteCheck.setFailReason(getFailReason(prerequisiteCheck, request)); http://git-wip-us.apache.org/repos/asf/ambari/blob/f4725228/ambari-server/src/main/java/org/apache/ambari/server/checks/UpgradeCheck.java ---------------------------------------------------------------------- diff --git a/ambari-server/src/main/java/org/apache/ambari/server/checks/UpgradeCheck.java b/ambari-server/src/main/java/org/apache/ambari/server/checks/UpgradeCheck.java new file mode 100644 index 0000000..9fa8916 --- /dev/null +++ b/ambari-server/src/main/java/org/apache/ambari/server/checks/UpgradeCheck.java @@ -0,0 +1,58 @@ +/** + * 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 static java.lang.annotation.RetentionPolicy.RUNTIME; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.Target; + +import com.google.inject.ScopeAnnotation; +import com.google.inject.Singleton; + +/** + * The {@link UpgradeCheck} annotation is used to provide ordering and grouping + * to any {@link AbstractCheckDescriptor} instance. + * <p/> + * Classes marked with this annotation should also be {@link Singleton}. They + * will be discovered on the classpath and then registered with the + * {@link UpgradeCheckRegistry}. + */ +@Target({ ElementType.TYPE }) +@Retention(RUNTIME) +@ScopeAnnotation +public @interface UpgradeCheck { + + /** + * The group that the pre-upgrade check belongs to. + * + * @return the group, or {@link UpgradeCheckGroup#DEFAULT} if not specified. + */ + UpgradeCheckGroup group() default UpgradeCheckGroup.DEFAULT; + + /** + * The order of the pre-upgrade check within its group. + * <p/> + * The order is determined by a {@code float} so that new checks can be added + * in between others without the need to reorder all of the existing checks. + * + * @return the order, or {@code 1.0f} if not specified. + */ + float order() default 1.0f; +} http://git-wip-us.apache.org/repos/asf/ambari/blob/f4725228/ambari-server/src/main/java/org/apache/ambari/server/checks/UpgradeCheckGroup.java ---------------------------------------------------------------------- diff --git a/ambari-server/src/main/java/org/apache/ambari/server/checks/UpgradeCheckGroup.java b/ambari-server/src/main/java/org/apache/ambari/server/checks/UpgradeCheckGroup.java new file mode 100644 index 0000000..16e56f3 --- /dev/null +++ b/ambari-server/src/main/java/org/apache/ambari/server/checks/UpgradeCheckGroup.java @@ -0,0 +1,83 @@ +/** + * 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; + +/** + * The {@link UpgradeCheckGroup} enum is used to organize pre-upgrade checks + * into specific groups that have their own relational ordering. + * <p/> + * The order for each group is determined by a {@code float} so that new groups + * can be added in between others without the need to reorder all of the groups. + */ +public enum UpgradeCheckGroup { + + /** + * Check for masters in maintenance mode and then services in maintenance + * mode. + */ + MAINTENANCE_MODE(1.0f), + + /** + * Checks the repository version on the hosts. + */ + REPOSITORY_VERSION(2.0f), + + /** + * Checks for NameNode HA and checks that depend on NameNode HA. + */ + NAMENODE_HA(3.0f), + + /** + * Checks for the state of a host or service being alive and responsive. + */ + LIVELINESS(4.0f), + + /** + * Checks for the client retry properties to be set in clients that support + * this. + */ + CLIENT_RETRY_PROPERTY(5.0f), + + /** + * All other checks. + */ + DEFAULT(Float.MAX_VALUE); + + /** + * The order of upgrade check groups. + */ + private final Float m_order; + + /** + * Constructor. + * + * @param order + */ + private UpgradeCheckGroup(Float order) { + m_order = order; + } + + /** + * Gets the group's order. + * + * @return the order of the group. + */ + public Float getOrder() { + return m_order; + } +} http://git-wip-us.apache.org/repos/asf/ambari/blob/f4725228/ambari-server/src/main/java/org/apache/ambari/server/checks/UpgradeCheckRegistry.java ---------------------------------------------------------------------- diff --git a/ambari-server/src/main/java/org/apache/ambari/server/checks/UpgradeCheckRegistry.java b/ambari-server/src/main/java/org/apache/ambari/server/checks/UpgradeCheckRegistry.java new file mode 100644 index 0000000..8be572c --- /dev/null +++ b/ambari-server/src/main/java/org/apache/ambari/server/checks/UpgradeCheckRegistry.java @@ -0,0 +1,113 @@ +/** + * 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.Comparator; +import java.util.List; +import java.util.Set; +import java.util.TreeSet; + +import com.google.inject.Singleton; + +/** + * The {@link UpgradeCheckRegistry} contains the ordered list of all pre-upgrade + * checks. This will order the checks according to + * {@link PreUpgradeCheckComparator}. + */ +@Singleton +public class UpgradeCheckRegistry { + + /** + * The list of upgrade checks to run through. + */ + private Set<AbstractCheckDescriptor> m_upgradeChecks = new TreeSet<AbstractCheckDescriptor>( + new PreUpgradeCheckComparator()); + + /** + * Register an upgrade check. + * + * @param upgradeCheck + * the check to register (not {@code null}). + */ + public void register(AbstractCheckDescriptor upgradeCheck) { + m_upgradeChecks.add(upgradeCheck); + } + + /** + * Gets an ordered list of all of the upgrade checks. + * + * @return + */ + public List<AbstractCheckDescriptor> getUpgradeChecks() { + return new ArrayList<AbstractCheckDescriptor>(m_upgradeChecks); + } + + /** + * THe {@link PreUpgradeCheckComparator} class is used to compare + * {@link AbstractCheckDescriptor} based on their {@link UpgradeCheck} + * annotations. + */ + private static final class PreUpgradeCheckComparator implements + Comparator<AbstractCheckDescriptor> { + + /** + * {@inheritDoc} + */ + @Override + public int compare(AbstractCheckDescriptor check1, AbstractCheckDescriptor check2) { + Class<? extends AbstractCheckDescriptor> clazz1 = check1.getClass(); + Class<? extends AbstractCheckDescriptor> clazz2 = check2.getClass(); + + UpgradeCheck annotation1 = clazz1.getAnnotation(UpgradeCheck.class); + UpgradeCheck annotation2 = clazz2.getAnnotation(UpgradeCheck.class); + + UpgradeCheckGroup group1 = UpgradeCheckGroup.DEFAULT; + UpgradeCheckGroup group2 = UpgradeCheckGroup.DEFAULT; + Float groupOrder1 = Float.valueOf(group1.getOrder()); + Float groupOrder2 = Float.valueOf(group2.getOrder()); + + Float order1 = 1.0f; + Float order2 = 1.0f; + + if (null != annotation1) { + group1 = annotation1.group(); + groupOrder1 = Float.valueOf(group1.getOrder()); + order1 = Float.valueOf(annotation1.order()); + } + + if (null != annotation2) { + group2 = annotation2.group(); + groupOrder2 = Float.valueOf(group2.getOrder()); + order2 = Float.valueOf(annotation2.order()); + } + + int groupComparison = groupOrder1.compareTo(groupOrder2); + if (groupComparison != 0) { + return groupComparison; + } + + int orderComparison = order1.compareTo(order2); + if (orderComparison != 0) { + return orderComparison; + } + + return clazz1.getName().compareTo(clazz2.getName()); + } + } +} http://git-wip-us.apache.org/repos/asf/ambari/blob/f4725228/ambari-server/src/main/java/org/apache/ambari/server/checks/YarnRMHighAvailabilityCheck.java ---------------------------------------------------------------------- diff --git a/ambari-server/src/main/java/org/apache/ambari/server/checks/YarnRMHighAvailabilityCheck.java b/ambari-server/src/main/java/org/apache/ambari/server/checks/YarnRMHighAvailabilityCheck.java new file mode 100644 index 0000000..db8af29 --- /dev/null +++ b/ambari-server/src/main/java/org/apache/ambari/server/checks/YarnRMHighAvailabilityCheck.java @@ -0,0 +1,80 @@ +/* + * 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.Map; + +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.Service; +import org.apache.ambari.server.state.stack.PrereqCheckStatus; +import org.apache.ambari.server.state.stack.PrerequisiteCheck; +import org.apache.commons.lang.BooleanUtils; + +import com.google.inject.Singleton; + +/** + * The {@link YarnRMHighAvailabilityCheck} checks that YARN has HA mode enabled + * for ResourceManager.. + */ +@Singleton +@UpgradeCheck(group = UpgradeCheckGroup.DEFAULT, order = 1.0f) +public class YarnRMHighAvailabilityCheck extends AbstractCheckDescriptor { + + /** + * Constructor. + */ + public YarnRMHighAvailabilityCheck() { + super(CheckDescription.SERVICES_YARN_RM_HA); + } + + /** + * {@inheritDoc} + */ + @Override + public boolean isApplicable(PrereqCheckRequest request) throws AmbariException { + if (!super.isApplicable(request)) { + return false; + } + + final Cluster cluster = clustersProvider.get().getCluster(request.getClusterName()); + Map<String, Service> services = cluster.getServices(); + if (!services.containsKey("YARN")) { + return false; + } + + return true; + } + + /** + * {@inheritDoc} + */ + @Override + public void perform(PrerequisiteCheck prerequisiteCheck, PrereqCheckRequest request) throws AmbariException { + // pretty weak sauce here; probably should do a bit more, like query JMX to + // see that there is at least 1 RM active and 1 in standby + String propertyValue = getProperty(request, "yarn-site", "yarn.resourcemanager.ha.enabled"); + + if (null == propertyValue || !BooleanUtils.toBoolean(propertyValue)) { + prerequisiteCheck.getFailedOn().add("YARN"); + prerequisiteCheck.setStatus(PrereqCheckStatus.WARNING); + prerequisiteCheck.setFailReason(getFailReason(prerequisiteCheck, request)); + } + } +} http://git-wip-us.apache.org/repos/asf/ambari/blob/f4725228/ambari-server/src/main/java/org/apache/ambari/server/checks/YarnTimelineServerStatePreservingCheck.java ---------------------------------------------------------------------- diff --git a/ambari-server/src/main/java/org/apache/ambari/server/checks/YarnTimelineServerStatePreservingCheck.java b/ambari-server/src/main/java/org/apache/ambari/server/checks/YarnTimelineServerStatePreservingCheck.java new file mode 100644 index 0000000..ef7cbff --- /dev/null +++ b/ambari-server/src/main/java/org/apache/ambari/server/checks/YarnTimelineServerStatePreservingCheck.java @@ -0,0 +1,94 @@ +/* + * 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.Map; + +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.Service; +import org.apache.ambari.server.state.stack.PrereqCheckStatus; +import org.apache.ambari.server.state.stack.PrerequisiteCheck; +import org.apache.ambari.server.utils.VersionUtils; +import org.apache.commons.lang.BooleanUtils; + +import com.google.inject.Singleton; + +/** + * The {@link YarnTimelineServerStatePreservingCheck} is used to check that the + * YARN Timeline server has state preserving mode enabled. This value is only + * present in HDP 2.2.4.2+. + */ +@Singleton +@UpgradeCheck(group = UpgradeCheckGroup.DEFAULT, order = 1.0f) +public class YarnTimelineServerStatePreservingCheck extends AbstractCheckDescriptor { + + private final static String YARN_TIMELINE_STATE_RECOVERY_ENABLED_KEY = "yarn.timeline-service.recovery.enabled"; + + /** + * Constructor. + */ + public YarnTimelineServerStatePreservingCheck() { + super(CheckDescription.SERVICES_YARN_TIMELINE_ST); + } + + /** + * {@inheritDoc} + */ + @Override + public boolean isApplicable(PrereqCheckRequest request) throws AmbariException { + if (!super.isApplicable(request)) { + return false; + } + + final Cluster cluster = clustersProvider.get().getCluster(request.getClusterName()); + Map<String, Service> services = cluster.getServices(); + if (!services.containsKey("YARN")) { + return false; + } + + // not applicable if not HDP 2.2.4.2 or later + String stackName = cluster.getCurrentStackVersion().getStackName(); + if (!"HDP".equals(stackName)) { + return false; + } + + String currentClusterRepositoryVersion = cluster.getCurrentClusterVersion().getRepositoryVersion().getVersion(); + if (VersionUtils.compareVersions(currentClusterRepositoryVersion, "2.2.4.2") < 0) { + return false; + } + + return true; + } + + /** + * {@inheritDoc} + */ + @Override + public void perform(PrerequisiteCheck prerequisiteCheck, PrereqCheckRequest request) throws AmbariException { + String propertyValue = getProperty(request, "yarn-site", + YARN_TIMELINE_STATE_RECOVERY_ENABLED_KEY); + + if (null == propertyValue || !BooleanUtils.toBoolean(propertyValue)) { + prerequisiteCheck.getFailedOn().add("YARN"); + prerequisiteCheck.setStatus(PrereqCheckStatus.FAIL); + prerequisiteCheck.setFailReason(getFailReason(prerequisiteCheck, request)); + } + } +} http://git-wip-us.apache.org/repos/asf/ambari/blob/f4725228/ambari-server/src/main/java/org/apache/ambari/server/controller/ControllerModule.java ---------------------------------------------------------------------- diff --git a/ambari-server/src/main/java/org/apache/ambari/server/controller/ControllerModule.java b/ambari-server/src/main/java/org/apache/ambari/server/controller/ControllerModule.java index 08a56d0..432e41a 100644 --- a/ambari-server/src/main/java/org/apache/ambari/server/controller/ControllerModule.java +++ b/ambari-server/src/main/java/org/apache/ambari/server/controller/ControllerModule.java @@ -56,6 +56,8 @@ import org.apache.ambari.server.actionmanager.HostRoleCommandFactoryImpl; import org.apache.ambari.server.actionmanager.RequestFactory; import org.apache.ambari.server.actionmanager.StageFactory; import org.apache.ambari.server.actionmanager.StageFactoryImpl; +import org.apache.ambari.server.checks.AbstractCheckDescriptor; +import org.apache.ambari.server.checks.UpgradeCheckRegistry; import org.apache.ambari.server.configuration.Configuration; import org.apache.ambari.server.configuration.Configuration.ConnectionPoolType; import org.apache.ambari.server.configuration.Configuration.DatabaseType; @@ -144,6 +146,7 @@ import com.mchange.v2.c3p0.ComboPooledDataSource; */ public class ControllerModule extends AbstractModule { private static Logger LOG = LoggerFactory.getLogger(ControllerModule.class); + private static final String AMBARI_PACKAGE = "org.apache.ambari.server"; private final Configuration configuration; private final OsFamily os_family; @@ -329,6 +332,7 @@ public class ControllerModule extends AbstractModule { bindByAnnotation(null); bindNotificationDispatchers(); + registerUpgradeChecks(); } @@ -451,7 +455,7 @@ public class ControllerModule extends AbstractModule { scanner.addIncludeFilter(new AnnotationTypeFilter(cls)); } - beanDefinitions = scanner.findCandidateComponents("org.apache.ambari.server"); + beanDefinitions = scanner.findCandidateComponents(AMBARI_PACKAGE); } if (null == beanDefinitions || beanDefinitions.size() == 0) { @@ -557,4 +561,52 @@ public class ControllerModule extends AbstractModule { } } } + + /** + * Searches for all instances of {@link AbstractCheckDescriptor} on the + * classpath and registers each as a singleton with the + * {@link UpgradeCheckRegistry}. + */ + @SuppressWarnings("unchecked") + private void registerUpgradeChecks() { + ClassPathScanningCandidateComponentProvider scanner = new ClassPathScanningCandidateComponentProvider( + false); + + // make the registry a singleton + UpgradeCheckRegistry registry = new UpgradeCheckRegistry(); + bind(UpgradeCheckRegistry.class).toInstance(registry); + + // match all implementations of the base check class + AssignableTypeFilter filter = new AssignableTypeFilter(AbstractCheckDescriptor.class); + scanner.addIncludeFilter(filter); + + Set<BeanDefinition> beanDefinitions = scanner.findCandidateComponents(AMBARI_PACKAGE); + + // no dispatchers is a problem + if (null == beanDefinitions || beanDefinitions.size() == 0) { + LOG.error("No instances of {} found to register", AbstractCheckDescriptor.class); + return; + } + + // for every discovered check, singleton-ize them and register with the + // registry + for (BeanDefinition beanDefinition : beanDefinitions) { + String className = beanDefinition.getBeanClassName(); + Class<?> clazz = ClassUtils.resolveClassName(className, ClassUtils.getDefaultClassLoader()); + + try { + AbstractCheckDescriptor upgradeCheck = (AbstractCheckDescriptor) clazz.newInstance(); + bind((Class<AbstractCheckDescriptor>) clazz).toInstance(upgradeCheck); + registry.register(upgradeCheck); + } catch (Exception exception) { + LOG.error("Unable to bind and register upgrade check {}", clazz, exception); + } + } + + // log the order of the pre-upgrade checks + List<AbstractCheckDescriptor> upgradeChecks = registry.getUpgradeChecks(); + for (AbstractCheckDescriptor upgradeCheck : upgradeChecks) { + LOG.error("Registered pre-upgrade check {}", upgradeCheck.getClass()); + } + } } http://git-wip-us.apache.org/repos/asf/ambari/blob/f4725228/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/PreUpgradeCheckResourceProvider.java ---------------------------------------------------------------------- diff --git a/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/PreUpgradeCheckResourceProvider.java b/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/PreUpgradeCheckResourceProvider.java index 3460423..207bf89 100644 --- a/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/PreUpgradeCheckResourceProvider.java +++ b/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/PreUpgradeCheckResourceProvider.java @@ -17,29 +17,15 @@ */ package org.apache.ambari.server.controller.internal; -import java.util.Arrays; 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.StaticallyInject; -import org.apache.ambari.server.checks.AbstractCheckDescriptor; -import org.apache.ambari.server.checks.ConfigurationMergeCheck; -import org.apache.ambari.server.checks.HostsHeartbeatCheck; -import org.apache.ambari.server.checks.HostsMasterMaintenanceCheck; -import org.apache.ambari.server.checks.HostsRepositoryVersionCheck; -import org.apache.ambari.server.checks.SecondaryNamenodeDeletedCheck; -import org.apache.ambari.server.checks.ServicesDecommissionCheck; -import org.apache.ambari.server.checks.ServicesMaintenanceModeCheck; -import org.apache.ambari.server.checks.ServicesMapReduceDistributedCacheCheck; -import org.apache.ambari.server.checks.ServicesNamenodeHighAvailabilityCheck; -import org.apache.ambari.server.checks.ServicesTezDistributedCacheCheck; -import org.apache.ambari.server.checks.ServicesUpCheck; -import org.apache.ambari.server.checks.ServicesYarnWorkPreservingCheck; +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; @@ -80,65 +66,13 @@ public class PreUpgradeCheckResourceProvider extends ReadOnlyResourceProvider { public static final String UPGRADE_CHECK_REPOSITORY_VERSION_PROPERTY_ID = PropertyHelper.getPropertyId("UpgradeChecks", "repository_version"); @Inject - private static ServicesMaintenanceModeCheck servicesMaintenanceModeCheck; - - @Inject - private static HostsMasterMaintenanceCheck hostsMasterMaintenanceCheck; - - @Inject - private static HostsRepositoryVersionCheck hostsRepositoryVersionCheck; - - @Inject - private static ServicesNamenodeHighAvailabilityCheck servicesNamenodeHighAvailabilityCheck; - - @Inject - private static SecondaryNamenodeDeletedCheck secondaryNamenodeDeletedCheck; - - @Inject - private static ServicesYarnWorkPreservingCheck servicesYarnWorkPreservingCheck; - - @Inject - private static ServicesDecommissionCheck servicesDecommissionCheck; - - @Inject - private static ServicesMapReduceDistributedCacheCheck servicesJobsDistributedCacheCheck; - - @Inject - private static HostsHeartbeatCheck heartbeatCheck; - - @Inject - private static ServicesUpCheck servicesUpCheck; - - @Inject - private static ServicesTezDistributedCacheCheck servicesTezDistributedCacheCheck; - - @Inject - private static ConfigurationMergeCheck configMergeCheck; - - @Inject private static Provider<Clusters> clustersProvider; @Inject private static RepositoryVersionDAO repositoryVersionDAO; - /** - * List of the registered upgrade checks. Make sure that if a check that - * depends on the result of another check comes earlier in the list. - * For example, MR2 and Tez distributed cache checks rely on NN-HA check passing. - */ - private List<AbstractCheckDescriptor> updateChecksRegistry = Arrays.asList( - hostsMasterMaintenanceCheck, - hostsRepositoryVersionCheck, - servicesMaintenanceModeCheck, - servicesNamenodeHighAvailabilityCheck, - secondaryNamenodeDeletedCheck, - servicesYarnWorkPreservingCheck, - servicesDecommissionCheck, - servicesJobsDistributedCacheCheck, - heartbeatCheck, - servicesUpCheck, - servicesTezDistributedCacheCheck, - configMergeCheck); + @Inject + private static UpgradeCheckRegistry upgradeCheckRegistry; private static Set<String> pkPropertyIds = Collections.singleton(UPGRADE_CHECK_ID_PROPERTY_ID); @@ -203,7 +137,7 @@ public class PreUpgradeCheckResourceProvider extends ReadOnlyResourceProvider { upgradeCheckRequest.setTargetStackId(repositoryVersionEntity.getStackId()); } - for (PrerequisiteCheck prerequisiteCheck : checkHelper.performChecks(upgradeCheckRequest, updateChecksRegistry)) { + for (PrerequisiteCheck prerequisiteCheck : checkHelper.performChecks(upgradeCheckRequest, upgradeCheckRegistry.getUpgradeChecks())) { 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); http://git-wip-us.apache.org/repos/asf/ambari/blob/f4725228/ambari-server/src/main/java/org/apache/ambari/server/state/CheckHelper.java ---------------------------------------------------------------------- diff --git a/ambari-server/src/main/java/org/apache/ambari/server/state/CheckHelper.java b/ambari-server/src/main/java/org/apache/ambari/server/state/CheckHelper.java index abaf8e7..5a8d4fd 100644 --- a/ambari-server/src/main/java/org/apache/ambari/server/state/CheckHelper.java +++ b/ambari-server/src/main/java/org/apache/ambari/server/state/CheckHelper.java @@ -37,27 +37,31 @@ public class CheckHelper { */ private static Logger LOG = LoggerFactory.getLogger(CheckHelper.class); - /** * Executes all registered pre-requisite checks. * - * @param request pre-requisite check request + * @param request + * pre-requisite check request * @return list of pre-requisite check results */ - public List<PrerequisiteCheck> performChecks(PrereqCheckRequest request, List<AbstractCheckDescriptor> checksRegistry) { + public List<PrerequisiteCheck> performChecks(PrereqCheckRequest request, + List<AbstractCheckDescriptor> checksRegistry) { final String clusterName = request.getClusterName(); final List<PrerequisiteCheck> prerequisiteCheckResults = new ArrayList<PrerequisiteCheck>(); for (AbstractCheckDescriptor checkDescriptor : checksRegistry) { final PrerequisiteCheck prerequisiteCheck = new PrerequisiteCheck( checkDescriptor.getDescription(), clusterName); - try { - if (checkDescriptor.isApplicable(request)) { - checkDescriptor.perform(prerequisiteCheck, request); - prerequisiteCheckResults.add(prerequisiteCheck); - request.addResult(checkDescriptor.getDescription(), prerequisiteCheck.getStatus()); + try { + if (!checkDescriptor.isApplicable(request)) { + continue; } + + checkDescriptor.perform(prerequisiteCheck, request); + prerequisiteCheckResults.add(prerequisiteCheck); + + request.addResult(checkDescriptor.getDescription(), prerequisiteCheck.getStatus()); } catch (ClusterNotFoundException ex) { prerequisiteCheck.setStatus(PrereqCheckStatus.FAIL); prerequisiteCheck.setFailReason("Cluster with name " + clusterName + " doesn't exists"); @@ -72,19 +76,8 @@ public class CheckHelper { request.addResult(checkDescriptor.getDescription(), prerequisiteCheck.getStatus()); } - - - - - - - - - - } - return prerequisiteCheckResults; } } http://git-wip-us.apache.org/repos/asf/ambari/blob/f4725228/ambari-server/src/test/java/org/apache/ambari/server/checks/ClientRetryPropertyCheckTest.java ---------------------------------------------------------------------- diff --git a/ambari-server/src/test/java/org/apache/ambari/server/checks/ClientRetryPropertyCheckTest.java b/ambari-server/src/test/java/org/apache/ambari/server/checks/ClientRetryPropertyCheckTest.java new file mode 100644 index 0000000..92b6a85 --- /dev/null +++ b/ambari-server/src/test/java/org/apache/ambari/server/checks/ClientRetryPropertyCheckTest.java @@ -0,0 +1,164 @@ +/* + * 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.HashMap; +import java.util.Map; + +import org.apache.ambari.server.controller.PrereqCheckRequest; +import org.apache.ambari.server.state.Cluster; +import org.apache.ambari.server.state.Clusters; +import org.apache.ambari.server.state.Config; +import org.apache.ambari.server.state.DesiredConfig; +import org.apache.ambari.server.state.Service; +import org.apache.ambari.server.state.stack.PrereqCheckStatus; +import org.apache.ambari.server.state.stack.PrerequisiteCheck; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; +import org.mockito.Mockito; + +import com.google.inject.Provider; + +/** + * Tests for {@link ClientRetryPropertyCheckTest} + */ +public class ClientRetryPropertyCheckTest { + private final Clusters m_clusters = Mockito.mock(Clusters.class); + + private final ClientRetryPropertyCheck m_check = new ClientRetryPropertyCheck(); + + /** + * + */ + @Before + public void setup() { + m_check.clustersProvider = new Provider<Clusters>() { + + @Override + public Clusters get() { + return m_clusters; + } + }; + } + + /** + * @throws Exception + */ + @Test + public void testIsApplicable() throws Exception { + final Cluster cluster = Mockito.mock(Cluster.class); + Mockito.when(cluster.getClusterId()).thenReturn(1L); + Mockito.when(m_clusters.getCluster("cluster")).thenReturn(cluster); + + Map<String, Service> services = new HashMap<String, Service>(); + Mockito.when(cluster.getServices()).thenReturn(services); + + PrereqCheckRequest request = new PrereqCheckRequest("cluster"); + request.setRepositoryVersion("2.3.0.0"); + + // nothing installed + Assert.assertFalse(m_check.isApplicable(request)); + + // YARN installed + services.put("HDFS", Mockito.mock(Service.class)); + Assert.assertTrue(m_check.isApplicable(request)); + + // OOZIE installed + services.clear(); + services.put("OOZIE", Mockito.mock(Service.class)); + Assert.assertTrue(m_check.isApplicable(request)); + } + + @Test + public void testPerform() throws Exception { + final Cluster cluster = Mockito.mock(Cluster.class); + + Mockito.when(cluster.getClusterId()).thenReturn(1L); + Mockito.when(m_clusters.getCluster("cluster")).thenReturn(cluster); + Map<String, Service> services = new HashMap<String, Service>(); + Mockito.when(cluster.getServices()).thenReturn(services); + + services.put("HDFS", Mockito.mock(Service.class)); + + final DesiredConfig desiredConfig = Mockito.mock(DesiredConfig.class); + Mockito.when(desiredConfig.getTag()).thenReturn("tag"); + Map<String, DesiredConfig> configMap = new HashMap<String, DesiredConfig>(); + configMap.put("hdfs-site", desiredConfig); + configMap.put("hive-site", desiredConfig); + configMap.put("oozie-env", desiredConfig); + + Mockito.when(cluster.getDesiredConfigs()).thenReturn(configMap); + final Config config = Mockito.mock(Config.class); + Mockito.when(cluster.getConfig(Mockito.anyString(), Mockito.anyString())).thenReturn(config); + final Map<String, String> properties = new HashMap<String, String>(); + Mockito.when(config.getProperties()).thenReturn(properties); + + PrerequisiteCheck check = new PrerequisiteCheck(null, null); + m_check.perform(check, new PrereqCheckRequest("cluster")); + Assert.assertEquals(PrereqCheckStatus.FAIL, check.getStatus()); + + // hdfs retry false + properties.put("dfs.client.retry.policy.enabled", "false"); + check = new PrerequisiteCheck(null, null); + m_check.perform(check, new PrereqCheckRequest("cluster")); + Assert.assertEquals(PrereqCheckStatus.FAIL, check.getStatus()); + + // hdfs retry true + properties.put("dfs.client.retry.policy.enabled", "true"); + check = new PrerequisiteCheck(null, null); + m_check.perform(check, new PrereqCheckRequest("cluster")); + Assert.assertEquals(PrereqCheckStatus.PASS, check.getStatus()); + + // add hive + services.put("HIVE", Mockito.mock(Service.class)); + + // fail with bad property + properties.put("hive.metastore.failure.retries", "0"); + check = new PrerequisiteCheck(null, null); + m_check.perform(check, new PrereqCheckRequest("cluster")); + Assert.assertEquals(PrereqCheckStatus.FAIL, check.getStatus()); + + // add hive retry + properties.put("hive.metastore.failure.retries", "5"); + check = new PrerequisiteCheck(null, null); + m_check.perform(check, new PrereqCheckRequest("cluster")); + Assert.assertEquals(PrereqCheckStatus.PASS, check.getStatus()); + + // add oozie + services.put("OOZIE", Mockito.mock(Service.class)); + + // fail without property + check = new PrerequisiteCheck(null, null); + m_check.perform(check, new PrereqCheckRequest("cluster")); + Assert.assertEquals(PrereqCheckStatus.FAIL, check.getStatus()); + + // fail without right property + properties.put("template", "foo bar baz"); + check = new PrerequisiteCheck(null, null); + m_check.perform(check, new PrereqCheckRequest("cluster")); + Assert.assertEquals(PrereqCheckStatus.FAIL, check.getStatus()); + + // pass with right property + properties.put("template", "foo bar baz -Doozie.connection.retry.count=5 foobarbaz"); + check = new PrerequisiteCheck(null, null); + m_check.perform(check, new PrereqCheckRequest("cluster")); + Assert.assertEquals(PrereqCheckStatus.PASS, check.getStatus()); + + } +} http://git-wip-us.apache.org/repos/asf/ambari/blob/f4725228/ambari-server/src/test/java/org/apache/ambari/server/checks/UpgradeCheckOrderTest.java ---------------------------------------------------------------------- diff --git a/ambari-server/src/test/java/org/apache/ambari/server/checks/UpgradeCheckOrderTest.java b/ambari-server/src/test/java/org/apache/ambari/server/checks/UpgradeCheckOrderTest.java new file mode 100644 index 0000000..7d70311 --- /dev/null +++ b/ambari-server/src/test/java/org/apache/ambari/server/checks/UpgradeCheckOrderTest.java @@ -0,0 +1,103 @@ +/** + * 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.io.File; +import java.util.List; +import java.util.Properties; +import java.util.Set; + +import org.apache.ambari.server.configuration.Configuration; +import org.apache.ambari.server.controller.ControllerModule; +import org.junit.Assert; +import org.junit.Test; +import org.springframework.beans.factory.config.BeanDefinition; +import org.springframework.context.annotation.ClassPathScanningCandidateComponentProvider; +import org.springframework.core.type.filter.AssignableTypeFilter; + +import com.google.inject.Guice; +import com.google.inject.Injector; + +/** + * Tests the order of pre-upgrade checks. + */ +public class UpgradeCheckOrderTest { + + /** + * Tests that instances of {@link AbstractCheckDescriptor} are ordered + * correctly. + * + * @throws Exception + */ + @Test + public void testUpgradeOrder() throws Exception { + String sourceResourceDirectory = "src" + File.separator + "test" + File.separator + "resources"; + + Properties properties = new Properties(); + properties.setProperty(Configuration.SERVER_PERSISTENCE_TYPE_KEY, "in-memory"); + properties.setProperty(Configuration.OS_VERSION_KEY, "centos6"); + properties.setProperty(Configuration.SHARED_RESOURCES_DIR_KEY, sourceResourceDirectory); + + Injector injector = Guice.createInjector(new ControllerModule(properties)); + UpgradeCheckRegistry registry = injector.getInstance(UpgradeCheckRegistry.class); + UpgradeCheckRegistry registry2 = injector.getInstance(UpgradeCheckRegistry.class); + + // verify singleton + Assert.assertEquals(registry, registry2); + + // get the check list + List<AbstractCheckDescriptor> checks = registry.getUpgradeChecks(); + + // scan for all checks + ClassPathScanningCandidateComponentProvider scanner = new ClassPathScanningCandidateComponentProvider(false); + AssignableTypeFilter filter = new AssignableTypeFilter(AbstractCheckDescriptor.class); + scanner.addIncludeFilter(filter); + + // verify they are equal + Set<BeanDefinition> beanDefinitions = scanner.findCandidateComponents("org.apache.ambari.server"); + Assert.assertEquals(beanDefinitions.size(), checks.size()); + + AbstractCheckDescriptor lastCheck = null; + for (AbstractCheckDescriptor check : checks) { + UpgradeCheckGroup group = UpgradeCheckGroup.DEFAULT; + UpgradeCheckGroup lastGroup = UpgradeCheckGroup.DEFAULT; + Float order = 1.0f; + Float lastOrder = 1.0f; + + if (null == lastCheck) { + lastCheck = check; + } + + UpgradeCheck annotation = check.getClass().getAnnotation(UpgradeCheck.class); + UpgradeCheck lastAnnotation = lastCheck.getClass().getAnnotation(UpgradeCheck.class); + + if (null != annotation) { + group = annotation.group(); + order = annotation.order(); + } + + if (null != lastAnnotation) { + lastGroup = lastAnnotation.group(); + lastOrder = lastAnnotation.order(); + } + + Assert.assertTrue(lastGroup.getOrder().compareTo(group.getOrder()) <= 0); + Assert.assertTrue(lastOrder.compareTo(order) <= 0); + } + } +} http://git-wip-us.apache.org/repos/asf/ambari/blob/f4725228/ambari-server/src/test/java/org/apache/ambari/server/checks/YarnTimelineServerStatePreservingCheckTest.java ---------------------------------------------------------------------- diff --git a/ambari-server/src/test/java/org/apache/ambari/server/checks/YarnTimelineServerStatePreservingCheckTest.java b/ambari-server/src/test/java/org/apache/ambari/server/checks/YarnTimelineServerStatePreservingCheckTest.java new file mode 100644 index 0000000..4f2da3b --- /dev/null +++ b/ambari-server/src/test/java/org/apache/ambari/server/checks/YarnTimelineServerStatePreservingCheckTest.java @@ -0,0 +1,127 @@ +/* + * 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.HashMap; +import java.util.Map; + +import org.apache.ambari.server.controller.PrereqCheckRequest; +import org.apache.ambari.server.orm.entities.ClusterVersionEntity; +import org.apache.ambari.server.orm.entities.RepositoryVersionEntity; +import org.apache.ambari.server.state.Cluster; +import org.apache.ambari.server.state.Clusters; +import org.apache.ambari.server.state.Config; +import org.apache.ambari.server.state.DesiredConfig; +import org.apache.ambari.server.state.Service; +import org.apache.ambari.server.state.StackId; +import org.apache.ambari.server.state.stack.PrereqCheckStatus; +import org.apache.ambari.server.state.stack.PrerequisiteCheck; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; +import org.mockito.Mockito; + +import com.google.inject.Provider; + +/** + * Tests for {@link YarnTimelineServerStatePreservingCheckTest} + */ +public class YarnTimelineServerStatePreservingCheckTest { + private final Clusters m_clusters = Mockito.mock(Clusters.class); + + private final YarnTimelineServerStatePreservingCheck m_check = new YarnTimelineServerStatePreservingCheck(); + + /** + * + */ + @Before + public void setup() { + m_check.clustersProvider = new Provider<Clusters>() { + + @Override + public Clusters get() { + return m_clusters; + } + }; + } + + /** + * @throws Exception + */ + @Test + public void testIsApplicable() throws Exception { + final Cluster cluster = Mockito.mock(Cluster.class); + Mockito.when(cluster.getClusterId()).thenReturn(1L); + Mockito.when(m_clusters.getCluster("cluster")).thenReturn(cluster); + Mockito.when(cluster.getCurrentStackVersion()).thenReturn(new StackId("HDP-2.2")); + + Map<String, Service> services = new HashMap<String, Service>(); + Mockito.when(cluster.getServices()).thenReturn(services); + + ClusterVersionEntity clusterVersionEntity = Mockito.mock(ClusterVersionEntity.class); + Mockito.when(cluster.getCurrentClusterVersion()).thenReturn(clusterVersionEntity); + + RepositoryVersionEntity repositoryVersionEntity = Mockito.mock(RepositoryVersionEntity.class); + Mockito.when(clusterVersionEntity.getRepositoryVersion()).thenReturn(repositoryVersionEntity); + Mockito.when(repositoryVersionEntity.getVersion()).thenReturn("2.2.4.2"); + + PrereqCheckRequest request = new PrereqCheckRequest("cluster"); + request.setRepositoryVersion("2.3.0.0"); + + // YARN not installed + Assert.assertFalse(m_check.isApplicable(request)); + + // YARN installed + services.put("YARN", Mockito.mock(Service.class)); + Assert.assertTrue(m_check.isApplicable(request)); + + Mockito.when(repositoryVersionEntity.getVersion()).thenReturn("2.2.0.0"); + Assert.assertFalse(m_check.isApplicable(request)); + + Mockito.when(repositoryVersionEntity.getVersion()).thenReturn("2.2.4.2"); + Assert.assertTrue(m_check.isApplicable(request)); + } + + @Test + public void testPerform() throws Exception { + final Cluster cluster = Mockito.mock(Cluster.class); + Mockito.when(cluster.getClusterId()).thenReturn(1L); + Mockito.when(m_clusters.getCluster("cluster")).thenReturn(cluster); + + final DesiredConfig desiredConfig = Mockito.mock(DesiredConfig.class); + Mockito.when(desiredConfig.getTag()).thenReturn("tag"); + Map<String, DesiredConfig> configMap = new HashMap<String, DesiredConfig>(); + configMap.put("yarn-site", desiredConfig); + configMap.put("core-site", desiredConfig); + + Mockito.when(cluster.getDesiredConfigs()).thenReturn(configMap); + final Config config = Mockito.mock(Config.class); + Mockito.when(cluster.getConfig(Mockito.anyString(), Mockito.anyString())).thenReturn(config); + final Map<String, String> properties = new HashMap<String, String>(); + Mockito.when(config.getProperties()).thenReturn(properties); + + PrerequisiteCheck check = new PrerequisiteCheck(null, null); + m_check.perform(check, new PrereqCheckRequest("cluster")); + Assert.assertEquals(PrereqCheckStatus.FAIL, check.getStatus()); + + properties.put("yarn.timeline-service.recovery.enabled", "true"); + check = new PrerequisiteCheck(null, null); + m_check.perform(check, new PrereqCheckRequest("cluster")); + Assert.assertEquals(PrereqCheckStatus.PASS, check.getStatus()); + } +} http://git-wip-us.apache.org/repos/asf/ambari/blob/f4725228/ambari-server/src/test/java/org/apache/ambari/server/state/CheckHelperTest.java ---------------------------------------------------------------------- diff --git a/ambari-server/src/test/java/org/apache/ambari/server/state/CheckHelperTest.java b/ambari-server/src/test/java/org/apache/ambari/server/state/CheckHelperTest.java index 17a8abe..e3836cb 100644 --- a/ambari-server/src/test/java/org/apache/ambari/server/state/CheckHelperTest.java +++ b/ambari-server/src/test/java/org/apache/ambari/server/state/CheckHelperTest.java @@ -58,7 +58,7 @@ public class CheckHelperTest { */ @Test - public void performPreUpgradeChecksTest_ok() throws Exception { + public void testPreUpgradeCheck() throws Exception { final CheckHelper helper = new CheckHelper(); List<AbstractCheckDescriptor> updateChecksRegistry = new ArrayList<AbstractCheckDescriptor>(); AbstractCheckDescriptor descriptor = EasyMock.createNiceMock(AbstractCheckDescriptor.class); @@ -73,7 +73,7 @@ public class CheckHelperTest { } @Test - public void performPreUpgradeChecksTest_notApplicable() throws Exception { + public void testPreUpgradeCheckNotApplicable() throws Exception { final CheckHelper helper = new CheckHelper(); List<AbstractCheckDescriptor> updateChecksRegistry = new ArrayList<AbstractCheckDescriptor>(); AbstractCheckDescriptor descriptor = EasyMock.createNiceMock(AbstractCheckDescriptor.class); @@ -85,7 +85,7 @@ public class CheckHelperTest { } @Test - public void performPreUpgradeChecksTest_throwsException() throws Exception { + public void testPreUpgradeCheckThrowsException() throws Exception { final CheckHelper helper = new CheckHelper(); List<AbstractCheckDescriptor> updateChecksRegistry = new ArrayList<AbstractCheckDescriptor>(); AbstractCheckDescriptor descriptor = EasyMock.createNiceMock(AbstractCheckDescriptor.class); @@ -102,7 +102,7 @@ public class CheckHelperTest { } @Test - public void performPreUpgradeChecksTest_clusterIsMissing() throws Exception { + public void testPreUpgradeCheckClusterMissing() throws Exception { final Clusters clusters = Mockito.mock(Clusters.class); Mockito.when(clusters.getCluster(Mockito.anyString())).thenAnswer(new Answer<Cluster>() { @Override @@ -115,6 +115,7 @@ public class CheckHelperTest { } } }); + final Injector injector = Guice.createInjector(new AbstractModule() { @Override @@ -124,11 +125,15 @@ public class CheckHelperTest { bind(RepositoryVersionDAO.class).toProvider(Providers.<RepositoryVersionDAO>of(null)); bind(RepositoryVersionHelper.class).toProvider(Providers.<RepositoryVersionHelper>of(null)); bind(AmbariMetaInfo.class).toProvider(Providers.<AmbariMetaInfo>of(null)); + bind(ServicesUpCheck.class).toInstance(new ServicesUpCheck()); } }); + final CheckHelper helper = injector.getInstance(CheckHelper.class); List<AbstractCheckDescriptor> updateChecksRegistry = new ArrayList<AbstractCheckDescriptor>(); - updateChecksRegistry.add(injector.getInstance(ServicesUpCheck.class)); //mocked Cluster has no services, so the check should always be PASS + + // mocked Cluster has no services, so the check should always be PASS + updateChecksRegistry.add(injector.getInstance(ServicesUpCheck.class)); List<PrerequisiteCheck> upgradeChecks = helper.performChecks(new PrereqCheckRequest("existing"), updateChecksRegistry); Assert.assertEquals(PrereqCheckStatus.PASS, upgradeChecks.get(0).getStatus()); upgradeChecks = helper.performChecks(new PrereqCheckRequest("non-existing"), updateChecksRegistry);
