Browse Source

Merge branch 'trunk' into branch-3.0-perf.

Conflicts:
	ambari-agent/conf/unix/install-helper.sh
	ambari-project/pom.xml
	ambari-server/pom.xml
	ambari-server/src/main/java/org/apache/ambari/server/actionmanager/ActionDBAccessorImpl.java
	ambari-server/src/main/resources/webapp/WEB-INF/spring-security.xml
	ambari-server/src/test/java/org/apache/ambari/server/upgrade/UpgradeCatalog270Test.java
Myroslav Papirkovskyi 7 years ago
parent
commit
21c5c8a0d7
44 changed files with 836 additions and 1149 deletions
  1. 14 17
      ambari-agent/conf/unix/install-helper.sh
  2. 6 0
      ambari-logsearch/ambari-logsearch-server/pom.xml
  3. 5 0
      ambari-project/pom.xml
  4. 2 2
      ambari-server/docs/configuration/index.md
  5. 4 0
      ambari-server/pom.xml
  6. 0 8
      ambari-server/src/main/java/org/apache/ambari/annotations/ExperimentalFeature.java
  7. 5 33
      ambari-server/src/main/java/org/apache/ambari/server/actionmanager/ActionDBAccessorImpl.java
  8. 164 0
      ambari-server/src/main/java/org/apache/ambari/server/checks/AbstractCheckDescriptor.java
  9. 0 58
      ambari-server/src/main/java/org/apache/ambari/server/checks/AtlasPresenceCheck.java
  10. 43 3
      ambari-server/src/main/java/org/apache/ambari/server/checks/ClientRetryPropertyCheck.java
  11. 23 11
      ambari-server/src/main/java/org/apache/ambari/server/checks/ComponentsExistInRepoCheck.java
  12. 22 16
      ambari-server/src/main/java/org/apache/ambari/server/checks/ComponentsInstallationCheck.java
  13. 6 0
      ambari-server/src/main/java/org/apache/ambari/server/checks/HealthCheck.java
  14. 3 0
      ambari-server/src/main/java/org/apache/ambari/server/checks/HostMaintenanceModeCheck.java
  15. 3 0
      ambari-server/src/main/java/org/apache/ambari/server/checks/HostsHeartbeatCheck.java
  16. 3 0
      ambari-server/src/main/java/org/apache/ambari/server/checks/HostsMasterMaintenanceCheck.java
  17. 3 0
      ambari-server/src/main/java/org/apache/ambari/server/checks/HostsRepositoryVersionCheck.java
  18. 13 4
      ambari-server/src/main/java/org/apache/ambari/server/checks/InstallPackagesCheck.java
  19. 8 0
      ambari-server/src/main/java/org/apache/ambari/server/checks/RequiredServicesInRepositoryCheck.java
  20. 76 4
      ambari-server/src/main/java/org/apache/ambari/server/checks/ServiceCheckValidityCheck.java
  21. 11 5
      ambari-server/src/main/java/org/apache/ambari/server/checks/ServicesUpCheck.java
  22. 1 27
      ambari-server/src/main/java/org/apache/ambari/server/configuration/Configuration.java
  23. 17 0
      ambari-server/src/main/java/org/apache/ambari/server/orm/models/HostComponentSummary.java
  24. 1 1
      ambari-server/src/main/java/org/apache/ambari/server/state/kerberos/AbstractKerberosDescriptorContainer.java
  25. 1 1
      ambari-server/src/main/java/org/apache/ambari/server/upgrade/SchemaUpgradeHelper.java
  26. 5 5
      ambari-server/src/main/java/org/apache/ambari/server/upgrade/UpgradeCatalog270.java
  27. 0 266
      ambari-server/src/main/java/org/apache/ambari/server/utils/Parallel.java
  28. 0 63
      ambari-server/src/main/java/org/apache/ambari/server/utils/ParallelLoopResult.java
  29. 0 42
      ambari-server/src/test/java/org/apache/ambari/server/checks/AtlasPresenceCheckTest.java
  30. 6 0
      ambari-server/src/test/java/org/apache/ambari/server/checks/ComponentExistsInRepoCheckTest.java
  31. 5 0
      ambari-server/src/test/java/org/apache/ambari/server/checks/ComponentsInstallationCheckTest.java
  32. 2 0
      ambari-server/src/test/java/org/apache/ambari/server/checks/HealthCheckTest.java
  33. 2 0
      ambari-server/src/test/java/org/apache/ambari/server/checks/HostMaintenanceModeCheckTest.java
  34. 3 0
      ambari-server/src/test/java/org/apache/ambari/server/checks/HostsHeartbeatCheckTest.java
  35. 2 0
      ambari-server/src/test/java/org/apache/ambari/server/checks/InstallPackagesCheckTest.java
  36. 2 0
      ambari-server/src/test/java/org/apache/ambari/server/checks/RequiredServicesInRepositoryCheckTest.java
  37. 9 0
      ambari-server/src/test/java/org/apache/ambari/server/checks/ServicesUpCheckTest.java
  38. 0 13
      ambari-server/src/test/java/org/apache/ambari/server/configuration/ConfigurationTest.java
  39. 100 100
      ambari-server/src/test/java/org/apache/ambari/server/upgrade/UpgradeCatalog270Test.java
  40. 1 1
      ambari-server/src/test/java/org/apache/ambari/server/upgrade/UpgradeCatalogTest.java
  41. 0 223
      ambari-server/src/test/java/org/apache/ambari/server/utils/TestParallel.java
  42. 7 0
      ambari-web/app/styles/modal_popups.less
  43. 256 244
      ambari-web/app/templates/common/host_progress_popup.hbs
  44. 2 2
      contrib/ambari-scom/ambari-scom-server/src/main/resources/META-INF/spring-security.xml

+ 14 - 17
ambari-agent/conf/unix/install-helper.sh

@@ -19,10 +19,12 @@
 ##################################################################
 
 INSTALL_HELPER_SERVER="/var/lib/ambari-server/install-helper.sh"
-COMMON_DIR_AGENT="/usr/lib/ambari-agent/lib/ambari_commons"
-RESOURCE_MANAGEMENT_DIR_AGENT="/usr/lib/ambari-agent/lib/resource_management"
-JINJA_AGENT_DIR="/usr/lib/ambari-agent/lib/ambari_jinja2"
-SIMPLEJSON_AGENT_DIR="/usr/lib/ambari-agent/lib/ambari_simplejson"
+COMMON_DIR="/usr/lib/ambari-agent/lib/ambari_commons"
+RESOURCE_MANAGEMENT_DIR="/usr/lib/ambari-agent/lib/resource_management"
+JINJA_DIR="/usr/lib/ambari-agent/lib/ambari_jinja2"
+SIMPLEJSON_DIR="/usr/lib/ambari-agent/lib/ambari_simplejson"
+OLD_OLD_COMMON_DIR="/usr/lib/ambari-agent/lib/common_functions"
+AMBARI_AGENT="/usr/lib/ambari-agent/lib/ambari_agent"
 PYTHON_WRAPER_TARGET="/usr/bin/ambari-python-wrap"
 AMBARI_AGENT_VAR="/var/lib/ambari-agent"
 AMBARI_AGENT_BINARY="/etc/init.d/ambari-agent"
@@ -35,15 +37,6 @@ OLD_JINJA_DIR="/usr/lib/python2.6/site-packages/ambari_jinja2"
 OLD_SIMPLEJSON_DIR="/usr/lib/python2.6/site-packages/ambari_simplejson"
 OLD_AMBARI_AGENT_DIR="/usr/lib/python2.6/site-packages/ambari_agent"
 
