ambari-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From alejan...@apache.org
Subject ambari git commit: AMBARI-12150. RU - Pre Reqs incorrectly reports that services are down (alejandro)
Date Sat, 27 Jun 2015 03:27:55 GMT
Repository: ambari
Updated Branches:
  refs/heads/branch-2.1 aa283e6a9 -> 0aeb37719


AMBARI-12150. RU - Pre Reqs incorrectly reports that services are down (alejandro)


Project: http://git-wip-us.apache.org/repos/asf/ambari/repo
Commit: http://git-wip-us.apache.org/repos/asf/ambari/commit/0aeb3771
Tree: http://git-wip-us.apache.org/repos/asf/ambari/tree/0aeb3771
Diff: http://git-wip-us.apache.org/repos/asf/ambari/diff/0aeb3771

Branch: refs/heads/branch-2.1
Commit: 0aeb377195ac372d2baa38f0622747741b79965d
Parents: aa283e6
Author: Alejandro Fernandez <afernandez@hortonworks.com>
Authored: Fri Jun 26 20:27:32 2015 -0700
Committer: Alejandro Fernandez <afernandez@hortonworks.com>
Committed: Fri Jun 26 20:27:32 2015 -0700

----------------------------------------------------------------------
 ambari-server/pom.xml                           |  15 +-
 .../ambari/server/checks/CheckDescription.java  |   2 +-
 .../ambari/server/checks/ServicesUpCheck.java   |  58 +++++++-
 .../orm/dao/HostComponentDesiredStateDAO.java   |  24 ++-
 .../server/orm/dao/HostComponentStateDAO.java   |  48 ++++++
 .../HostComponentDesiredStateEntity.java        |  17 +++
 .../orm/entities/HostComponentStateEntity.java  |  10 ++
 .../server/orm/models/HostComponentSummary.java | 104 +++++++++++++
 .../ambari/server/state/ServiceComponent.java   |   2 +
 .../server/state/ServiceComponentImpl.java      |   9 ++
 .../stacks/HDP/2.3/upgrades/upgrade-2.3.xml     |   2 +-
 .../server/checks/ServicesUpCheckTest.java      | 147 ++++++++++++++++++-
 12 files changed, 416 insertions(+), 22 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/ambari/blob/0aeb3771/ambari-server/pom.xml
----------------------------------------------------------------------
diff --git a/ambari-server/pom.xml b/ambari-server/pom.xml
index 7a8ff09..4790ff4 100644
--- a/ambari-server/pom.xml
+++ b/ambari-server/pom.xml
@@ -40,6 +40,7 @@
     <ambari-web-dir>${basedir}/../ambari-web/public</ambari-web-dir>
     <ambari-admin-dir>${basedir}/../ambari-admin</ambari-admin-dir>
     <contrib-views-dir>${basedir}/../contrib/views</contrib-views-dir>
+    <powermock.version>1.5</powermock.version>
   </properties>
   <build>
     <plugins>
@@ -1727,25 +1728,31 @@
     <dependency>
       <groupId>org.powermock</groupId>
       <artifactId>powermock-core</artifactId>
-      <version>1.5</version>
+      <version>${powermock.version}</version>
       <scope>test</scope>
     </dependency>
     <dependency>
       <groupId>org.powermock</groupId>
       <artifactId>powermock-reflect</artifactId>
-      <version>1.5</version>
+      <version>${powermock.version}</version>
       <scope>test</scope>
     </dependency>
     <dependency>
       <groupId>org.powermock</groupId>
       <artifactId>powermock-api-easymock</artifactId>
-      <version>1.5</version>
+      <version>${powermock.version}</version>
       <scope>test</scope>
     </dependency>
     <dependency>
       <groupId>org.powermock</groupId>
       <artifactId>powermock-module-junit4</artifactId>
-      <version>1.5</version>
+      <version>${powermock.version}</version>
+      <scope>test</scope>
+    </dependency>
+    <dependency>
+      <groupId>org.powermock</groupId>
+      <artifactId>powermock-api-mockito</artifactId>
+      <version>1.4.9</version>
       <scope>test</scope>
     </dependency>
     <dependency>

