You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ambari.apache.org by ao...@apache.org on 2017/09/28 13:25:37 UTC

[48/50] [abbrv] ambari git commit: Merge remote-tracking branch 'remotes/origin/trunk' into branch-3.0-perf

http://git-wip-us.apache.org/repos/asf/ambari/blob/be73d167/ambari-server/src/main/java/org/apache/ambari/server/agent/HeartBeatHandler.java
----------------------------------------------------------------------
diff --cc ambari-server/src/main/java/org/apache/ambari/server/agent/HeartBeatHandler.java
index fcf32f0,53cceb0..00d469f
--- a/ambari-server/src/main/java/org/apache/ambari/server/agent/HeartBeatHandler.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/agent/HeartBeatHandler.java
@@@ -233,30 -266,10 +235,30 @@@ public class HeartBeatHandler 
      return response;
    }
  
 +  public void handleComponentReportStatus(List<ComponentStatus> componentStatuses, String hostname) throws AmbariException {
 +    heartbeatProcessor.processStatusReports(componentStatuses, hostname);
 +    heartbeatProcessor.processHostStatus(componentStatuses, null, hostname);
 +  }
  
 +  public void handleCommandReportStatus(List<CommandReport> reports, String hostname) throws AmbariException {
 +    heartbeatProcessor.processCommandReports(reports, hostname, System.currentTimeMillis());
 +    heartbeatProcessor.processHostStatus(null, reports, hostname);
 +  }
 +
 +  public void handleHostReportStatus(HostStatusReport hostStatusReport, String hostname) throws AmbariException {
 +    Host host = clusterFsm.getHost(hostname);
 +    try {
 +      host.handleEvent(new HostHealthyHeartbeatEvent(hostname, System.currentTimeMillis(),
 +          hostStatusReport.getAgentEnv(), hostStatusReport.getMounts()));
 +    } catch (InvalidStateTransitionException ex) {
 +      LOG.warn("Asking agent to re-register due to " + ex.getMessage(), ex);
 +      host.setState(HostState.INIT);
 +      agentSessionManager.unregisterByHost(hostname);
 +    }
 +  }
  
    protected void processRecoveryReport(RecoveryReport recoveryReport, String hostname) throws AmbariException {
-     LOG.debug("Received recovery report: " + recoveryReport.toString());
+     LOG.debug("Received recovery report: {}", recoveryReport);
      Host host = clusterFsm.getHost(hostname);
      host.setRecoveryReport(recoveryReport);
    }

http://git-wip-us.apache.org/repos/asf/ambari/blob/be73d167/ambari-server/src/main/java/org/apache/ambari/server/agent/HeartBeatResponse.java
----------------------------------------------------------------------

http://git-wip-us.apache.org/repos/asf/ambari/blob/be73d167/ambari-server/src/main/java/org/apache/ambari/server/agent/HeartbeatMonitor.java
----------------------------------------------------------------------

http://git-wip-us.apache.org/repos/asf/ambari/blob/be73d167/ambari-server/src/main/java/org/apache/ambari/server/agent/HeartbeatProcessor.java
----------------------------------------------------------------------
diff --cc ambari-server/src/main/java/org/apache/ambari/server/agent/HeartbeatProcessor.java
index 43470cf,2690008..ef9b0f2
--- a/ambari-server/src/main/java/org/apache/ambari/server/agent/HeartbeatProcessor.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/agent/HeartbeatProcessor.java
@@@ -55,9 -59,7 +59,8 @@@ import org.apache.ambari.server.state.C
  import org.apache.ambari.server.state.ComponentInfo;
  import org.apache.ambari.server.state.Host;
  import org.apache.ambari.server.state.HostHealthStatus;
 +import org.apache.ambari.server.state.HostState;
  import org.apache.ambari.server.state.MaintenanceState;
- import org.apache.ambari.server.state.SecurityState;
  import org.apache.ambari.server.state.Service;
  import org.apache.ambari.server.state.ServiceComponent;
  import org.apache.ambari.server.state.ServiceComponentHost;
@@@ -300,13 -297,13 +303,12 @@@ public class HeartbeatProcessor extend
          int slaveCount = 0;
          int slavesRunning = 0;
  
-         StackId stackId;
 -        Cluster cluster = clusterFsm.getCluster(clusterName);
 -
 +        Cluster cluster = clusterFsm.getCluster(clusterId);
-         stackId = cluster.getDesiredStackVersion();
- 
  
 -        List<ServiceComponentHost> scHosts = cluster.getServiceComponentHosts(heartbeat.getHostname());
 +        List<ServiceComponentHost> scHosts = cluster.getServiceComponentHosts(hostName);
          for (ServiceComponentHost scHost : scHosts) {
+           StackId stackId = scHost.getDesiredStackId();
+ 
            ComponentInfo componentInfo =
                ambariMetaInfo.getComponent(stackId.getStackName(),
                    stackId.getStackVersion(), scHost.getServiceName(),
@@@ -372,13 -368,22 +374,14 @@@
  
      for (CommandReport report : reports) {
  
 -      Long clusterId = null;
 -      if (report.getClusterName() != null) {
 -        try {
 -          Cluster cluster = clusterFsm.getCluster(report.getClusterName());
 -          clusterId = cluster.getClusterId();
 -        } catch (AmbariException e) {
 -          // null clusterId reported and handled by the listener (DistributeRepositoriesActionListener)
 -        }
 -      }
 +      Long clusterId = Long.parseLong(report.getClusterId());
  
-       LOG.debug("Received command report: " + report);
+       LOG.debug("Received command report: {}", report);
+ 
+       // get this locally; don't touch the database
 -      Host host = clusterFsm.getHost(hostname);
 +      Host host = clusterFsm.getHost(hostName);
- //      HostEntity hostEntity = hostDAO.findByName(hostname); //don't touch database
        if (host == null) {
 -        LOG.error("Received a command report and was unable to retrieve Host for hostname = " + hostname);
 +        LOG.error("Received a command report and was unable to retrieve Host for hostname = " + hostName);
          continue;
        }
  
@@@ -444,6 -449,12 +447,12 @@@
                }
              }
            }
+         } else if (CHECK_KEYTABS.equalsIgnoreCase(customCommand)) {
+           ListKeytabsStructuredOut structuredOut = gson.fromJson(report.getStructuredOut(), ListKeytabsStructuredOut.class);
+           for (MissingKeytab each : structuredOut.missingKeytabs){
 -            LOG.info("Missing keytab: {} on host: {} principal: {}", each.keytabFilePath, hostname, each.principal);
++            LOG.info("Missing keytab: {} on host: {} principal: {}", each.keytabFilePath, hostName, each.principal);
+             kerberosPrincipalHostDAO.remove(each.principal, host.getHostId());
+           }
          }
        }
  

http://git-wip-us.apache.org/repos/asf/ambari/blob/be73d167/ambari-server/src/main/java/org/apache/ambari/server/agent/HostInfo.java
----------------------------------------------------------------------

http://git-wip-us.apache.org/repos/asf/ambari/blob/be73d167/ambari-server/src/main/java/org/apache/ambari/server/agent/HostStatus.java
----------------------------------------------------------------------

http://git-wip-us.apache.org/repos/asf/ambari/blob/be73d167/ambari-server/src/main/java/org/apache/ambari/server/agent/RecoveryConfig.java
----------------------------------------------------------------------

http://git-wip-us.apache.org/repos/asf/ambari/blob/be73d167/ambari-server/src/main/java/org/apache/ambari/server/agent/RecoveryConfigHelper.java
----------------------------------------------------------------------