-COMMON_DIR="/usr/lib/ambari-agent/lib/ambari_commons"
-RESOURCE_MANAGEMENT_DIR="/usr/lib/ambari-agent/lib/resource_management"
-JINJA_DIR="/usr/lib/ambari-agent/lib/ambari_jinja2"
-SIMPLEJSON_DIR="/usr/lib/ambari-agent/lib/ambari_simplejson"
-STOMP_DIR="/usr/lib/ambari-agent/lib/ambari_stomp"
-WS4PY_DIR="/usr/lib/ambari-agent/lib/ambari_ws4py"
-OLD_COMMON_DIR="/usr/lib/ambari-agent/lib/common_functions"
-AMBARI_AGENT="/usr/lib/ambari-agent/lib/ambari_agent"
-
 clean_pyc_files(){
   # cleaning old *.pyc files
   find ${RESOURCE_MANAGEMENT_DIR:?} -name *.pyc -exec rm {} \;
@@ -59,8 +52,12 @@ do_install(){
     mv /etc/ambari-agent/conf.save /etc/ambari-agent/conf_$(date '+%d_%m_%y_%H_%M').save
   fi
 
-  # these symlinks (or directories) where created in ambari releases prior to ambari-2.6.2. Do clean up.
-  rm -rf "$OLD_COMMON_DIR" "$OLD_RESOURCE_MANAGEMENT_DIR" "$OLD_JINJA_DIR" "$OLD_SIMPLEJSON_DIR" "$OLD_COMMON_DIR" "$OLD_AMBARI_AGENT_DIR"
+  # these symlinks (or directories) where created in ambari releases prior to ambari-2.6.2. Do clean up.   
+  rm -rf "$OLD_COMMON_DIR" "$OLD_RESOURCE_MANAGEMENT_DIR" "$OLD_JINJA_DIR" "$OLD_SIMPLEJSON_DIR" "$OLD_OLD_COMMON_DIR" "$OLD_AMBARI_AGENT_DIR"
+
+  # setting up /usr/sbin/ambari-agent symlink
+  rm -f "$AMBARI_AGENT_BINARY_SYMLINK"
+  ln -s "$AMBARI_AGENT_BINARY" "$AMBARI_AGENT_BINARY_SYMLINK"
 
   # on nano Ubuntu, when umask=027 those folders are created without 'x' bit for 'others'.
   # which causes failures when hadoop users try to access tmp_dir
@@ -142,7 +139,7 @@ do_remove(){
   fi
 
   if [ -d "$COMMON_DIR" ]; then
-    rm -f $COMMON_DIR
+    rm -rf $COMMON_DIR
   fi
 
   if [ -d "$RESOURCE_MANAGEMENT_DIR" ]; then
@@ -154,7 +151,7 @@ do_remove(){
   fi
 
   if [ -d "$SIMPLEJSON_DIR" ]; then
-    rm -f $SIMPLEJSON_DIR
+    rm -rf $SIMPLEJSON_DIR
   fi
 
   # if server package exists, restore their settings

+ 6 - 0
ambari-logsearch/ambari-logsearch-server/pom.xml

@@ -220,6 +220,12 @@
       <groupId>org.springframework.security.kerberos</groupId>
       <artifactId>spring-security-kerberos-client</artifactId>
       <version>1.0.1.RELEASE</version>
+      <exclusions>
+        <exclusion>
+          <groupId>org.apache.httpcomponents</groupId>
+          <artifactId>httpclient</artifactId>
+        </exclusion>
+      </exclusions>
     </dependency>
     <dependency>
       <groupId>org.springframework.boot</groupId>

+ 5 - 0
ambari-project/pom.xml

@@ -145,6 +145,11 @@
         <artifactId>spring-security-kerberos-web</artifactId>
         <version>1.0.1.RELEASE</version>
       </dependency>
+      <dependency>
+        <groupId>org.springframework</groupId>
+        <artifactId>spring-jdbc</artifactId>
+        <version>3.2.10.RELEASE</version>
+      </dependency>
       <dependency>
         <groupId>org.springframework</groupId>
         <artifactId>spring-test</artifactId>

+ 2 - 2
ambari-server/docs/configuration/index.md

@@ -88,9 +88,9 @@ The following are the properties which can be used to configure Ambari.
 | auto.group.creation | The auto group creation by Ambari |`false` | 
 | bootstrap.dir | The directory on the Ambari Server file system used for storing Ambari Agent bootstrap information such as request responses. |`/var/run/ambari-server/bootstrap` | 
 | bootstrap.master_host_name | The host name of the Ambari Server which will be used by the Ambari Agents for communication. | | 
-| bootstrap.script | The location and name of the Python script used to bootstrap new Ambari Agent hosts. |`/usr/lib/python2.6/site-packages/ambari_server/bootstrap.py` | 
+| bootstrap.script | The location and name of the Python script used to bootstrap new Ambari Agent hosts. |`/usr/lib/ambari-server/lib/ambari_server/bootstrap.py` | 
 | bootstrap.setup_agent.password | The password to set on the `AMBARI_PASSPHRASE` environment variable before invoking the bootstrap script. |`password` | 
-| bootstrap.setup_agent.script | The location and name of the Python script executed on the Ambari Agent host during the bootstrap process. |`/usr/lib/python2.6/site-packages/ambari_server/setupAgent.py` | 
+| bootstrap.setup_agent.script | The location and name of the Python script executed on the Ambari Agent host during the bootstrap process. |`/usr/lib/ambari-server/lib/ambari_server/setupAgent.py` | 
 | client.api.acceptor.count | Count of acceptors to configure for the jetty connector used for Ambari API. | | 
 | client.api.port | The port that client connections will use with the REST API. The Ambari Web client runs on this port. |`8080` | 
 | client.api.ssl.cert_pass_file | The filename which contains the password for the keystores, truststores, and certificates for the REST API when it's protected by SSL. |`https.pass.txt` | 

+ 4 - 0
ambari-server/pom.xml

@@ -1210,6 +1210,10 @@
       <groupId>org.springframework.security.kerberos</groupId>
       <artifactId>spring-security-kerberos-web</artifactId>
     </dependency>
+    <dependency>
+      <groupId>org.springframework</groupId>
+      <artifactId>spring-jdbc</artifactId>
+    </dependency>
     <dependency>
       <groupId>org.springframework</groupId>
       <artifactId>spring-test</artifactId>

+ 0 - 8
ambari-server/src/main/java/org/apache/ambari/annotations/ExperimentalFeature.java

@@ -17,20 +17,12 @@
  */
 package org.apache.ambari.annotations;
 
-import java.util.concurrent.Executor;
-
 /**
  * The {@link ExperimentalFeature} enumeration is meant to be used with the
  * {@link Experimental} annotation to indicate which feature set experimental
  * code belongs to.
  */
 public enum ExperimentalFeature {
-  /**
-   * The processing of arbitrary, atomic list elements by an {@link Executor} in
-   * order to arrive at a full processed list faster.
-   */
-  PARALLEL_PROCESSING,
-
   /**
    * The caching of current alert information in order to reduce overall load on
    * the database by preventing frequent updates and JPA entity invalidation.

+ 5 - 33
ambari-server/src/main/java/org/apache/ambari/server/actionmanager/ActionDBAccessorImpl.java

@@ -30,8 +30,6 @@ import java.util.Objects;
 import java.util.Set;
 import java.util.concurrent.TimeUnit;
 
-import org.apache.ambari.annotations.Experimental;
-import org.apache.ambari.annotations.ExperimentalFeature;
 import org.apache.ambari.annotations.TransactionalLock;
 import org.apache.ambari.annotations.TransactionalLock.LockArea;
 import org.apache.ambari.annotations.TransactionalLock.LockType;
@@ -286,7 +284,6 @@ public class ActionDBAccessorImpl implements ActionDBAccessor {
    * {@inheritDoc}
    */
   @Override
-  @Experimental(feature = ExperimentalFeature.PARALLEL_PROCESSING)
   public List<Stage> getStagesInProgressForRequest(Long requestId) {
     List<StageEntity> stageEntities = stageDAO.findByRequestIdAndCommandStatuses(requestId, HostRoleStatus.IN_PROGRESS_STATUSES);
     return getStagesForEntities(stageEntities);
@@ -308,38 +305,13 @@ public class ActionDBAccessorImpl implements ActionDBAccessor {
     return stages;
   }
 
-  @Experimental(feature = ExperimentalFeature.PARALLEL_PROCESSING)
   private List<Stage> getStagesForEntities(List<StageEntity> stageEntities) {
-    // experimentally enable parallel stage processing
-    @Experimental(feature = ExperimentalFeature.PARALLEL_PROCESSING)
-    boolean useConcurrentStageProcessing = configuration.isExperimentalConcurrentStageProcessingEnabled();
-    if (useConcurrentStageProcessing) {
-      ParallelLoopResult<Stage> loopResult = Parallel.forLoop(stageEntities,
-          new LoopBody<StageEntity, Stage>() {
-            @Override
-            public Stage run(StageEntity stageEntity) {
-              return stageFactory.createExisting(stageEntity);
-            }
-          });
-      if (loopResult.getIsCompleted()) {
-        return loopResult.getResult();
-      } else {
-        // Fetch any missing results sequentially
-        List<Stage> stages = loopResult.getResult();
-        for (int i = 0; i < stages.size(); i++) {
-          if (stages.get(i) == null) {
-            stages.set(i, stageFactory.createExisting(stageEntities.get(i)));
-          }
-        }
-        return stages;
-      }
-    } else {
-      List<Stage> stages = new ArrayList<>(stageEntities.size());
-      for (StageEntity stageEntity : stageEntities) {
-        stages.add(stageFactory.createExisting(stageEntity));
-      }
-      return stages;
+    List<Stage> stages = new ArrayList<>(stageEntities.size());
+    for (StageEntity stageEntity : stageEntities) {
+      stages.add(stageFactory.createExisting(stageEntity));
     }
+
+    return stages;
   }
 
   /**

+ 164 - 0
ambari-server/src/main/java/org/apache/ambari/server/checks/AbstractCheckDescriptor.java

@@ -18,9 +18,11 @@
 package org.apache.ambari.server.checks;
 
 import java.util.Collections;
+import java.util.Comparator;
 import java.util.LinkedHashSet;
 import java.util.List;
 import java.util.Map;
+import java.util.Objects;
 import java.util.Set;
 
 import org.apache.ambari.server.AmbariException;
@@ -47,6 +49,7 @@ import org.apache.ambari.server.state.stack.upgrade.RepositoryVersionHelper;
 import org.apache.ambari.server.state.stack.upgrade.UpgradeType;
 import org.apache.commons.lang.ArrayUtils;
 import org.apache.commons.lang.StringUtils;
+import org.codehaus.jackson.annotate.JsonProperty;
 
 import com.google.common.collect.Lists;
 import com.google.gson.Gson;
@@ -468,4 +471,165 @@ public abstract class AbstractCheckDescriptor {
       return false;
     }
   }
+
+  /**
+   * Used to represent information about a service. This class is safe to use in
+   * sorted & unique collections.
+   */
+  static class ServiceDetail implements Comparable<ServiceDetail> {
+    @JsonProperty("service_name")
+    final String serviceName;
+
+    ServiceDetail(String serviceName) {
+      this.serviceName = serviceName;
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public int hashCode() {
+      return Objects.hash(serviceName);
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public boolean equals(Object obj) {
+      if (this == obj) {
+        return true;
+      }
+
+      if (obj == null) {
+        return false;
+      }
+
+      if (getClass() != obj.getClass()) {
+        return false;
+      }
+
+      ServiceDetail other = (ServiceDetail) obj;
+      return Objects.equals(serviceName, other.serviceName);
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public int compareTo(ServiceDetail other) {
+      return serviceName.compareTo(other.serviceName);
+    }
+  }
+
+  /**
+   * Used to represent information about a service component. This class is safe
+   * to use in sorted & unique collections.
+   */
+  static class ServiceComponentDetail implements Comparable<ServiceComponentDetail> {
+    @JsonProperty("service_name")
+    final String serviceName;
+
+    @JsonProperty("component_name")
+    final String componentName;
+
+    ServiceComponentDetail(String serviceName, String componentName) {
+      this.serviceName = serviceName;
+      this.componentName = componentName;
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public int hashCode() {
+      return Objects.hash(serviceName, componentName);
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public boolean equals(Object obj) {
+      if (this == obj) {
+        return true;
+      }
+
+      if (obj == null) {
+        return false;
+      }
+
+      if (getClass() != obj.getClass()) {
+        return false;
+      }
+
+      ServiceComponentDetail other = (ServiceComponentDetail) obj;
+      return Objects.equals(serviceName, other.serviceName)
+          && Objects.equals(componentName, other.componentName);
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public int compareTo(ServiceComponentDetail other) {
+      return Comparator.comparing(
+          (ServiceComponentDetail detail) -> detail.serviceName).thenComparing(
+              detail -> detail.componentName).compare(this, other);
+    }
+  }
+
+  /**
+   * Used to represent information about a host. This class is safe to use in
+   * sorted & unique collections.
+   */
+  static class HostDetail implements Comparable<HostDetail> {
+    @JsonProperty("host_id")
+    final Long hostId;
+
+    @JsonProperty("host_name")
+    final String hostName;
+
+    HostDetail(Long hostId, String hostName) {
+      this.hostId = hostId;
+      this.hostName = hostName;
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public int hashCode() {
+      return Objects.hash(hostId, hostName);
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public boolean equals(Object obj) {
+      if (this == obj) {
+        return true;
+      }
+
+      if (obj == null) {
+        return false;
+      }
+
+      if (getClass() != obj.getClass()) {
+        return false;
+      }
+
+      HostDetail other = (HostDetail) obj;
+      return Objects.equals(hostId, other.hostId) && Objects.equals(hostName, other.hostName);
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public int compareTo(HostDetail other) {
+      return hostName.compareTo(other.hostName);
+    }
+  }
 }

+ 0 - 58
ambari-server/src/main/java/org/apache/ambari/server/checks/AtlasPresenceCheck.java

@@ -1,58 +0,0 @@
-/*
- * 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.Set;
-
-import org.apache.ambari.server.AmbariException;
-import org.apache.ambari.server.controller.PrereqCheckRequest;
-import org.apache.ambari.server.state.stack.PrereqCheckStatus;
-import org.apache.ambari.server.state.stack.PrerequisiteCheck;
-
-import com.google.common.collect.Sets;
-import com.google.inject.Singleton;
-
-/**
- * Checks if Atlas service is present. Upgrade to stack HDP 2.5 from previous stack
- * must first delete Atlas from the cluster.
- */
-@Singleton
-@UpgradeCheck(group = UpgradeCheckGroup.DEFAULT)
-public class AtlasPresenceCheck extends AbstractCheckDescriptor{
-
-  private static final String serviceName = "ATLAS";
-
-  public AtlasPresenceCheck(){
-    super(CheckDescription.ATLAS_SERVICE_PRESENCE_CHECK);
-  }
-
-  /**
-   * {@inheritDoc}
-   */
-  @Override
-  public Set<String> getApplicableServices() {
-    return Sets.newHashSet(serviceName);
-  }
-
-  @Override
-  public void perform(PrerequisiteCheck prerequisiteCheck, PrereqCheckRequest request) throws AmbariException {
-    prerequisiteCheck.getFailedOn().add(serviceName);
-    prerequisiteCheck.setStatus(PrereqCheckStatus.FAIL);
-    prerequisiteCheck.setFailReason(getFailReason(prerequisiteCheck, request));
-  }
-}

+ 43 - 3
ambari-server/src/main/java/org/apache/ambari/server/checks/ClientRetryPropertyCheck.java

@@ -30,6 +30,7 @@ import org.apache.ambari.server.state.stack.PrereqCheckStatus;
 import org.apache.ambari.server.state.stack.PrerequisiteCheck;
 import org.apache.ambari.server.state.stack.upgrade.UpgradeType;
 import org.apache.commons.lang.StringUtils;
+import org.codehaus.jackson.annotate.JsonProperty;
 
 import com.google.common.collect.Sets;
 import com.google.inject.Singleton;
@@ -48,6 +49,10 @@ public class ClientRetryPropertyCheck extends AbstractCheckDescriptor {
   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";
 
+  private static final String HDFS_CLIENT_RETRY_PROPERTY = "dfs.client.retry.policy.enabled";
+  private static final String HIVE_CLIENT_RETRY_PROPERTY = "hive.metastore.failure.retries";
+  private static final String OOZIE_CLIENT_RETRY_PROPERTY = "-Doozie.connection.retry.count";
+
   /**
    * Constructor.
    */
@@ -76,8 +81,13 @@ public class ClientRetryPropertyCheck extends AbstractCheckDescriptor {
 
     // HDFS needs to actually prevent client retry since that causes them to try too long and not failover quickly.
     if (services.containsKey("HDFS")) {
-      String clientRetryPolicyEnabled = getProperty(request, "hdfs-site", "dfs.client.retry.policy.enabled");
+      String clientRetryPolicyEnabled = getProperty(request, "hdfs-site", HDFS_CLIENT_RETRY_PROPERTY);
       if (null != clientRetryPolicyEnabled && Boolean.parseBoolean(clientRetryPolicyEnabled)) {
+        MissingClientRetryProperty missingProperty = new MissingClientRetryProperty("HDFS",
+            "hdfs-site", HDFS_CLIENT_RETRY_PROPERTY);
+
+        prerequisiteCheck.getFailedDetail().add(missingProperty);
+
         errorMessages.add(getFailReason(HDFS_CLIENT_RETRY_DISABLED_KEY, prerequisiteCheck, request));
         prerequisiteCheck.getFailedOn().add("HDFS");
       }
@@ -85,8 +95,13 @@ public class ClientRetryPropertyCheck extends AbstractCheckDescriptor {
 
     // check hive client properties
     if (services.containsKey("HIVE")) {
-      String hiveClientRetryCount = getProperty(request, "hive-site", "hive.metastore.failure.retries");
+      String hiveClientRetryCount = getProperty(request, "hive-site", HIVE_CLIENT_RETRY_PROPERTY);
       if (null != hiveClientRetryCount && Integer.parseInt(hiveClientRetryCount) <= 0) {
+        MissingClientRetryProperty missingProperty = new MissingClientRetryProperty("HIVE",
+            "hive-site", HIVE_CLIENT_RETRY_PROPERTY);
+
+        prerequisiteCheck.getFailedDetail().add(missingProperty);
+
         errorMessages.add(getFailReason(HIVE_CLIENT_RETRY_MISSING_KEY, prerequisiteCheck, request));
         prerequisiteCheck.getFailedOn().add("HIVE");
       }
@@ -94,7 +109,12 @@ public class ClientRetryPropertyCheck extends AbstractCheckDescriptor {
 
     if (services.containsKey("OOZIE")) {
       String oozieClientRetry = getProperty(request, "oozie-env", "content");
-      if (null == oozieClientRetry || !oozieClientRetry.contains("-Doozie.connection.retry.count")) {
+      if (null == oozieClientRetry || !oozieClientRetry.contains(OOZIE_CLIENT_RETRY_PROPERTY)) {
+        MissingClientRetryProperty missingProperty = new MissingClientRetryProperty("OOZIE",
+            "oozie-env", OOZIE_CLIENT_RETRY_PROPERTY);
+
+        prerequisiteCheck.getFailedDetail().add(missingProperty);
+
         errorMessages.add(getFailReason(OOZIE_CLIENT_RETRY_MISSING_KEY, prerequisiteCheck, request));
         prerequisiteCheck.getFailedOn().add("OOZIE");
       }
@@ -105,4 +125,24 @@ public class ClientRetryPropertyCheck extends AbstractCheckDescriptor {
       prerequisiteCheck.setStatus(PrereqCheckStatus.FAIL);
     }
   }
+
+  /**
+   * Used to represent a missing retry property.
+   */
+  private static class MissingClientRetryProperty {
+    @JsonProperty("service_name")
+    public String serviceName;
+
+    @JsonProperty("type")
+    public String propertyType;
+
+    @JsonProperty("property_name")
+    public String propertyName;
+
+    MissingClientRetryProperty(String serviceName, String propertyType, String propertyName) {
+      this.serviceName = serviceName;
+      this.propertyType = propertyType;
+      this.propertyName = propertyName;
+    }
+  }
 }

+ 23 - 11
ambari-server/src/main/java/org/apache/ambari/server/checks/ComponentsExistInRepoCheck.java

@@ -22,6 +22,7 @@ import java.util.LinkedHashSet;
 import java.util.Map;
 import java.util.Set;
 import java.util.TreeSet;
+import java.util.stream.Collectors;
 
 import org.apache.ambari.server.AmbariException;
 import org.apache.ambari.server.StackAccessException;
@@ -68,8 +69,8 @@ public class ComponentsExistInRepoCheck extends AbstractCheckDescriptor {
     StackId sourceStack = request.getSourceStackId();
     StackId targetStack = repositoryVersion.getStackId();
 
-    Set<String> failedServices = new TreeSet<>();
-    Set<String> failedComponents = new TreeSet<>();
+    Set<ServiceDetail> failedServices = new TreeSet<>();
+    Set<ServiceComponentDetail> failedComponents = new TreeSet<>();
 
     Set<String> servicesInUpgrade = getServicesInUpgrade(request);
     for (String serviceName : servicesInUpgrade) {
@@ -78,7 +79,7 @@ public class ComponentsExistInRepoCheck extends AbstractCheckDescriptor {
             targetStack.getStackVersion(), serviceName);
 
         if (serviceInfo.isDeleted() || !serviceInfo.isValid()) {
-          failedServices.add(serviceName);
+          failedServices.add(new ServiceDetail(serviceName));
           continue;
         }
 
@@ -96,30 +97,41 @@ public class ComponentsExistInRepoCheck extends AbstractCheckDescriptor {
             }
 
             if (componentInfo.isDeleted()) {
-              failedComponents.add(componentName);
+              failedComponents.add(new ServiceComponentDetail(serviceName, componentName));
             }
 
           } catch (StackAccessException stackAccessException) {
-            failedComponents.add(componentName);
+            failedComponents.add(new ServiceComponentDetail(serviceName, componentName));
           }
         }
       } catch (StackAccessException stackAccessException) {
-        failedServices.add(serviceName);
+        failedServices.add(new ServiceDetail(serviceName));
       }
     }
 
-    if( failedServices.isEmpty() && failedComponents.isEmpty() ){
+    if (failedServices.isEmpty() && failedComponents.isEmpty()) {
       prerequisiteCheck.setStatus(PrereqCheckStatus.PASS);
       return;
     }
 
-    LinkedHashSet<String> failedOn = new LinkedHashSet<>();
-    failedOn.addAll(failedServices);
-    failedOn.addAll(failedComponents);
+    Set<String> failedServiceNames = failedServices.stream().map(
+        failureDetail -> failureDetail.serviceName).collect(
+            Collectors.toCollection(LinkedHashSet::new));
 
-    prerequisiteCheck.setFailedOn(failedOn);
+    Set<String> failedComponentNames = failedComponents.stream().map(
+        failureDetail -> failureDetail.componentName).collect(
+            Collectors.toCollection(LinkedHashSet::new));
+
+    LinkedHashSet<String> failures = new LinkedHashSet<>();
+    failures.addAll(failedServiceNames);
+    failures.addAll(failedComponentNames);
+
+    prerequisiteCheck.setFailedOn(failures);
     prerequisiteCheck.setStatus(PrereqCheckStatus.FAIL);
 
+    prerequisiteCheck.getFailedDetail().addAll(failedServices);
+    prerequisiteCheck.getFailedDetail().addAll(failedComponents);
+
     String message = "The following {0} exist in {1} but are not included in {2}. They must be removed before upgrading.";
     String messageFragment = "";
     if (!failedServices.isEmpty()) {

+ 22 - 16
ambari-server/src/main/java/org/apache/ambari/server/checks/ComponentsInstallationCheck.java

@@ -70,23 +70,28 @@ public class ComponentsInstallationCheck extends AbstractCheckDescriptor {
     for (String serviceName : servicesInUpgrade) {
       final Service service = cluster.getService(serviceName);
       // Skip service if it is in maintenance mode
-      if (service.getMaintenanceState() != MaintenanceState.ON) {
-        Map<String, ServiceComponent> serviceComponents = service.getServiceComponents();
-        for (Map.Entry<String, ServiceComponent> component : serviceComponents.entrySet()) {
-          ServiceComponent serviceComponent = component.getValue();
-          if (serviceComponent.isVersionAdvertised()) {
-            List<HostComponentSummary> hostComponentSummaries = HostComponentSummary.getHostComponentSummaries(
-                service.getName(), serviceComponent.getName());
+      if (service.getMaintenanceState() == MaintenanceState.ON) {
+        continue;
+      }
+
+      Map<String, ServiceComponent> serviceComponents = service.getServiceComponents();
+      for (Map.Entry<String, ServiceComponent> component : serviceComponents.entrySet()) {
+        ServiceComponent serviceComponent = component.getValue();
+        if (serviceComponent.isVersionAdvertised()) {
+          List<HostComponentSummary> hostComponentSummaries = HostComponentSummary.getHostComponentSummaries(
+              service.getName(), serviceComponent.getName());
+
+          for (HostComponentSummary hcs : hostComponentSummaries) {
+            // Skip host if it is in maintenance mode
+            Host host = clustersProvider.get().getHost(hcs.getHostName());
+            if (host.getMaintenanceState(cluster.getClusterId()) != MaintenanceState.ON) {
+              if (hcs.getCurrentState() == State.INSTALL_FAILED) {
 
-            for (HostComponentSummary hcs : hostComponentSummaries) {
-              // Skip host if it is in maintenance mode
-              Host host = clustersProvider.get().getHost(hcs.getHostName());
-              if (host.getMaintenanceState(cluster.getClusterId()) != MaintenanceState.ON) {
-                if (hcs.getCurrentState() == State.INSTALL_FAILED) {
-                  failedServiceNames.add(service.getName());
-                  installFailedHostComponents.add(MessageFormat.format(
-                      "[{0}:{1} on {2}]", service.getName(), serviceComponent.getName(), hcs.getHostName()));
-                }
+                prerequisiteCheck.getFailedDetail().add(hcs);
+
+                failedServiceNames.add(service.getName());
+                installFailedHostComponents.add(MessageFormat.format("[{0}:{1} on {2}]",
+                    service.getName(), serviceComponent.getName(), hcs.getHostName()));
               }
             }
           }
@@ -97,6 +102,7 @@ public class ComponentsInstallationCheck extends AbstractCheckDescriptor {
     if(!installFailedHostComponents.isEmpty()) {
       String message = MessageFormat.format("Service components in INSTALL_FAILED state: {0}.",
           StringUtils.join(installFailedHostComponents, ", "));
+
       prerequisiteCheck.setFailedOn(new LinkedHashSet<>(failedServiceNames));
       prerequisiteCheck.setStatus(PrereqCheckStatus.FAIL);
       prerequisiteCheck.setFailReason(

+ 6 - 0
ambari-server/src/main/java/org/apache/ambari/server/checks/HealthCheck.java

@@ -37,6 +37,7 @@ import org.apache.ambari.server.state.stack.PrereqCheckStatus;
 import org.apache.ambari.server.state.stack.PrerequisiteCheck;
 import org.apache.ambari.server.state.stack.upgrade.UpgradeType;
 import org.apache.commons.lang.StringUtils;
+import org.codehaus.jackson.annotate.JsonProperty;
 
 import com.google.inject.Inject;
 import com.google.inject.Provider;
@@ -108,8 +109,13 @@ public class HealthCheck extends AbstractCheckDescriptor {
    * Used to represent specific detail about alert.
    */
   private static class AlertDetail {
+    @JsonProperty("state")
     public String state;
+
+    @JsonProperty("label")
     public String label;
+
+    @JsonProperty("host_name")
     public String hostName;
 
     AlertDetail(String state, String label, String hostName) {

+ 3 - 0
ambari-server/src/main/java/org/apache/ambari/server/checks/HostMaintenanceModeCheck.java

@@ -70,6 +70,9 @@ public class HostMaintenanceModeCheck extends AbstractCheckDescriptor {
       MaintenanceState maintenanceState = host.getMaintenanceState(cluster.getClusterId());
       if (maintenanceState != MaintenanceState.OFF) {
         prerequisiteCheck.getFailedOn().add(host.getHostName());
+
+        prerequisiteCheck.getFailedDetail().add(
+            new HostDetail(host.getHostId(), host.getHostName()));
       }
     }
 

+ 3 - 0
ambari-server/src/main/java/org/apache/ambari/server/checks/HostsHeartbeatCheck.java

@@ -73,6 +73,9 @@ public class HostsHeartbeatCheck extends AbstractCheckDescriptor {
         case UNKNOWN:
           if (maintenanceState == MaintenanceState.OFF) {
             prerequisiteCheck.getFailedOn().add(host.getHostName());
+
+            prerequisiteCheck.getFailedDetail().add(
+                new HostDetail(host.getHostId(), host.getHostName()));
           }
           break;
         default:

+ 3 - 0
ambari-server/src/main/java/org/apache/ambari/server/checks/HostsMasterMaintenanceCheck.java

@@ -104,6 +104,9 @@ public class HostsMasterMaintenanceCheck extends AbstractCheckDescriptor {
       final Host host = hostEntry.getValue();
       if (host.getMaintenanceState(cluster.getClusterId()) == MaintenanceState.ON && hostsWithMasterComponent.contains(host.getHostName())) {
         prerequisiteCheck.getFailedOn().add(host.getHostName());
+
+        prerequisiteCheck.getFailedDetail().add(
+            new HostDetail(host.getHostId(), host.getHostName()));
       }
     }
 

+ 3 - 0
ambari-server/src/main/java/org/apache/ambari/server/checks/HostsRepositoryVersionCheck.java

@@ -82,6 +82,9 @@ public class HostsRepositoryVersionCheck extends AbstractCheckDescriptor {
 
       if (hostVersion == null || !okStates.contains(hostVersion.getState())) {
         prerequisiteCheck.getFailedOn().add(host.getHostName());
+
+        prerequisiteCheck.getFailedDetail().add(
+            new HostDetail(host.getHostId(), host.getHostName()));
       }
     }
 

+ 13 - 4
ambari-server/src/main/java/org/apache/ambari/server/checks/InstallPackagesCheck.java

@@ -18,9 +18,10 @@
 package org.apache.ambari.server.checks;
 
 import java.text.MessageFormat;
-import java.util.HashSet;
 import java.util.LinkedHashSet;
 import java.util.Set;
+import java.util.TreeSet;
+import java.util.stream.Collectors;
 
 import org.apache.ambari.server.AmbariException;
 import org.apache.ambari.server.controller.PrereqCheckRequest;
@@ -73,14 +74,15 @@ public class InstallPackagesCheck extends AbstractCheckDescriptor {
       return;
     }
 
-    final Set<String> failedHosts = new HashSet<>();
+    final Set<HostDetail> failedHosts = new TreeSet<>();
 
     for (Host host : cluster.getHosts()) {
       if (host.getMaintenanceState(cluster.getClusterId()) != MaintenanceState.ON) {
         for (HostVersionEntity hve : hostVersionDaoProvider.get().findByHost(host.getHostName())) {
           if (StringUtils.equals(hve.getRepositoryVersion().getVersion(), repositoryVersion.getVersion())
               && hve.getState() == RepositoryVersionState.INSTALL_FAILED) {
-            failedHosts.add(host.getHostName());
+
+            failedHosts.add(new HostDetail(host.getHostId(), host.getHostName()));
           }
         }
       }
@@ -92,9 +94,16 @@ public class InstallPackagesCheck extends AbstractCheckDescriptor {
               "in Maintenance mode: {4}", cluster.getClusterName(), targetStackId.getStackName(),
           targetStackId.getStackVersion(), repositoryVersion.getVersion(),
           StringUtils.join(failedHosts, ", "));
-      prerequisiteCheck.setFailedOn(new LinkedHashSet<>(failedHosts));
+
+      LinkedHashSet<String> failedHostNames = failedHosts.stream().map(
+          failedHost -> failedHost.hostName).collect(
+              Collectors.toCollection(LinkedHashSet::new));
+
+      prerequisiteCheck.setFailedOn(failedHostNames);
       prerequisiteCheck.setStatus(PrereqCheckStatus.FAIL);
       prerequisiteCheck.setFailReason(message);
+      prerequisiteCheck.getFailedDetail().addAll(failedHosts);
+
       return;
     }
 

+ 8 - 0
ambari-server/src/main/java/org/apache/ambari/server/checks/RequiredServicesInRepositoryCheck.java

@@ -19,6 +19,8 @@ package org.apache.ambari.server.checks;
 
 import java.util.LinkedHashSet;
 import java.util.Set;
+import java.util.TreeSet;
+import java.util.stream.Collectors;
 
 import org.apache.ambari.server.AmbariException;
 import org.apache.ambari.server.controller.PrereqCheckRequest;
@@ -77,6 +79,12 @@ public class RequiredServicesInRepositoryCheck extends AbstractCheckDescriptor {
       prerequisiteCheck.setFailedOn(new LinkedHashSet<>(missingDependencies));
       prerequisiteCheck.setStatus(PrereqCheckStatus.FAIL);
       prerequisiteCheck.setFailReason(String.format(failReasonTemplate, message));
+
+      Set<ServiceDetail> missingServiceDetails = missingDependencies.stream().map(
+          missingService -> new ServiceDetail(missingService)).collect(
+              Collectors.toCollection(TreeSet::new));
+
+      prerequisiteCheck.getFailedDetail().addAll(missingServiceDetails);
       return;
     }
 

+ 76 - 4
ambari-server/src/main/java/org/apache/ambari/server/checks/ServiceCheckValidityCheck.java

@@ -25,6 +25,10 @@ import java.util.LinkedHashSet;
 import java.util.List;
 import java.util.Map;
 import java.util.Map.Entry;
+import java.util.Objects;
+import java.util.stream.Collectors;
+
+import javax.annotation.Nullable;
 
 import org.apache.ambari.server.AmbariException;
 import org.apache.ambari.server.controller.PrereqCheckRequest;
@@ -42,6 +46,7 @@ import org.apache.ambari.server.state.stack.PrereqCheckStatus;
 import org.apache.ambari.server.state.stack.PrerequisiteCheck;
 import org.apache.ambari.server.state.stack.upgrade.UpgradeType;
 import org.apache.commons.lang.StringUtils;
+import org.codehaus.jackson.annotate.JsonProperty;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -118,7 +123,7 @@ public class ServiceCheckValidityCheck extends AbstractCheckDescriptor {
       lastServiceChecksByRole.put(lastServiceCheck.role, lastServiceCheck.endTime);
     }
 
-    LinkedHashSet<String> failedServiceNames = new LinkedHashSet<>();
+    LinkedHashSet<ServiceCheckConfigDetail> failures = new LinkedHashSet<>();
 
     // for every service, see if there was a service check executed and then
     for( Entry<String, Long> entry : lastServiceConfigUpdates.entrySet() ) {
@@ -128,13 +133,15 @@ public class ServiceCheckValidityCheck extends AbstractCheckDescriptor {
 
       if(!lastServiceChecksByRole.containsKey(role) ) {
         LOG.info("There was no service check found for service {} matching role {}", serviceName, role);
-        failedServiceNames.add(serviceName);
+        failures.add(new ServiceCheckConfigDetail(serviceName, null, null));
         continue;
       }
 
       long lastServiceCheckTime = lastServiceChecksByRole.get(role);
       if (lastServiceCheckTime < configCreationTime) {
-        failedServiceNames.add(serviceName);
+        failures.add(
+            new ServiceCheckConfigDetail(serviceName, lastServiceCheckTime, configCreationTime));
+
         LOG.info(
             "The {} service (role {}) had its configurations updated on {}, but the last service check was {}",
             serviceName, role, DATE_FORMAT.format(new Date(configCreationTime)),
@@ -142,7 +149,12 @@ public class ServiceCheckValidityCheck extends AbstractCheckDescriptor {
       }
     }
 
-    if (!failedServiceNames.isEmpty()) {
+    if (!failures.isEmpty()) {
+      prerequisiteCheck.getFailedDetail().addAll(failures);
+
+      LinkedHashSet<String> failedServiceNames = failures.stream().map(
+          failure -> failure.serviceName).collect(Collectors.toCollection(LinkedHashSet::new));
+
       prerequisiteCheck.setFailedOn(failedServiceNames);
       prerequisiteCheck.setStatus(PrereqCheckStatus.FAIL);
       String failReason = getFailReason(prerequisiteCheck, request);
@@ -160,4 +172,64 @@ public class ServiceCheckValidityCheck extends AbstractCheckDescriptor {
     return false;
   }
 
+  /**
+   * Used to represent information about a service component. This class is safe
+   * to use in sorted & unique collections.
+   */
+  static class ServiceCheckConfigDetail implements Comparable<ServiceCheckConfigDetail> {
+    @JsonProperty("service_name")
+    final String serviceName;
+
+    @JsonProperty("service_check_date")
+    final Long serviceCheckDate;
+
+    @JsonProperty("configuration_date")
+    final Long configurationDate;
+
+    ServiceCheckConfigDetail(String serviceName, @Nullable Long serviceCheckDate,
+        @Nullable Long configurationDate) {
+      this.serviceName = serviceName;
+      this.serviceCheckDate = serviceCheckDate;
+      this.configurationDate = configurationDate;
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public int hashCode() {
+      return Objects.hash(serviceName, serviceCheckDate, configurationDate);
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public boolean equals(Object obj) {
+      if (this == obj) {
+        return true;
+      }
+
+      if (obj == null) {
+        return false;
+      }
+
+      if (getClass() != obj.getClass()) {
+        return false;
+      }
+
+      ServiceCheckConfigDetail other = (ServiceCheckConfigDetail) obj;
+      return Objects.equals(serviceName, other.serviceName)
+          && Objects.equals(serviceCheckDate, other.serviceCheckDate)
+          && Objects.equals(configurationDate, other.configurationDate);
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public int compareTo(ServiceCheckConfigDetail other) {
+      return serviceName.compareTo(other.serviceName);
+    }
+  }
 }

+ 11 - 5
ambari-server/src/main/java/org/apache/ambari/server/checks/ServicesUpCheck.java

@@ -19,11 +19,11 @@ package org.apache.ambari.server.checks;
 
 import java.text.MessageFormat;
 import java.util.ArrayList;
-import java.util.HashSet;
 import java.util.LinkedHashSet;
 import java.util.List;
 import java.util.Map;
 import java.util.Set;
+import java.util.stream.Collectors;
 
 import org.apache.ambari.server.AmbariException;
 import org.apache.ambari.server.controller.PrereqCheckRequest;
@@ -89,7 +89,7 @@ public class ServicesUpCheck extends AbstractCheckDescriptor {
     final String clusterName = request.getClusterName();
     final Cluster cluster = clustersProvider.get().getCluster(clusterName);
     List<String> errorMessages = new ArrayList<>();
-    Set<String> failedServiceNames = new HashSet<>();
+    LinkedHashSet<ServiceDetail> failedServices = new LinkedHashSet<>();
 
     Set<String> servicesInUpgrade = getServicesInUpgrade(request);
     for (String serviceName : servicesInUpgrade) {
@@ -160,7 +160,8 @@ public class ServicesUpCheck extends AbstractCheckDescriptor {
           }
 
           if ((float) down / total > SLAVE_THRESHOLD) { // arbitrary
-            failedServiceNames.add(service.getName());
+            failedServices.add(new ServiceDetail(serviceName));
+
             String message = MessageFormat.format(
                 "{0}: {1} out of {2} {3} are started; there should be {4,number,percent} started before upgrading.",
                 service.getName(), up, total, serviceComponent.getName(), SLAVE_THRESHOLD);
@@ -169,7 +170,8 @@ public class ServicesUpCheck extends AbstractCheckDescriptor {
         } else {
           for (HostComponentSummary summary : hostComponentSummaries) {
             if (isConsideredDown(cluster, serviceComponent, summary)) {
-              failedServiceNames.add(service.getName());
+              failedServices.add(new ServiceDetail(serviceName));
+
               String message = MessageFormat.format("{0}: {1} (in {2} on host {3})",
                   service.getName(), serviceComponent.getName(), summary.getCurrentState(),
                   summary.getHostName());
@@ -182,7 +184,11 @@ public class ServicesUpCheck extends AbstractCheckDescriptor {
     }
 
     if (!errorMessages.isEmpty()) {
-      prerequisiteCheck.setFailedOn(new LinkedHashSet<>(failedServiceNames));
+      prerequisiteCheck.setFailedOn(
+          failedServices.stream().map(failedService -> failedService.serviceName).collect(
+              Collectors.toCollection(LinkedHashSet::new)));
+
+      prerequisiteCheck.getFailedDetail().addAll(failedServices);
       prerequisiteCheck.setStatus(PrereqCheckStatus.FAIL);
       prerequisiteCheck.setFailReason(
           "The following Service Components should be in a started state.  Please invoke a service Stop and full Start and try again. "

+ 1 - 27
ambari-server/src/main/java/org/apache/ambari/server/configuration/Configuration.java

@@ -58,14 +58,12 @@ import org.apache.ambari.annotations.Markdown;
 import org.apache.ambari.server.AmbariException;
 import org.apache.ambari.server.actionmanager.CommandExecutionType;
 import org.apache.ambari.server.actionmanager.HostRoleCommand;
-import org.apache.ambari.server.actionmanager.Stage;
 import org.apache.ambari.server.controller.spi.PropertyProvider;
 import org.apache.ambari.server.controller.utilities.ScalingThreadPoolExecutor;
 import org.apache.ambari.server.events.listeners.alerts.AlertReceivedListener;
 import org.apache.ambari.server.orm.JPATableGenerationStrategy;
 import org.apache.ambari.server.orm.PersistenceType;
 import org.apache.ambari.server.orm.dao.HostRoleCommandStatusSummaryDTO;
-import org.apache.ambari.server.orm.entities.StageEntity;
 import org.apache.ambari.server.security.ClientSecurityType;
 import org.apache.ambari.server.security.authentication.jwt.JwtAuthenticationProperties;
 import org.apache.ambari.server.security.authentication.kerberos.AmbariKerberosAuthenticationProperties;
@@ -78,7 +76,6 @@ import org.apache.ambari.server.upgrade.AbstractUpgradeCatalog;
 import org.apache.ambari.server.utils.AmbariPath;
 import org.apache.ambari.server.utils.DateUtils;
 import org.apache.ambari.server.utils.HostUtils;
-import org.apache.ambari.server.utils.Parallel;
 import org.apache.ambari.server.utils.PasswordUtils;
 import org.apache.ambari.server.utils.ShellCommandUtil;
 import org.apache.ambari.server.utils.StageUtils;
@@ -2097,16 +2094,6 @@ public class Configuration {
   public static final ConfigurationProperty<Boolean> AMBARI_METRICS_HTTPS_ENABLED = new ConfigurationProperty<>(
       "server.timeline.metrics.https.enabled", Boolean.FALSE);
 
-  /**
-   * Governs the use of {@link Parallel} to process {@link StageEntity}
-   * instances into {@link Stage}.
-   */
-  @Markdown(
-      internal = true,
-      description = "Determines whether to allow stages retrieved from the database to be processed by multiple threads.")
-  public static final ConfigurationProperty<Boolean> EXPERIMENTAL_CONCURRENCY_STAGE_PROCESSING_ENABLED = new ConfigurationProperty<>(
-      "experimental.concurrency.stage_processing.enabled", Boolean.FALSE);
-
   /**
    * The full path to the XML file that describes the different alert templates.
    */
@@ -2585,7 +2572,7 @@ public class Configuration {
           "notification.dispatch.alert.script.directory",AmbariPath.getPath("/var/lib/ambari-server/resources/scripts"));
 
   @Markdown(description = "Whether security password encryption is enabled or not. In case it is we store passwords in their own file(s); otherwise we store passwords in the Ambari credential store.")
-  public static final ConfigurationProperty<Boolean> SECURITY_PASSWORD_ENCRYPTON_ENABLED = new ConfigurationProperty<Boolean>("security.passwords.encryption.enabled", false);
+  public static final ConfigurationProperty<Boolean> SECURITY_PASSWORD_ENCRYPTON_ENABLED = new ConfigurationProperty<>("security.passwords.encryption.enabled", false);
 
   /**
    * The maximum number of authentication attempts permitted to a local user. Once the number of failures reaches this limit the user will be locked out. 0 indicates unlimited failures
@@ -5186,19 +5173,6 @@ public class Configuration {
     return getProperty(SERVER_TMP_DIR);
   }
 
-  /**
-   * Gets whether to use experiemental concurrent processing to convert
-   * {@link StageEntity} instances into {@link Stage} instances. The default is
-   * {@code false}.
-   *
-   * @return {code true} if the experimental feature is enabled, {@code false}
-   *         otherwise.
-   */
-  @Experimental(feature = ExperimentalFeature.PARALLEL_PROCESSING)
-  public boolean isExperimentalConcurrentStageProcessingEnabled() {
-    return Boolean.parseBoolean(getProperty(EXPERIMENTAL_CONCURRENCY_STAGE_PROCESSING_ENABLED));
-  }
-
   /**
    * If {@code true}, then alerts processed by the {@link AlertReceivedListener}
    * will not write alert data to the database on every event. Instead, data

+ 17 - 0
ambari-server/src/main/java/org/apache/ambari/server/orm/models/HostComponentSummary.java

@@ -29,16 +29,33 @@ import org.apache.ambari.server.orm.entities.HostComponentDesiredStateEntity;
 import org.apache.ambari.server.orm.entities.HostComponentStateEntity;
 import org.apache.ambari.server.orm.entities.HostEntity;
 import org.apache.ambari.server.state.State;
+import org.codehaus.jackson.annotate.JsonProperty;
 
 import com.google.inject.Inject;
 
+/**
+ * The {@link HostComponentSum1mary} class provides a concise representation of
+ * the state of a component on a given host. Some of its fields are serializable
+ * to JSON.
+ */
 @StaticallyInject
 public class HostComponentSummary {
+  @JsonProperty("service_name")
   private String serviceName;
+
+  @JsonProperty("component_name")
   private String componentName;
+
+  @JsonProperty("host_id")
   private Long hostId;
+
+  @JsonProperty("host_name")
   private String hostName;
+
+  @JsonProperty("desired_state")
   private State desiredState;
+
+  @JsonProperty("current_state")
   private State currentState;
 
   @Inject

+ 1 - 1
ambari-server/src/main/java/org/apache/ambari/server/state/kerberos/AbstractKerberosDescriptorContainer.java

@@ -789,7 +789,7 @@ public abstract class AbstractKerberosDescriptorContainer extends AbstractKerber
   public List<KerberosIdentityDescriptor> getIdentitiesSkipReferences() {
     return nullToEmpty(getIdentities())
       .stream()
-      .filter(identity -> !identity.getReferencedServiceName().isPresent() && identity.getName() != null && !identity.getName().startsWith("/"))
+      .filter(identity -> !identity.getReferencedServiceName().isPresent() && !identity.isReference())
       .collect(toList());
   }
 

+ 1 - 1
ambari-server/src/main/java/org/apache/ambari/server/upgrade/SchemaUpgradeHelper.java

@@ -187,7 +187,7 @@ public class SchemaUpgradeHelper {
       catalogBinder.addBinding().to(UpgradeCatalog260.class);
       catalogBinder.addBinding().to(UpgradeCatalog261.class);
       catalogBinder.addBinding().to(UpgradeCatalog262.class);
-      catalogBinder.addBinding().to(UpgradeCatalog300.class);
+      catalogBinder.addBinding().to(UpgradeCatalog270.class);
       catalogBinder.addBinding().to(UpdateAlertScriptPaths.class);
       catalogBinder.addBinding().to(FinalUpgradeCatalog.class);
 

+ 5 - 5
ambari-server/src/main/java/org/apache/ambari/server/upgrade/UpgradeCatalog300.java → ambari-server/src/main/java/org/apache/ambari/server/upgrade/UpgradeCatalog270.java

@@ -71,13 +71,13 @@ import com.google.common.net.HostAndPort;
 import com.google.inject.Inject;
 import com.google.inject.Injector;
 
-public class UpgradeCatalog300 extends AbstractUpgradeCatalog {
+public class UpgradeCatalog270 extends AbstractUpgradeCatalog {
 
   public static final String HOST_ID_COLUMN = "host_id";
   /**
    * Logger.
    */
-  private static final Logger LOG = LoggerFactory.getLogger(UpgradeCatalog300.class);
+  private static final Logger LOG = LoggerFactory.getLogger(UpgradeCatalog270.class);
 
   protected static final String STAGE_TABLE = "stage";
   protected static final String STAGE_STATUS_COLUMN = "status";
@@ -173,7 +173,7 @@ public class UpgradeCatalog300 extends AbstractUpgradeCatalog {
    * @param injector Guice injector to track dependencies and uses bindings to inject them.
    */
   @Inject
-  public UpgradeCatalog300(Injector injector) {
+  public UpgradeCatalog270(Injector injector) {
     super(injector);
 
     daoUtils = injector.getInstance(DaoUtils.class);
@@ -186,7 +186,7 @@ public class UpgradeCatalog300 extends AbstractUpgradeCatalog {
    */
   @Override
   public String getTargetVersion() {
-    return "3.0.0";
+    return "2.7.0";
   }
 
   // ----- AbstractUpgradeCatalog --------------------------------------------
@@ -196,7 +196,7 @@ public class UpgradeCatalog300 extends AbstractUpgradeCatalog {
    */
   @Override
   public String getSourceVersion() {
-    return "2.6.0";
+    return "2.6.2";
   }
 
   /**

+ 0 - 266
ambari-server/src/main/java/org/apache/ambari/server/utils/Parallel.java

@@ -1,266 +0,0 @@
-/*
- * 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.utils;
-
-import java.util.Arrays;
-import java.util.Collections;
-import java.util.LinkedList;
-import java.util.List;
-import java.util.concurrent.BlockingQueue;
-import java.util.concurrent.Callable;
-import java.util.concurrent.CancellationException;
-import java.util.concurrent.CompletionService;
-import java.util.concurrent.ExecutionException;
-import java.util.concurrent.ExecutorCompletionService;
-import java.util.concurrent.ExecutorService;
-import java.util.concurrent.Executors;
-import java.util.concurrent.Future;
-import java.util.concurrent.SynchronousQueue;
-import java.util.concurrent.ThreadFactory;
-import java.util.concurrent.ThreadPoolExecutor;
-import java.util.concurrent.TimeUnit;
-import java.util.concurrent.atomic.AtomicInteger;
-
-import org.eclipse.persistence.internal.helper.ConcurrencyManager;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-/**
- * <b>TEMPORARILY DO NOT USE WITH JPA ENTITIES</b>
- * <p/>
- * Deprecated since the use of this class to access JPA from multiple Ambari
- * threads seems to cause thread liveliness problems in
- * {@link ConcurrencyManager}.
- * <p/>
- * This class provides support for parallel loops. Iterations in the loop run in
- * parallel in parallel loops.
- */
-@Deprecated
-public class Parallel {
-
-  /**
-   * Max pool size
-   */
-  private static final int MAX_POOL_SIZE = Math.max(8, Runtime.getRuntime().availableProcessors());
-
-  /**
-   * Keep alive time (15 min)
-   */
-  // !!! changed from 1 second because EclipseLink was making threads idle and
-  // they kept timing out
-  private static final int KEEP_ALIVE_TIME_MINUTES = 15;
-
-  /**
-   * Poll duration (10 secs)
-   */
-  private static final int POLL_DURATION_MILLISECONDS = 10000;
-
-  /**
-   * Core pool size
-   */
-  private static final int CORE_POOL_SIZE = 2;
-
-  /**
-   * Logger
-   */
-  private static final Logger LOG = LoggerFactory.getLogger(Parallel.class);
-
-  /**
-   *  Thread pool executor
-   */
-  private static ExecutorService executor = initExecutor();
-
-  /**
-   * Initialize executor
-   *
-   * @return
-   */
-  private static ExecutorService initExecutor() {
-
-    BlockingQueue<Runnable> blockingQueue = new SynchronousQueue<>(); // Using synchronous queue
-
-    // Create thread pool
-    ThreadPoolExecutor threadPool = new ThreadPoolExecutor(
-        CORE_POOL_SIZE,                           // Core pool size
-        MAX_POOL_SIZE,                            // Max pool size
-        KEEP_ALIVE_TIME_MINUTES,                  // Keep alive time for idle threads
-        TimeUnit.MINUTES,
-        blockingQueue,                            // Using synchronous queue
-        new ParallelLoopsThreadFactory(),         // Thread pool factory to use
-        new ThreadPoolExecutor.CallerRunsPolicy() // Rejected tasks will run on calling thread.
-    );
-    threadPool.allowCoreThreadTimeOut(true);
-    LOG.debug(
-        "Parallel library initialized: ThreadCount = {}, CurrentPoolSize = {}, CorePoolSize = {}, MaxPoolSize = {}",
-        Thread.activeCount(), threadPool.getPoolSize(), threadPool.getCorePoolSize(), threadPool.getMaximumPoolSize());
-    return threadPool;
-  }
-
-  /**
-   * Executes a "for" parallel loop operation over all items in the data source in which iterations run in parallel.
-   *
-   * @param source      Data source to iterate over
-   * @param loopBody    The loop body that is invoked once per iteration
-   * @param <T>         The type of data in the source
-   * @param <R>         The type of data to be returned
-   * @return            {@link ParallelLoopResult} Parallel loop result
-   */
-  public static <T, R> ParallelLoopResult<R> forLoop(
-      List<T> source,
-      final LoopBody<T, R> loopBody) {
-
-    if(source == null || source.isEmpty()) {
-      return new ParallelLoopResult<>(true, Collections.<R>emptyList());
-    }
-    return forLoop(source, 0, source.size(), loopBody);
-  }
-
-  /**
-   * Executes a "for" parallel loop operation in which iterations run in parallel.
-   *
-   * @param source      Data source to iterate over
-   * @param startIndex  The loop start index, inclusive
-   * @param endIndex    The loop end index, exclusive
-   * @param loopBody    The loop body that is invoked once per iteration
-   * @param <T>         The type of data in the source
-   * @param <R>         The type of data to be returned
-   * @return            {@link ParallelLoopResult} Parallel loop result
-   *
-   */
-  public static <T, R> ParallelLoopResult<R> forLoop(
-      final List<T> source,
-      int startIndex,
-      int endIndex,
-      final LoopBody<T, R> loopBody) {
-
-    if(source == null || source.isEmpty() || startIndex == endIndex) {
-      return new ParallelLoopResult<>(true, Collections.<R>emptyList());
-    }
-    if(startIndex < 0 || startIndex >= source.size()) {
-      throw new IndexOutOfBoundsException("startIndex is out of bounds");
-    }
-    if(endIndex < 0 || endIndex > source.size()) {
-      throw new IndexOutOfBoundsException("endIndex is out of bounds");
-    }
-    if(startIndex > endIndex) {
-      throw new IndexOutOfBoundsException("startIndex > endIndex");
-    }
-    if(source.size() == 1 || (endIndex - startIndex) == 1) {
-      // Don't spawn a new thread for a single element list
-      List<R> result = Collections.singletonList(loopBody.run(source.get(startIndex)));
-      return new ParallelLoopResult<>(true, result);
-    }
-
-    // Create a completion service for each call
-    CompletionService<ResultWrapper<R>> completionService = new ExecutorCompletionService<>(executor);
-
-    List<Future<ResultWrapper<R>>> futures = new LinkedList<>();
-    for (int i = startIndex; i < endIndex; i++) {
-      final Integer k = i;
-      Future<ResultWrapper<R>> future = completionService.submit(new Callable<ResultWrapper<R>>() {
-        @Override
-        public ResultWrapper<R> call() throws Exception {
-          ResultWrapper<R> res = new ResultWrapper<>();
-          res.index = k;
-          res.result = loopBody.run(source.get(k));
-          return res;
-        }
-      });
-      futures.add(future);
-    }
-
-    boolean completed = true;
-    R[] result = (R[]) new Object[futures.size()];
-    for (int i = 0; i < futures.size(); i++) {
-      try {
-        Future<ResultWrapper<R>> futureResult = null;
-        try {
-          futureResult = completionService.poll(POLL_DURATION_MILLISECONDS, TimeUnit.MILLISECONDS);
-        } catch (InterruptedException e) {
-          LOG.error("Caught InterruptedException in Parallel.forLoop", e);
-        }
-        if (futureResult == null) {
-          // Timed out! no progress was made during the last poll duration. Abort the threads and cancel the threads.
-          LOG.error("Completion service in Parallel.forLoop timed out!");
-          completed = false;
-          for(int fIndex = 0; fIndex < futures.size(); fIndex++) {
-            Future<ResultWrapper<R>> future = futures.get(fIndex);
-            if(future.isDone()) {
-              LOG.debug("    Task - {} has already completed", fIndex);
-            } else if(future.isCancelled()) {
-              LOG.debug("    Task - {} has already been cancelled", fIndex);
-            } else if(!future.cancel(true)) {
-              LOG.debug("    Task - {} could not be cancelled", fIndex);
-            } else {
-              LOG.debug("    Task - {} successfully cancelled", fIndex);
-            }
-          }
-          // Finished processing all futures
-          break;
-        } else {
-          ResultWrapper<R> res = futureResult.get();
-          if(res.result != null) {
-            result[res.index] = res.result;
-          } else {
-            LOG.error("Result is null for {}", res.index);
-            completed = false;
-          }
-        }
-      } catch (InterruptedException e) {
-        LOG.error("Caught InterruptedException in Parallel.forLoop", e);
-        completed = false;
-      } catch (ExecutionException e) {
-        LOG.error("Caught ExecutionException in Parallel.forLoop", e);
-        completed = false;
-      } catch (CancellationException e) {
-        LOG.error("Caught CancellationException in Parallel.forLoop", e);
-        completed = false;
-      }
-    }
-    // Return parallel loop result
-    return new ParallelLoopResult<>(completed, Arrays.asList(result));
-  }
-
-  /**
-   * A custom {@link ThreadFactory} for the threads that will handle
-   * {@link org.apache.ambari.server.utils.Parallel} loop iterations.
-   */
-  private static final class ParallelLoopsThreadFactory implements ThreadFactory {
-
-    private static final AtomicInteger threadId = new AtomicInteger(1);
-
-    /**
-     * {@inheritDoc}
-     */
-    @Override
-    public Thread newThread(Runnable r) {
-      Thread thread = Executors.defaultThreadFactory().newThread(r);
-      thread.setName("parallel-loop-" + threadId.getAndIncrement());
-      return thread;
-    }
-  }
-
-  /**
-   * Result wrapper for Parallel.forLoop used internally
-   * @param <R> Type of result to wrap
-   */
-  private static final class ResultWrapper<R> {
-    int index;
-    R result;
-  }
-}

+ 0 - 63
ambari-server/src/main/java/org/apache/ambari/server/utils/ParallelLoopResult.java

@@ -1,63 +0,0 @@
-/*
- * 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.utils;
-
-import java.util.List;
-
-/**
- * Provides completion status and results of a {@link Parallel} loop
- * @param <R> Result type
- */
-public class ParallelLoopResult<R> {
-  private boolean isCompleted;
-  private List<R> result;
-
-  /**
-   * Flag to indicate if the parallel loop completed all iterations
-   * @return
-   */
-  public boolean getIsCompleted() {
-    return isCompleted;
-  }
-
-  /**
-   * Flag to indicate if the parallel loop completed all iterations
-   * @return
-   */
-  public void setIsCompleted(boolean completed) {
-    isCompleted = completed;
-  }
-
-  public List<R> getResult() {
-    return result;
-  }
-
-  public void setResult(List<R> result) {
-    this.result = result;
-  }
-
-  /**
-   * Constructor
-   * @param completed Indicates if the parallel loop completed all iterations
-   * @param result    Results of parallel loop. Results could be partially completed.
-   */
-  public ParallelLoopResult(boolean completed, List<R> result) {
-    isCompleted = completed;
-    this.result = result;
-  }
-}

+ 0 - 42
ambari-server/src/test/java/org/apache/ambari/server/checks/AtlasPresenceCheckTest.java

@@ -1,42 +0,0 @@
-/*
- * 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 org.junit.Assert.assertEquals;
-
-import org.apache.ambari.server.controller.PrereqCheckRequest;
-import org.apache.ambari.server.orm.entities.RepositoryVersionEntity;
-import org.apache.ambari.server.state.stack.PrereqCheckStatus;
-import org.apache.ambari.server.state.stack.PrerequisiteCheck;
-import org.junit.Test;
-import org.mockito.Mockito;
-
-
-public class AtlasPresenceCheckTest {
-  private final AtlasPresenceCheck m_check = new AtlasPresenceCheck();
-
-  @Test
-  public void perform() throws Exception {
-    PrerequisiteCheck check = new PrerequisiteCheck(null, null);
-    PrereqCheckRequest request = new PrereqCheckRequest("cluster");
-    request.setTargetRepositoryVersion(Mockito.mock(RepositoryVersionEntity.class));
-    m_check.perform(check, request);
-
-    assertEquals(PrereqCheckStatus.FAIL, check.getStatus());
-  }
-}

+ 6 - 0
ambari-server/src/test/java/org/apache/ambari/server/checks/ComponentExistsInRepoCheckTest.java

@@ -183,6 +183,7 @@ public class ComponentExistsInRepoCheckTest extends EasyMockSupport {
     m_check.perform(check, request);
 
     Assert.assertEquals(PrereqCheckStatus.PASS, check.getStatus());
+    Assert.assertTrue(check.getFailedDetail().isEmpty());
     Assert.assertTrue(StringUtils.isBlank(check.getFailReason()));
   }
 
@@ -220,6 +221,7 @@ public class ComponentExistsInRepoCheckTest extends EasyMockSupport {
     m_check.perform(check, request);
 
     Assert.assertEquals(PrereqCheckStatus.PASS, check.getStatus());
+    Assert.assertTrue(check.getFailedDetail().isEmpty());
     Assert.assertTrue(StringUtils.isBlank(check.getFailReason()));
   }
 
@@ -246,6 +248,7 @@ public class ComponentExistsInRepoCheckTest extends EasyMockSupport {
     m_check.perform(check, request);
 
     Assert.assertEquals(PrereqCheckStatus.FAIL, check.getStatus());
+    Assert.assertEquals(1, check.getFailedDetail().size());
     Assert.assertTrue(check.getFailedOn().contains("ZOOKEEPER"));
   }
 
@@ -274,6 +277,7 @@ public class ComponentExistsInRepoCheckTest extends EasyMockSupport {
     m_check.perform(check, request);
 
     Assert.assertEquals(PrereqCheckStatus.FAIL, check.getStatus());
+    Assert.assertEquals(1, check.getFailedDetail().size());
     Assert.assertTrue(check.getFailedOn().contains("ZOOKEEPER_SERVER"));
   }
 
@@ -308,6 +312,7 @@ public class ComponentExistsInRepoCheckTest extends EasyMockSupport {
     m_check.perform(check, request);
 
     Assert.assertEquals(PrereqCheckStatus.FAIL, check.getStatus());
+    Assert.assertEquals(1, check.getFailedDetail().size());
     Assert.assertTrue(check.getFailedOn().contains("FOO_SERVICE"));
   }
 
@@ -348,6 +353,7 @@ public class ComponentExistsInRepoCheckTest extends EasyMockSupport {
     m_check.perform(check, request);
 
     Assert.assertEquals(PrereqCheckStatus.FAIL, check.getStatus());
+    Assert.assertEquals(1, check.getFailedDetail().size());
     Assert.assertTrue(check.getFailedOn().contains("FOO_COMPONENT"));
   }
 

+ 5 - 0
ambari-server/src/test/java/org/apache/ambari/server/checks/ComponentsInstallationCheckTest.java

@@ -293,6 +293,7 @@ public class ComponentsInstallationCheckTest {
     PrerequisiteCheck check = new PrerequisiteCheck(null, null);
     componentsInstallationCheck.perform(check, request);
     Assert.assertEquals(PrereqCheckStatus.PASS, check.getStatus());
+    Assert.assertTrue(check.getFailedDetail().isEmpty());
 
     // Case 2. Ensure that AMS is ignored even if their current state is not INSTALLED
     Mockito.when(hcsMetricsCollector.getCurrentState()).thenReturn(State.INSTALL_FAILED);
@@ -300,6 +301,7 @@ public class ComponentsInstallationCheckTest {
     check = new PrerequisiteCheck(null, null);
     componentsInstallationCheck.perform(check, request);
     Assert.assertEquals(PrereqCheckStatus.PASS, check.getStatus());
+    Assert.assertTrue(check.getFailedDetail().isEmpty());
 
     // Case 3: Change TEZ client state to INSTALL_FAILED, should fail
     Mockito.when(hcsTezClient.getCurrentState()).thenReturn(State.INSTALL_FAILED);
@@ -307,6 +309,7 @@ public class ComponentsInstallationCheckTest {
     componentsInstallationCheck.perform(check, request);
     Assert.assertEquals(PrereqCheckStatus.FAIL, check.getStatus());
     Assert.assertTrue(check.getFailReason().indexOf("Service components in INSTALL_FAILED state") > -1);
+    Assert.assertEquals(1, check.getFailedDetail().size());
 
     // Case 4: Change TEZ client state to INSTALL_FAILED and place TEZ in Maintenance mode, should succeed
     Mockito.when(tezService.getMaintenanceState()).thenReturn(MaintenanceState.ON);
@@ -314,6 +317,7 @@ public class ComponentsInstallationCheckTest {
     check = new PrerequisiteCheck(null, null);
     componentsInstallationCheck.perform(check, request);
     Assert.assertEquals(PrereqCheckStatus.PASS, check.getStatus());
+    Assert.assertTrue(check.getFailedDetail().isEmpty());
 
     // Case 5: Change TEZ client state to INSTALL_FAILED and place host2 in Maintenance mode, should succeed
     Mockito.when(tezService.getMaintenanceState()).thenReturn(MaintenanceState.OFF);
@@ -322,5 +326,6 @@ public class ComponentsInstallationCheckTest {
     check = new PrerequisiteCheck(null, null);
     componentsInstallationCheck.perform(check, request);
     Assert.assertEquals(PrereqCheckStatus.PASS, check.getStatus());
+    Assert.assertTrue(check.getFailedDetail().isEmpty());
   }
 }

+ 2 - 0
ambari-server/src/test/java/org/apache/ambari/server/checks/HealthCheckTest.java

@@ -82,6 +82,7 @@ public class HealthCheckTest {
     PrerequisiteCheck check = new PrerequisiteCheck(null, CLUSTER_NAME);
     healthCheck.perform(check, new PrereqCheckRequest(CLUSTER_NAME));
     Assert.assertEquals(PrereqCheckStatus.PASS, check.getStatus());
+    Assert.assertTrue(check.getFailedDetail().isEmpty());
   }
 
   @Test
@@ -112,5 +113,6 @@ public class HealthCheckTest {
     PrerequisiteCheck check = new PrerequisiteCheck(null, CLUSTER_NAME);
     healthCheck.perform(check, new PrereqCheckRequest(CLUSTER_NAME));
     Assert.assertEquals(PrereqCheckStatus.WARNING, check.getStatus());
+    Assert.assertFalse(check.getFailedDetail().isEmpty());
   }
 }

+ 2 - 0
ambari-server/src/test/java/org/apache/ambari/server/checks/HostMaintenanceModeCheckTest.java

@@ -123,12 +123,14 @@ public class HostMaintenanceModeCheckTest {
     PrerequisiteCheck check = new PrerequisiteCheck(null, null);
     hostMaintenanceModeCheck.perform(check, new PrereqCheckRequest("cluster"));
     Assert.assertEquals(PrereqCheckStatus.PASS, check.getStatus());
+    Assert.assertTrue(check.getFailedDetail().isEmpty());
 
     // put a host into MM in order to trigger the warning
     check = new PrerequisiteCheck(null, null);
     Mockito.when(host3.getMaintenanceState(1L)).thenReturn(MaintenanceState.ON);
     hostMaintenanceModeCheck.perform(check, new PrereqCheckRequest("cluster", UpgradeType.HOST_ORDERED));
     Assert.assertEquals(PrereqCheckStatus.FAIL, check.getStatus());
+    Assert.assertFalse(check.getFailedDetail().isEmpty());
     Assert.assertEquals("The following hosts cannot be in Maintenance Mode: h3.", check.getFailReason());
   }
 }

+ 3 - 0
ambari-server/src/test/java/org/apache/ambari/server/checks/HostsHeartbeatCheckTest.java

@@ -120,12 +120,14 @@ public class HostsHeartbeatCheckTest {
     PrerequisiteCheck check = new PrerequisiteCheck(null, null);
     hostHeartbeatCheck.perform(check, new PrereqCheckRequest("cluster"));
     Assert.assertEquals(PrereqCheckStatus.FAIL, check.getStatus());
+    Assert.assertFalse(check.getFailedDetail().isEmpty());
 
     // put the unhealthy host into MM which will allow this check to pass
     check = new PrerequisiteCheck(null, null);
     Mockito.when(host3.getMaintenanceState(1L)).thenReturn(MaintenanceState.ON);
     hostHeartbeatCheck.perform(check, new PrereqCheckRequest("cluster"));
     Assert.assertEquals(PrereqCheckStatus.PASS, check.getStatus());
+    Assert.assertTrue(check.getFailedDetail().isEmpty());
 
     // make the host healthy and take it out of MM to produce a PASS result
     Mockito.when(status3.getHealthStatus()).thenReturn(HealthStatus.HEALTHY);
@@ -133,5 +135,6 @@ public class HostsHeartbeatCheckTest {
     Mockito.when(host3.getMaintenanceState(1L)).thenReturn(MaintenanceState.OFF);
     hostHeartbeatCheck.perform(check, new PrereqCheckRequest("cluster"));
     Assert.assertEquals(PrereqCheckStatus.PASS, check.getStatus());
+    Assert.assertTrue(check.getFailedDetail().isEmpty());
   }
 }

+ 2 - 0
ambari-server/src/test/java/org/apache/ambari/server/checks/InstallPackagesCheckTest.java

@@ -170,6 +170,7 @@ public class InstallPackagesCheckTest {
     PrerequisiteCheck check = new PrerequisiteCheck(null, null);
     installPackagesCheck.perform(check, checkRequest);
     Assert.assertEquals(PrereqCheckStatus.PASS, check.getStatus());
+    Assert.assertTrue(check.getFailedDetail().isEmpty());
 
     // Case 2: Install Packages failed on host1
     Mockito.when(hostVersionEntities.get(0).getState()).thenReturn(RepositoryVersionState.INSTALL_FAILED);
@@ -178,5 +179,6 @@ public class InstallPackagesCheckTest {
     Assert.assertEquals(PrereqCheckStatus.FAIL, check.getStatus());
     Assert.assertNotNull(check.getFailedOn());
     Assert.assertTrue(check.getFailedOn().contains("host1"));
+    Assert.assertFalse(check.getFailedDetail().isEmpty());
   }
 }

+ 2 - 0
ambari-server/src/test/java/org/apache/ambari/server/checks/RequiredServicesInRepositoryCheckTest.java

@@ -92,6 +92,7 @@ public class RequiredServicesInRepositoryCheckTest {
     PrerequisiteCheck check = new PrerequisiteCheck(null, CLUSTER_NAME);
     m_requiredServicesCheck.perform(check, request);
     Assert.assertEquals(PrereqCheckStatus.PASS, check.getStatus());
+    Assert.assertTrue(check.getFailedDetail().isEmpty());
   }
 
   /**
@@ -109,5 +110,6 @@ public class RequiredServicesInRepositoryCheckTest {
     PrerequisiteCheck check = new PrerequisiteCheck(null, CLUSTER_NAME);
     m_requiredServicesCheck.perform(check, request);
     Assert.assertEquals(PrereqCheckStatus.FAIL, check.getStatus());
+    Assert.assertFalse(check.getFailedDetail().isEmpty());
   }
 }

+ 9 - 0
ambari-server/src/test/java/org/apache/ambari/server/checks/ServicesUpCheckTest.java

@@ -296,6 +296,7 @@ public class ServicesUpCheckTest {
     PrerequisiteCheck check = new PrerequisiteCheck(null, null);
     servicesUpCheck.perform(check, request);
     Assert.assertEquals(PrereqCheckStatus.PASS, check.getStatus());
+    Assert.assertTrue(check.getFailedDetail().isEmpty());
 
     // Case 2. Change some desired states to STARTED, should still pass
     Mockito.when(hcsNameNode.getDesiredState()).thenReturn(State.STARTED);
@@ -304,6 +305,7 @@ public class ServicesUpCheckTest {
     check = new PrerequisiteCheck(null, null);
     servicesUpCheck.perform(check, request);
     Assert.assertEquals(PrereqCheckStatus.PASS, check.getStatus());
+    Assert.assertTrue(check.getFailedDetail().isEmpty());
 
     // Case 3. Ensure that ZKFC and AMS are ignored even if their current state is not STARTED
     Mockito.when(hcsZKFC.getCurrentState()).thenReturn(State.INSTALLED);
@@ -313,6 +315,7 @@ public class ServicesUpCheckTest {
     check = new PrerequisiteCheck(null, null);
     servicesUpCheck.perform(check, request);
     Assert.assertEquals(PrereqCheckStatus.PASS, check.getStatus());
+    Assert.assertTrue(check.getFailedDetail().isEmpty());
 
     // Case 4. Change HDFS current states to INSTALLED, should fail.
     Mockito.when(hcsNameNode.getCurrentState()).thenReturn(State.INSTALLED);
@@ -321,6 +324,7 @@ public class ServicesUpCheckTest {
     check = new PrerequisiteCheck(null, null);
     servicesUpCheck.perform(check, request);
     Assert.assertEquals(PrereqCheckStatus.FAIL, check.getStatus());
+    Assert.assertFalse(check.getFailedDetail().isEmpty());
 
     // Case 5. Change HDFS master to STARTED, but one slave to INSTALLED, should pass (2/3 are up).
     Mockito.when(hcsNameNode.getCurrentState()).thenReturn(State.STARTED);
@@ -328,6 +332,7 @@ public class ServicesUpCheckTest {
     check = new PrerequisiteCheck(null, null);
     servicesUpCheck.perform(check, request);
     Assert.assertEquals(PrereqCheckStatus.PASS, check.getStatus());
+    Assert.assertTrue(check.getFailedDetail().isEmpty());
 
     // Case 6. Change HDFS master to STARTED, but 2 slaves to INSTALLED, should fail (2/3 are down)
     Mockito.when(hcsNameNode.getCurrentState()).thenReturn(State.STARTED);
@@ -337,6 +342,7 @@ public class ServicesUpCheckTest {
     servicesUpCheck.perform(check, request);
     Assert.assertEquals(PrereqCheckStatus.FAIL, check.getStatus());
     Assert.assertTrue(check.getFailReason().indexOf("50%") > -1);
+    Assert.assertFalse(check.getFailedDetail().isEmpty());
 
     // place the DN slaves into MM which will allow them to be skipped
     Mockito.when(host1.getMaintenanceState(Mockito.anyLong())).thenReturn(MaintenanceState.ON);
@@ -344,6 +350,7 @@ public class ServicesUpCheckTest {
     check = new PrerequisiteCheck(null, null);
     servicesUpCheck.perform(check, request);
     Assert.assertEquals(PrereqCheckStatus.PASS, check.getStatus());
+    Assert.assertTrue(check.getFailedDetail().isEmpty());
 
     // put everything back to normal, then fail NN
     Mockito.when(hcsNameNode.getCurrentState()).thenReturn(State.INSTALLED);
@@ -355,11 +362,13 @@ public class ServicesUpCheckTest {
     check = new PrerequisiteCheck(null, null);
     servicesUpCheck.perform(check, request);
     Assert.assertEquals(PrereqCheckStatus.FAIL, check.getStatus());
+    Assert.assertFalse(check.getFailedDetail().isEmpty());
 
     // put NN into MM; should still fail since it's a master
     Mockito.when(host1.getMaintenanceState(Mockito.anyLong())).thenReturn(MaintenanceState.ON);
     check = new PrerequisiteCheck(null, null);
     servicesUpCheck.perform(check, request);
     Assert.assertEquals(PrereqCheckStatus.FAIL, check.getStatus());
+    Assert.assertFalse(check.getFailedDetail().isEmpty());
   }
 }

+ 0 - 13
ambari-server/src/test/java/org/apache/ambari/server/configuration/ConfigurationTest.java

@@ -514,19 +514,6 @@ public class ConfigurationTest {
     Assert.assertEquals(new Long(1000L), configuration.getExecutionSchedulerWait());
   }
 
-  @Test
-  public void testExperimentalConcurrentStageProcessing() throws Exception {
-    final Properties ambariProperties = new Properties();
-    final Configuration configuration = new Configuration(ambariProperties);
-
-    Assert.assertFalse(configuration.isExperimentalConcurrentStageProcessingEnabled());
-
-    ambariProperties.setProperty(Configuration.EXPERIMENTAL_CONCURRENCY_STAGE_PROCESSING_ENABLED.getKey(),
-        Boolean.TRUE.toString());
-
-    Assert.assertTrue(configuration.isExperimentalConcurrentStageProcessingEnabled());
-  }
-
   @Test
   public void testServerLocksProfilingEnabled() throws Exception {
     final Properties ambariProperties = new Properties();

+ 100 - 100
ambari-server/src/test/java/org/apache/ambari/server/upgrade/UpgradeCatalog300Test.java → ambari-server/src/test/java/org/apache/ambari/server/upgrade/UpgradeCatalog270Test.java

@@ -17,68 +17,68 @@
  */
 package org.apache.ambari.server.upgrade;
 
-import static org.apache.ambari.server.upgrade.UpgradeCatalog300.ADMINPRIVILEGE_PERMISSION_ID_COLUMN;
-import static org.apache.ambari.server.upgrade.UpgradeCatalog300.ADMINPRIVILEGE_PRINCIPAL_ID_COLUMN;
-import static org.apache.ambari.server.upgrade.UpgradeCatalog300.ADMINPRIVILEGE_PRIVILEGE_ID_COLUMN;
-import static org.apache.ambari.server.upgrade.UpgradeCatalog300.ADMINPRIVILEGE_RESOURCE_ID_COLUMN;
-import static org.apache.ambari.server.upgrade.UpgradeCatalog300.ADMINPRIVILEGE_TABLE;
-import static org.apache.ambari.server.upgrade.UpgradeCatalog300.AMBARI_CONFIGURATION_CATEGORY_NAME_COLUMN;
-import static org.apache.ambari.server.upgrade.UpgradeCatalog300.AMBARI_CONFIGURATION_PROPERTY_NAME_COLUMN;
-import static org.apache.ambari.server.upgrade.UpgradeCatalog300.AMBARI_CONFIGURATION_PROPERTY_VALUE_COLUMN;
-import static org.apache.ambari.server.upgrade.UpgradeCatalog300.AMBARI_CONFIGURATION_TABLE;
-import static org.apache.ambari.server.upgrade.UpgradeCatalog300.COMPONENT_DESIRED_STATE_TABLE;
-import static org.apache.ambari.server.upgrade.UpgradeCatalog300.COMPONENT_NAME_COLUMN;
-import static org.apache.ambari.server.upgrade.UpgradeCatalog300.COMPONENT_STATE_TABLE;
-import static org.apache.ambari.server.upgrade.UpgradeCatalog300.FK_KKP_HOST_ID;
-import static org.apache.ambari.server.upgrade.UpgradeCatalog300.FK_KKP_KEYTAB_PATH;
-import static org.apache.ambari.server.upgrade.UpgradeCatalog300.FK_KKP_PRINCIPAL_NAME;
-import static org.apache.ambari.server.upgrade.UpgradeCatalog300.FK_KKP_SERVICE_PRINCIPAL;
-import static org.apache.ambari.server.upgrade.UpgradeCatalog300.HOSTS_TABLE;
-import static org.apache.ambari.server.upgrade.UpgradeCatalog300.HOST_ID_COLUMN;
-import static org.apache.ambari.server.upgrade.UpgradeCatalog300.KERBEROS_KEYTAB_PRINCIPAL_TABLE;
-import static org.apache.ambari.server.upgrade.UpgradeCatalog300.KERBEROS_KEYTAB_TABLE;
-import static org.apache.ambari.server.upgrade.UpgradeCatalog300.KERBEROS_PRINCIPAL_HOST_TABLE;
-import static org.apache.ambari.server.upgrade.UpgradeCatalog300.KERBEROS_PRINCIPAL_TABLE;
-import static org.apache.ambari.server.upgrade.UpgradeCatalog300.KEYTAB_PATH_FIELD;
-import static org.apache.ambari.server.upgrade.UpgradeCatalog300.KKP_ID_COLUMN;
-import static org.apache.ambari.server.upgrade.UpgradeCatalog300.KKP_MAPPING_SERVICE_TABLE;
-import static org.apache.ambari.server.upgrade.UpgradeCatalog300.MEMBERS_GROUP_ID_COLUMN;
-import static org.apache.ambari.server.upgrade.UpgradeCatalog300.MEMBERS_MEMBER_ID_COLUMN;
-import static org.apache.ambari.server.upgrade.UpgradeCatalog300.MEMBERS_TABLE;
-import static org.apache.ambari.server.upgrade.UpgradeCatalog300.MEMBERS_USER_ID_COLUMN;
-import static org.apache.ambari.server.upgrade.UpgradeCatalog300.PK_KERBEROS_KEYTAB;
-import static org.apache.ambari.server.upgrade.UpgradeCatalog300.PK_KKP;
-import static org.apache.ambari.server.upgrade.UpgradeCatalog300.PK_KKP_MAPPING_SERVICE;
-import static org.apache.ambari.server.upgrade.UpgradeCatalog300.PRINCIPAL_NAME_COLUMN;
-import static org.apache.ambari.server.upgrade.UpgradeCatalog300.REQUEST_DISPLAY_STATUS_COLUMN;
-import static org.apache.ambari.server.upgrade.UpgradeCatalog300.REQUEST_TABLE;
-import static org.apache.ambari.server.upgrade.UpgradeCatalog300.SECURITY_STATE_COLUMN;
-import static org.apache.ambari.server.upgrade.UpgradeCatalog300.SERVICE_DESIRED_STATE_TABLE;
-import static org.apache.ambari.server.upgrade.UpgradeCatalog300.SERVICE_NAME_COLUMN;
-import static org.apache.ambari.server.upgrade.UpgradeCatalog300.STAGE_DISPLAY_STATUS_COLUMN;
-import static org.apache.ambari.server.upgrade.UpgradeCatalog300.STAGE_STATUS_COLUMN;
-import static org.apache.ambari.server.upgrade.UpgradeCatalog300.STAGE_TABLE;
-import static org.apache.ambari.server.upgrade.UpgradeCatalog300.UNIQUE_USERS_0_INDEX;
-import static org.apache.ambari.server.upgrade.UpgradeCatalog300.UNI_KKP;
-import static org.apache.ambari.server.upgrade.UpgradeCatalog300.USERS_CONSECUTIVE_FAILURES_COLUMN;
-import static org.apache.ambari.server.upgrade.UpgradeCatalog300.USERS_DISPLAY_NAME_COLUMN;
-import static org.apache.ambari.server.upgrade.UpgradeCatalog300.USERS_LDAP_USER_COLUMN;
-import static org.apache.ambari.server.upgrade.UpgradeCatalog300.USERS_LOCAL_USERNAME_COLUMN;
-import static org.apache.ambari.server.upgrade.UpgradeCatalog300.USERS_TABLE;
-import static org.apache.ambari.server.upgrade.UpgradeCatalog300.USERS_USER_ID_COLUMN;
-import static org.apache.ambari.server.upgrade.UpgradeCatalog300.USERS_USER_NAME_COLUMN;
-import static org.apache.ambari.server.upgrade.UpgradeCatalog300.USERS_USER_PASSWORD_COLUMN;
-import static org.apache.ambari.server.upgrade.UpgradeCatalog300.USERS_USER_TYPE_COLUMN;
-import static org.apache.ambari.server.upgrade.UpgradeCatalog300.USERS_VERSION_COLUMN;
-import static org.apache.ambari.server.upgrade.UpgradeCatalog300.USER_AUTHENTICATION_AUTHENTICATION_KEY_COLUMN;
-import static org.apache.ambari.server.upgrade.UpgradeCatalog300.USER_AUTHENTICATION_AUTHENTICATION_TYPE_COLUMN;
-import static org.apache.ambari.server.upgrade.UpgradeCatalog300.USER_AUTHENTICATION_CREATE_TIME_COLUMN;
-import static org.apache.ambari.server.upgrade.UpgradeCatalog300.USER_AUTHENTICATION_PRIMARY_KEY;
-import static org.apache.ambari.server.upgrade.UpgradeCatalog300.USER_AUTHENTICATION_TABLE;
-import static org.apache.ambari.server.upgrade.UpgradeCatalog300.USER_AUTHENTICATION_UPDATE_TIME_COLUMN;
-import static org.apache.ambari.server.upgrade.UpgradeCatalog300.USER_AUTHENTICATION_USER_AUTHENTICATION_ID_COLUMN;
-import static org.apache.ambari.server.upgrade.UpgradeCatalog300.USER_AUTHENTICATION_USER_AUTHENTICATION_USERS_FOREIGN_KEY;
-import static org.apache.ambari.server.upgrade.UpgradeCatalog300.USER_AUTHENTICATION_USER_ID_COLUMN;
+import static org.apache.ambari.server.upgrade.UpgradeCatalog270.ADMINPRIVILEGE_PERMISSION_ID_COLUMN;
+import static org.apache.ambari.server.upgrade.UpgradeCatalog270.ADMINPRIVILEGE_PRINCIPAL_ID_COLUMN;
+import static org.apache.ambari.server.upgrade.UpgradeCatalog270.ADMINPRIVILEGE_PRIVILEGE_ID_COLUMN;
+import static org.apache.ambari.server.upgrade.UpgradeCatalog270.ADMINPRIVILEGE_RESOURCE_ID_COLUMN;
+import static org.apache.ambari.server.upgrade.UpgradeCatalog270.ADMINPRIVILEGE_TABLE;
+import static org.apache.ambari.server.upgrade.UpgradeCatalog270.AMBARI_CONFIGURATION_CATEGORY_NAME_COLUMN;
+import static org.apache.ambari.server.upgrade.UpgradeCatalog270.AMBARI_CONFIGURATION_PROPERTY_NAME_COLUMN;
+import static org.apache.ambari.server.upgrade.UpgradeCatalog270.AMBARI_CONFIGURATION_PROPERTY_VALUE_COLUMN;
+import static org.apache.ambari.server.upgrade.UpgradeCatalog270.AMBARI_CONFIGURATION_TABLE;
+import static org.apache.ambari.server.upgrade.UpgradeCatalog270.COMPONENT_DESIRED_STATE_TABLE;
+import static org.apache.ambari.server.upgrade.UpgradeCatalog270.COMPONENT_NAME_COLUMN;
+import static org.apache.ambari.server.upgrade.UpgradeCatalog270.COMPONENT_STATE_TABLE;
+import static org.apache.ambari.server.upgrade.UpgradeCatalog270.FK_KKP_HOST_ID;
+import static org.apache.ambari.server.upgrade.UpgradeCatalog270.FK_KKP_KEYTAB_PATH;
+import static org.apache.ambari.server.upgrade.UpgradeCatalog270.FK_KKP_PRINCIPAL_NAME;
+import static org.apache.ambari.server.upgrade.UpgradeCatalog270.FK_KKP_SERVICE_PRINCIPAL;
+import static org.apache.ambari.server.upgrade.UpgradeCatalog270.HOSTS_TABLE;
+import static org.apache.ambari.server.upgrade.UpgradeCatalog270.HOST_ID_COLUMN;
+import static org.apache.ambari.server.upgrade.UpgradeCatalog270.KERBEROS_KEYTAB_PRINCIPAL_TABLE;
+import static org.apache.ambari.server.upgrade.UpgradeCatalog270.KERBEROS_KEYTAB_TABLE;
+import static org.apache.ambari.server.upgrade.UpgradeCatalog270.KERBEROS_PRINCIPAL_HOST_TABLE;
+import static org.apache.ambari.server.upgrade.UpgradeCatalog270.KERBEROS_PRINCIPAL_TABLE;
+import static org.apache.ambari.server.upgrade.UpgradeCatalog270.KEYTAB_PATH_FIELD;
+import static org.apache.ambari.server.upgrade.UpgradeCatalog270.KKP_ID_COLUMN;
+import static org.apache.ambari.server.upgrade.UpgradeCatalog270.KKP_MAPPING_SERVICE_TABLE;
+import static org.apache.ambari.server.upgrade.UpgradeCatalog270.MEMBERS_GROUP_ID_COLUMN;
+import static org.apache.ambari.server.upgrade.UpgradeCatalog270.MEMBERS_MEMBER_ID_COLUMN;
+import static org.apache.ambari.server.upgrade.UpgradeCatalog270.MEMBERS_TABLE;
+import static org.apache.ambari.server.upgrade.UpgradeCatalog270.MEMBERS_USER_ID_COLUMN;
+import static org.apache.ambari.server.upgrade.UpgradeCatalog270.PK_KERBEROS_KEYTAB;
+import static org.apache.ambari.server.upgrade.UpgradeCatalog270.PK_KKP;
+import static org.apache.ambari.server.upgrade.UpgradeCatalog270.PK_KKP_MAPPING_SERVICE;
+import static org.apache.ambari.server.upgrade.UpgradeCatalog270.PRINCIPAL_NAME_COLUMN;
+import static org.apache.ambari.server.upgrade.UpgradeCatalog270.REQUEST_DISPLAY_STATUS_COLUMN;
+import static org.apache.ambari.server.upgrade.UpgradeCatalog270.REQUEST_TABLE;
+import static org.apache.ambari.server.upgrade.UpgradeCatalog270.SECURITY_STATE_COLUMN;
+import static org.apache.ambari.server.upgrade.UpgradeCatalog270.SERVICE_DESIRED_STATE_TABLE;
+import static org.apache.ambari.server.upgrade.UpgradeCatalog270.SERVICE_NAME_COLUMN;
+import static org.apache.ambari.server.upgrade.UpgradeCatalog270.STAGE_DISPLAY_STATUS_COLUMN;
+import static org.apache.ambari.server.upgrade.UpgradeCatalog270.STAGE_STATUS_COLUMN;
+import static org.apache.ambari.server.upgrade.UpgradeCatalog270.STAGE_TABLE;
+import static org.apache.ambari.server.upgrade.UpgradeCatalog270.UNIQUE_USERS_0_INDEX;
+import static org.apache.ambari.server.upgrade.UpgradeCatalog270.UNI_KKP;
+import static org.apache.ambari.server.upgrade.UpgradeCatalog270.USERS_CONSECUTIVE_FAILURES_COLUMN;
+import static org.apache.ambari.server.upgrade.UpgradeCatalog270.USERS_DISPLAY_NAME_COLUMN;
+import static org.apache.ambari.server.upgrade.UpgradeCatalog270.USERS_LDAP_USER_COLUMN;
+import static org.apache.ambari.server.upgrade.UpgradeCatalog270.USERS_LOCAL_USERNAME_COLUMN;
+import static org.apache.ambari.server.upgrade.UpgradeCatalog270.USERS_TABLE;
+import static org.apache.ambari.server.upgrade.UpgradeCatalog270.USERS_USER_ID_COLUMN;
+import static org.apache.ambari.server.upgrade.UpgradeCatalog270.USERS_USER_NAME_COLUMN;
+import static org.apache.ambari.server.upgrade.UpgradeCatalog270.USERS_USER_PASSWORD_COLUMN;
+import static org.apache.ambari.server.upgrade.UpgradeCatalog270.USERS_USER_TYPE_COLUMN;
+import static org.apache.ambari.server.upgrade.UpgradeCatalog270.USERS_VERSION_COLUMN;
+import static org.apache.ambari.server.upgrade.UpgradeCatalog270.USER_AUTHENTICATION_AUTHENTICATION_KEY_COLUMN;
+import static org.apache.ambari.server.upgrade.UpgradeCatalog270.USER_AUTHENTICATION_AUTHENTICATION_TYPE_COLUMN;
+import static org.apache.ambari.server.upgrade.UpgradeCatalog270.USER_AUTHENTICATION_CREATE_TIME_COLUMN;
+import static org.apache.ambari.server.upgrade.UpgradeCatalog270.USER_AUTHENTICATION_PRIMARY_KEY;
+import static org.apache.ambari.server.upgrade.UpgradeCatalog270.USER_AUTHENTICATION_TABLE;
+import static org.apache.ambari.server.upgrade.UpgradeCatalog270.USER_AUTHENTICATION_UPDATE_TIME_COLUMN;
+import static org.apache.ambari.server.upgrade.UpgradeCatalog270.USER_AUTHENTICATION_USER_AUTHENTICATION_ID_COLUMN;
+import static org.apache.ambari.server.upgrade.UpgradeCatalog270.USER_AUTHENTICATION_USER_AUTHENTICATION_USERS_FOREIGN_KEY;
+import static org.apache.ambari.server.upgrade.UpgradeCatalog270.USER_AUTHENTICATION_USER_ID_COLUMN;
 import static org.easymock.EasyMock.anyObject;
 import static org.easymock.EasyMock.anyString;
 import static org.easymock.EasyMock.capture;
@@ -204,7 +204,7 @@ import com.google.inject.assistedinject.FactoryModuleBuilder;
 import com.google.inject.persist.UnitOfWork;
 
 @RunWith(EasyMockRunner.class)
-public class UpgradeCatalog300Test {
+public class UpgradeCatalog270Test {
   @Rule
   public ExpectedException expectedException = ExpectedException.none();
 
@@ -257,16 +257,16 @@ public class UpgradeCatalog300Test {
   @Test
   public void testExecuteDMLUpdates() throws Exception {
     Method addNewConfigurationsFromXml = AbstractUpgradeCatalog.class.getDeclaredMethod("addNewConfigurationsFromXml");
-    Method showHcatDeletedUserMessage = UpgradeCatalog300.class.getDeclaredMethod("showHcatDeletedUserMessage");
-    Method setStatusOfStagesAndRequests = UpgradeCatalog300.class.getDeclaredMethod("setStatusOfStagesAndRequests");
-    Method updateLogSearchConfigs = UpgradeCatalog300.class.getDeclaredMethod("updateLogSearchConfigs");
-    Method updateKerberosConfigurations = UpgradeCatalog300.class.getDeclaredMethod("updateKerberosConfigurations");
+    Method showHcatDeletedUserMessage = UpgradeCatalog270.class.getDeclaredMethod("showHcatDeletedUserMessage");
+    Method setStatusOfStagesAndRequests = UpgradeCatalog270.class.getDeclaredMethod("setStatusOfStagesAndRequests");
+    Method updateLogSearchConfigs = UpgradeCatalog270.class.getDeclaredMethod("updateLogSearchConfigs");
+    Method updateKerberosConfigurations = UpgradeCatalog270.class.getDeclaredMethod("updateKerberosConfigurations");
     Method updateHostComponentLastStateTable = UpgradeCatalog300.class.getDeclaredMethod("updateHostComponentLastStateTable");
-    Method upgradeLdapConfiguration = UpgradeCatalog300.class.getDeclaredMethod("upgradeLdapConfiguration");
-    Method createRoleAuthorizations = UpgradeCatalog300.class.getDeclaredMethod("createRoleAuthorizations");
-    Method addUserAuthenticationSequence = UpgradeCatalog300.class.getDeclaredMethod("addUserAuthenticationSequence");
+    Method upgradeLdapConfiguration = UpgradeCatalog270.class.getDeclaredMethod("upgradeLdapConfiguration");
+    Method createRoleAuthorizations = UpgradeCatalog270.class.getDeclaredMethod("createRoleAuthorizations");
+    Method addUserAuthenticationSequence = UpgradeCatalog270.class.getDeclaredMethod("addUserAuthenticationSequence");
 
-    UpgradeCatalog300 upgradeCatalog300 = createMockBuilder(UpgradeCatalog300.class)
+    UpgradeCatalog270 upgradeCatalog270 = createMockBuilder(UpgradeCatalog270.class)
         .addMockedMethod(showHcatDeletedUserMessage)
         .addMockedMethod(addNewConfigurationsFromXml)
         .addMockedMethod(setStatusOfStagesAndRequests)
@@ -279,36 +279,36 @@ public class UpgradeCatalog300Test {
         .createMock();
 
 
-    upgradeCatalog300.addNewConfigurationsFromXml();
+    upgradeCatalog270.addNewConfigurationsFromXml();
     expectLastCall().once();
 
-    upgradeCatalog300.showHcatDeletedUserMessage();
+    upgradeCatalog270.showHcatDeletedUserMessage();
     expectLastCall().once();
 
-    upgradeCatalog300.createRoleAuthorizations();
+    upgradeCatalog270.createRoleAuthorizations();
     expectLastCall().once();
 
-    upgradeCatalog300.setStatusOfStagesAndRequests();
+    upgradeCatalog270.setStatusOfStagesAndRequests();
     expectLastCall().once();
 
-    upgradeCatalog300.updateLogSearchConfigs();
+    upgradeCatalog270.updateLogSearchConfigs();
     upgradeCatalog300.updateHostComponentLastStateTable();
     expectLastCall().once();
 
-    upgradeCatalog300.updateKerberosConfigurations();
+    upgradeCatalog270.updateKerberosConfigurations();
     expectLastCall().once();
 
-    upgradeCatalog300.upgradeLdapConfiguration();
+    upgradeCatalog270.upgradeLdapConfiguration();
     expectLastCall().once();
 
-    upgradeCatalog300.addUserAuthenticationSequence();
+    upgradeCatalog270.addUserAuthenticationSequence();
     expectLastCall().once();
 
-    replay(upgradeCatalog300);
+    replay(upgradeCatalog270);
 
-    upgradeCatalog300.executeDMLUpdates();
+    upgradeCatalog270.executeDMLUpdates();
 
-    verify(upgradeCatalog300);
+    verify(upgradeCatalog270);
   }
 
   @Test
@@ -324,7 +324,7 @@ public class UpgradeCatalog300Test {
 
     // addOpsDisplayNameColumnToHostRoleCommand
     Capture<DBAccessor.DBColumnInfo> hrcOpsDisplayNameColumn = newCapture();
-    dbAccessor.addColumn(eq(UpgradeCatalog300.HOST_ROLE_COMMAND_TABLE), capture(hrcOpsDisplayNameColumn));
+    dbAccessor.addColumn(eq(UpgradeCatalog270.HOST_ROLE_COMMAND_TABLE), capture(hrcOpsDisplayNameColumn));
     expectLastCall().once();
 
     Capture<DBAccessor.DBColumnInfo> lastValidColumn = newCapture();
@@ -400,8 +400,8 @@ public class UpgradeCatalog300Test {
     replay(dbAccessor);
 
     Injector injector = Guice.createInjector(getTestGuiceModule());
-    UpgradeCatalog300 upgradeCatalog300 = injector.getInstance(UpgradeCatalog300.class);
-    upgradeCatalog300.executeDDLUpdates();
+    UpgradeCatalog270 upgradeCatalog270 = injector.getInstance(UpgradeCatalog270.class);
+    upgradeCatalog270.executeDDLUpdates();
 
     // Validate updateStageTableCaptures
     Assert.assertTrue(updateStageTableCaptures.hasCaptured());
@@ -413,7 +413,7 @@ public class UpgradeCatalog300Test {
     );
 
     DBAccessor.DBColumnInfo capturedOpsDisplayNameColumn = hrcOpsDisplayNameColumn.getValue();
-    Assert.assertEquals(UpgradeCatalog300.HRC_OPS_DISPLAY_NAME_COLUMN, capturedOpsDisplayNameColumn.getName());
+    Assert.assertEquals(UpgradeCatalog270.HRC_OPS_DISPLAY_NAME_COLUMN, capturedOpsDisplayNameColumn.getName());
     Assert.assertEquals(null, capturedOpsDisplayNameColumn.getDefaultValue());
     Assert.assertEquals(String.class, capturedOpsDisplayNameColumn.getType());
 
@@ -843,7 +843,7 @@ public class UpgradeCatalog300Test {
     replay(logFeederLog4jConf, logSearchLog4jConf);
     replay(logSearchServiceLogsConf, logSearchAuditLogsConf);
     replay(logFeederOutputConf);
-    new UpgradeCatalog300(injector2).updateLogSearchConfigs();
+    new UpgradeCatalog270(injector2).updateLogSearchConfigs();
     easyMockSupport.verifyAll();
 
     Map<String, String> newLogFeederProperties = logFeederPropertiesCapture.getValue();
@@ -898,7 +898,7 @@ public class UpgradeCatalog300Test {
     expect(cluster1.getClusterId()).andReturn(1L).atLeastOnce();
     expect(cluster1.getDesiredStackVersion()).andReturn(stackId).atLeastOnce();
     expect(cluster1.getConfig(eq("kerberos-env"), anyString())).andReturn(newConfig).atLeastOnce();
-    expect(cluster1.addDesiredConfig("ambari-upgrade", Collections.singleton(newConfig), "Updated kerberos-env during Ambari Upgrade from 2.6.0 to 3.0.0.")).andReturn(response).once();
+    expect(cluster1.addDesiredConfig("ambari-upgrade", Collections.singleton(newConfig), "Updated kerberos-env during Ambari Upgrade from 2.6.2 to 2.7.0.")).andReturn(response).once();
 
     Map<String, String> propertiesWithoutGroup = new HashMap<>();
     propertiesWithoutGroup.put("kdc_host", "host2.example.com");
@@ -946,19 +946,19 @@ public class UpgradeCatalog300Test {
 
     Field field = AbstractUpgradeCatalog.class.getDeclaredField("configuration");
 
-    UpgradeCatalog300 upgradeCatalog300 = createMockBuilder(UpgradeCatalog300.class).addMockedMethod("getPrepareIdentityServerAction").addMockedMethod("executeInTransaction").createMock();
+    UpgradeCatalog270 upgradeCatalog270 = createMockBuilder(UpgradeCatalog270.class).addMockedMethod("getPrepareIdentityServerAction").addMockedMethod("executeInTransaction").createMock();
     PrepareKerberosIdentitiesServerAction mockAction = createNiceMock(PrepareKerberosIdentitiesServerAction.class);
-    expect(upgradeCatalog300.getPrepareIdentityServerAction()).andReturn(mockAction).times(2);
-    upgradeCatalog300.executeInTransaction(anyObject());
+    expect(upgradeCatalog270.getPrepareIdentityServerAction()).andReturn(mockAction).times(2);
+    upgradeCatalog270.executeInTransaction(anyObject());
     expectLastCall().times(2);
-    upgradeCatalog300.injector = injector;
+    upgradeCatalog270.injector = injector;
 
-    replay(upgradeCatalog300);
+    replay(upgradeCatalog270);
 
-    field.set(upgradeCatalog300, createNiceMock(Configuration.class));
-    upgradeCatalog300.updateKerberosConfigurations();
+    field.set(upgradeCatalog270, createNiceMock(Configuration.class));
+    upgradeCatalog270.updateKerberosConfigurations();
 
-    verify(controller, clusters, cluster1, cluster2, configWithGroup, configWithoutGroup, newConfig, response, injector, upgradeCatalog300);
+    verify(controller, clusters, cluster1, cluster2, configWithGroup, configWithoutGroup, newConfig, response, injector, upgradeCatalog270);
 
 
     Assert.assertEquals(1, capturedProperties.getValues().size());
@@ -987,8 +987,8 @@ public class UpgradeCatalog300Test {
 
     final Injector injector = Guice.createInjector(module);
     injector.getInstance(Configuration.class).setProperty("ambari.ldap.isConfigured", "true");
-    final UpgradeCatalog300 upgradeCatalog300 = new UpgradeCatalog300(injector);
-    upgradeCatalog300.upgradeLdapConfiguration();
+    final UpgradeCatalog270 upgradeCatalog270 = new UpgradeCatalog270(injector);
+    upgradeCatalog270.upgradeLdapConfiguration();
     verify(entityManager, ambariConfigurationDao);
   }
 
@@ -1002,8 +1002,8 @@ public class UpgradeCatalog300Test {
     replay(entityManager, ambariConfigurationDao);
 
     final Injector injector = Guice.createInjector(module);
-    final UpgradeCatalog300 upgradeCatalog300 = new UpgradeCatalog300(injector);
-    upgradeCatalog300.upgradeLdapConfiguration();
+    final UpgradeCatalog270 upgradeCatalog270 = new UpgradeCatalog270(injector);
+    upgradeCatalog270.upgradeLdapConfiguration();
 
     expectedException.expect(AssertionError.class);
     expectedException.expectMessage("Expectation failure on verify");

+ 1 - 1
ambari-server/src/test/java/org/apache/ambari/server/upgrade/UpgradeCatalogTest.java

@@ -84,7 +84,7 @@ public class UpgradeCatalogTest {
       catalogBinder.addBinding().to(UpgradeCatalog201.class);
       catalogBinder.addBinding().to(UpgradeCatalog251.class);
       catalogBinder.addBinding().to(UpgradeCatalog252.class);
-      catalogBinder.addBinding().to(UpgradeCatalog300.class);
+      catalogBinder.addBinding().to(UpgradeCatalog270.class);
     }
   }
 

+ 0 - 223
ambari-server/src/test/java/org/apache/ambari/server/utils/TestParallel.java

@@ -1,223 +0,0 @@
-/*
- * 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.utils;
-
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Collections;
-import java.util.LinkedList;
-import java.util.List;
-
-import org.junit.Test;
-
-import junit.framework.Assert;
-
-/**
- * Tests parallel loops
- */
-public class TestParallel {
-
-  /**
-   * Tests {@link org.apache.ambari.server.utils.Parallel} forLoop base cases.
-   * @throws Exception
-   */
-  @Test
-  public void testParallelForLoopBaseCases() throws Exception {
-
-    ParallelLoopResult<Integer> nullLoopResult = Parallel.forLoop(
-        null,
-        new LoopBody<Integer, Integer>() {
-          @Override
-          public Integer run(Integer integer) {
-            return integer;
-          }
-        });
-    Assert.assertTrue(nullLoopResult.getIsCompleted());
-    Assert.assertTrue(nullLoopResult.getResult().isEmpty());
-
-    ParallelLoopResult<Integer> emptyLoopResult = Parallel.forLoop(
-      new ArrayList<>(),
-        new LoopBody<Integer, Integer>() {
-          @Override
-          public Integer run(Integer integer) {
-            return integer;
-          }
-        });
-    Assert.assertTrue(emptyLoopResult.getIsCompleted());
-    Assert.assertTrue(emptyLoopResult.getResult().isEmpty());
-
-    ParallelLoopResult<Integer> singleElementLoopResult = Parallel.forLoop(
-        Collections.singletonList(7),
-        new LoopBody<Integer, Integer>() {
-          @Override
-          public Integer run(Integer integer) {
-            return integer;
-          }
-        });
-    Assert.assertTrue(singleElementLoopResult.getIsCompleted());
-    List<Integer> singleElementList = singleElementLoopResult.getResult();
-    Assert.assertTrue(singleElementLoopResult.getIsCompleted());
-    Assert.assertFalse(singleElementList.isEmpty());
-    Assert.assertEquals(1, singleElementList.size());
-    Assert.assertNotNull(singleElementList.get(0));
-  }
-
-  /**
-   * Tests Parallel.forLoop
-   * @throws Exception
-   */
-  @Test
-  public void testParallelForLoop() throws Exception {
-    final List<Integer> input = new LinkedList<>();
-    for(int i = 0; i < 10; i++) {
-      input.add(i);
-    }
-
-    ParallelLoopResult<Integer> loopResult = Parallel.forLoop(input, new LoopBody<Integer, Integer>() {
-      @Override
-      public Integer run(Integer in1) {
-        return in1 * in1;
-      }
-    });
-    Assert.assertTrue(loopResult.getIsCompleted());
-    Assert.assertNotNull(loopResult.getResult());
-
-    List<Integer> output = loopResult.getResult();
-    Assert.assertEquals(input.size(), output.size());
-    for(int i = 0; i < input.size(); i++) {
-      Assert.assertEquals( i * i,  (int)output.get(i));
-    }
-  }
-
-  /**
-   * Tests nested {@link org.apache.ambari.server.utils.Parallel} forLoop
-   * @throws Exception
-   */
-  @Test
-  public void testNestedParallelForLoop() throws Exception {
-    final List<Integer> input = new LinkedList<>();
-    for(int i = 0; i < 10; i++) {
-      input.add(i);
-    }
-    final ParallelLoopResult<Integer>[] innerLoopResults =  new ParallelLoopResult[input.size()];
-    ParallelLoopResult<Integer> loopResult = Parallel.forLoop(input, new LoopBody<Integer, Integer>() {
-      @Override
-      public Integer run(final Integer in1) {
-        int sq = in1 * in1;
-        ParallelLoopResult<Integer> innerLoopResult = Parallel.forLoop(input, new LoopBody<Integer, Integer>() {
-          @Override
-          public Integer run(Integer in2) {
-            return in1 * in2;
-          }
-        });
-        innerLoopResults[in1] = innerLoopResult;
-        return in1 * in1;
-      }
-    });
-    Assert.assertNotNull(loopResult);
-    Assert.assertTrue(loopResult.getIsCompleted());
-    List<Integer> output = loopResult.getResult();
-    Assert.assertNotNull(output);
-    Assert.assertEquals(input.size(), output.size());
-
-    for(int i = 0; i < input.size(); i++) {
-      Assert.assertEquals(i * i, (int) output.get(i));
-      ParallelLoopResult<Integer> innerLoopResult = innerLoopResults[i];
-      Assert.assertNotNull(innerLoopResult);
-      Assert.assertTrue(innerLoopResult.getIsCompleted());
-      List<Integer> innerOutput = innerLoopResult.getResult();
-      Assert.assertNotNull(innerOutput);
-      Assert.assertEquals(input.size(), innerOutput.size());
-
-      for(int j = 0; j < input.size(); j++) {
-        Assert.assertEquals(i*j, (int) innerOutput.get(j));
-      }
-    }
-  }
-
-  /**
-   * Tests {@link org.apache.ambari.server.utils.Parallel} forLoop iteration failures
-   * @throws Exception
-   */
-  @Test
-  public void testParallelForLoopIterationFailures() throws Exception {
-    final List<Integer> input = new LinkedList<>();
-    for(int i = 0; i < 10; i++) {
-      input.add(i);
-    }
-    final List<Integer> failForList = Arrays.asList(new Integer[] { 2, 5, 7});
-    ParallelLoopResult<Integer> loopResult = Parallel.forLoop(input, new LoopBody<Integer, Integer>() {
-      @Override
-      public Integer run(Integer in1) {
-        if(failForList.contains(in1)) {
-          // Return null
-          return null;
-        }
-        return in1 * in1;
-      }
-    });
-    Assert.assertFalse(loopResult.getIsCompleted());
-    Assert.assertNotNull(loopResult.getResult());
-    List<Integer> output = loopResult.getResult();
-    Assert.assertEquals(input.size(), output.size());
-
-    for(int i = 0; i < input.size(); i++) {
-      if(failForList.contains(i)) {
-        Assert.assertNull(output.get(i));
-        output.set(i, i * i);
-      } else {
-        Assert.assertEquals(i * i, (int) output.get(i));
-      }
-    }
-  }
-
-  /**
-   * Tests {@link org.apache.ambari.server.utils.Parallel} forLoop iteration exceptions
-   * @throws Exception
-   */
-  @Test
-  public void testParallelForLoopIterationExceptions() throws Exception {
-    final List<Integer> input = new LinkedList<>();
-    for(int i = 0; i < 10; i++) {
-      input.add(i);
-    }
-    final List<Integer> failForList = Arrays.asList(new Integer[] { 2, 5, 7});
-    ParallelLoopResult<Integer> loopResult = Parallel.forLoop(input, new LoopBody<Integer, Integer>() {
-      @Override
-      public Integer run(Integer in1) {
-        if(failForList.contains(in1)) {
-          throw new RuntimeException("Ignore this exception");
-        }
-        return in1 * in1;
-      }
-    });
-    Assert.assertFalse(loopResult.getIsCompleted());
-    Assert.assertNotNull(loopResult.getResult());
-    List<Integer> output = loopResult.getResult();
-    Assert.assertEquals(input.size(), output.size());
-
-    for(int i = 0; i < input.size(); i++) {
-      if(failForList.contains(i)) {
-        Assert.assertNull(output.get(i));
-        output.set(i, i * i);
-      } else {
-        Assert.assertEquals(i * i, (int) output.get(i));
-      }
-    }
-  }
-}

+ 7 - 0
ambari-web/app/styles/modal_popups.less

@@ -66,10 +66,17 @@
       padding: 10px 10px 10px 20px;
     }
     .progress-wrapper {
+      padding: 8px 0px;
       .progress {
         margin-bottom: 0;
       }
     }
+    .progress-percentage {
+      padding: 8px 5px;
+    }
+    td {
+      vertical-align: middle;
+    }
   }
   .status-dropdown {
     .btn.dropdown-toggle:first-child {

+ 256 - 244
ambari-web/app/templates/common/host_progress_popup.hbs

@@ -18,71 +18,78 @@
 
 <div class="host-component-popup-wrap">
 
-{{#if view.parentView.isLoaded}}
-{{!-- OPERATIONS --}}
+  {{#if view.parentView.isLoaded}}
+  {{!-- OPERATIONS --}}
 
-  <div {{bindAttr class="view.parentView.isServiceListHidden:hidden :task-list-main-wrap :table-body-wrap"}}>
-    <div class="top-wrap">
-      <div class="row">
-        <h2 class="table-title col-sm-6">{{view view.parentView.titleClass}}</h2>
-        <div class="table-controls col-sm-6">
-          <div class="btn-group pull-right status-dropdown">
-            <button type="button" class="btn btn-default dropdown-toggle" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
-              {{view.serviceCategory.label}} <span class="caret"></span>
-            </button>
-            <ul class="dropdown-menu">
-              {{#each category in view.categories}}
-                <li><a href="#" {{action selectServiceCategory category target="view"}}>{{category.label}}</a></li>
-              {{/each}}
-            </ul>
+    <div {{bindAttr class="view.parentView.isServiceListHidden:hidden :task-list-main-wrap :table-body-wrap"}}>
+      <div class="top-wrap">
+        <div class="row">
+          <h2 class="table-title col-sm-6">{{view view.parentView.titleClass}}</h2>
+          <div class="table-controls col-sm-6">
+            <div class="btn-group pull-right status-dropdown">
+              <button type="button" class="btn btn-default dropdown-toggle" data-toggle="dropdown" aria-haspopup="true"
+                      aria-expanded="false">
+                {{view.serviceCategory.label}} <span class="caret"></span>
+              </button>
+              <ul class="dropdown-menu">
+                {{#each category in view.categories}}
+                  <li><a href="#" {{action selectServiceCategory category target="view"}}>{{category.label}}</a></li>
+                {{/each}}
+              </ul>
+            </div>
           </div>
         </div>
       </div>
-    </div>
-    <table class="table table-hover">
-      <thead>
+      <div id="service-info">
+      <table class="table table-hover">
+        <thead>
         <tr>
           <th class="col-sm-3">{{t common.operations}}</th>
+          <th class="col-sm-3">{{t common.status}}</th>
+          <th class="col-sm-2">{{t common.user}}</th>
           <th class="col-sm-3">{{t common.startTime}}</th>
-          <th colspan="3" class="col-sm-6">{{t common.duration}}</th>
+          <th class="col-sm-2" colspan="2">{{t common.duration}}</th>
         </tr>
-      </thead>
-    </table>
-    <div id="service-info">
-      {{#if view.isServiceEmptyList}}
-        <div class="log-list-wrap">{{t hostPopup.noServicesToShow}}</div>
-      {{else}}
-        <table class="table table-hover">
-          <tbody>
-            {{#each servicesInfo in view.services}}
-              <tr {{action onOpClick servicesInfo}} {{bindAttr class="servicesInfo.isVisible::hidden :pointer"}}>
-                <td class="col-sm-3">
-                  {{view statusIcon servicesInfoBinding="servicesInfo"}}
-                  <a href="#">
-                    {{servicesInfo.name}}
-                  </a>
-                </td>
-                <td class="col-sm-3">{{servicesInfo.startTime}}</td>
-                <td class="col-sm-2">{{servicesInfo.duration}}</td>
-                <td class="col-sm-3">
-                  <div class="progress-wrapper col-sm-10">
-                    <div class="progress">
-                      <div {{bindAttr class="servicesInfo.isInProgress:active servicesInfo.isInProgress:progress-bar-striped servicesInfo.barColor :progress-bar" style="servicesInfo.barWidth"}}></div>
-                    </div>
-                  </div>
-                  <div class="col-sm-2">{{servicesInfo.progress}}%</div>
-                </td>
-                <td class="col-sm-1 text-right">
-                  {{#if servicesInfo.isAbortable}}
-                    {{view abortIcon servicesInfoBinding="servicesInfo"}}
-                  {{/if}}
-                  <a class="action" href="#">
-                    <span class="icon icon-caret-right"></span>
-                  </a>
-                </td>
-              </tr>
-            {{/each}}
-          </tbody>
+        </thead>
+      <tbody>
+        {{#if view.isServiceEmptyList}}
+        <tr>
+          <td colspan="5">
+            <div class="log-list-wrap">{{t hostPopup.noServicesToShow}}</div>
+          </td>
+        </tr>
+        {{else}}
+          {{#each servicesInfo in view.services}}
+          <tr {{action onOpClick servicesInfo}} {{bindAttr class="servicesInfo.isVisible::hidden :pointer"}}>
+            <td class="col-sm-3">
+              {{view statusIcon servicesInfoBinding="servicesInfo"}}
+              <a href="#">
+                {{servicesInfo.name}}
+              </a>
+            </td>
+            <td class="col-sm-3">
+              <div class="progress-wrapper col-sm-8">
+                <div class="progress">
+                  <div {{bindAttr class="servicesInfo.isInProgress:active servicesInfo.isInProgress:progress-bar-striped servicesInfo.barColor :progress-bar" style="servicesInfo.barWidth"}}></div>
+                </div>
+              </div>
+              <div class="progress-percentage col-sm-2">{{servicesInfo.progress}}%</div>
+            </td>
+            {{!-- Hardcoding this for now. Will change it once BE returns this value --}}
+            <td class="col-sm-2">Admin</td>
+            <td class="col-sm-3">{{servicesInfo.startTime}}</td>
+            <td class="col-sm-2">{{servicesInfo.duration}}</td>
+            <td class="col-sm-1 text-right">
+              {{#if servicesInfo.isAbortable}}
+                {{view abortIcon servicesInfoBinding="servicesInfo"}}
+              {{/if}}
+              <a class="action" href="#">
+                <span class="icon icon-caret-right"></span>
+              </a>
+            </td>
+          </tr>
+          {{/each}}
+        </tbody>
           {{#if view.isPaginate}}
             <tfoot>
             <tr>
@@ -93,58 +100,59 @@
             </tfoot>
           {{/if}}
         </table>
-      {{/if}}
-      {{#if view.isShowMore}}
-        <div class="show-more" {{action requestMoreOperations}}><a href="#">{{t hostPopup.serviceInfo.showMore}}</a>
-        </div>
-      {{/if}}
+        {{/if}}
+        {{#if view.isShowMore}}
+          <div class="show-more" {{action requestMoreOperations}}><a href="#">{{t hostPopup.serviceInfo.showMore}}</a>
+          </div>
+        {{/if}}
+      </div>
     </div>
-  </div>
 
 
-  {{!-- HOSTS ---}}
+    {{!-- HOSTS ---}}
 
-  <div {{bindAttr class="view.parentView.isHostListHidden:hidden :task-list-main-wrap :table-body-wrap"}}>
-    <div class="top-wrap">
-      <div class="row">
-        <h2 class="table-title col-sm-2">{{t common.hosts}}</h2>
-        <div class="table-controls col-sm-10">
-          <div class="btn-group pull-right status-dropdown">
-            <button type="button" class="btn btn-default dropdown-toggle" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
-              {{view.hostCategory.label}} <span class="caret"></span>
-            </button>
-            <ul class="dropdown-menu">
-              {{#each category in view.categories}}
-                <li><a href="#" {{action selectHostCategory category target="view"}}>{{category.label}}</a></li>
-              {{/each}}
-            </ul>
+    <div {{bindAttr class="view.parentView.isHostListHidden:hidden :task-list-main-wrap :table-body-wrap"}}>
+      <div class="top-wrap">
+        <div class="row">
+          <h2 class="table-title col-sm-2">{{t common.hosts}}</h2>
+          <div class="table-controls col-sm-10">
+            <div class="btn-group pull-right status-dropdown">
+              <button type="button" class="btn btn-default dropdown-toggle" data-toggle="dropdown" aria-haspopup="true"
+                      aria-expanded="false">
+                {{view.hostCategory.label}} <span class="caret"></span>
+              </button>
+              <ul class="dropdown-menu">
+                {{#each category in view.categories}}
+                  <li><a href="#" {{action selectHostCategory category target="view"}}>{{category.label}}</a></li>
+                {{/each}}
+              </ul>
+            </div>
           </div>
         </div>
       </div>
-    </div>
-    {{#if view.isRequestSchedule}}
-      {{#if view.sourceRequestScheduleRunning}}
-        <div class="alert alert-info request-schedule-abort">
-          {{t hostPopup.bgop.sourceRequestSchedule.running}}
-          <button type="button" class="btn btn-warning pull-right"
-            {{action doAbortRequestSchedule view.sourceRequestScheduleId target="view"}}>
-            {{view.requestScheduleAbortLabel}}
-          </button>
-        </div>
-      {{/if}}
-      {{#if view.sourceRequestScheduleAborted}}
-        <div class="alert alert-info request-schedule-abort">
-          {{t hostPopup.bgop.sourceRequestSchedule.aborted}}
-        </div>
+      {{#if view.isRequestSchedule}}
+        {{#if view.sourceRequestScheduleRunning}}
+          <div class="alert alert-info request-schedule-abort">
+            {{t hostPopup.bgop.sourceRequestSchedule.running}}
+            <button type="button" class="btn btn-warning pull-right"
+              {{action doAbortRequestSchedule view.sourceRequestScheduleId target="view"}}>
+              {{view.requestScheduleAbortLabel}}
+            </button>
+          </div>
+        {{/if}}
+        {{#if view.sourceRequestScheduleAborted}}
+          <div class="alert alert-info request-schedule-abort">
+            {{t hostPopup.bgop.sourceRequestSchedule.aborted}}
+          </div>
+        {{/if}}
       {{/if}}
-    {{/if}}
-    {{#if view.isLevelLoaded}}
-      <div id="host-info" {{bindAttr class="view.isRequestSchedule:scheduled"}}>
-        {{#if view.isHostEmptyList}}
-          <div class="log-list-wrap">{{t hostPopup.noHostsToShow}}</div>
-        {{else}}
-          <table class="table table-hover">
-            <tbody>
+      {{#if view.isLevelLoaded}}
+        <div id="host-info" {{bindAttr class="view.isRequestSchedule:scheduled"}}>
+          {{#if view.isHostEmptyList}}
+            <div class="log-list-wrap">{{t hostPopup.noHostsToShow}}</div>
+          {{else}}
+            <table class="table table-hover">
+              <tbody>
               {{#each hostInfo in view.pageContent}}
                 <tr {{action onHostClick hostInfo}} {{bindAttr class="hostInfo.isVisible::hidden :pointer"}}>
                   <td class="col-sm-6 text-nowrap">
@@ -159,7 +167,7 @@
                         <div {{bindAttr class="hostInfo.isInProgress:progress-bar-striped :active hostInfo.barColor :progress-bar" style="hostInfo.barWidth"}}></div>
                       </div>
                     </div>
-                    <div class="col-sm-2">{{hostInfo.progress}}%</div>
+                    <div class="progress-percentage col-sm-2">{{hostInfo.progress}}%</div>
                   </td>
                   <td class="col-sm-1 text-right">
                     <a class="action" href="#">
@@ -168,52 +176,53 @@
                   </td>
                 </tr>
               {{/each}}
-            </tbody>
-            {{#if view.isPaginate}}
-              <tfoot>
+              </tbody>
+              {{#if view.isPaginate}}
+                <tfoot>
                 <tr>
                   <td colspan="3">
                     {{view App.PaginationView}}
                   </td>
                 </tr>
-              </tfoot>
-            {{/if}}
-          </table>
-        {{/if}}
-      </div>
-    {{else}}
-      {{view App.SpinnerView}}
-    {{/if}}
-  </div>
+                </tfoot>
+              {{/if}}
+            </table>
+          {{/if}}
+        </div>
+      {{else}}
+        {{view App.SpinnerView}}
+      {{/if}}
+    </div>
 
 
-  {{!-- TASKS ---}}
+    {{!-- TASKS ---}}
 
-  <div {{bindAttr class="view.parentView.isTaskListHidden:hidden :task-list-main-wrap :table-body-wrap"}}>
-    <div class="top-wrap">
-      <div class="row">
-        <h2 class="table-title col-sm-2">{{t common.tasks}}</h2>
-        <div class="table-controls col-sm-10">
-          <div class="btn-group pull-right status-dropdown">
-            <button type="button" class="btn btn-default dropdown-toggle" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
-              {{view.taskCategory.label}} <span class="caret"></span>
-            </button>
-            <ul class="dropdown-menu">
-              {{#each category in view.categories}}
-                <li><a href="#" {{action selectTaskCategory category target="view"}}>{{category.label}}</a></li>
-              {{/each}}
-            </ul>
+    <div {{bindAttr class="view.parentView.isTaskListHidden:hidden :task-list-main-wrap :table-body-wrap"}}>
+      <div class="top-wrap">
+        <div class="row">
+          <h2 class="table-title col-sm-2">{{t common.tasks}}</h2>
+          <div class="table-controls col-sm-10">
+            <div class="btn-group pull-right status-dropdown">
+              <button type="button" class="btn btn-default dropdown-toggle" data-toggle="dropdown" aria-haspopup="true"
+                      aria-expanded="false">
+                {{view.taskCategory.label}} <span class="caret"></span>
+              </button>
+              <ul class="dropdown-menu">
+                {{#each category in view.categories}}
+                  <li><a href="#" {{action selectTaskCategory category target="view"}}>{{category.label}}</a></li>
+                {{/each}}
+              </ul>
+            </div>
           </div>
         </div>
       </div>
-    </div>
-    <div id="host-log">
-      {{#if view.hostInfoLoaded}}
-        {{#if view.isTasksEmptyList}}
-          <div class="log-list-wrap">{{t hostPopup.noTasksToShow}}</div>
-        {{else}}
-          <table class="table table-hover">
-            <tbody>
+      <div id="host-log">
+        {{#if view.hostInfoLoaded}}
+          {{#if view.isTasksEmptyList}}
+            <div class="log-list-wrap">{{t hostPopup.noTasksToShow}}</div>
+          {{else}}
+            <table class="table table-hover">
+              <tbody>
               {{#each taskInfo in view.tasks}}
                 <tr {{action onTaskClick taskInfo}} {{bindAttr class="taskInfo.isVisible::hidden :pointer"}}>
                   <td class="col-sm-3">
@@ -229,126 +238,129 @@
                   </td>
                 </tr>
               {{/each}}
-            </tbody>
-            {{#if view.isPaginate}}
-              <tfoot>
-              <tr>
-                <td colspan="2">
-                  {{view App.PaginationView}}
-                </td>
-              </tr>
-              </tfoot>
-            {{/if}}
-          </table>
+              </tbody>
+              {{#if view.isPaginate}}
+                <tfoot>
+                <tr>
+                  <td colspan="2">
+                    {{view App.PaginationView}}
+                  </td>
+                </tr>
+                </tfoot>
+              {{/if}}
+            </table>
+          {{/if}}
+        {{else}}
+          {{view App.SpinnerView}}
         {{/if}}
-      {{else}}
-        {{view App.SpinnerView}}
-      {{/if}}
+      </div>
     </div>
-  </div>
 
 
-  <!-- TASK DETAILS --->
+    <!-- TASK DETAILS --->
 
-  <div {{bindAttr class="view.parentView.isLogWrapHidden:hidden :task-detail-info view.hostComponentLogsExists:task-detail-info-tabbed"}}>
-    <div class="task-top-wrap top-wrap">
-      <div {{bindAttr class="view.hostComponentLogsExists:task-detail-log-nav-actions :row"}}>
-        <h2 class="table-title col-sm-5">{{t common.taskLog}}</h2>
-        <div class="table-controls col-sm-7 pull-right">
-          {{#if App.supports.logSearch}}
-            {{#if view.isLogSearchInstalled}}
-              {{#havePermissions "SERVICE.VIEW_OPERATIONAL_LOGS"}}
-                <button type="button" class="btn btn-link pull-right" {{action navigateToHostLogs target="view"}}
-                  {{bindAttr class="view.isLogsLinkVisible::hidden" disabled="App.router.wizardWatcherController.isNonWizardUser"}}>
-                  <i class="glyphicon glyphicon-file"></i>&nbsp;{{t common.host}} {{t common.logs}}
-                </button>
-              {{/havePermissions}}
+    <div {{bindAttr class="view.parentView.isLogWrapHidden:hidden :task-detail-info view.hostComponentLogsExists:task-detail-info-tabbed"}}>
+      <div class="task-top-wrap top-wrap">
+        <div {{bindAttr class="view.hostComponentLogsExists:task-detail-log-nav-actions :row"}}>
+          <h2 class="table-title col-sm-5">{{t common.taskLog}}</h2>
+          <div class="table-controls col-sm-7 pull-right">
+            {{#if App.supports.logSearch}}
+              {{#if view.isLogSearchInstalled}}
+                {{#havePermissions "SERVICE.VIEW_OPERATIONAL_LOGS"}}
+                  <button type="button" class="btn btn-link pull-right" {{action navigateToHostLogs target="view"}}
+                    {{bindAttr class="view.isLogsLinkVisible::hidden" disabled="App.router.wizardWatcherController.isNonWizardUser"}}>
+                    <i class="glyphicon glyphicon-file"></i>&nbsp;{{t common.host}} {{t common.logs}}
+                  </button>
+                {{/havePermissions}}
+              {{/if}}
             {{/if}}
-          {{/if}}
-          <button type="button" class="btn btn-link pull-right"
-            {{translateAttr title="common.openNewWindow"}}
-            {{action openTaskLogInDialog}}>
-            <i class="icon icon-external-link"></i>&nbsp;{{t common.open}}
-          </button>
-          <button type="button" class="btn btn-link pull-right copy-clipboard"
-            {{translateAttr title="common.fullLogPopup.clickToCopy"}}
-            {{action "textTrigger" taskInfo target="view"}}>
-            <i class="glyphicon glyphicon-copy"></i>&nbsp;{{t common.copy}}
-          </button>
+            <button type="button" class="btn btn-link pull-right"
+              {{translateAttr title="common.openNewWindow"}}
+              {{action openTaskLogInDialog}}>
+              <i class="icon icon-external-link"></i>&nbsp;{{t common.open}}
+            </button>
+            <button type="button" class="btn btn-link pull-right copy-clipboard"
+              {{translateAttr title="common.fullLogPopup.clickToCopy"}}
+              {{action "textTrigger" taskInfo target="view"}}>
+              <i class="glyphicon glyphicon-copy"></i>&nbsp;{{t common.copy}}
+            </button>
+          </div>
         </div>
-      </div>
-      <ul {{bindAttr class="view.hostComponentLogsExists::hide :nav :nav-tabs :task-detail-nav"}}>
-        <li {{bindAttr class="view.isLevelLoaded:active"}}>
-          <a href="#" data-target="#task-log-tab" data-toggle="tab" {{action setActiveTaskLogTab target="view"}}>{{t app.name}} stdout/stderr</a>
-        </li>
-        {{#each hostLog in view.hostComponentLogs}}
-          <li>
-            <a href="#" {{action setActiveLogTab hostLog target="view"}} {{bindAttr data-target="hostLog.tabClassNameSelector"}} data-toggle="tab">{{hostLog.displayedFileName}}</a>
+        <ul {{bindAttr class="view.hostComponentLogsExists::hide :nav :nav-tabs :task-detail-nav"}}>
+          <li {{bindAttr class="view.isLevelLoaded:active"}}>
+            <a href="#" data-target="#task-log-tab"
+               data-toggle="tab" {{action setActiveTaskLogTab target="view"}}>{{t app.name}} stdout/stderr</a>
           </li>
-        {{/each}}
-      </ul>
-    </div>
-    {{#if view.isLevelLoaded}}
-      <div class="task-detail-log-info">
-        <div class="content-area">
-          <div class="tab-content">
-            <div class="task-detail-log-clipboard-wrap">
-              {{#if view.isClipBoardActive}}
-                {{view App.NotScrollableTextArea class="task-detail-log-clipboard" valueBinding="view.textAreaValue"}}
-              {{/if}}
-            </div>
-            <div id="task-log-tab" class="tab-pane active">
-              <div {{bindAttr class=":task-detail-log-maintext view.isClipBoardActive:hidden"}}>
-                {{#if view.openedTask.isRebalanceHDFSTask }}
-                  <h5>{{t services.hdfs.rebalance.title}}</h5>
+          {{#each hostLog in view.hostComponentLogs}}
+            <li>
+              <a href="#" {{action setActiveLogTab hostLog target="view"}} {{bindAttr data-target="hostLog.tabClassNameSelector"}}
+                 data-toggle="tab">{{hostLog.displayedFileName}}</a>
+            </li>
+          {{/each}}
+        </ul>
+      </div>
+      {{#if view.isLevelLoaded}}
+        <div class="task-detail-log-info">
+          <div class="content-area">
+            <div class="tab-content">
+              <div class="task-detail-log-clipboard-wrap">
+                {{#if view.isClipBoardActive}}
+                  {{view App.NotScrollableTextArea class="task-detail-log-clipboard" valueBinding="view.textAreaValue"}}
+                {{/if}}
+              </div>
+              <div id="task-log-tab" class="tab-pane active">
+                <div {{bindAttr class=":task-detail-log-maintext view.isClipBoardActive:hidden"}}>
+                  {{#if view.openedTask.isRebalanceHDFSTask }}
+                    <h5>{{t services.hdfs.rebalance.title}}</h5>
 
-                  <div class="progresspopup-rebalancehdfs">
-                    <div class="progress-bar">
-                      <div {{bindAttr class=":progress view.openedTask.isInProgress:progress-bar-striped view.openedTask.barColor :active" style="view.openedTask.completionProgressStyle"}}></div>
+                    <div class="progresspopup-rebalancehdfs">
+                      <div class="progress-bar">
+                        <div {{bindAttr class=":progress view.openedTask.isInProgress:progress-bar-striped view.openedTask.barColor :active" style="view.openedTask.completionProgressStyle"}}></div>
+                      </div>
                     </div>
-                  </div>
-                  <div class="clearfix">
-                    <div class="pull-left">
-                      {{view.openedTask.dataMoved}} moved /
-                      {{view.openedTask.dataLeft}} left /
-                      {{view.openedTask.dataBeingMoved}} being processed
+                    <div class="clearfix">
+                      <div class="pull-left">
+                        {{view.openedTask.dataMoved}} moved /
+                        {{view.openedTask.dataLeft}} left /
+                        {{view.openedTask.dataBeingMoved}} being processed
+                      </div>
+                      {{#if view.openedTask.isNotComplete}}
+                        <button class="btn btn-danger pull-right" {{action stopRebalanceHDFS}}>{{t common.cancel}}</button>
+                      {{/if}}
                     </div>
-                    {{#if view.openedTask.isNotComplete}}
-                      <button class="btn btn-danger pull-right" {{action stopRebalanceHDFS}}>{{t common.cancel}}</button>
-                    {{/if}}
-                  </div>
-                  <hr>
-                {{/if}}
-                <p>{{t common.stderr}}: &nbsp; <span class="muted">{{view.openedTask.errorLog}} </span></p>
-                <pre class="stderr">{{view.openedTask.stderr}}</pre>
-                <p>{{t common.stdout}}: &nbsp; <span class="muted"> {{view.openedTask.outputLog}} </span></p>
-                <pre class="stdout">{{view.openedTask.stdout}}</pre>
-              </div>
-            </div>
-            {{#each hostLog in view.hostComponentLogs}}
-              <div {{bindAttr class=":tab-pane :log-component-tab hostLog.tabClassName"}}>
-                <p {{bindAttr class="view.isClipBoardActive:hidden"}}>
-                  <strong>{{t common.file}}: &nbsp; </strong>
-                  <strong class="muted">{{hostLog.fileName}}</strong>
-                  {{#view App.LogSearchUILinkView linkQueryParamsBinding="hostLog.linkTail" tagName="span"}}
-                    <a {{bindAttr href="view.formatedLink" class=":pull-right view.isLodaded::disabled"}} target="_blank">
-                      <i class="icon-external-link"></i>
-                      {{t popup.logTail.openInLogSearch}}</a>
-                  {{/view}}
-                </p>
-                <div {{bindAttr class="view.isClipBoardActive:hidden"}}>
-                  {{view view.logTailView contentBinding="hostLog"}}
+                    <hr>
+                  {{/if}}
+                  <p>{{t common.stderr}}: &nbsp; <span class="muted">{{view.openedTask.errorLog}} </span></p>
+                  <pre class="stderr">{{view.openedTask.stderr}}</pre>
+                  <p>{{t common.stdout}}: &nbsp; <span class="muted"> {{view.openedTask.outputLog}} </span></p>
+                  <pre class="stdout">{{view.openedTask.stdout}}</pre>
                 </div>
               </div>
-            {{/each}}
+              {{#each hostLog in view.hostComponentLogs}}
+                <div {{bindAttr class=":tab-pane :log-component-tab hostLog.tabClassName"}}>
+                  <p {{bindAttr class="view.isClipBoardActive:hidden"}}>
+                    <strong>{{t common.file}}: &nbsp; </strong>
+                    <strong class="muted">{{hostLog.fileName}}</strong>
+                    {{#view App.LogSearchUILinkView linkQueryParamsBinding="hostLog.linkTail" tagName="span"}}
+                      <a {{bindAttr href="view.formatedLink" class=":pull-right view.isLodaded::disabled"}}
+                              target="_blank">
+                        <i class="icon-external-link"></i>
+                        {{t popup.logTail.openInLogSearch}}</a>
+                    {{/view}}
+                  </p>
+                  <div {{bindAttr class="view.isClipBoardActive:hidden"}}>
+                    {{view view.logTailView contentBinding="hostLog"}}
+                  </div>
+                </div>
+              {{/each}}
+            </div>
           </div>
         </div>
-      </div>
-    {{else}}
-      {{view App.SpinnerView}}
-    {{/if}}
-  </div>
-{{else}}
-  {{view App.SpinnerView}}
-{{/if}}
+      {{else}}
+        {{view App.SpinnerView}}
+      {{/if}}
+    </div>
+  {{else}}
+    {{view App.SpinnerView}}
+  {{/if}}
 </div>

+ 2 - 2
contrib/ambari-scom/ambari-scom-server/src/main/resources/META-INF/spring-security.xml

@@ -20,7 +20,7 @@
              xsi:schemaLocation="http://www.springframework.org/schema/beans
                     http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
                     http://www.springframework.org/schema/security
-                    http://www.springframework.org/schema/security/spring-security-3.1.xsd">
+                    http://www.springframework.org/schema/security/spring-security-3.2.xsd">
 
     <http use-expressions="true"
           disable-url-rewriting="true" entry-point-ref="ambariEntryPoint">
@@ -43,4 +43,4 @@
 
     <beans:bean id="ambariEntryPoint" class="org.apache.ambari.server.security.AmbariEntryPoint">
     </beans:bean>
-</beans:beans>
+</beans:beans>