You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ambari.apache.org by al...@apache.org on 2016/02/24 20:59:04 UTC

ambari git commit: AMBARI-13424. Allow disabling RU/EU PreChecks (alejandro)

Repository: ambari
Updated Branches:
  refs/heads/trunk 3cee3de48 -> 970f2cf8f


AMBARI-13424. Allow disabling RU/EU PreChecks (alejandro)


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

Branch: refs/heads/trunk
Commit: 970f2cf8f5ca6ca80fc683cab8b781d04e7e2d1f
Parents: 3cee3de
Author: Alejandro Fernandez <af...@hortonworks.com>
Authored: Wed Feb 24 11:47:02 2016 -0800
Committer: Alejandro Fernandez <af...@hortonworks.com>
Committed: Wed Feb 24 11:53:48 2016 -0800

----------------------------------------------------------------------
 .../server/checks/AbstractCheckDescriptor.java  |  8 +++
 .../server/configuration/Configuration.java     | 14 +++++
 .../apache/ambari/server/state/CheckHelper.java | 62 +++++++++++++++++---
 .../server/state/stack/PrereqCheckStatus.java   | 13 ++++
 .../ambari/server/state/CheckHelperTest.java    | 59 ++++++++++++++++++-
 .../main/admin/stack_and_upgrade_controller.js  | 33 +++++++++--
 ambari-web/app/messages.js                      |  3 +
 ambari-web/app/styles/stack_versions.less       |  2 +-
 .../modal_popups/cluster_check_dialog.hbs       | 19 ++++++
 .../admin/stack_upgrade/upgrade_options.hbs     |  3 +
 .../common/modal_popups/cluster_check_popup.js  |  4 +-
 11 files changed, 205 insertions(+), 15 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/ambari/blob/970f2cf8/ambari-server/src/main/java/org/apache/ambari/server/checks/AbstractCheckDescriptor.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/checks/AbstractCheckDescriptor.java b/ambari-server/src/main/java/org/apache/ambari/server/checks/AbstractCheckDescriptor.java
index 8a81aa9..597c121 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/checks/AbstractCheckDescriptor.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/checks/AbstractCheckDescriptor.java
@@ -286,4 +286,12 @@ public abstract class AbstractCheckDescriptor {
   public Boolean isRequired(){
       return getClass().getAnnotation(UpgradeCheck.class).required();
   }
+  
+  /**
+   * Return a boolean indicating whether or not configs allow bypassing errors during the RU/EU PreChecks.
+   * @return
+   */
+  public boolean isStackUpgradeAllowedToBypassPreChecks() {
+    return config.isUpgradePrecheckBypass();
+  }
 }