http://git-wip-us.apache.org/repos/asf/ambari/blob/be73d167/ambari-server/src/main/java/org/apache/ambari/server/agent/RecoveryReport.java
----------------------------------------------------------------------

http://git-wip-us.apache.org/repos/asf/ambari/blob/be73d167/ambari-server/src/main/java/org/apache/ambari/server/agent/Register.java
----------------------------------------------------------------------

http://git-wip-us.apache.org/repos/asf/ambari/blob/be73d167/ambari-server/src/main/java/org/apache/ambari/server/agent/RegistrationResponse.java
----------------------------------------------------------------------

http://git-wip-us.apache.org/repos/asf/ambari/blob/be73d167/ambari-server/src/main/java/org/apache/ambari/server/agent/StatusCommand.java
----------------------------------------------------------------------

http://git-wip-us.apache.org/repos/asf/ambari/blob/be73d167/ambari-server/src/main/java/org/apache/ambari/server/agent/rest/AgentResource.java
----------------------------------------------------------------------

http://git-wip-us.apache.org/repos/asf/ambari/blob/be73d167/ambari-server/src/main/java/org/apache/ambari/server/agent/stomp/AgentReportsController.java
----------------------------------------------------------------------
diff --cc ambari-server/src/main/java/org/apache/ambari/server/agent/stomp/AgentReportsController.java
index 4d2b9d6,0000000..5599254
mode 100644,000000..100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/agent/stomp/AgentReportsController.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/agent/stomp/AgentReportsController.java
@@@ -1,109 -1,0 +1,105 @@@
 +/*
 + * 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.agent.stomp;
 +
 +import java.util.ArrayList;
 +import java.util.Arrays;
 +import java.util.List;
 +import java.util.Map;
 +
 +import javax.ws.rs.WebApplicationException;
 +
 +import org.apache.ambari.server.AmbariException;
 +import org.apache.ambari.server.agent.AgentSessionManager;
 +import org.apache.ambari.server.agent.CommandReport;
 +import org.apache.ambari.server.agent.ComponentStatus;
 +import org.apache.ambari.server.agent.HeartBeatHandler;
 +import org.apache.ambari.server.agent.stomp.dto.CommandStatusReports;
 +import org.apache.ambari.server.agent.stomp.dto.ComponentStatusReport;
 +import org.apache.ambari.server.agent.stomp.dto.ComponentStatusReports;
 +import org.apache.ambari.server.agent.stomp.dto.HostStatusReport;
 +import org.apache.ambari.server.state.Alert;
 +import org.apache.ambari.server.state.fsm.InvalidStateTransitionException;
 +import org.slf4j.Logger;
 +import org.slf4j.LoggerFactory;
 +import org.springframework.messaging.handler.annotation.Header;
 +import org.springframework.messaging.handler.annotation.MessageMapping;
 +import org.springframework.messaging.simp.annotation.SendToUser;
 +import org.springframework.messaging.simp.annotation.SubscribeMapping;
 +import org.springframework.stereotype.Controller;
 +
 +import com.google.inject.Injector;
 +
 +@Controller
 +@SendToUser("/")
 +@MessageMapping("/reports")
 +public class AgentReportsController {
 +  private static final Logger LOG = LoggerFactory.getLogger(AgentReportsController.class);
 +  private final HeartBeatHandler hh;
 +  private final AgentSessionManager agentSessionManager;
 +
 +  public AgentReportsController(Injector injector) {
 +    hh = injector.getInstance(HeartBeatHandler.class);
 +    agentSessionManager = injector.getInstance(AgentSessionManager.class);
 +  }
 +
 +  @SubscribeMapping("/component_status")
 +  public void handleComponentReportStatus(@Header String simpSessionId, ComponentStatusReports message)
 +      throws WebApplicationException, InvalidStateTransitionException, AmbariException {
 +    List<ComponentStatus> statuses = new ArrayList<>();
 +    for (Map.Entry<String, List<ComponentStatusReport>> clusterReport : message.getComponentStatusReports().entrySet()) {
 +      for (ComponentStatusReport report : clusterReport.getValue()) {
 +        ComponentStatus componentStatus = new ComponentStatus();
 +        componentStatus.setClusterId(report.getClusterId());
 +        componentStatus.setComponentName(report.getComponentName());
 +        componentStatus.setServiceName(report.getServiceName());
-         if (report.getCommand().equals(ComponentStatusReport.CommandStatusCommand.STATUS)) {
-           componentStatus.setStatus(report.getStatus());
-         } else {
-           componentStatus.setSecurityState(report.getStatus());
-         }
++        componentStatus.setStatus(report.getStatus());
 +        statuses.add(componentStatus);
 +      }
 +    }
 +
 +    hh.handleComponentReportStatus(statuses,
 +        agentSessionManager.getHost(simpSessionId).getHostName());
 +  }
 +
 +  @SubscribeMapping("/commands_status")
 +  public void handleCommandReportStatus(@Header String simpSessionId, CommandStatusReports message)
 +      throws WebApplicationException, InvalidStateTransitionException, AmbariException {
 +    List<CommandReport> statuses = new ArrayList<>();
 +    for (Map.Entry<String, List<CommandReport>> clusterReport : message.getClustersComponentReports().entrySet()) {
 +      statuses.addAll(clusterReport.getValue());
 +    }
 +
 +    hh.handleCommandReportStatus(statuses,
 +        agentSessionManager.getHost(simpSessionId).getHostName());
 +  }
 +
 +  @SubscribeMapping("/host_status")
 +  public void handleHostReportStatus(@Header String simpSessionId, HostStatusReport message) throws AmbariException {
 +    hh.handleHostReportStatus(message, agentSessionManager.getHost(simpSessionId).getHostName());
 +  }
 +
 +  @SubscribeMapping("/alerts_status")
 +  public void handleAlertsStatus(@Header String simpSessionId, Alert[] message) throws AmbariException {
 +    String hostName = agentSessionManager.getHost(simpSessionId).getHostName();
 +    List<Alert> alerts = Arrays.asList(message);
 +    LOG.info("Handling {} alerts status for host {}", alerts.size(), hostName);
 +    hh.getHeartbeatProcessor().processAlerts(hostName, alerts);
 +  }
 +
 +}

http://git-wip-us.apache.org/repos/asf/ambari/blob/be73d167/ambari-server/src/main/java/org/apache/ambari/server/agent/stomp/HostLevelParamsHolder.java
----------------------------------------------------------------------
diff --cc ambari-server/src/main/java/org/apache/ambari/server/agent/stomp/HostLevelParamsHolder.java
index db093f8,0000000..3d17ef2
mode 100644,000000..100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/agent/stomp/HostLevelParamsHolder.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/agent/stomp/HostLevelParamsHolder.java
@@@ -1,83 -1,0 +1,84 @@@
 +/**
 + * 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.agent.stomp;
 +
 +import java.util.TreeMap;
 +
 +import org.apache.ambari.server.AmbariException;
 +import org.apache.ambari.server.agent.RecoveryConfigHelper;
 +import org.apache.ambari.server.agent.stomp.dto.HostLevelParamsCluster;
 +import org.apache.ambari.server.api.services.AmbariMetaInfo;
 +import org.apache.ambari.server.events.HostLevelParamsUpdateEvent;
 +import org.apache.ambari.server.events.publishers.StateUpdateEventPublisher;
 +import org.apache.ambari.server.state.Cluster;
 +import org.apache.ambari.server.state.Clusters;
 +import org.apache.ambari.server.state.Host;
 +
 +import com.google.inject.Inject;
 +import com.google.inject.Singleton;
 +
 +@Singleton
 +public class HostLevelParamsHolder extends AgentHostDataHolder<HostLevelParamsUpdateEvent> {
 +
 +  @Inject
 +  private RecoveryConfigHelper recoveryConfigHelper;
 +
 +  @Inject
 +  private AmbariMetaInfo ambariMetaInfo;
 +
 +  @Inject
 +  private Clusters clusters;
 +
 +  private StateUpdateEventPublisher stateUpdateEventPublisher;
 +
 +  @Inject
 +  public HostLevelParamsHolder(StateUpdateEventPublisher stateUpdateEventPublisher) {
 +    this.stateUpdateEventPublisher = stateUpdateEventPublisher;
 +    stateUpdateEventPublisher.register(this);
 +  }
 +
 +  @Override
 +  public HostLevelParamsUpdateEvent getCurrentData(String hostName) throws AmbariException {
 +    TreeMap<String, HostLevelParamsCluster> hostLevelParamsClusters = new TreeMap<>();
 +    for (Cluster cl : clusters.getClustersForHost(hostName)) {
 +      Host host = clusters.getHost(hostName);
++      //TODO fix repo info host param
 +      HostLevelParamsCluster hostLevelParamsCluster = new HostLevelParamsCluster(
-           ambariMetaInfo.getRepoInfo(cl, host),
++          null,//ambariMetaInfo.getRepoInfo(cl, host),
 +          recoveryConfigHelper.getRecoveryConfig(cl.getClusterName(), hostName));
 +
 +      hostLevelParamsClusters.put(Long.toString(cl.getClusterId()),
 +          hostLevelParamsCluster);
 +    }
 +    HostLevelParamsUpdateEvent hostLevelParamsUpdateEvent = new HostLevelParamsUpdateEvent(hostLevelParamsClusters);
 +    return hostLevelParamsUpdateEvent;
 +  }
 +
 +  public void updateData(HostLevelParamsUpdateEvent update) throws AmbariException {
 +    //TODO implement update host level params process
 +    setData(update, update.getHostName());
 +    regenerateHash(update.getHostName());
 +    update.setHash(getData(update.getHostName()).getHash());
 +    stateUpdateEventPublisher.publish(update);
 +  }
 +
 +  @Override
 +  protected HostLevelParamsUpdateEvent getEmptyData() {
 +    return HostLevelParamsUpdateEvent.emptyUpdate();
 +  }
 +}

http://git-wip-us.apache.org/repos/asf/ambari/blob/be73d167/ambari-server/src/main/java/org/apache/ambari/server/alerts/AgentHeartbeatAlertRunnable.java
----------------------------------------------------------------------

http://git-wip-us.apache.org/repos/asf/ambari/blob/be73d167/ambari-server/src/main/java/org/apache/ambari/server/alerts/AlertRunnable.java
----------------------------------------------------------------------
diff --cc ambari-server/src/main/java/org/apache/ambari/server/alerts/AlertRunnable.java
index ea583e4,3d7d3c7..bdcffbc
--- a/ambari-server/src/main/java/org/apache/ambari/server/alerts/AlertRunnable.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/alerts/AlertRunnable.java
@@@ -162,4 -163,30 +163,30 @@@ public abstract class AlertRunnable imp
      Number number = NumberUtils.createNumber((String) value);
      return number.intValue();
    }
+ 
+   /**
+    * Builds an {@link Alert} instance.
+    *
+    * @param cluster
+    *          the cluster the alert is for (not {@code null}).
+    * @param myDefinition
+    *          the alert's definition (not {@code null}).
+    * @param alertState
+    *          the state of the alert (not {@code null}).
+    * @param message
+    *          the alert text.
+    * @return and alert.
+    */
+   protected Alert buildAlert(Cluster cluster, AlertDefinitionEntity myDefinition,
+       AlertState alertState, String message) {
+     Alert alert = new Alert(myDefinition.getDefinitionName(), null, myDefinition.getServiceName(),
+         myDefinition.getComponentName(), null, alertState);
+ 
+     alert.setLabel(myDefinition.getLabel());
+     alert.setText(message);
+     alert.setTimestamp(System.currentTimeMillis());
 -    alert.setCluster(cluster.getClusterName());
++    alert.setClusterId(cluster.getClusterId());
+ 
+     return alert;
+   }
  }