http://git-wip-us.apache.org/repos/asf/ambari/blob/0aeb3771/ambari-server/src/main/java/org/apache/ambari/server/checks/CheckDescription.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/checks/CheckDescription.java
b/ambari-server/src/main/java/org/apache/ambari/server/checks/CheckDescription.java
index 23a575a..5e029f4 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/checks/CheckDescription.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/checks/CheckDescription.java
@@ -130,7 +130,7 @@ public enum CheckDescription {
       "All services must be started",
       new HashMap<String, String>() {{
         put(AbstractCheckDescriptor.DEFAULT,
-          "The following Services must be started: {{fails}}");
+          "The following Services must be started: {{fails}}. Try to do a Stop & Start
in case they were started outside of Ambari.");
       }}),
 
   SERVICES_YARN_WP(PrereqCheckType.SERVICE,

http://git-wip-us.apache.org/repos/asf/ambari/blob/0aeb3771/ambari-server/src/main/java/org/apache/ambari/server/checks/ServicesUpCheck.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/checks/ServicesUpCheck.java
b/ambari-server/src/main/java/org/apache/ambari/server/checks/ServicesUpCheck.java
index 243b26d..00c798b 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/checks/ServicesUpCheck.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/checks/ServicesUpCheck.java
@@ -17,17 +17,27 @@
  */
 package org.apache.ambari.server.checks;
 
+import java.text.MessageFormat;
+import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.List;
 import java.util.Map;
+import java.util.Set;
 
+import com.google.inject.Inject;
 import org.apache.ambari.server.AmbariException;
 import org.apache.ambari.server.controller.PrereqCheckRequest;
+import org.apache.ambari.server.orm.dao.HostDAO;
+import org.apache.ambari.server.orm.models.HostComponentSummary;
 import org.apache.ambari.server.state.Cluster;
 import org.apache.ambari.server.state.Service;
+import org.apache.ambari.server.state.ServiceComponent;
 import org.apache.ambari.server.state.State;
 import org.apache.ambari.server.state.stack.PrereqCheckStatus;
 import org.apache.ambari.server.state.stack.PrerequisiteCheck;
 
 import com.google.inject.Singleton;
+import org.apache.commons.lang.StringUtils;
 
 /**
  * Checks that services are up.
@@ -45,21 +55,57 @@ public class ServicesUpCheck extends AbstractCheckDescriptor {
 
   @Override
   public void perform(PrerequisiteCheck prerequisiteCheck, PrereqCheckRequest request) throws
AmbariException {
-
     final String clusterName = request.getClusterName();
     final Cluster cluster = clustersProvider.get().getCluster(clusterName);
-    for (Map.Entry<String, Service> serviceEntry : cluster.getServices().entrySet())
{
+    List<String> errorMessages = new ArrayList<String>();
+    Set<String> failedServiceNames = new HashSet<String>();
 
+    for (Map.Entry<String, Service> serviceEntry : cluster.getServices().entrySet())
{
       final Service service = serviceEntry.getValue();
 
-      if (!service.isClientOnlyService() && service.getDesiredState() != State.STARTED)
{
-        prerequisiteCheck.getFailedOn().add(service.getName());
+      // Ignore services like Tez that are clientOnly.
+      if (!service.isClientOnlyService()) {
+        Map<String, ServiceComponent> serviceComponents = service.getServiceComponents();
+
+        for (Map.Entry<String, ServiceComponent> component : serviceComponents.entrySet())
{
+
+          boolean ignoreComponent = false;
+
+          ServiceComponent serviceComponent = component.getValue();
+          // In Services like HDFS, ignore components like HDFS Client
+          if (serviceComponent.isClientComponent()) {
+            ignoreComponent = true;
+          }
+
+          if (!serviceComponent.isVersionAdvertised()) {
+            ignoreComponent = true;
+          }
+
+          // TODO, add more logic that checks the Upgrade Pack.
+          // These components are not in the upgrade pack and do not advertise a version:
+          // ZKFC, Ambari Metrics, Kerberos, Atlas (right now).
+          // Generally, if it advertises a version => in the upgrade pack.
+          // So it can be in the Upgrade Pack but not advertise a version.
+          if (!ignoreComponent) {
+            List<HostComponentSummary> hostComponentSummaries = HostComponentSummary.getHostComponentSummaries(service.getName(),
serviceComponent.getName());
+
+            for(HostComponentSummary s : hostComponentSummaries) {
+              if ((s.getDesiredState() == State.INSTALLED || s.getDesiredState() == State.STARTED)
&& State.STARTED != s.getCurrentState()) {
+                failedServiceNames.add(service.getName());
+                String message = MessageFormat.format("{0} - {1} (in {2} on host {3})", service.getName(),
serviceComponent.getName(), s.getCurrentState(), s.getHostName());
+                errorMessages.add(message);
+                continue;
+              }
+            }
+          }
+        }
       }
     }
 
-    if (!prerequisiteCheck.getFailedOn().isEmpty()) {
+    if (!errorMessages.isEmpty()) {
+      prerequisiteCheck.setFailedOn(new ArrayList<String>(failedServiceNames));
       prerequisiteCheck.setStatus(PrereqCheckStatus.FAIL);
-      prerequisiteCheck.setFailReason(getFailReason(prerequisiteCheck, request));
+      prerequisiteCheck.setFailReason("The following Service Components should be in a started
state.  Please invoke a service Stop and full Start and try again. " + StringUtils.join(errorMessages,
", "));
     }
   }
 }
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/ambari/blob/0aeb3771/ambari-server/src/main/java/org/apache/ambari/server/orm/dao/HostComponentDesiredStateDAO.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/orm/dao/HostComponentDesiredStateDAO.java
b/ambari-server/src/main/java/org/apache/ambari/server/orm/dao/HostComponentDesiredStateDAO.java
index 2d699b7..2620c8c 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/orm/dao/HostComponentDesiredStateDAO.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/orm/dao/HostComponentDesiredStateDAO.java
@@ -40,6 +40,9 @@ public class HostComponentDesiredStateDAO {
   @Inject
   HostDAO hostDAO;
 
+  @Inject
+  DaoUtils daoUtils;
+
   @RequiresSession
   public HostComponentDesiredStateEntity findByPK(HostComponentDesiredStateEntityPK primaryKey)
{
     return entityManagerProvider.get().find(HostComponentDesiredStateEntity.class, primaryKey);
@@ -47,8 +50,7 @@ public class HostComponentDesiredStateDAO {
 
   @RequiresSession
   public List<HostComponentDesiredStateEntity> findAll() {
-    TypedQuery<HostComponentDesiredStateEntity> query = entityManagerProvider.get()
-      .createQuery("SELECT hcd from HostComponentDesiredStateEntity hcd", HostComponentDesiredStateEntity.class);
+    final TypedQuery<HostComponentDesiredStateEntity> query = entityManagerProvider.get().createNamedQuery("HostComponentDesiredStateEntity.findAll",
HostComponentDesiredStateEntity.class);
     try {
       return query.getResultList();
     } catch (NoResultException ignored) {
@@ -56,6 +58,24 @@ public class HostComponentDesiredStateDAO {
     return null;
   }
 
+  /**
+   * Retrieve the single Host Component Desired State for the given unique service, component,
and host.
+   *
+   * @param serviceName Service Name
+   * @param componentName Component Name
+   * @param hostName Host Name
+   * @return Return all of the Host Component States that match the criteria.
+   */
+  @RequiresSession
+  public HostComponentDesiredStateEntity findByServiceComponentAndHost(String serviceName,
String componentName, String hostName) {
+    final TypedQuery<HostComponentDesiredStateEntity> query = entityManagerProvider.get().createNamedQuery("HostComponentDesiredStateEntity.findByServiceComponentAndHost",
HostComponentDesiredStateEntity.class);
+    query.setParameter("serviceName", serviceName);
+    query.setParameter("componentName", componentName);
+    query.setParameter("hostName", hostName);
+
+    return daoUtils.selectSingle(query);
+  }
+
   @Transactional
   public void refresh(HostComponentDesiredStateEntity hostComponentDesiredStateEntity) {
     entityManagerProvider.get().refresh(hostComponentDesiredStateEntity);

http://git-wip-us.apache.org/repos/asf/ambari/blob/0aeb3771/ambari-server/src/main/java/org/apache/ambari/server/orm/dao/HostComponentStateDAO.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/orm/dao/HostComponentStateDAO.java
b/ambari-server/src/main/java/org/apache/ambari/server/orm/dao/HostComponentStateDAO.java
index e7b5c10..00ffd5a 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/orm/dao/HostComponentStateDAO.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/orm/dao/HostComponentStateDAO.java
@@ -71,6 +71,54 @@ public class HostComponentStateDAO {
     return daoUtils.selectList(query);
   }
 
+  /**
+   * Retrieve all of the Host Component States for the given service.
+   *
+   * @param serviceName Service Name
+   * @return Return all of the Host Component States that match the criteria.
+   */
+  @RequiresSession
+  public List<HostComponentStateEntity> findByService(String serviceName) {
+    final TypedQuery<HostComponentStateEntity> query = entityManagerProvider.get().createNamedQuery("HostComponentStateEntity.findByService",
HostComponentStateEntity.class);
+    query.setParameter("serviceName", serviceName);
+
+    return daoUtils.selectList(query);
+  }
+
+  /**
+   * Retrieve all of the Host Component States for the given service and component.
+   *
+   * @param serviceName Service Name
+   * @param componentName Component Name
+   * @return Return all of the Host Component States that match the criteria.
+   */
+  @RequiresSession
+  public List<HostComponentStateEntity> findByServiceAndComponent(String serviceName,
String componentName) {
+    final TypedQuery<HostComponentStateEntity> query = entityManagerProvider.get().createNamedQuery("HostComponentStateEntity.findByServiceAndComponent",
HostComponentStateEntity.class);
+    query.setParameter("serviceName", serviceName);
+    query.setParameter("componentName", componentName);
+
+    return daoUtils.selectList(query);
+  }
+
+  /**
+   * Retrieve the single Host Component State for the given unique service, component, and
host.
+   *
+   * @param serviceName Service Name
+   * @param componentName Component Name
+   * @param hostName Host Name
+   * @return Return all of the Host Component States that match the criteria.
+   */
+  @RequiresSession
+  public HostComponentStateEntity findByServiceComponentAndHost(String serviceName, String
componentName, String hostName) {
+    final TypedQuery<HostComponentStateEntity> query = entityManagerProvider.get().createNamedQuery("HostComponentStateEntity.findByServiceComponentAndHost",
HostComponentStateEntity.class);
+    query.setParameter("serviceName", serviceName);
+    query.setParameter("componentName", componentName);
+    query.setParameter("hostName", hostName);
+
+    return daoUtils.selectSingle(query);
+  }
+
   @Transactional
   public void refresh(HostComponentStateEntity hostComponentStateEntity) {
     entityManagerProvider.get().refresh(hostComponentStateEntity);

http://git-wip-us.apache.org/repos/asf/ambari/blob/0aeb3771/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/HostComponentDesiredStateEntity.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/HostComponentDesiredStateEntity.java
b/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/HostComponentDesiredStateEntity.java
index 570c84b..101aea1 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/HostComponentDesiredStateEntity.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/HostComponentDesiredStateEntity.java
@@ -29,6 +29,8 @@ import javax.persistence.Id;
 import javax.persistence.JoinColumn;
 import javax.persistence.JoinColumns;
 import javax.persistence.ManyToOne;
+import javax.persistence.NamedQueries;
+import javax.persistence.NamedQuery;
 import javax.persistence.OneToOne;
 
 import org.apache.ambari.server.state.HostComponentAdminState;
@@ -39,6 +41,21 @@ import org.apache.ambari.server.state.State;
 @javax.persistence.IdClass(HostComponentDesiredStateEntityPK.class)
 @javax.persistence.Table(name = "hostcomponentdesiredstate")
 @Entity
+@NamedQueries({
+    @NamedQuery(name = "HostComponentDesiredStateEntity.findAll", query = "SELECT hcds from
HostComponentDesiredStateEntity hcds"),
+
+    @NamedQuery(name = "HostComponentDesiredStateEntity.findByHost", query =
+        "SELECT hcds from HostComponentDesiredStateEntity hcds WHERE hcds.hostEntity.hostName=:hostName"),
+
+    @NamedQuery(name = "HostComponentDesiredStateEntity.findByService", query =
+        "SELECT hcds from HostComponentDesiredStateEntity hcds WHERE hcds.serviceName=:serviceName"),
+
+    @NamedQuery(name = "HostComponentDesiredStateEntity.findByServiceAndComponent", query
=
+        "SELECT hcds from HostComponentDesiredStateEntity hcds WHERE hcds.serviceName=:serviceName
AND hcds.componentName=:componentName"),
+
+    @NamedQuery(name = "HostComponentDesiredStateEntity.findByServiceComponentAndHost", query
=
+        "SELECT hcds from HostComponentDesiredStateEntity hcds WHERE hcds.serviceName=:serviceName
AND hcds.componentName=:componentName AND hcds.hostEntity.hostName=:hostName"),
+})
 public class HostComponentDesiredStateEntity {
 
   @Id

http://git-wip-us.apache.org/repos/asf/ambari/blob/0aeb3771/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/HostComponentStateEntity.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/HostComponentStateEntity.java
b/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/HostComponentStateEntity.java
index dabe98b..45e036b 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/HostComponentStateEntity.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/HostComponentStateEntity.java
@@ -42,8 +42,18 @@ import org.apache.ambari.server.state.UpgradeState;
 @Entity
 @NamedQueries({
     @NamedQuery(name = "HostComponentStateEntity.findAll", query = "SELECT hcs from HostComponentStateEntity
hcs"),
+
     @NamedQuery(name = "HostComponentStateEntity.findByHost", query =
         "SELECT hcs from HostComponentStateEntity hcs WHERE hcs.hostEntity.hostName=:hostName"),
+
+    @NamedQuery(name = "HostComponentStateEntity.findByService", query =
+        "SELECT hcs from HostComponentStateEntity hcs WHERE hcs.serviceName=:serviceName"),
+
+    @NamedQuery(name = "HostComponentStateEntity.findByServiceAndComponent", query =
+        "SELECT hcs from HostComponentStateEntity hcs WHERE hcs.serviceName=:serviceName
AND hcs.componentName=:componentName"),
+
+    @NamedQuery(name = "HostComponentStateEntity.findByServiceComponentAndHost", query =
+        "SELECT hcs from HostComponentStateEntity hcs WHERE hcs.serviceName=:serviceName
AND hcs.componentName=:componentName AND hcs.hostEntity.hostName=:hostName"),
 })
 public class HostComponentStateEntity {
 

http://git-wip-us.apache.org/repos/asf/ambari/blob/0aeb3771/ambari-server/src/main/java/org/apache/ambari/server/orm/models/HostComponentSummary.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/orm/models/HostComponentSummary.java
b/ambari-server/src/main/java/org/apache/ambari/server/orm/models/HostComponentSummary.java
new file mode 100644
index 0000000..c79ec8a
--- /dev/null
+++ b/ambari-server/src/main/java/org/apache/ambari/server/orm/models/HostComponentSummary.java
@@ -0,0 +1,104 @@
+/**
+ * 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.orm.models;
+
+import com.google.inject.Inject;
+import org.apache.ambari.server.StaticallyInject;
+import org.apache.ambari.server.orm.dao.HostComponentDesiredStateDAO;
+import org.apache.ambari.server.orm.dao.HostComponentStateDAO;
+import org.apache.ambari.server.orm.dao.HostDAO;
+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 java.util.ArrayList;
+import java.util.List;
+
+@StaticallyInject
+public class HostComponentSummary {
+  private String serviceName;
+  private String componentName;
+  private Long hostId;
+  private String hostName;
+  private State desiredState;
+  private State currentState;
+
+  @Inject
+  private static HostDAO hostDao;
+
+  @Inject
+  private static HostComponentStateDAO hostComponentStateDao;
+
+  @Inject
+  private static HostComponentDesiredStateDAO hostComponentDesiredStateDao;
+
+  public HostComponentSummary(String serviceName, String componentName, Long hostId, State
desiredState, State currentState) {
+    this.serviceName = serviceName;
+    this.componentName = componentName;
+    this.hostId = hostId;
+
+    HostEntity host = hostDao.findById(hostId);
+    if (host != null) {
+      this.hostName = host.getHostName();
+    }
+
+    this.desiredState = desiredState;
+    this.currentState = currentState;
+  }
+
+  public String getHostName() {
+    return (this.hostName == null || this.hostName.isEmpty()) ? "" : this.hostName;
+  }
+
+  public State getDesiredState() {
+    return desiredState;
+  }
+
+  public State getCurrentState() {
+    return currentState;
+  }
+
+  public static List<HostComponentSummary> getHostComponentSummaries(String serviceName,
String componentName) {
+    List<HostComponentSummary> hostComponentSummaries = new ArrayList<HostComponentSummary>();
+    List<HostComponentStateEntity> hostComponentStates = hostComponentStateDao.findByServiceAndComponent(serviceName,
componentName);
+
+    if (hostComponentStates != null) {
+      for (HostComponentStateEntity hcse : hostComponentStates) {
+        // Find the corresponding record for HostComponentDesiredStateEntity
+        HostComponentDesiredStateEntity hcdse = hostComponentDesiredStateDao.findByServiceComponentAndHost(hcse.getServiceName(),
hcse.getComponentName(), hcse.getHostName());
+        if (hcdse != null) {
+          HostComponentSummary s = new HostComponentSummary(hcse.getServiceName(), hcse.getComponentName(),
hcse.getHostId(), hcdse.getDesiredState(), hcse.getCurrentState());
+
+          hostComponentSummaries.add(s);
+        }
+      }
+    }
+    return hostComponentSummaries;
+  }
+
+  @Override
+  public int hashCode() {
+    int result = 1;
+    result = 31 + (serviceName != null ? serviceName.hashCode() : 0);
+    result = result + (componentName != null ? componentName.hashCode() : 0);
+    result = result + (hostId != null ? hostId.hashCode() : 0);
+    return result;
+  }
+}

http://git-wip-us.apache.org/repos/asf/ambari/blob/0aeb3771/ambari-server/src/main/java/org/apache/ambari/server/state/ServiceComponent.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/state/ServiceComponent.java
b/ambari-server/src/main/java/org/apache/ambari/server/state/ServiceComponent.java
index 65c37f4..60a16eb 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/state/ServiceComponent.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/state/ServiceComponent.java
@@ -70,6 +70,8 @@ public interface ServiceComponent {
 
   public boolean isMasterComponent();
 
+  public boolean isVersionAdvertised();
+
   public boolean canBeRemoved();
 
   public void deleteAllServiceComponentHosts() throws AmbariException;

http://git-wip-us.apache.org/repos/asf/ambari/blob/0aeb3771/ambari-server/src/main/java/org/apache/ambari/server/state/ServiceComponentImpl.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/state/ServiceComponentImpl.java
b/ambari-server/src/main/java/org/apache/ambari/server/state/ServiceComponentImpl.java
index 560cd04..aa147de 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/state/ServiceComponentImpl.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/state/ServiceComponentImpl.java
@@ -61,6 +61,7 @@ public class ServiceComponentImpl implements ServiceComponent {
   private final ReadWriteLock readWriteLock = new ReentrantReadWriteLock();
   private final boolean isClientComponent;
   private final boolean isMasterComponent;
+  private final boolean isVersionAdvertised;
   volatile boolean persisted = false;
   @Inject
   private ServiceComponentDesiredStateDAO serviceComponentDesiredStateDAO;
@@ -101,6 +102,7 @@ public class ServiceComponentImpl implements ServiceComponent {
           stackId.getStackVersion(), service.getName(), componentName);
       isClientComponent = compInfo.isClient();
       isMasterComponent = compInfo.isMaster();
+      isVersionAdvertised = compInfo.isVersionAdvertised();
     } catch (ObjectNotFoundException e) {
       throw new RuntimeException("Trying to create a ServiceComponent"
           + " not recognized in stack info"
@@ -149,6 +151,7 @@ public class ServiceComponentImpl implements ServiceComponent {
           getName());
       isClientComponent = compInfo.isClient();
       isMasterComponent = compInfo.isMaster();
+      isVersionAdvertised = compInfo.isVersionAdvertised();
     } catch (ObjectNotFoundException e) {
       throw new AmbariException("Trying to create a ServiceComponent"
           + " not recognized in stack info"
@@ -532,6 +535,12 @@ public class ServiceComponentImpl implements ServiceComponent {
     return isMasterComponent;
   }
 
+
+  @Override
+  public boolean isVersionAdvertised() {
+    return isVersionAdvertised;
+  }
+
   @Override
   public boolean canBeRemoved() {
     clusterGlobalLock.readLock().lock();

http://git-wip-us.apache.org/repos/asf/ambari/blob/0aeb3771/ambari-server/src/main/resources/stacks/HDP/2.3/upgrades/upgrade-2.3.xml
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/resources/stacks/HDP/2.3/upgrades/upgrade-2.3.xml b/ambari-server/src/main/resources/stacks/HDP/2.3/upgrades/upgrade-2.3.xml
index 1884f2e..3762422 100644
--- a/ambari-server/src/main/resources/stacks/HDP/2.3/upgrades/upgrade-2.3.xml
+++ b/ambari-server/src/main/resources/stacks/HDP/2.3/upgrades/upgrade-2.3.xml
@@ -67,7 +67,7 @@
       </execute-stage>
 
       <execute-stage service="TEZ" component="TEZ_CLIENT" title="Check Tez Tarball">
-        <task xsi:type="execute" hosts="any"> <!-- hosts="any" -->
+        <task xsi:type="execute" hosts="any">
           <script>scripts/pre_upgrade.py</script>
           <function>prepare</function>
         </task>

http://git-wip-us.apache.org/repos/asf/ambari/blob/0aeb3771/ambari-server/src/test/java/org/apache/ambari/server/checks/ServicesUpCheckTest.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/test/java/org/apache/ambari/server/checks/ServicesUpCheckTest.java
b/ambari-server/src/test/java/org/apache/ambari/server/checks/ServicesUpCheckTest.java
index c59ded4..87cb8a9 100644
--- a/ambari-server/src/test/java/org/apache/ambari/server/checks/ServicesUpCheckTest.java
+++ b/ambari-server/src/test/java/org/apache/ambari/server/checks/ServicesUpCheckTest.java
@@ -17,27 +17,38 @@
  */
 package org.apache.ambari.server.checks;
 
-import java.util.Collections;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
 
+import com.google.inject.Provider;
 import org.apache.ambari.server.api.services.AmbariMetaInfo;
 import org.apache.ambari.server.controller.PrereqCheckRequest;
+import org.apache.ambari.server.orm.models.HostComponentSummary;
 import org.apache.ambari.server.state.Cluster;
 import org.apache.ambari.server.state.Clusters;
 import org.apache.ambari.server.state.Service;
+import org.apache.ambari.server.state.ServiceComponent;
 import org.apache.ambari.server.state.StackId;
 import org.apache.ambari.server.state.State;
 import org.apache.ambari.server.state.stack.PrereqCheckStatus;
 import org.apache.ambari.server.state.stack.PrerequisiteCheck;
 import org.junit.Assert;
 import org.junit.Test;
+import org.junit.runner.RunWith;
 import org.mockito.Mockito;
+import org.powermock.api.mockito.PowerMockito;
+import org.powermock.core.classloader.annotations.PrepareForTest;
+import org.powermock.modules.junit4.PowerMockRunner;
 
-import com.google.inject.Provider;
 
 /**
  * Unit tests for ServicesUpCheck
  *
  */
+@RunWith(PowerMockRunner.class)               // Allow mocking static methods
+@PrepareForTest(HostComponentSummary.class)   // This class has a static method that will
be mocked
 public class ServicesUpCheckTest {
   private final Clusters clusters = Mockito.mock(Clusters.class);
 
@@ -53,6 +64,8 @@ public class ServicesUpCheckTest {
 
   @Test
   public void testPerform() throws Exception {
+    PowerMockito.mockStatic(HostComponentSummary.class);
+
     final ServicesUpCheck servicesUpCheck = new ServicesUpCheck();
     servicesUpCheck.clustersProvider = new Provider<Clusters>() {
 
@@ -74,18 +87,136 @@ public class ServicesUpCheckTest {
     Mockito.when(cluster.getClusterId()).thenReturn(1L);
     Mockito.when(cluster.getCurrentStackVersion()).thenReturn(new StackId("HDP", "2.2"));
     Mockito.when(clusters.getCluster("cluster")).thenReturn(cluster);
-    final Service service = Mockito.mock(Service.class);
-    Mockito.when(cluster.getServices()).thenReturn(Collections.singletonMap("service", service));
-    Mockito.when(service.isClientOnlyService()).thenReturn(false);
-    Mockito.when(service.getDesiredState()).thenReturn(State.UNKNOWN);
 
+    final Service hdfsService = Mockito.mock(Service.class);
+    final Service tezService = Mockito.mock(Service.class);
+    final Service amsService = Mockito.mock(Service.class);
+
+    HashMap<String, Service> clusterServices = new HashMap<String, Service>();
+    clusterServices.put("HDFS", hdfsService);
+    clusterServices.put("TEZ", tezService);
+    clusterServices.put("AMBARI_METRICS", amsService);
+
+    Mockito.when(hdfsService.getName()).thenReturn("HDFS");
+    Mockito.when(tezService.getName()).thenReturn("TEZ");
+    Mockito.when(amsService.getName()).thenReturn("AMBARI_METRICS");
+
+    Mockito.when(hdfsService.isClientOnlyService()).thenReturn(false);
+    Mockito.when(tezService.isClientOnlyService()).thenReturn(true);
+    Mockito.when(amsService.isClientOnlyService()).thenReturn(false);
+
+    Mockito.when(cluster.getServices()).thenReturn(clusterServices);
+
+
+    // Put Components inside Services
+    // HDFS
+    Map<String, ServiceComponent> hdfsComponents = new HashMap<String, ServiceComponent>();
+
+    ServiceComponent nameNode = Mockito.mock(ServiceComponent.class);
+    Mockito.when(nameNode.getName()).thenReturn("NAMENODE");
+    Mockito.when(nameNode.isClientComponent()).thenReturn(false);
+    Mockito.when(nameNode.isVersionAdvertised()).thenReturn(true);
+
+    ServiceComponent dataNode = Mockito.mock(ServiceComponent.class);
+    Mockito.when(dataNode.getName()).thenReturn("DATANODE");
+    Mockito.when(dataNode.isClientComponent()).thenReturn(false);
+    Mockito.when(dataNode.isVersionAdvertised()).thenReturn(true);
+
+    ServiceComponent zkfc = Mockito.mock(ServiceComponent.class);
+    Mockito.when(zkfc.getName()).thenReturn("ZKFC");
+    Mockito.when(zkfc.isClientComponent()).thenReturn(false);
+    Mockito.when(zkfc.isVersionAdvertised()).thenReturn(false);
+
+    hdfsComponents.put("NAMENODE", nameNode);
+    hdfsComponents.put("DATANODE", dataNode);
+    hdfsComponents.put("ZKFC", zkfc);
+
+    Mockito.when(hdfsService.getServiceComponents()).thenReturn(hdfsComponents);
+
+    // TEZ
+    Map<String, ServiceComponent> tezComponents = new HashMap<String, ServiceComponent>();
+
+    ServiceComponent tezClient = Mockito.mock(ServiceComponent.class);
+    Mockito.when(tezClient.getName()).thenReturn("TEZ_CLIENT");
+    Mockito.when(tezClient.isClientComponent()).thenReturn(true);
+    Mockito.when(tezClient.isVersionAdvertised()).thenReturn(true);
+
+    tezComponents.put("TEZ_CLIENT", tezClient);
+
+    Mockito.when(tezService.getServiceComponents()).thenReturn(tezComponents);
+
+    // AMS
+    Map<String, ServiceComponent> amsComponents = new HashMap<String, ServiceComponent>();
+
+    ServiceComponent metricsCollector = Mockito.mock(ServiceComponent.class);
+    Mockito.when(metricsCollector.getName()).thenReturn("METRICS_COLLECTOR");
+    Mockito.when(metricsCollector.isClientComponent()).thenReturn(false);
+    Mockito.when(metricsCollector.isVersionAdvertised()).thenReturn(false);
+
+    ServiceComponent metricsMonitor = Mockito.mock(ServiceComponent.class);
+    Mockito.when(metricsMonitor.getName()).thenReturn("METRICS_MONITOR");
+    Mockito.when(metricsMonitor.isClientComponent()).thenReturn(false);
+    Mockito.when(metricsMonitor.isVersionAdvertised()).thenReturn(false);
+
+    amsComponents.put("METRICS_COLLECTOR", metricsCollector);
+    amsComponents.put("METRICS_MONITOR", metricsMonitor);
+
+    Mockito.when(amsService.getServiceComponents()).thenReturn(amsComponents);
+
+    final HostComponentSummary hcsNameNode = Mockito.mock(HostComponentSummary.class);
+    final HostComponentSummary hcsDataNode = Mockito.mock(HostComponentSummary.class);
+    final HostComponentSummary hcsZKFC = Mockito.mock(HostComponentSummary.class);
+    final HostComponentSummary hcsTezClient = Mockito.mock(HostComponentSummary.class);
+    final HostComponentSummary hcsMetricsCollector = Mockito.mock(HostComponentSummary.class);
+    final HostComponentSummary hcsMetricsMonitor = Mockito.mock(HostComponentSummary.class);
+
+    List<HostComponentSummary> allHostComponentSummaries = new ArrayList<HostComponentSummary>();
+    allHostComponentSummaries.add(hcsNameNode);
+    allHostComponentSummaries.add(hcsDataNode);
+    allHostComponentSummaries.add(hcsZKFC);
+    allHostComponentSummaries.add(hcsTezClient);
+    allHostComponentSummaries.add(hcsMetricsCollector);
+    allHostComponentSummaries.add(hcsMetricsMonitor);
+
+    // Mock the static method
+    Mockito.when(HostComponentSummary.getHostComponentSummaries("HDFS", "NAMENODE")).thenReturn(new
ArrayList<HostComponentSummary>(){{ add(hcsNameNode); }});
+    Mockito.when(HostComponentSummary.getHostComponentSummaries("HDFS", "DATANODE")).thenReturn(new
ArrayList<HostComponentSummary>(){{ add(hcsDataNode); }});
+    Mockito.when(HostComponentSummary.getHostComponentSummaries("HDFS", "ZKFC")).thenReturn(new
ArrayList<HostComponentSummary>(){{ add(hcsZKFC); }});
+    Mockito.when(HostComponentSummary.getHostComponentSummaries("TEZ", "TEZ_CLIENT")).thenReturn(new
ArrayList<HostComponentSummary>(){{ add(hcsTezClient); }});
+    Mockito.when(HostComponentSummary.getHostComponentSummaries("AMBARI_METRICS", "METRICS_COLLECTOR")).thenReturn(new
ArrayList<HostComponentSummary>(){{ add(hcsMetricsCollector); }});
+    Mockito.when(HostComponentSummary.getHostComponentSummaries("AMBARI_METRICS", "METRICS_MONITOR")).thenReturn(new
ArrayList<HostComponentSummary>(){{ add(hcsMetricsMonitor); }});
+
+    // Case 1. Initialize with good values
+    for (HostComponentSummary hcs : allHostComponentSummaries) {
+      Mockito.when(hcs.getDesiredState()).thenReturn(State.INSTALLED);
+      Mockito.when(hcs.getCurrentState()).thenReturn(State.STARTED);
+    }
     PrerequisiteCheck check = new PrerequisiteCheck(null, null);
     servicesUpCheck.perform(check, new PrereqCheckRequest("cluster"));
-    Assert.assertEquals(PrereqCheckStatus.FAIL, check.getStatus());
 
-    Mockito.when(service.getDesiredState()).thenReturn(State.STARTED);
+    // Case 2. Change some desired states to STARTED, should still pass
+    Mockito.when(hcsNameNode.getDesiredState()).thenReturn(State.STARTED);
+    Mockito.when(hcsDataNode.getDesiredState()).thenReturn(State.STARTED);
+
     check = new PrerequisiteCheck(null, null);
     servicesUpCheck.perform(check, new PrereqCheckRequest("cluster"));
     Assert.assertEquals(PrereqCheckStatus.PASS, check.getStatus());
+
+    // Case 3. Ensure that ZKFC and AMS are ignored even if their current state is not STARTED
+    Mockito.when(hcsZKFC.getCurrentState()).thenReturn(State.INSTALLED);
+    Mockito.when(hcsMetricsCollector.getCurrentState()).thenReturn(State.INSTALLED);
+    Mockito.when(hcsMetricsMonitor.getCurrentState()).thenReturn(State.INSTALLED);
+
+    check = new PrerequisiteCheck(null, null);
+    servicesUpCheck.perform(check, new PrereqCheckRequest("cluster"));
+    Assert.assertEquals(PrereqCheckStatus.PASS, check.getStatus());
+
+    // Case 4. Change HDFS current states to INSTALLED, should fail.
+    Mockito.when(hcsNameNode.getCurrentState()).thenReturn(State.INSTALLED);
+    Mockito.when(hcsDataNode.getCurrentState()).thenReturn(State.INSTALLED);
+
+    check = new PrerequisiteCheck(null, null);
+    servicesUpCheck.perform(check, new PrereqCheckRequest("cluster"));
+    Assert.assertEquals(PrereqCheckStatus.FAIL, check.getStatus());
   }
 }


Mime
View raw message