http://git-wip-us.apache.org/repos/asf/ambari/blob/970f2cf8/ambari-server/src/main/java/org/apache/ambari/server/configuration/Configuration.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/configuration/Configuration.java b/ambari-server/src/main/java/org/apache/ambari/server/configuration/Configuration.java
index c63d043..882adb2 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/configuration/Configuration.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/configuration/Configuration.java
@@ -195,8 +195,13 @@ public class Configuration {
   public static final String SERVER_JDBC_DRIVER_KEY = "server.jdbc.driver";
   public static final String SERVER_JDBC_URL_KEY = "server.jdbc.url";
   public static final String SERVER_JDBC_PROPERTIES_PREFIX = "server.jdbc.properties.";
+
+  // Properties for stack upgrade (Rolling, Express)
   public static final String ROLLING_UPGRADE_SKIP_PACKAGES_PREFIXES_KEY = "rolling.upgrade.skip.packages.prefixes";
   public static final String ROLLING_UPGRADE_SKIP_PACKAGES_PREFIXES_DEFAULT = "";
+  public static final String STACK_UPGRADE_BYPASS_PRECHECKS_KEY = "stack.upgrade.bypass.prechecks";
+  public static final String STACK_UPGRADE_BYPASS_PRECHECKS_DEFAULT = "false";
+
   public static final String JWT_AUTH_ENBABLED = "authentication.jwt.enabled";
   public static final String JWT_AUTH_PROVIDER_URL = "authentication.jwt.providerUrl";
   public static final String JWT_PUBLIC_KEY = "authentication.jwt.publicKey";
@@ -1061,6 +1066,15 @@ public class Configuration {
   }
 
   /**
+   * Determine whether or not a Rolling/Express upgrade can bypass the PreChecks. Default value should be false.
+   *
+   * @return true if RU/EU can bypass PreChecks, otherwise, false.
+   */
+  public boolean isUpgradePrecheckBypass() {
+    return Boolean.parseBoolean(properties.getProperty(STACK_UPGRADE_BYPASS_PRECHECKS_KEY, STACK_UPGRADE_BYPASS_PRECHECKS_DEFAULT));
+  }
+
+  /**
    * Get the map with server config parameters.
    * Keys - public constants of this class
    * @return the map with server config parameters

http://git-wip-us.apache.org/repos/asf/ambari/blob/970f2cf8/ambari-server/src/main/java/org/apache/ambari/server/state/CheckHelper.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/state/CheckHelper.java b/ambari-server/src/main/java/org/apache/ambari/server/state/CheckHelper.java
index 5a8d4fd..9192285 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/state/CheckHelper.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/state/CheckHelper.java
@@ -18,6 +18,7 @@
 package org.apache.ambari.server.state;
 
 import java.util.ArrayList;
+import java.util.LinkedList;
 import java.util.List;
 
 import org.apache.ambari.server.ClusterNotFoundException;
@@ -25,11 +26,24 @@ import org.apache.ambari.server.checks.AbstractCheckDescriptor;
 import org.apache.ambari.server.controller.PrereqCheckRequest;
 import org.apache.ambari.server.state.stack.PrereqCheckStatus;
 import org.apache.ambari.server.state.stack.PrerequisiteCheck;
+import org.apache.commons.lang.StringUtils;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
 import com.google.inject.Singleton;
 
+
+class DescriptorPreCheck {
+
+  public AbstractCheckDescriptor descriptor;
+  public PrerequisiteCheck check;
+
+  public DescriptorPreCheck(AbstractCheckDescriptor descriptor, PrerequisiteCheck check) {
+    this.descriptor = descriptor;
+    this.check = check;
+  }
+}
+
 @Singleton
 public class CheckHelper {
   /**
@@ -37,6 +51,33 @@ public class CheckHelper {
    */
   private static Logger LOG = LoggerFactory.getLogger(CheckHelper.class);
 
+
+  /**
+   * Get the list of applicable prechecks. This function exists because it had to be mocked during a test in
+   * {@see CheckHelperTest }
+   * @param request Pre Check Request
+   * @param checksRegistry Registry with all PreChecks that may be applied.
+   * @return List of applicable PreChecks.
+   */
+  public List<DescriptorPreCheck> getApplicablePrerequisiteChecks(PrereqCheckRequest request,
+                                                       List<AbstractCheckDescriptor> checksRegistry) {
+    List<DescriptorPreCheck> applicablePreChecks = new LinkedList<>();
+
+    final String clusterName = request.getClusterName();
+    for (AbstractCheckDescriptor checkDescriptor : checksRegistry) {
+      final PrerequisiteCheck prerequisiteCheck = new PrerequisiteCheck(checkDescriptor.getDescription(), clusterName);
+
+      try {
+        if (checkDescriptor.isApplicable(request)) {
+          applicablePreChecks.add(new DescriptorPreCheck(checkDescriptor, prerequisiteCheck));
+        }
+      } catch (Exception ex) {
+        LOG.error("Check " + checkDescriptor.getDescription().name() + " failed", ex);
+      }
+    }
+    return applicablePreChecks;
+  }
+
   /**
    * Executes all registered pre-requisite checks.
    *
@@ -49,16 +90,23 @@ public class CheckHelper {
 
     final String clusterName = request.getClusterName();
     final List<PrerequisiteCheck> prerequisiteCheckResults = new ArrayList<PrerequisiteCheck>();
-    for (AbstractCheckDescriptor checkDescriptor : checksRegistry) {
-      final PrerequisiteCheck prerequisiteCheck = new PrerequisiteCheck(
-          checkDescriptor.getDescription(), clusterName);
 
+    List<DescriptorPreCheck> applicablePreChecks = getApplicablePrerequisiteChecks(request, checksRegistry);
+    for (DescriptorPreCheck descriptorPreCheck : applicablePreChecks) {
+      AbstractCheckDescriptor checkDescriptor = descriptorPreCheck.descriptor;
+      PrerequisiteCheck prerequisiteCheck = descriptorPreCheck.check;
       try {
-        if (!checkDescriptor.isApplicable(request)) {
-          continue;
-        }
-
         checkDescriptor.perform(prerequisiteCheck, request);
+
+        boolean canBypassPreChecks = checkDescriptor.isStackUpgradeAllowedToBypassPreChecks();
+
+        if (prerequisiteCheck.getStatus() == PrereqCheckStatus.FAIL && canBypassPreChecks) {
+          LOG.error("Check {} failed but stack upgrade is allowed to bypass failures. Error to bypass: {}. Failed on: {}",
+              checkDescriptor.getDescription().name(),
+              prerequisiteCheck.getFailReason(),
+              StringUtils.join(prerequisiteCheck.getFailedOn(), ", "));
+          prerequisiteCheck.setStatus(PrereqCheckStatus.BYPASS);
+        }
         prerequisiteCheckResults.add(prerequisiteCheck);
 
         request.addResult(checkDescriptor.getDescription(), prerequisiteCheck.getStatus());

http://git-wip-us.apache.org/repos/asf/ambari/blob/970f2cf8/ambari-server/src/main/java/org/apache/ambari/server/state/stack/PrereqCheckStatus.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/state/stack/PrereqCheckStatus.java b/ambari-server/src/main/java/org/apache/ambari/server/state/stack/PrereqCheckStatus.java
index f8009e3..1402b3d 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/state/stack/PrereqCheckStatus.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/state/stack/PrereqCheckStatus.java
@@ -21,7 +21,20 @@ package org.apache.ambari.server.state.stack;
  * Indicates status of prerequisite check.
  */
 public enum PrereqCheckStatus {
+  /**
+   * The check passed with no warnings or errors.
+   */
   PASS,
+  /**
+   * The check passed but reporting a warning that should be examined.
+   */
   WARNING,
+  /**
+   * The check failed but a configuration allows bypassing failures.
+   */
+  BYPASS,
+  /**
+   * The check failed and is not allowed to bypass errors.
+   */
   FAIL
 }

http://git-wip-us.apache.org/repos/asf/ambari/blob/970f2cf8/ambari-server/src/test/java/org/apache/ambari/server/state/CheckHelperTest.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/test/java/org/apache/ambari/server/state/CheckHelperTest.java b/ambari-server/src/test/java/org/apache/ambari/server/state/CheckHelperTest.java
index 283a3ca..deca9b8 100644
--- a/ambari-server/src/test/java/org/apache/ambari/server/state/CheckHelperTest.java
+++ b/ambari-server/src/test/java/org/apache/ambari/server/state/CheckHelperTest.java
@@ -19,6 +19,7 @@
 package org.apache.ambari.server.state;
 
 import java.util.ArrayList;
+import java.util.LinkedList;
 import java.util.List;
 
 import junit.framework.Assert;
@@ -29,7 +30,6 @@ import org.apache.ambari.server.api.services.AmbariMetaInfo;
 import org.apache.ambari.server.checks.AbstractCheckDescriptor;
 import org.apache.ambari.server.checks.CheckDescription;
 import org.apache.ambari.server.checks.ServicesUpCheck;
-import org.apache.ambari.server.configuration.Configuration;
 import org.apache.ambari.server.controller.PrereqCheckRequest;
 import org.apache.ambari.server.orm.dao.ClusterVersionDAO;
 import org.apache.ambari.server.orm.dao.HostVersionDAO;
@@ -61,6 +61,9 @@ public class CheckHelperTest {
    * Makes sure that people don't forget to add new checks to registry.
    */
 
+  /**
+   * Sunny case when applicable.
+   */
   @Test
   public void testPreUpgradeCheck() throws Exception {
     final CheckHelper helper = new CheckHelper();
@@ -76,6 +79,9 @@ public class CheckHelperTest {
     EasyMock.verify(descriptor);
   }
 
+  /**
+   * Checks can be ignored, even if they are expected to fail.
+   */
   @Test
   public void testPreUpgradeCheckNotApplicable() throws Exception {
     final CheckHelper helper = new CheckHelper();
@@ -88,6 +94,9 @@ public class CheckHelperTest {
     EasyMock.verify(descriptor);
   }
 
+  /**
+   * Check that throwing an exception still fails.
+   */
   @Test
   public void testPreUpgradeCheckThrowsException() throws Exception {
     final CheckHelper helper = new CheckHelper();
@@ -105,6 +114,25 @@ public class CheckHelperTest {
     Assert.assertEquals(PrereqCheckStatus.FAIL, upgradeChecks.get(0).getStatus());
   }
 
+  /**
+   * Test that applicable tests that fail when configured to bypass failures results in a status of {@see PrereqCheckStatus.BYPASS}
+   */
+  @Test
+  public void testPreUpgradeCheckBypassesFailure() throws Exception {
+    // This mock class extends CheckHelper and overrides the getPrerequisiteChecks method in order to return
+    // a PrerequisiteCheck object whose status is FAIL.
+    final CheckHelperMock helper =  new CheckHelperMock();
+    List<AbstractCheckDescriptor> updateChecksRegistry = new ArrayList<AbstractCheckDescriptor>();
+
+    PrereqCheckRequest checkRequest = EasyMock.createNiceMock(PrereqCheckRequest.class);
+    EasyMock.expect(checkRequest.getClusterName()).andReturn("c1").anyTimes();
+    EasyMock.replay(checkRequest);
+
+    final List<PrerequisiteCheck> upgradeChecks = helper.performChecks(checkRequest, updateChecksRegistry);
+    Assert.assertEquals(1, upgradeChecks.size());
+    Assert.assertEquals(PrereqCheckStatus.BYPASS, upgradeChecks.get(0).getStatus());
+  }
+
   @Test
   public void testPreUpgradeCheckClusterMissing() throws Exception {
     final Clusters clusters = Mockito.mock(Clusters.class);
@@ -150,5 +178,34 @@ public class CheckHelperTest {
     //non existing cluster is an expected error
     Assert.assertTrue(!upgradeChecks.get(0).getFailReason().equals("Unexpected server error happened"));
   }
+
+  class CheckHelperMock extends CheckHelper {
+    @Override
+    public List<DescriptorPreCheck> getApplicablePrerequisiteChecks(PrereqCheckRequest request,
+                                                          List<AbstractCheckDescriptor> checksRegistry) {
+
+      List<DescriptorPreCheck> applicablePreChecks = new LinkedList<>();
+
+      try {
+        CheckDescription description = CheckDescription.SERVICES_UP;
+        PrerequisiteCheck check = new PrerequisiteCheck(description, "c1");
+        check.setStatus(PrereqCheckStatus.FAIL);
+
+        AbstractCheckDescriptor descriptor = EasyMock.createNiceMock(AbstractCheckDescriptor.class);
+        EasyMock.expect(descriptor.isApplicable(EasyMock.<PrereqCheckRequest>anyObject())).andReturn(true);
+        EasyMock.expect(descriptor.getDescription()).andReturn(description).anyTimes();
+
+        // Allow bypassing failures
+        EasyMock.expect(descriptor.isStackUpgradeAllowedToBypassPreChecks()).andReturn(true);
+        EasyMock.replay(descriptor);
+
+        applicablePreChecks.add(new DescriptorPreCheck(descriptor, check));
+      } catch (AmbariException e) {
+        ;
+      }
+
+      return applicablePreChecks;
+    }
+  }
 }
 

http://git-wip-us.apache.org/repos/asf/ambari/blob/970f2cf8/ambari-web/app/controllers/main/admin/stack_and_upgrade_controller.js
----------------------------------------------------------------------
diff --git a/ambari-web/app/controllers/main/admin/stack_and_upgrade_controller.js b/ambari-web/app/controllers/main/admin/stack_and_upgrade_controller.js
index c226059..06f8ae1 100644
--- a/ambari-web/app/controllers/main/admin/stack_and_upgrade_controller.js
+++ b/ambari-web/app/controllers/main/admin/stack_and_upgrade_controller.js
@@ -881,9 +881,16 @@ App.MainAdminStackAndUpgradeController = Em.Controller.extend(App.LocalStorage,
         openMessage: function (event) {
           if (isInUpgradeWizard || !event.context.get('allowed')) return;
           var data = event.context.get('precheckResultsData');
+
+          var failTitle = Em.I18n.t('popup.clusterCheck.Upgrade.fail.title');
+          var failAlert = new Em.Handlebars.SafeString(Em.I18n.t('popup.clusterCheck.Upgrade.fail.alert'));
+          var bypassedFailures = data.items.filterProperty('UpgradeChecks.status', 'BYPASS').length > 0;
+          if (data.items.filterProperty('UpgradeChecks.status', 'ERROR').length == 0 && bypassedFailures) {
+            failTitle = Em.I18n.t('popup.clusterCheck.Upgrade.bypassed-failures.title');
+            failAlert = new Em.Handlebars.SafeString(Em.I18n.t('popup.clusterCheck.Upgrade.bypassed-failures.alert'));
+          }
+
           var header = Em.I18n.t('popup.clusterCheck.Upgrade.header').format(version.get('displayName')),
-            failTitle = Em.I18n.t('popup.clusterCheck.Upgrade.fail.title'),
-            failAlert = new Em.Handlebars.SafeString(Em.I18n.t('popup.clusterCheck.Upgrade.fail.alert')),
             warningTitle = Em.I18n.t('popup.clusterCheck.Upgrade.warning.title'),
             warningAlert = new Em.Handlebars.SafeString(Em.I18n.t('popup.clusterCheck.Upgrade.warning.alert')),
             configsMergeWarning = data.items.findProperty('UpgradeChecks.id', "CONFIG_MERGE"),
@@ -899,6 +906,7 @@ App.MainAdminStackAndUpgradeController = Em.Controller.extend(App.LocalStorage,
             warningAlert: warningAlert,
             primary: Em.I18n.t('admin.stackVersions.version.upgrade.upgradeOptions.preCheck.rerun'),
             secondary: Em.I18n.t('common.cancel'),
+            bypassedFailures: bypassedFailures,
             callback: function () {
               self.runPreUpgradeCheckOnly.call(self, {
                 value: version.get('repositoryVersion'),
@@ -1028,7 +1036,7 @@ App.MainAdminStackAndUpgradeController = Em.Controller.extend(App.LocalStorage,
 
   /**
    * success callback of <code>runPreUpgradeCheckOnly()</code>
-   * Show a message how many fails/warnings/passed
+   * Show a message how many fails/warnings/bypass/passed
    * on clicking that message a popup window show up
    * @param data {object}
    * @param opt {object}
@@ -1038,15 +1046,27 @@ App.MainAdminStackAndUpgradeController = Em.Controller.extend(App.LocalStorage,
     var self = this;
     var message = '';
     var messageClass = 'GREEN';
+    var allowedToStart = true;
     var messageIconClass = 'icon-ok';
+    var bypassedFailures = false;
+
     if (data.items.someProperty('UpgradeChecks.status', 'WARNING')) {
       message = message + data.items.filterProperty('UpgradeChecks.status', 'WARNING').length + ' Warning ';
       messageClass = 'ORANGE';
+      allowedToStart = true;
       messageIconClass = 'icon-warning-sign';
     }
+    if (data.items.someProperty('UpgradeChecks.status', 'BYPASS')) {
+      message = data.items.filterProperty('UpgradeChecks.status', 'BYPASS').length + ' Error ' + message;
+      messageClass = 'RED';
+      allowedToStart = true;
+      messageIconClass = 'icon-remove';
+      bypassedFailures = true;
+    }
     if (data.items.someProperty('UpgradeChecks.status', 'FAIL')) {
       message = data.items.filterProperty('UpgradeChecks.status', 'FAIL').length + ' Required ' + message;
       messageClass = 'RED';
+      allowedToStart = false;
       messageIconClass = 'icon-remove';
     }
 
@@ -1058,10 +1078,11 @@ App.MainAdminStackAndUpgradeController = Em.Controller.extend(App.LocalStorage,
       precheckResultsMessage: message,
       precheckResultsMessageClass: messageClass,
       precheckResultsTitle: Em.I18n.t('admin.stackVersions.version.upgrade.upgradeOptions.preCheck.msg.title'),
-      isPrecheckFailed: messageClass == 'RED',
+      isPrecheckFailed: allowedToStart === false,
       precheckResultsMessageIconClass: messageIconClass,
       precheckResultsData: data,
       isCheckComplete: true,
+      bypassedFailures: bypassedFailures,
       action: 'openMessage'
     });
     this.updateSelectedMethod(false);
@@ -1147,7 +1168,7 @@ App.MainAdminStackAndUpgradeController = Em.Controller.extend(App.LocalStorage,
    */
   runPreUpgradeCheckSuccess: function (data, opt, params) {
     var self = this;
-    if (data.items.someProperty('UpgradeChecks.status', 'FAIL') || data.items.someProperty('UpgradeChecks.status', 'WARNING')) {
+    if (data.items.someProperty('UpgradeChecks.status', 'FAIL') || data.items.someProperty('UpgradeChecks.status', 'WARNING') || data.items.someProperty('UpgradeChecks.status', 'BYPASS')) {
       this.set('requestInProgress', false);
       var hasFails = data.items.someProperty('UpgradeChecks.status', 'FAIL'),
         header = Em.I18n.t('popup.clusterCheck.Upgrade.header').format(params.label),
@@ -1155,6 +1176,7 @@ App.MainAdminStackAndUpgradeController = Em.Controller.extend(App.LocalStorage,
         failAlert = new Em.Handlebars.SafeString(Em.I18n.t('popup.clusterCheck.Upgrade.fail.alert')),
         warningTitle = Em.I18n.t('popup.clusterCheck.Upgrade.warning.title'),
         warningAlert = new Em.Handlebars.SafeString(Em.I18n.t('popup.clusterCheck.Upgrade.warning.alert')),
+        bypassedFailures = data.items.someProperty('UpgradeChecks.status', 'BYPASS').length > 0,
         configsMergeWarning = data.items.findProperty('UpgradeChecks.id', 'CONFIG_MERGE'),
         popupData = {
           items: data.items.rejectProperty('UpgradeChecks.id', 'CONFIG_MERGE')
@@ -1166,6 +1188,7 @@ App.MainAdminStackAndUpgradeController = Em.Controller.extend(App.LocalStorage,
         failAlert: failAlert,
         warningTitle: warningTitle,
         warningAlert: warningAlert,
+        bypassedFailures: bypassedFailures,
         noCallbackCondition: hasFails,
         callback: function () {
           self.upgrade(params);

http://git-wip-us.apache.org/repos/asf/ambari/blob/970f2cf8/ambari-web/app/messages.js
----------------------------------------------------------------------
diff --git a/ambari-web/app/messages.js b/ambari-web/app/messages.js
index 95f87f8..733ac86 100644
--- a/ambari-web/app/messages.js
+++ b/ambari-web/app/messages.js
@@ -392,6 +392,8 @@ Em.I18n.translations = {
   'popup.clusterCheck.Upgrade.header': 'Upgrade to {0}',
   'popup.clusterCheck.Upgrade.fail.title': 'Requirements',
   'popup.clusterCheck.Upgrade.fail.alert': 'You <strong>must</strong> meet these requirements before you can proceed.',
+  'popup.clusterCheck.Upgrade.bypassed-failures.title': 'Errors that can be bypassed',
+  'popup.clusterCheck.Upgrade.bypassed-failures.alert': 'Errors are allowed to be bypassed since config stack.upgrade.bypass.prechecks is set to true. It is strongly encouraged to look into these failures.',
   'popup.clusterCheck.Upgrade.warning.title': 'Warnings',
   'popup.clusterCheck.Upgrade.warning.alert': 'Correcting the warnings is not required but is <strong>recommended</strong>.',
   'popup.clusterCheck.Upgrade.configsMerge.title': 'Configuration Changes',
@@ -1515,6 +1517,7 @@ Em.I18n.translations = {
   'admin.stackVersions.version.upgrade.upgradeOptions.RU.description': "Services remain running while the upgrade is performed. Minimized disruption but slower upgrade.",
   'admin.stackVersions.version.upgrade.upgradeOptions.EU.title': "Express Upgrade",
   'admin.stackVersions.version.upgrade.upgradeOptions.EU.description': "Services are stopped while the upgrade is performed. Incurs downtime, but faster upgrade.",
+  'admin.stackVersions.version.upgrade.upgradeOptions.errors_bypassed': "Bypassed errors,<br/>proceed at your own risk.",
   'admin.stackVersions.version.upgrade.upgradeOptions.preCheck.rerun':'Rerun Checks',
   'admin.stackVersions.version.upgrade.upgradeOptions.preCheck.msg.title':'Checks:',
   'admin.stackVersions.version.upgrade.upgradeOptions.preCheck.msg.checking': 'Checking...',

http://git-wip-us.apache.org/repos/asf/ambari/blob/970f2cf8/ambari-web/app/styles/stack_versions.less
----------------------------------------------------------------------
diff --git a/ambari-web/app/styles/stack_versions.less b/ambari-web/app/styles/stack_versions.less
index 25f474e..646e441 100644
--- a/ambari-web/app/styles/stack_versions.less
+++ b/ambari-web/app/styles/stack_versions.less
@@ -435,7 +435,7 @@
       width: 43.5%;
     }
     .thumbnail {
-      height: 165px;
+
       cursor: pointer;
       border: none;
       width: 99%;

http://git-wip-us.apache.org/repos/asf/ambari/blob/970f2cf8/ambari-web/app/templates/common/modal_popups/cluster_check_dialog.hbs
----------------------------------------------------------------------
diff --git a/ambari-web/app/templates/common/modal_popups/cluster_check_dialog.hbs b/ambari-web/app/templates/common/modal_popups/cluster_check_dialog.hbs
index 8fd2746..766c6e6 100644
--- a/ambari-web/app/templates/common/modal_popups/cluster_check_dialog.hbs
+++ b/ambari-web/app/templates/common/modal_popups/cluster_check_dialog.hbs
@@ -35,6 +35,25 @@
       {{/each}}
     </div>
   {{/if}}
+
+  <!-- Errors that can by bypassed. -->
+  {{#if view.bypass.length}}
+    {{#if view.failTitle}}
+      <h4>{{view.failTitle}}</h4>
+    {{/if}}
+    {{#if view.failAlert}}
+      <div class="alert alert-warning">
+        {{view.failAlert}}
+      </div>
+    {{/if}}
+    <div class="limited-height-2">
+      {{#each item in view.bypass}}
+        <i class="icon-remove"></i>&nbsp;<span>{{item.UpgradeChecks.check}}</span>
+        <pre>{{t popup.clusterCheck.reason}}{{item.UpgradeChecks.reason}}<br/>{{t popup.clusterCheck.failedOn}}{{item.UpgradeChecks.failed_on}}</pre>
+      {{/each}}
+    </div>
+  {{/if}}
+
   {{#if view.warnings.length}}
     {{#if view.warningTitle}}
       <h4>{{view.warningTitle}}</h4>

http://git-wip-us.apache.org/repos/asf/ambari/blob/970f2cf8/ambari-web/app/templates/main/admin/stack_upgrade/upgrade_options.hbs
----------------------------------------------------------------------
diff --git a/ambari-web/app/templates/main/admin/stack_upgrade/upgrade_options.hbs b/ambari-web/app/templates/main/admin/stack_upgrade/upgrade_options.hbs
index 268ea1d..d150a27 100644
--- a/ambari-web/app/templates/main/admin/stack_upgrade/upgrade_options.hbs
+++ b/ambari-web/app/templates/main/admin/stack_upgrade/upgrade_options.hbs
@@ -41,6 +41,9 @@
                   <a {{action runAction method target="view"}}>
                     {{method.precheckResultsMessage}}
                   </a>
+                  {{#if method.bypassedFailures}}
+                    <div class="alert-danger">{{t admin.stackVersions.version.upgrade.upgradeOptions.errors_bypassed}}</div>
+                  {{/if}}
                 </div>
               {{/if}}
             {{/unless}}

http://git-wip-us.apache.org/repos/asf/ambari/blob/970f2cf8/ambari-web/app/views/common/modal_popups/cluster_check_popup.js
----------------------------------------------------------------------
diff --git a/ambari-web/app/views/common/modal_popups/cluster_check_popup.js b/ambari-web/app/views/common/modal_popups/cluster_check_popup.js
index 54f20ba..a2f6f83 100644
--- a/ambari-web/app/views/common/modal_popups/cluster_check_popup.js
+++ b/ambari-web/app/views/common/modal_popups/cluster_check_popup.js
@@ -30,6 +30,7 @@ var App = require('app');
 App.showClusterCheckPopup = function (data, popup, configs, upgradeVersion) {
   var fails = data.items.filterProperty('UpgradeChecks.status', 'FAIL'),
     warnings = data.items.filterProperty('UpgradeChecks.status', 'WARNING'),
+    bypass = data.items.filterProperty('UpgradeChecks.status', 'BYPASS'),
     hasConfigsMergeConflicts = !!(configs && configs.length),
     primary,
     secondary,
@@ -45,9 +46,10 @@ App.showClusterCheckPopup = function (data, popup, configs, upgradeVersion) {
     warningAlert: popup.warningAlert,
     templateName: require('templates/common/modal_popups/cluster_check_dialog'),
     fails: fails,
+    bypass: bypass, // errors that can be bypassed
     warnings: warnings,
     hasConfigsMergeConflicts: hasConfigsMergeConflicts,
-    isAllPassed: !fails.length && !warnings.length && !hasConfigsMergeConflicts
+    isAllPassed: !fails.length && !warnings.length && !bypass.length && !hasConfigsMergeConflicts
   };
   if (hasConfigsMergeConflicts) {
     popupBody.configsMergeTable = Em.View.extend({