http://git-wip-us.apache.org/repos/asf/ambari/blob/be73d167/ambari-server/src/main/java/org/apache/ambari/server/alerts/AmbariPerformanceRunnable.java
----------------------------------------------------------------------

http://git-wip-us.apache.org/repos/asf/ambari/blob/be73d167/ambari-server/src/main/java/org/apache/ambari/server/alerts/StaleAlertRunnable.java
----------------------------------------------------------------------

http://git-wip-us.apache.org/repos/asf/ambari/blob/be73d167/ambari-server/src/main/java/org/apache/ambari/server/api/query/render/AlertStateSummary.java
----------------------------------------------------------------------

http://git-wip-us.apache.org/repos/asf/ambari/blob/be73d167/ambari-server/src/main/java/org/apache/ambari/server/api/query/render/AlertStateValues.java
----------------------------------------------------------------------

http://git-wip-us.apache.org/repos/asf/ambari/blob/be73d167/ambari-server/src/main/java/org/apache/ambari/server/api/query/render/AlertSummaryGroupedRenderer.java
----------------------------------------------------------------------

http://git-wip-us.apache.org/repos/asf/ambari/blob/be73d167/ambari-server/src/main/java/org/apache/ambari/server/api/resources/ClusterResourceDefinition.java
----------------------------------------------------------------------
diff --cc ambari-server/src/main/java/org/apache/ambari/server/api/resources/ClusterResourceDefinition.java
index e181347,9d0c169..8933dd3
--- a/ambari-server/src/main/java/org/apache/ambari/server/api/resources/ClusterResourceDefinition.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/api/resources/ClusterResourceDefinition.java
@@@ -85,6 -85,9 +85,8 @@@ public class ClusterResourceDefinition 
      directives.add(KerberosHelper.DIRECTIVE_REGENERATE_KEYTABS);
      directives.add(KerberosHelper.DIRECTIVE_MANAGE_KERBEROS_IDENTITIES);
      directives.add(KerberosHelper.DIRECTIVE_FORCE_TOGGLE_KERBEROS);
+     directives.add(KerberosHelper.DIRECTIVE_HOSTS);
+     directives.add(KerberosHelper.DIRECTIVE_COMPONENTS);
 -    directives.add(KerberosHelper.DIRECTIVE_IGNORE_CONFIGS);
      return directives;
    }
  

http://git-wip-us.apache.org/repos/asf/ambari/blob/be73d167/ambari-server/src/main/java/org/apache/ambari/server/api/services/AmbariMetaInfo.java
----------------------------------------------------------------------
diff --cc ambari-server/src/main/java/org/apache/ambari/server/api/services/AmbariMetaInfo.java
index ca4eed9,de84965..5f4ba17
--- a/ambari-server/src/main/java/org/apache/ambari/server/api/services/AmbariMetaInfo.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/api/services/AmbariMetaInfo.java
@@@ -37,12 -36,12 +36,16 @@@ import java.util.List
  import java.util.Map;
  import java.util.Scanner;
  import java.util.Set;
++import java.util.function.Function;
  
  import javax.xml.bind.JAXBException;
  
++import org.apache.ambari.annotations.Experimental;
++import org.apache.ambari.annotations.ExperimentalFeature;
  import org.apache.ambari.server.AmbariException;
  import org.apache.ambari.server.ParentObjectNotFoundException;
  import org.apache.ambari.server.StackAccessException;
++import org.apache.ambari.server.agent.CommandRepository;
  import org.apache.ambari.server.configuration.Configuration;
  import org.apache.ambari.server.controller.RootServiceResponseFactory.Services;
  import org.apache.ambari.server.controller.utilities.PropertyHelper;
@@@ -53,15 -52,8 +56,11 @@@ import org.apache.ambari.server.events.
  import org.apache.ambari.server.events.publishers.AmbariEventPublisher;
  import org.apache.ambari.server.metadata.AmbariServiceAlertDefinitions;
  import org.apache.ambari.server.orm.dao.AlertDefinitionDAO;
- import org.apache.ambari.server.orm.dao.ClusterVersionDAO;
  import org.apache.ambari.server.orm.dao.MetainfoDAO;
  import org.apache.ambari.server.orm.entities.AlertDefinitionEntity;
- import org.apache.ambari.server.orm.entities.ClusterVersionEntity;
- import org.apache.ambari.server.orm.entities.MetainfoEntity;
 +import org.apache.ambari.server.orm.entities.OperatingSystemEntity;
 +import org.apache.ambari.server.orm.entities.RepositoryEntity;
 +import org.apache.ambari.server.orm.entities.RepositoryVersionEntity;
- import org.apache.ambari.server.stack.StackDirectory;
  import org.apache.ambari.server.stack.StackManager;
  import org.apache.ambari.server.stack.StackManagerFactory;
  import org.apache.ambari.server.state.Cluster;
@@@ -73,8 -64,7 +72,9 @@@ import org.apache.ambari.server.state.H
  import org.apache.ambari.server.state.OperatingSystemInfo;
  import org.apache.ambari.server.state.PropertyInfo;
  import org.apache.ambari.server.state.RepositoryInfo;
 +import org.apache.ambari.server.state.RepositoryVersionState;
  import org.apache.ambari.server.state.Service;
++import org.apache.ambari.server.state.ServiceComponent;
  import org.apache.ambari.server.state.ServiceInfo;
  import org.apache.ambari.server.state.StackId;
  import org.apache.ambari.server.state.StackInfo;
@@@ -95,6 -85,6 +95,9 @@@ import org.slf4j.Logger
  import org.slf4j.LoggerFactory;
  
  import com.google.gson.Gson;
++import com.google.gson.JsonArray;
++import com.google.gson.JsonElement;
++import com.google.gson.JsonObject;
  import com.google.gson.reflect.TypeToken;
  import com.google.inject.Inject;
  import com.google.inject.Singleton;
@@@ -151,23 -110,8 +123,11 @@@ public class AmbariMetaInfo 
  
    // all the supported OS'es
    @Inject
--  private OsFamily osFamily;
++  private OsFamily os_family;
 +
 +  @Inject
 +  private Gson gson;
  
-   @Inject
-   private ClusterVersionDAO clusterVersionDAO;
- 
    /**
     * ALL_SUPPORTED_OS is dynamically generated list from loaded families from os_family.json
     * Instead of append values here, please, add new families in json for tests and production
@@@ -280,12 -224,12 +240,12 @@@
    @Inject
    public void init() throws Exception {
      // Need to be initialized before all actions
--    ALL_SUPPORTED_OS = new ArrayList<>(osFamily.os_list());
++    ALL_SUPPORTED_OS = new ArrayList<>(os_family.os_list());
  
      readServerVersion();
  
      stackManager = stackManagerFactory.create(stackRoot, commonServicesRoot, extensionsRoot,
--        osFamily, false);
++        os_family, false);
  
      getCustomActionDefinitions(customActionRoot);
    }
@@@ -1498,132 -1406,33 +1422,262 @@@
  
      return versionDefinitions;
    }
 +  /**
 +   * Get repository info given a cluster and host.
 +   *
 +   * @param cluster  the cluster
 +   * @param host     the host
 +   *
 +   * @return the repo info
 +   *
 +   * @throws AmbariException if the repository information can not be obtained
-    */
 +  public String getRepoInfoString(Cluster cluster, Host host) throws AmbariException {
 +
 +    return getRepoInfoString(cluster, host.getOsType(), host.getOsFamily(), host.getHostName());
-   }
++  }*/
 +
-   public String getRepoInfoString(Cluster cluster, String hostOSType, String hostOSFamily, String hostName) throws AmbariException {
-     return gson.toJson(getRepoInfo(cluster, hostOSType, hostOSFamily, hostName));
++  public String getRepoInfoString(Cluster cluster, ServiceComponent component, Host host) throws AmbariException {
++    return gson.toJson(getCommandRepository(cluster, component, host));
 +  }
 +
 +  /**
 +   * Get repository info given a cluster and host.
 +   *
 +   * @param cluster  the cluster
 +   * @param host     the host
 +   *
 +   * @return the repo info
 +   *
++   * @deprecated use {@link #getCommandRepository(Cluster, ServiceComponent, Host)} instead.
 +   * @throws AmbariException if the repository information can not be obtained
 +   */
-   public List<RepositoryInfo> getRepoInfo(Cluster cluster, Host host) throws AmbariException {
++  @Deprecated
++  public String getRepoInfo(Cluster cluster, ServiceComponent component, Host host) throws AmbariException {
++
++    Function<List<RepositoryInfo>, JsonArray> function = new Function<List<RepositoryInfo>, JsonArray>() {
++      @Override
++      public JsonArray apply(List<RepositoryInfo> input) {
++        return null == input ? null : (JsonArray) gson.toJsonTree(input);
++      }
++    };
++
++    final JsonArray gsonList = getBaseUrls(cluster, component, host, function);
++
++    if (null == gsonList) {
++      return "";
++    }
++
++    BaseUrlUpdater<JsonArray> updater = new BaseUrlUpdater<JsonArray>(gsonList) {
++      @Override
++      public JsonArray apply(final RepositoryVersionEntity rve) {
++
++        JsonArray result = new JsonArray();
++
++        for (JsonElement e : gsonList) {
++          JsonObject obj = e.getAsJsonObject();
++
++          String repoId = obj.has("repoId") ? obj.get("repoId").getAsString() : null;
++          String repoName = obj.has("repoName") ? obj.get("repoName").getAsString() : null;
++          String baseUrl = obj.has("baseUrl") ? obj.get("baseUrl").getAsString() : null;
++          String osType = obj.has("osType") ? obj.get("osType").getAsString() : null;
++
++          if (null == repoId || null == baseUrl || null == osType || null == repoName) {
++            continue;
++          }
++
++          for (OperatingSystemEntity ose : rve.getOperatingSystems()) {
++            if (ose.getOsType().equals(osType) && ose.isAmbariManagedRepos()) {
++              for (RepositoryEntity re : ose.getRepositories()) {
++                if (re.getName().equals(repoName) &&
++                    !re.getBaseUrl().equals(baseUrl)) {
++                  obj.addProperty("baseUrl", re.getBaseUrl());
++                }
++              }
++              result.add(e);
++            }
++          }
++        }
 +
-     return getRepoInfo(cluster, host.getOsType(), host.getOsFamily(), host.getHostName());
++        return result;
++      }
++    };
++
++    return updateBaseUrls(cluster, component, updater).toString();
 +  }
 +
-   public List<RepositoryInfo> getRepoInfo(Cluster cluster, String hostOSType, String hostOSFamily, String hostName) throws AmbariException {
++  /**
++   * Builds repository information for inclusion in a command.  This replaces escaping json on
++   * a command.
++   *
++   * @param cluster the cluster
++   * @param host    the host
++   * @return  the command repository
++   * @throws AmbariException
++   */
++  @Experimental(feature=ExperimentalFeature.PATCH_UPGRADES)
++  public CommandRepository getCommandRepository(final Cluster cluster, ServiceComponent component, final Host host) throws AmbariException {
++
++    final CommandRepository command = new CommandRepository();
++    StackId stackId = component.getDesiredStackId();
++    command.setRepositories(Collections.<RepositoryInfo>emptyList());
++    command.setStackName(stackId.getStackName());
++
++    final BaseUrlUpdater<Void> updater = new BaseUrlUpdater<Void>(null) {
++      @Override
++      public Void apply(RepositoryVersionEntity rve) {
++        command.setRepositoryVersionId(rve.getId());
++        command.setRepositoryVersion(rve.getVersion());
++        command.setStackName(rve.getStackName());
++
++        // !!! a repository version entity has all the repos worked out.  We shouldn't use
++        // the stack at all.
++        for (OperatingSystemEntity osEntity : rve.getOperatingSystems()) {
++          String osEntityFamily = os_family.find(osEntity.getOsType());
++          if (osEntityFamily.equals(host.getOsFamily())) {
++            command.setRepositories(osEntity.getOsType(), osEntity.getRepositories());
++
++            if (!osEntity.isAmbariManagedRepos()) {
++              command.setNonManaged();
++            } else {
++              command.setUniqueSuffix(String.format("-repo-%s", rve.getId()));
++            }
++          }
++        }
++
++        return null;
++      }
++    };
 +
-     StackId stackId = cluster.getDesiredStackVersion();
++    updateBaseUrls(cluster, component, updater);
++
++    return command;
++  }
++
++  /**
++   * Executed by two different representations of repos.  When we are comfortable with the new
++   * implementation, this may be removed and called inline in {@link #getCommandRepository(Cluster, ServiceComponent, Host)}
++   *
++   * @param cluster   the cluster to isolate the stack
++   * @param component the component
++   * @param host      used to resolve the family for the repositories
++   * @param function  function that will transform the supplied repositories for specific use.
++   * @return <T> the type as defined by the supplied {@code function}.
++   * @throws AmbariException
++   */
++  @Experimental(feature = ExperimentalFeature.PATCH_UPGRADES)
++  private <T> T getBaseUrls(Cluster cluster, ServiceComponent component, Host host,
++                            Function<List<RepositoryInfo>, T> function) throws AmbariException {
++
++    String hostOsType = host.getOsType();
++    String hostOsFamily = host.getOsFamily();
++    String hostName = host.getHostName();
++
++    StackId stackId = component.getDesiredStackId();
 +
 +    Map<String, List<RepositoryInfo>> repos = getRepository(
 +        stackId.getStackName(), stackId.getStackVersion());
 +
-     String family = osFamily.find(hostOSType);
++    String family = os_family.find(hostOsType);
 +    if (null == family) {
-       family = hostOSFamily;
++      family = hostOsFamily;
 +    }
 +
-     List<RepositoryInfo> repoInfos = new ArrayList<>();
++    final List<RepositoryInfo> repoInfos;
 +
 +    // !!! check for the most specific first
-     if (repos.containsKey(hostOSType)) {
-       repoInfos = repos.get(hostOSType);
++    if (repos.containsKey(hostOsType)) {
++      repoInfos = repos.get(hostOsType);
 +    } else if (null != family && repos.containsKey(family)) {
 +      repoInfos = repos.get(family);
 +    } else {
++      repoInfos = null;
 +      LOG.warn("Could not retrieve repo information for host"
 +          + ", hostname=" + hostName
 +          + ", clusterName=" + cluster.getClusterName()
 +          + ", stackInfo=" + stackId.getStackId());
 +    }
 +
-     if (null != repoInfos) {
-       updateBaseUrls(cluster, repoInfos);
-       return repoInfos;
-     } else {
-       return null;
-     }
++    // leave it to function implementation to handle null.
++    return function.apply(repoInfos);
 +  }
++
 +  /**
 +   * Checks repo URLs against the current version for the cluster and makes
 +   * adjustments to the Base URL when the current is different.
-    * @param cluster   the cluster to load the current version
-    * @param repoInfos the array containing stack repo data
++   *
++   * @param <T> the result after appling the repository version, if found.
 +   */
-   private void updateBaseUrls(Cluster cluster, List<RepositoryInfo> repoInfos) throws AmbariException {
-     ClusterVersionEntity cve = cluster.getCurrentClusterVersion();
- 
-     if (null == cve) {
-       List<ClusterVersionEntity> list = clusterVersionDAO.findByClusterAndState(cluster.getClusterName(),
-           RepositoryVersionState.INIT);
- 
-       if (!list.isEmpty()) {
-         if (list.size() > 1) {
-           throw new AmbariException(String.format("The cluster can only be initialized by one version: %s found",
-               list.size()));
-         } else {
-           cve = list.get(0);
-         }
-       }
-     }
++  @Experimental(feature = ExperimentalFeature.PATCH_UPGRADES)
++  private <T> T updateBaseUrls(Cluster cluster, ServiceComponent component, BaseUrlUpdater<T> function) throws AmbariException {
 +
-     if (null == cve || null == cve.getRepositoryVersion()) {
-       LOG.info("Cluster {} has no specific Repository Versions.  Using stack-defined values", cluster.getClusterName());
-       return;
++    RepositoryVersionEntity repositoryEntity = null;
++
++    // !!! try to find the component repo first
++    if (null != component) {
++      repositoryEntity = component.getDesiredRepositoryVersion();
++    } else {
++      LOG.info("Service component not passed in, attempt to resolve the repository for cluster {}",
++          cluster.getClusterName());
 +    }
 +
-     RepositoryVersionEntity rve = cve.getRepositoryVersion();
++    if (null == repositoryEntity && null != component) {
++      Service service = cluster.getService(component.getServiceName());
 +
-     for (Iterator<RepositoryInfo> iter = repoInfos.iterator(); iter.hasNext(); ) {
++      repositoryEntity = service.getDesiredRepositoryVersion();
++    }
 +
-       RepositoryInfo repositoryInfo = iter.next();
++    if (null == repositoryEntity) {
++      LOG.info("Cluster {} has no specific Repository Versions.  Using stack-defined values", cluster.getClusterName());
++      return function.getDefault();
++    }
 +
-       String repoId = repositoryInfo.getRepoId();
-       String repoName = repositoryInfo.getRepoName();
-       String baseUrl = repositoryInfo.getBaseUrl();
-       String osType = repositoryInfo.getOsType();
++    return function.apply(repositoryEntity);
++  }
  
-       if (null == repoId || null == baseUrl || null == osType || null == repoName) {
-         continue;
-       }
+   /**
+    * Reads a Kerberos descriptor from the specified file path.
+    *
+    * @param fileLocation the path to the file
+    * @return a KerberosDescriptor or <code>null</code>, if no path is specified
+    * @throws AmbariException if an error occurs reading or parsing the Kerberos descriptor file
+    */
+   KerberosDescriptor readKerberosDescriptorFromFile(String fileLocation) throws AmbariException {
+     if (!StringUtils.isEmpty(fileLocation)) {
+       File file = new File(fileLocation);
  
-       boolean toResult = false;
-       for (OperatingSystemEntity ose : rve.getOperatingSystems()) {
-         if (ose.getOsType().equals(osType) && ose.isAmbariManagedRepos()) {
-           for (RepositoryEntity re : ose.getRepositories()) {
-             if (re.getName().equals(repoName) &&
-                 re.getRepositoryId().equals(repoId) &&
-                 !re.getBaseUrl().equals(baseUrl)) {
-               repositoryInfo.setBaseUrl(re.getBaseUrl());
-             }
-           }
-           toResult = true;
+       if (file.canRead()) {
+         try {
+           return kerberosDescriptorFactory.createInstance(file);
+         } catch (IOException e) {
+           throw new AmbariException(String.format("Failed to parse Kerberos descriptor file %s",
+               file.getAbsolutePath()), e);
          }
+       } else {
+         throw new AmbariException(String.format("Unable to read Kerberos descriptor file %s",
+             file.getAbsolutePath()));
        }
-       if (!toResult) {
-         iter.remove();
-       }
+     } else {
+       LOG.debug("Missing path to Kerberos descriptor, returning null");
      }
+ 
+     return null;
+   }
++
++  /**
++   * Class that is used to update base urls.  There are two implementations of this - when we no
++   * longer are sure the deprecated repo info can be removed, so too can this class.
++   */
++  @Experimental(feature= ExperimentalFeature.PATCH_UPGRADES)
++  abstract static class BaseUrlUpdater<T> implements Function<RepositoryVersionEntity, T> {
++    private T m_default;
++
++    private BaseUrlUpdater(T defaultValue) {
++      m_default = defaultValue;
++    }
++
++    private T getDefault() {
++      return m_default;
++    }
++
 +  }
  }

http://git-wip-us.apache.org/repos/asf/ambari/blob/be73d167/ambari-server/src/main/java/org/apache/ambari/server/checks/CheckDescription.java
----------------------------------------------------------------------
diff --cc ambari-server/src/main/java/org/apache/ambari/server/checks/CheckDescription.java
index e17185f,c4d0820..4fd37dc
--- 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
@@@ -328,10 -323,36 +323,24 @@@ public class CheckDescription 
      PrereqCheckType.SERVICE,
      "Change Ranger SSL configuration path for Keystore and Truststore.",
      new ImmutableMap.Builder<String, String>()
-             .put(AbstractCheckDescriptor.DEFAULT,
-               "As Ranger is SSL enabled, Ranger SSL configurations will need to be changed from default value of /etc/ranger/*/conf folder to /etc/ranger/security. " +
-               "Since the certificates/keystores/truststores in this path may affect the upgrade/downgrade process, it is recommended to manually move the certificates/keystores/truststores out of the conf folders and change the appropriate config values before proceeding.").build());
+       .put(AbstractCheckDescriptor.DEFAULT,
+         "As Ranger is SSL enabled, Ranger SSL configurations will need to be changed from default value of /etc/ranger/*/conf folder to /etc/ranger/security. " +
+         "Since the certificates/keystores/truststores in this path may affect the upgrade/downgrade process, it is recommended to manually move the certificates/keystores/truststores out of the conf folders and change the appropriate config values before proceeding.").build());
+ 
+   public static CheckDescription JAVA_VERSION = new CheckDescription("JAVA_VERSION",
+       PrereqCheckType.CLUSTER,
+       "Verify Java version requirement",
+       new ImmutableMap.Builder<String, String>()
+         .put(AbstractCheckDescriptor.DEFAULT, "Ambari requires JDK with minimum version %s. Reconfigure Ambari with a JDK that meets the version requirement.")
+           .build());
+ 
+   public static CheckDescription COMPONENTS_EXIST_IN_TARGET_REPO = new CheckDescription("COMPONENTS_EXIST_IN_TARGET_REPO",
+       PrereqCheckType.CLUSTER,
+       "Verify Cluster Components Exist In Target Repository",
+       new ImmutableMap.Builder<String, String>()
+         .put(AbstractCheckDescriptor.DEFAULT, "The following components do not exist in the target repository's stack. They must be removed from the cluster before upgrading.")
+           .build());
  
 -  public static CheckDescription DRUID_HA_WARNING = new CheckDescription(
 -      "DRUID_HA",
 -      PrereqCheckType.SERVICE,
 -      "Druid Downtime During Upgrade",
 -      new ImmutableMap.Builder<String, String>()
 -          .put(
 -              AbstractCheckDescriptor.DEFAULT,
 -              "High Availability is not enabled for Druid. Druid Service may have some downtime during upgrade. Deploy multiple instances of %s in the Cluster to avoid any downtime."
 -          )
 -          .build()
 -  );
 -
    private String m_name;
    private PrereqCheckType m_type;
    private String m_description;

http://git-wip-us.apache.org/repos/asf/ambari/blob/be73d167/ambari-server/src/main/java/org/apache/ambari/server/checks/DatabaseConsistencyCheckHelper.java
----------------------------------------------------------------------
diff --cc ambari-server/src/main/java/org/apache/ambari/server/checks/DatabaseConsistencyCheckHelper.java
index b2a03e4,34888f2..054c470
--- a/ambari-server/src/main/java/org/apache/ambari/server/checks/DatabaseConsistencyCheckHelper.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/checks/DatabaseConsistencyCheckHelper.java
@@@ -57,7 -58,11 +57,9 @@@ import org.apache.ambari.server.orm.ent
  import org.apache.ambari.server.orm.entities.HostComponentDesiredStateEntity;
  import org.apache.ambari.server.orm.entities.HostComponentStateEntity;
  import org.apache.ambari.server.orm.entities.MetainfoEntity;
- import org.apache.ambari.server.state.SecurityState;
+ import org.apache.ambari.server.orm.entities.ServiceComponentDesiredStateEntity;
+ import org.apache.ambari.server.state.ClientConfigFileDefinition;
 -import org.apache.ambari.server.state.Cluster;
 -import org.apache.ambari.server.state.Clusters;
+ import org.apache.ambari.server.state.ComponentInfo;
  import org.apache.ambari.server.state.ServiceInfo;
  import org.apache.ambari.server.state.State;
  import org.apache.ambari.server.state.UpgradeState;
@@@ -313,10 -322,10 +314,10 @@@ public class DatabaseConsistencyCheckHe
            } else if (tableRowCount != -1 && tableRowCount < TABLE_ROW_COUNT_LIMIT) {
              LOG.info(String.format("The database table %s currently has %d rows and is within normal limits (%d)", tableName, tableRowCount, TABLE_ROW_COUNT_LIMIT));
            } else {
-             throw new SQLException();
+             warning("Unable to get size for table {}!", tableName);
            }
          } catch (SQLException ex) {
-           LOG.error(String.format("Failed to get %s row count: ", tableName), e);
 -          warning(String.format("Failed to get %s row count: ", tableName), e);
++          error(String.format("Failed to get %s row count: ", tableName), e);
          }
        } finally {
          if (rs != null) {
@@@ -375,7 -384,7 +376,7 @@@
        }
  
      } catch (SQLException e) {
-       LOG.error("Exception occurred during check for config selected more than ones procedure: ", e);
 -      warning("Exception occurred during check for config selected more than once procedure: ", e);
++      error("Exception occurred during check for config selected more than once procedure: ", e);
      } finally {
        if (rs != null) {
          try {
@@@ -424,7 -433,7 +425,7 @@@
        }
  
      } catch (SQLException e) {
-       LOG.error("Exception occurred during check for host without state procedure: ", e);
 -      warning("Exception occurred during check for host without state procedure: ", e);
++      error("Exception occurred during check for host without state procedure: ", e);
      } finally {
        if (rs != null) {
          try {
@@@ -489,15 -465,8 +457,8 @@@
          }
        }
  
-       if (topologyRequestCount != topologyRequestTablesJoinedCount) {
-         error("Your topology request hierarchy is not complete for each row in topology_request should exist " +
-           "at least one raw in topology_logical_request, topology_host_request, topology_host_task, " +
-           "topology_logical_task.");
-       }
- 
- 
      } catch (SQLException e) {
-       LOG.error("Exception occurred during topology request tables check: ", e);
 -      warning("Exception occurred during topology request tables check: ", e);
++      error("Exception occurred during topology request tables check: ", e);
      } finally {
        if (rs != null) {
          try {
@@@ -587,7 -547,7 +539,7 @@@
        }
  
      } catch (SQLException e) {
-       LOG.error("Exception occurred during check for same count of host component states and host component desired states: ", e);
 -      warning("Exception occurred during check for same count of host component states and host component desired states: ", e);
++      error("Exception occurred during check for same count of host component states and host component desired states: ", e);
      } finally {
        if (rs != null) {
          try {
@@@ -819,7 -786,7 +778,7 @@@
          }
        }
      } catch (SQLException e) {
-       LOG.error("Exception occurred during checking MySQL engine to be innodb: ", e);
 -      warning("Exception occurred during checking MySQL engine to be innodb: ", e);
++      error("Exception occurred during checking MySQL engine to be innodb: ", e);
      } finally {
        if (rs != null) {
          try {
@@@ -1053,13 -1122,11 +1024,11 @@@
        for (String clusterName : clusterServiceConfigType.keySet()) {
          Multimap<String, String> serviceConfig = clusterServiceConfigType.get(clusterName);
          for (String serviceName : serviceConfig.keySet()) {
 -          warning("You have non selected configs: {} for service {} from cluster {}!", StringUtils.join(serviceConfig.get(serviceName), ","), serviceName, clusterName);
 +          error("You have non selected configs: {} for service {} from cluster {}!", StringUtils.join(serviceConfig.get(serviceName), ","), serviceName, clusterName);
          }
        }
-     } catch (SQLException e) {
-       LOG.error("Exception occurred during complex service check procedure: ", e);
-     } catch (AmbariException e) {
-       LOG.error("Exception occurred during complex service check procedure: ", e);
+     } catch (SQLException | AmbariException e) {
 -      warning("Exception occurred during complex service check procedure: ", e);
++      error("Exception occurred during complex service check procedure: ", e);
      } finally {
        if (rs != null) {
          try {

http://git-wip-us.apache.org/repos/asf/ambari/blob/be73d167/ambari-server/src/main/java/org/apache/ambari/server/checks/ServiceCheckValidityCheck.java
----------------------------------------------------------------------
diff --cc ambari-server/src/main/java/org/apache/ambari/server/checks/ServiceCheckValidityCheck.java
index 4ccdc0a,a4c2430..ad68a2c
--- a/ambari-server/src/main/java/org/apache/ambari/server/checks/ServiceCheckValidityCheck.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/checks/ServiceCheckValidityCheck.java
@@@ -73,15 -63,6 +73,17 @@@ public class ServiceCheckValidityCheck 
    private static final Logger LOG = LoggerFactory.getLogger(ServiceCheckValidityCheck.class);
  
    private static final SimpleDateFormat DATE_FORMAT = new SimpleDateFormat("MM-dd-yyyy hh:mm:ss");
 +  private static List<SortRequestProperty> sortRequestProperties =
 +      Collections.singletonList(new SortRequestProperty(TaskResourceProvider.TASK_START_TIME_PROPERTY_ID, SortRequest.Order.DESC));
 +  private static SortRequest sortRequest = new SortRequestImpl(sortRequestProperties);
 +  private static final PageRequestImpl PAGE_REQUEST = new PageRequestImpl(PageRequest.StartingPoint.End, 1000, 0, null, null);
 +  private static final RequestImpl REQUEST = new RequestImpl(null, null, null, null, sortRequest, PAGE_REQUEST);
-   private static final Predicate PREDICATE = new PredicateBuilder().property(TaskResourceProvider.TASK_COMMAND_PROPERTY_ID)
-       .equals(RoleCommand.SERVICE_CHECK.name()).toPredicate();
++  private static final Predicate PREDICATE = new PredicateBuilder()
++    .property(TaskResourceProvider.TASK_COMMAND_PROPERTY_ID).equals(RoleCommand.SERVICE_CHECK.name())
++    .and().property(TaskResourceProvider.TASK_START_TIME_PROPERTY_ID).greaterThan(-1)
++    .toPredicate();
 +
 +
  
    @Inject
    Provider<ServiceConfigDAO> serviceConfigDAOProvider;
@@@ -89,6 -70,9 +91,7 @@@
    @Inject
    Provider<HostRoleCommandDAO> hostRoleCommandDAOProvider;
  
 -  @Inject
 -  Provider<ActionMetadata> actionMetadataProvider;
+ 
    /**
     * Constructor.
     */
@@@ -127,43 -111,34 +130,43 @@@
        }
      }
  
 -    // get the latest service checks, grouped by role
 -    List<LastServiceCheckDTO> lastServiceChecks = hostRoleCommandDAO.getLatestServiceChecksByRole(clusterId);
 -    Map<String, Long> lastServiceChecksByRole = new HashMap<>();
 -    for( LastServiceCheckDTO lastServiceCheck : lastServiceChecks ) {
 -      lastServiceChecksByRole.put(lastServiceCheck.role, lastServiceCheck.endTime);
 -    }
 +    List<HostRoleCommandEntity> commands = hostRoleCommandDAO.findAll(REQUEST, PREDICATE);
  
 -    LinkedHashSet<String> failedServiceNames = new LinkedHashSet<>();
 +    // !!! build a map of Role to latest-config-check in case it was rerun multiple times, we want the latest
 +    Map<Role, HostRoleCommandEntity> latestTimestamps = new HashMap<>();
 +    for (HostRoleCommandEntity command : commands) {
 +      Role role = command.getRole();
  
 -    // for every service, see if there was a service check executed and then
 -    for( Entry<String, Long> entry : lastServiceConfigUpdates.entrySet() ) {
 -      String serviceName = entry.getKey();
 -      long configCreationTime = entry.getValue();
 -      String role = actionMetadataProvider.get().getServiceCheckAction(serviceName);
 +      // Because results are already sorted by start_time desc, first occurrence is guaranteed to have max(start_time).
 +      if (!latestTimestamps.containsKey(role)) {
 +        latestTimestamps.put(role, command);
 +      }
 +    }
  
 -      if(!lastServiceChecksByRole.containsKey(role) ) {
 -        LOG.info("There was no service check found for service {} matching role {}", serviceName, role);
 -        failedServiceNames.add(serviceName);
 -        continue;
 +    LinkedHashSet<String> failedServiceNames = new LinkedHashSet<>();
 +    for (Map.Entry<String, Long> serviceEntry : lastServiceConfigUpdates.entrySet()) {
 +      String serviceName = serviceEntry.getKey();
 +      Long configTimestamp = serviceEntry.getValue();
 +
 +      boolean serviceCheckWasExecuted = false;
 +      for (HostRoleCommandEntity command : latestTimestamps.values()) {
-         if (command.getCommandDetail().contains(serviceName)) {
++        if (null !=  command.getCommandDetail() && command.getCommandDetail().contains(serviceName)) {
 +          serviceCheckWasExecuted = true;
 +          Long serviceCheckTimestamp = command.getStartTime();
 +
 +          if (serviceCheckTimestamp < configTimestamp) {
 +            failedServiceNames.add(serviceName);
 +            LOG.info("Service {} latest config change is {}, latest service check executed at {}",
 +                serviceName,
 +                DATE_FORMAT.format(new Date(configTimestamp)),
 +                DATE_FORMAT.format(new Date(serviceCheckTimestamp)));
 +          }
 +        }
        }
  
 -      long lastServiceCheckTime = lastServiceChecksByRole.get(role);
 -      if (lastServiceCheckTime < configCreationTime) {
 +      if (!serviceCheckWasExecuted) {
          failedServiceNames.add(serviceName);
 -        LOG.info(
 -            "The {} service (role {}) had its configurations updated on {}, but the last service check was {}",
 -            serviceName, role, DATE_FORMAT.format(new Date(configCreationTime)),
 -            DATE_FORMAT.format(new Date(lastServiceCheckTime)));
 +        LOG.info("Service {} service check has never been executed", serviceName);
        }
      }
  

http://git-wip-us.apache.org/repos/asf/ambari/blob/be73d167/ambari-server/src/main/java/org/apache/ambari/server/checks/ServicesUpCheck.java
----------------------------------------------------------------------

http://git-wip-us.apache.org/repos/asf/ambari/blob/be73d167/ambari-server/src/main/java/org/apache/ambari/server/configuration/Configuration.java
----------------------------------------------------------------------

http://git-wip-us.apache.org/repos/asf/ambari/blob/be73d167/ambari-server/src/main/java/org/apache/ambari/server/controller/AmbariCustomCommandExecutionHelper.java
----------------------------------------------------------------------
diff --cc ambari-server/src/main/java/org/apache/ambari/server/controller/AmbariCustomCommandExecutionHelper.java
index 02e52ea,d0dd7e0..d3e1488
--- a/ambari-server/src/main/java/org/apache/ambari/server/controller/AmbariCustomCommandExecutionHelper.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/controller/AmbariCustomCommandExecutionHelper.java
@@@ -71,9 -71,10 +68,8 @@@ import org.apache.ambari.server.control
  import org.apache.ambari.server.controller.internal.RequestResourceFilter;
  import org.apache.ambari.server.controller.spi.Resource;
  import org.apache.ambari.server.metadata.ActionMetadata;
- import org.apache.ambari.server.orm.dao.ClusterVersionDAO;
  import org.apache.ambari.server.orm.dao.HostRoleCommandDAO;
- import org.apache.ambari.server.orm.entities.ClusterVersionEntity;
 -import org.apache.ambari.server.orm.entities.OperatingSystemEntity;
 -import org.apache.ambari.server.orm.entities.RepositoryEntity;
+ import org.apache.ambari.server.orm.entities.RepositoryVersionEntity;
  import org.apache.ambari.server.state.Cluster;
  import org.apache.ambari.server.state.Clusters;
  import org.apache.ambari.server.state.CommandScriptDefinition;
@@@ -85,8 -87,9 +82,8 @@@ import org.apache.ambari.server.state.H
  import org.apache.ambari.server.state.HostComponentAdminState;
  import org.apache.ambari.server.state.HostState;
  import org.apache.ambari.server.state.MaintenanceState;
+ import org.apache.ambari.server.state.PropertyInfo;
  import org.apache.ambari.server.state.PropertyInfo.PropertyType;
- import org.apache.ambari.server.state.RepositoryVersionState;
 -import org.apache.ambari.server.state.RepositoryInfo;
  import org.apache.ambari.server.state.Service;
  import org.apache.ambari.server.state.ServiceComponent;
  import org.apache.ambari.server.state.ServiceComponentHost;
@@@ -391,8 -409,10 +399,8 @@@ public class AmbariCustomCommandExecuti
  
        Map<String, String> hostLevelParams = new TreeMap<>();
  
 -      hostLevelParams.put(CUSTOM_COMMAND, commandName);
 -
        // Set parameters required for re-installing clients on restart
-       hostLevelParams.put(REPO_INFO, ambariMetaInfo.getRepoInfoString(cluster, host));
 -      hostLevelParams.put(REPO_INFO, getRepoInfo(cluster, component, host));
++      hostLevelParams.put(REPO_INFO, ambariMetaInfo.getRepoInfoString(cluster, component, host));
        hostLevelParams.put(STACK_NAME, stackId.getStackName());
        hostLevelParams.put(STACK_VERSION, stackId.getStackVersion());
  
@@@ -424,10 -445,9 +433,10 @@@
            commandParams.put(key, additionalCommandParams.get(key));
          }
        }
 +      commandParams.put(CUSTOM_COMMAND, commandName);
  
        boolean isInstallCommand = commandName.equals(RoleCommand.INSTALL.toString());
-       String commandTimeout = configs.getDefaultAgentTaskTimeout(isInstallCommand);
+       int commandTimeout = Short.valueOf(configs.getDefaultAgentTaskTimeout(isInstallCommand)).intValue();
  
        ComponentInfo componentInfo = ambariMetaInfo.getComponent(
            stackId.getStackName(), stackId.getStackVersion(),
@@@ -471,6 -510,8 +499,8 @@@
        execCmd.setCommandParams(commandParams);
        execCmd.setRoleParams(roleParams);
  
 -      execCmd.setRepositoryFile(getCommandRepository(cluster, component, host));
++      execCmd.setRepositoryFile(ambariMetaInfo.getCommandRepository(cluster, component, host));
+ 
        // perform any server side command related logic - eg - set desired states on restart
        applyCustomCommandBackendLogic(cluster, serviceName, componentName, commandName, hostName);
      }
@@@ -1248,10 -1520,23 +1308,19 @@@
     */
    public boolean isTopologyRefreshRequired(String actionName, String clusterName, String serviceName)
        throws AmbariException {
+ 
      if (actionName.equals(START_COMMAND_NAME) || actionName.equals(RESTART_COMMAND_NAME)) {
        Cluster cluster = clusters.getCluster(clusterName);
-       StackId stackId = cluster.getDesiredStackVersion();
+       StackId stackId = null;
 -      if (serviceName != null) {
 -        try {
 -          Service service = cluster.getService(serviceName);
 -          stackId = service.getDesiredStackId();
 -        } catch (AmbariException e) {
 -          LOG.debug("Could not load service {}, skipping topology check", serviceName);
 -        }
 -      }
 -
 -      if (stackId == null) {
++      try {
++        Service service = cluster.getService(serviceName);
++        stackId = service.getDesiredStackId();
++      } catch (AmbariException e) {
++        LOG.debug("Could not load service {}, skipping topology check", serviceName);
+         stackId = cluster.getDesiredStackVersion();
+       }
+ 
 +
        AmbariMetaInfo ambariMetaInfo = managementController.getAmbariMetaInfo();
  
        StackInfo stack = ambariMetaInfo.getStack(stackId.getStackName(), stackId.getStackVersion());

http://git-wip-us.apache.org/repos/asf/ambari/blob/be73d167/ambari-server/src/main/java/org/apache/ambari/server/controller/AmbariHandlerList.java
----------------------------------------------------------------------