You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ambari.apache.org by vb...@apache.org on 2016/02/11 14:58:45 UTC

ambari git commit: AMBARI-14948. Config consistency checker.(vbrodetskyi)

Repository: ambari
Updated Branches:
  refs/heads/branch-2.2 7ce5a0072 -> 58b0b5014


AMBARI-14948. Config consistency checker.(vbrodetskyi)


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

Branch: refs/heads/branch-2.2
Commit: 58b0b5014ee3753230782b9e97c52662c25ceed2
Parents: 7ce5a00
Author: Vitaly Brodetskyi <vb...@hortonworks.com>
Authored: Thu Feb 11 01:10:42 2016 +0200
Committer: Vitaly Brodetskyi <vb...@hortonworks.com>
Committed: Thu Feb 11 01:10:42 2016 +0200

----------------------------------------------------------------------
 ambari-server/sbin/ambari-server                |   6 +-
 .../server/checks/CheckDatabaseHelper.java      | 473 +++++++++++++++++++
 ambari-server/src/main/python/ambari-server.py  |   9 +-
 .../main/python/ambari_server/checkDatabase.py  |  80 ++++
 .../main/python/ambari_server/setupActions.py   |   1 +
 .../server/checks/CheckDatabaseHelperTest.java  | 292 ++++++++++++
 .../src/test/python/TestAmbariServer.py         |  37 ++
 7 files changed, 894 insertions(+), 4 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/ambari/blob/58b0b501/ambari-server/sbin/ambari-server
----------------------------------------------------------------------
diff --git a/ambari-server/sbin/ambari-server b/ambari-server/sbin/ambari-server
index 72d94ed..e676cbc 100755
--- a/ambari-server/sbin/ambari-server
+++ b/ambari-server/sbin/ambari-server
@@ -138,9 +138,13 @@ case "$1" in
         echo -e "Updating host names"
         $PYTHON /usr/sbin/ambari-server.py $@
         ;;
+  check-database)
+        echo -e "Checking database"
+        $PYTHON /usr/sbin/ambari-server.py $@
+        ;;
   *)
         echo "Usage: /usr/sbin/ambari-server
-        {start|stop|restart|setup|setup-jce|upgrade|status|upgradestack|setup-ldap|sync-ldap|set-current|setup-security|refresh-stack-hash|backup|restore|update-host-names} [options]
+        {start|stop|restart|setup|setup-jce|upgrade|status|upgradestack|setup-ldap|sync-ldap|set-current|setup-security|refresh-stack-hash|backup|restore|update-host-names|check-database} [options]
         Use usr/sbin/ambari-server <action> --help to get details on options available.
         Or, simply invoke ambari-server.py --help to print the options."
         exit 1

http://git-wip-us.apache.org/repos/asf/ambari/blob/58b0b501/ambari-server/src/main/java/org/apache/ambari/server/checks/CheckDatabaseHelper.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/checks/CheckDatabaseHelper.java b/ambari-server/src/main/java/org/apache/ambari/server/checks/CheckDatabaseHelper.java
new file mode 100644
index 0000000..a078c8a
--- /dev/null
+++ b/ambari-server/src/main/java/org/apache/ambari/server/checks/CheckDatabaseHelper.java
@@ -0,0 +1,473 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.ambari.server.checks;
+
+import com.google.common.collect.HashMultimap;
+import com.google.common.collect.Multimap;
+import com.google.inject.Guice;
+import com.google.inject.Inject;
+import com.google.inject.Injector;
+import com.google.inject.persist.PersistService;
+import org.apache.ambari.server.AmbariException;
+import org.apache.ambari.server.api.services.AmbariMetaInfo;
+import org.apache.ambari.server.controller.ControllerModule;
+import org.apache.ambari.server.orm.DBAccessor;
+import org.apache.ambari.server.state.ServiceInfo;
+import org.apache.ambari.server.utils.EventBusSynchronizer;
+import org.apache.commons.lang.StringUtils;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.sql.Connection;
+import java.sql.ResultSet;
+import java.sql.SQLException;
+import java.sql.Statement;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+/*
+* Class for database validation.
+* Here we will check configs, services, components and etc.
+*/
+public class CheckDatabaseHelper {
+  private static final Logger LOG = LoggerFactory.getLogger
+          (CheckDatabaseHelper.class);
+
+  private static final String AUTHENTICATED_USER_NAME = "ambari-check-database";
+
+  private PersistService persistService;
+  private DBAccessor dbAccessor;
+  private Connection connection;
+  private AmbariMetaInfo ambariMetaInfo;
+  private Injector injector;
+
+  @Inject
+  public CheckDatabaseHelper(DBAccessor dbAccessor,
+                             Injector injector,
+                             PersistService persistService) {
+    this.dbAccessor = dbAccessor;
+    this.injector = injector;
+    this.persistService = persistService;
+  }
+
+  /**
+   * Extension of main controller module
+   */
+  public static class CheckHelperModule extends ControllerModule {
+
+    public CheckHelperModule() throws Exception {
+    }
+
+    @Override
+    protected void configure() {
+      super.configure();
+      EventBusSynchronizer.synchronizeAmbariEventPublisher(binder());
+    }
+  }
+
+  /*
+  * init method to create connection
+  * */
+  protected void init() {
+    connection = dbAccessor.getConnection();
+    ambariMetaInfo = injector.getInstance(AmbariMetaInfo.class);
+  }
+
+  /*
+  * method to close connection
+  * */
+  private void closeConnection() {
+    try {
+      connection.close();
+    } catch (SQLException e) {
+      LOG.error("Exception occurred during connection close procedure: ", e);
+    }
+  }
+
+  public void startPersistenceService() {
+    persistService.start();
+  }
+
+  public void stopPersistenceService() {
+    persistService.stop();
+  }
+
+  /*
+  * This method checks if all configurations that we have in clusterconfig table
+  * have at least one mapping in clusterconfigmapping table. If we found not mapped config
+  * then we are showing warning message for user.
+  * */
+  protected void checkForNotMappedConfigsToCluster() {
+    String GET_NOT_MAPPED_CONFIGS_QUERY = "select type_name from clusterconfig where type_name not in (select type_name from clusterconfigmapping)";
+    Set<String> nonSelectedConfigs = new HashSet<>();
+    ResultSet rs = null;
+    try {
+      Statement statement = connection.createStatement(ResultSet.TYPE_SCROLL_SENSITIVE, ResultSet.CONCUR_UPDATABLE);
+      rs = statement.executeQuery(GET_NOT_MAPPED_CONFIGS_QUERY);
+      if (rs != null) {
+        while (rs.next()) {
+          nonSelectedConfigs.add(rs.getString("type_name"));
+        }
+      }
+      if (!nonSelectedConfigs.isEmpty()) {
+        LOG.warn("You have config(s) that is(are) not mapped to any cluster: " + StringUtils.join(nonSelectedConfigs, ","));
+      }
+    } catch (SQLException e) {
+      LOG.error("Exception occurred during check for not mapped configs to cluster procedure: ", e);
+    } finally {
+      if (rs != null) {
+        try {
+          rs.close();
+        } catch (SQLException e) {
+          LOG.error("Exception occurred during result set closing procedure: ", e);
+        }
+      }
+    }
+  }
+
+  /*
+  * This method checks if any config type in clusterconfigmapping table, has
+  * more than one versions selected. If config version is selected(in selected column = 1),
+  * it means that this version of config is actual. So, if any config type has more
+  * than one selected version it's a bug and we are showing error message for user.
+  * */
+  protected void checkForConfigsSelectedMoreThanOnce() {
+    String GET_CONFIGS_SELECTED_MORE_THAN_ONCE_QUERY = "select type_name from clusterconfigmapping group by type_name having sum(selected) > 1";
+    Set<String> configsSelectedMoreThanOnce = new HashSet<>();
+    ResultSet rs = null;
+    try {
+      Statement statement = connection.createStatement(ResultSet.TYPE_SCROLL_SENSITIVE, ResultSet.CONCUR_UPDATABLE);
+      rs = statement.executeQuery(GET_CONFIGS_SELECTED_MORE_THAN_ONCE_QUERY);
+      if (rs != null) {
+        while (rs.next()) {
+          configsSelectedMoreThanOnce.add(rs.getString("type_name"));
+        }
+      }
+      if (!configsSelectedMoreThanOnce.isEmpty()) {
+        LOG.error("You have config(s) that is(are) selected more than once in clusterconfigmapping: " + StringUtils.join(configsSelectedMoreThanOnce, ","));
+      }
+    } catch (SQLException e) {
+      LOG.error("Exception occurred during check for config selected more than ones procedure: ", e);
+    } finally {
+      if (rs != null) {
+        try {
+          rs.close();
+        } catch (SQLException e) {
+          LOG.error("Exception occurred during result set closing procedure: ", e);
+        }
+      }
+    }
+  }
+
+  /*
+  * This method checks if all hosts from hosts table
+  * has related host state info in hoststate table.
+  * If not then we are showing error.
+  * */
+  protected void checkForHostsWithoutState() {
+    String GET_HOSTS_WITHOUT_STATUS_QUERY = "select host_name from hosts where host_id not in (select host_id from hoststate)";
+    Set<String> hostsWithoutStatus = new HashSet<>();
+    ResultSet rs = null;
+    try {
+      Statement statement = connection.createStatement(ResultSet.TYPE_SCROLL_SENSITIVE, ResultSet.CONCUR_UPDATABLE);
+      rs = statement.executeQuery(GET_HOSTS_WITHOUT_STATUS_QUERY);
+      if (rs != null) {
+        while (rs.next()) {
+          LOG.error(rs.getString("host_name"));
+          LOG.error(rs.getString("HOST_NAME"));
+          System.out.println("ERROR" + rs.getString("HOST_NAME"));
+          System.out.println("ERROR" + rs.getString("host_name"));
+          hostsWithoutStatus.add(rs.getString("host_name"));
+        }
+      }
+
+      if (!hostsWithoutStatus.isEmpty()) {
+        LOG.error("You have host(s) without status: " + StringUtils.join(hostsWithoutStatus, ","));
+      }
+    } catch (SQLException e) {
+      LOG.error("Exception occurred during check for host without state procedure: ", e);
+    } finally {
+      if (rs != null) {
+        try {
+          rs.close();
+        } catch (SQLException e) {
+          LOG.error("Exception occurred during result set closing procedure: ", e);
+        }
+      }
+    }
+  }
+
+  /*
+  * This method checks if count of host component states equals count
+  * of desired host component states. According to ambari logic these
+  * two tables should have the same count of rows. If not then we are
+  * showing error for user.
+  * */
+  protected void checkHostComponentStatesCountEqualsHostComponentsDesiredStates() {
+    String GET_HOST_COMPONENT_STATE_COUNT_QUERY = "select count(*) from hostcomponentstate";
+    String GET_HOST_COMPONENT_DESIRED_STATE_COUNT_QUERY = "select count(*) from hostcomponentdesiredstate";
+    String GET_MERGED_TABLE_ROW_COUNT_QUERY = "select count(*) FROM hostcomponentstate hcs " +
+            "JOIN hostcomponentdesiredstate hcds ON hcs.service_name = hcds.service_name AND hcs.component_name = hcds.component_name AND hcs.host_id = hcds.host_id";
+    int hostComponentStateCount = 0;
+    int hostComponentDesiredStateCount = 0;
+    int mergedCount = 0;
+    ResultSet rs = null;
+    try {
+      Statement statement = connection.createStatement(ResultSet.TYPE_SCROLL_SENSITIVE, ResultSet.CONCUR_UPDATABLE);
+
+      rs = statement.executeQuery(GET_HOST_COMPONENT_STATE_COUNT_QUERY);
+      if (rs != null) {
+        while (rs.next()) {
+          hostComponentStateCount = rs.getInt(1);
+        }
+      }
+
+      rs = statement.executeQuery(GET_HOST_COMPONENT_DESIRED_STATE_COUNT_QUERY);
+      if (rs != null) {
+        while (rs.next()) {
+          hostComponentDesiredStateCount = rs.getInt(1);
+        }
+      }
+
+      rs = statement.executeQuery(GET_MERGED_TABLE_ROW_COUNT_QUERY);
+      if (rs != null) {
+        while (rs.next()) {
+          mergedCount = rs.getInt(1);
+        }
+      }
+
+      if (hostComponentStateCount != hostComponentDesiredStateCount || hostComponentStateCount != mergedCount) {
+        LOG.error("Your host component state count not equals host component desired state count!");
+      }
+
+    } catch (SQLException e) {
+      LOG.error("Exception occurred during check for same count of host component states and host component desired states: ", e);
+    } finally {
+      if (rs != null) {
+        try {
+          rs.close();
+        } catch (SQLException e) {
+          LOG.error("Exception occurred during result set closing procedure: ", e);
+        }
+      }
+    }
+
+  }
+
+
+  /*
+  * This method checks several potential problems for services:
+  * 1) Check if we have services in cluster which doesn't have service config id(not available in serviceconfig table).
+  * 2) Check if service has no mapped configs to it's service config id.
+  * 3) Check if service has all required configs mapped to it.
+  * 4) Check if service has config which is not selected(has no actual config version) in clusterconfigmapping table.
+  * If any issue was discovered, we are showing error message for user.
+  * */
+  protected void checkServiceConfigs()  {
+    String GET_SERVICES_WITHOUT_CONFIGS_QUERY = "select service_name from clusterservices where service_name not in (select service_name from serviceconfig where group_id is null)";
+    String GET_SERVICE_CONFIG_WITHOUT_MAPPING_QUERY = "select service_name from serviceconfig where service_config_id not in (select service_config_id from serviceconfigmapping) and group_id is null";
+    String GET_STACK_NAME_VERSION_QUERY = "select s.stack_name, s.stack_version from clusters c join stack s on c.desired_stack_id = s.stack_id";
+    String GET_SERVICES_WITH_CONFIGS_QUERY = "select cs.service_name, type_name, sc.version from clusterservices cs " +
+            "join serviceconfig sc on cs.service_name=sc.service_name " +
+            "join serviceconfigmapping scm on sc.service_config_id=scm.service_config_id " +
+            "join clusterconfig cc on scm.config_id=cc.config_id " +
+            "where sc.group_id is null " +
+            "group by cs.service_name, type_name, sc.version";
+    String GET_NOT_SELECTED_SERVICE_CONFIGS_QUERY = "select cs.service_name,cc.type_name from clusterservices cs " +
+            "join serviceconfig sc on cs.service_name=sc.service_name " +
+            "join serviceconfigmapping scm on sc.service_config_id=scm.service_config_id " +
+            "join clusterconfig cc on scm.config_id=cc.config_id " +
+            "join clusterconfigmapping ccm on cc.type_name=ccm.type_name and cc.version_tag=ccm.version_tag " +
+            "where sc.group_id is null and sc.service_config_id = (select max(service_config_id) from serviceconfig sc2 where sc2.service_name=sc.service_name) " +
+            "group by cs.service_name,cc.type_name " +
+            "having sum(ccm.selected) < 1";
+    String stackName = null, stackVersion = null;
+    Set<String> servicesWithoutConfigs = new HashSet<>();
+    Set<String> servicesWithoutMappedConfigs = new HashSet<>();
+    Map<String, List<String>> notSelectedServiceConfigs = new HashMap<>();
+    ResultSet rs = null;
+
+    try {
+      Statement statement = connection.createStatement(ResultSet.TYPE_SCROLL_SENSITIVE, ResultSet.CONCUR_UPDATABLE);
+
+      rs = statement.executeQuery(GET_SERVICES_WITHOUT_CONFIGS_QUERY);
+      if (rs != null) {
+        while (rs.next()) {
+          servicesWithoutConfigs.add(rs.getString("service_name"));
+        }
+      }
+
+      if (!servicesWithoutConfigs.isEmpty()) {
+        LOG.error("You have services without configs at all: " + StringUtils.join(servicesWithoutConfigs, ","));
+      }
+
+      rs = statement.executeQuery(GET_SERVICE_CONFIG_WITHOUT_MAPPING_QUERY);
+      if (rs != null) {
+        while (rs.next()) {
+          servicesWithoutMappedConfigs.add(rs.getString("service_name"));
+        }
+      }
+
+      if (!servicesWithoutMappedConfigs.isEmpty()) {
+        LOG.error("You have services without mapped configs: " + StringUtils.join(servicesWithoutMappedConfigs, ","));
+      }
+
+      rs = statement.executeQuery(GET_STACK_NAME_VERSION_QUERY);
+      if (rs != null) {
+        while (rs.next()) {
+          stackName = rs.getString("stack_name");
+          stackVersion = rs.getString("stack_version");
+        }
+      }
+
+      if (stackName != null && stackVersion != null) {
+        Set<String> serviceNames = new HashSet<>();
+        Map<Integer, Multimap<String, String>> dbServiceVersionConfigs = new HashMap<>();
+        Multimap<String, String> stackServiceConfigs = HashMultimap.create();
+
+        rs = statement.executeQuery(GET_SERVICES_WITH_CONFIGS_QUERY);
+        if (rs != null) {
+          String serviceName = null, configType = null;
+          Integer serviceVersion = null;
+          while (rs.next()) {
+            serviceName = rs.getString("service_name");
+            configType = rs.getString("type_name");
+            serviceVersion = rs.getInt("version");
+
+            serviceNames.add(serviceName);
+
+            if (dbServiceVersionConfigs.get(serviceVersion) == null) {
+              Multimap<String, String> dbServiceConfigs = HashMultimap.create();
+              dbServiceConfigs.put(serviceName, configType);
+              dbServiceVersionConfigs.put(serviceVersion, dbServiceConfigs);
+            } else {
+              dbServiceVersionConfigs.get(serviceVersion).put(serviceName, configType);
+            }
+          }
+        }
+
+
+        Map<String, ServiceInfo> serviceInfoMap = ambariMetaInfo.getServices(stackName, stackVersion);
+        for (String serviceName : serviceNames) {
+          ServiceInfo serviceInfo = serviceInfoMap.get(serviceName);
+          Set<String> configTypes = serviceInfo.getConfigTypeAttributes().keySet();
+          for (String configType : configTypes) {
+            stackServiceConfigs.put(serviceName, configType);
+          }
+        }
+
+        for (Integer serviceVersion : dbServiceVersionConfigs.keySet()) {
+          Multimap<String, String> dbServiceConfigs = dbServiceVersionConfigs.get(serviceVersion);
+          for (String serviceName : dbServiceConfigs.keySet()) {
+            Collection<String> serviceConfigsFromStack = stackServiceConfigs.get(serviceName);
+            Collection<String> serviceConfigsFromDB = dbServiceConfigs.get(serviceName);
+            if (serviceConfigsFromDB != null && serviceConfigsFromStack != null) {
+              serviceConfigsFromStack.removeAll(serviceConfigsFromDB);
+              if (!serviceConfigsFromStack.isEmpty()) {
+                LOG.error(String.format("Required config(s): %s is(are) not available for service %s with service config version %s",
+                        StringUtils.join(serviceConfigsFromStack, ","), serviceName, Integer.toString(serviceVersion)));
+              }
+            }
+          }
+        }
+      }
+
+      rs = statement.executeQuery(GET_NOT_SELECTED_SERVICE_CONFIGS_QUERY);
+      if (rs != null) {
+        String serviceName = null, configType = null;
+        while (rs.next()) {
+          serviceName = rs.getString("service_name");
+          configType = rs.getString("type_name");
+
+          if (notSelectedServiceConfigs.get(serviceName) != null) {
+            notSelectedServiceConfigs.get(serviceName).add(configType);
+          } else {
+            List<String> configTypes = new ArrayList<>();
+            configTypes.add(configType);
+            notSelectedServiceConfigs.put(serviceName, configTypes);
+          }
+        }
+      }
+
+      for (String serviceName : notSelectedServiceConfigs.keySet()) {
+        LOG.error(String.format("You have non selected configs: %s for service %s.", StringUtils.join(notSelectedServiceConfigs.get(serviceName), ","), serviceName));
+      }
+    } 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);
+    } finally {
+      if (rs != null) {
+        try {
+          rs.close();
+        } catch (SQLException e) {
+          LOG.error("Exception occurred during result set closing procedure: ", e);
+        }
+      }
+    }
+
+  }
+
+  /*
+  * Main method from which we are calling all checks
+  * */
+  public static void main(String[] args) throws Exception {
+    CheckDatabaseHelper checkDatabaseHelper = null;
+    try {
+      LOG.info("******************************* Check database started *******************************");
+
+      Injector injector = Guice.createInjector(new CheckHelperModule());
+      checkDatabaseHelper = injector.getInstance(CheckDatabaseHelper.class);
+
+      checkDatabaseHelper.startPersistenceService();
+
+      checkDatabaseHelper.init();
+
+      checkDatabaseHelper.checkForNotMappedConfigsToCluster();
+
+      checkDatabaseHelper.checkForConfigsSelectedMoreThanOnce();
+
+      checkDatabaseHelper.checkForHostsWithoutState();
+
+      checkDatabaseHelper.checkHostComponentStatesCountEqualsHostComponentsDesiredStates();
+
+      checkDatabaseHelper.checkServiceConfigs();
+
+      checkDatabaseHelper.stopPersistenceService();
+
+      LOG.info("******************************* Check database completed *******************************");
+    } catch (Throwable e) {
+      if (e instanceof AmbariException) {
+        LOG.error("Exception occurred during database check:", e);
+        throw (AmbariException)e;
+      }else{
+        LOG.error("Unexpected error, database check failed", e);
+        throw new Exception("Unexpected error, database check failed", e);
+      }
+    } finally {
+      if (checkDatabaseHelper != null) {
+        checkDatabaseHelper.closeConnection();
+      }
+    }
+  }
+}

http://git-wip-us.apache.org/repos/asf/ambari/blob/58b0b501/ambari-server/src/main/python/ambari-server.py
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/python/ambari-server.py b/ambari-server/src/main/python/ambari-server.py
index 8be79a5..38bf11f 100755
--- a/ambari-server/src/main/python/ambari-server.py
+++ b/ambari-server/src/main/python/ambari-server.py
@@ -37,10 +37,12 @@ from ambari_server.serverSetup import reset, setup, setup_jce_policy
 from ambari_server.serverUpgrade import upgrade, upgrade_stack, set_current
 from ambari_server.setupHttps import setup_https, setup_truststore
 from ambari_server.hostUpdate import update_host_names
+from ambari_server.checkDatabase import check_database
 
 from ambari_server.setupActions import BACKUP_ACTION, LDAP_SETUP_ACTION, LDAP_SYNC_ACTION, PSTART_ACTION, \
-  REFRESH_STACK_HASH_ACTION, RESET_ACTION, RESTORE_ACTION, UPDATE_HOST_NAMES_ACTION, SETUP_ACTION, SETUP_SECURITY_ACTION, \
-  START_ACTION, STATUS_ACTION, STOP_ACTION, UPGRADE_ACTION, UPGRADE_STACK_ACTION, SETUP_JCE_ACTION, SET_CURRENT_ACTION
+  REFRESH_STACK_HASH_ACTION, RESET_ACTION, RESTORE_ACTION, UPDATE_HOST_NAMES_ACTION, CHECK_DATABASE_ACTION, \
+  SETUP_ACTION, SETUP_SECURITY_ACTION,START_ACTION, STATUS_ACTION, STOP_ACTION, UPGRADE_ACTION, UPGRADE_STACK_ACTION, \
+  SETUP_JCE_ACTION, SET_CURRENT_ACTION
 from ambari_server.setupSecurity import setup_ldap, sync_ldap, setup_master_key, setup_ambari_krb5_jaas
 from ambari_server.userInput import get_validated_string_input
 
@@ -523,7 +525,8 @@ def create_user_action_map(args, options):
         REFRESH_STACK_HASH_ACTION: UserAction(refresh_stack_hash_action),
         BACKUP_ACTION: UserActionPossibleArgs(backup, [1, 2], args),
         RESTORE_ACTION: UserActionPossibleArgs(restore, [1, 2], args),
-        UPDATE_HOST_NAMES_ACTION: UserActionPossibleArgs(update_host_names, [2], args, options)
+        UPDATE_HOST_NAMES_ACTION: UserActionPossibleArgs(update_host_names, [2], args, options),
+        CHECK_DATABASE_ACTION: UserAction(check_database, options)
       }
   return action_map
 

http://git-wip-us.apache.org/repos/asf/ambari/blob/58b0b501/ambari-server/src/main/python/ambari_server/checkDatabase.py
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/python/ambari_server/checkDatabase.py b/ambari-server/src/main/python/ambari_server/checkDatabase.py
new file mode 100644
index 0000000..af1d74f
--- /dev/null
+++ b/ambari-server/src/main/python/ambari_server/checkDatabase.py
@@ -0,0 +1,80 @@
+#!/usr/bin/env python
+
+'''
+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.
+'''
+
+import os
+import sys
+
+from ambari_commons.exceptions import FatalException
+from ambari_server import serverConfiguration
+from ambari_server import dbConfiguration
+from ambari_server import setupSecurity
+from ambari_commons import os_utils
+from ambari_server import userInput
+from ambari_server import serverUtils
+from ambari_server.serverConfiguration import configDefaults, get_java_exe_path, get_ambari_properties, read_ambari_user, \
+  parse_properties_file, JDBC_DATABASE_PROPERTY
+from ambari_commons.logging_utils import print_info_msg, print_warning_msg, print_error_msg
+from ambari_server.dbConfiguration import ensure_jdbc_driver_is_installed, LINUX_DBMS_KEYS_LIST
+from ambari_server.serverClassPath import ServerClassPath
+from ambari_server.setupSecurity import ensure_can_start_under_current_user, generate_env
+from ambari_commons.os_utils import run_os_command
+from ambari_server.serverUtils import is_server_runing
+from ambari_server.userInput import get_YN_input
+
+CHECK_DATABASE_HELPER_CMD = "{0} -cp {1} " + \
+                         "org.apache.ambari.server.checks.CheckDatabaseHelper" + \
+                         " > " + configDefaults.SERVER_LOG_FILE + " 2>&1"
+
+def check_database(options):
+
+  jdk_path = serverConfiguration.get_java_exe_path()
+
+  if jdk_path is None:
+    print_error_msg("No JDK found, please run the \"setup\" "
+                    "command to install a JDK automatically or install any "
+                    "JDK manually to " + configDefaults.JDK_INSTALL_DIR)
+    sys.exit(1)
+
+  properties = serverConfiguration.get_ambari_properties()
+  serverConfiguration.parse_properties_file(options)
+  options.database_index = LINUX_DBMS_KEYS_LIST.index(properties[JDBC_DATABASE_PROPERTY])
+
+  dbConfiguration.ensure_jdbc_driver_is_installed(options, serverConfiguration.get_ambari_properties())
+
+  serverClassPath = ServerClassPath(serverConfiguration.get_ambari_properties(), options)
+  class_path = serverClassPath.get_full_ambari_classpath_escaped_for_shell()
+
+  command = CHECK_DATABASE_HELPER_CMD.format(jdk_path, class_path)
+
+  ambari_user = serverConfiguration.read_ambari_user()
+  current_user = setupSecurity.ensure_can_start_under_current_user(ambari_user)
+  environ = setupSecurity.generate_env(options, ambari_user, current_user)
+
+  (retcode, stdout, stderr) = os_utils.run_os_command(command, env=environ)
+  print_info_msg("Return code from check database command, retcode = " + str(retcode))
+
+  if retcode > 0:
+    print_error_msg("Database check failed to complete. Please check ambari-server.log for problem.")
+    raise FatalException(1, 'Database check failed.')
+  else:
+    print_info_msg('Check database completed successfully. Please check ambari-server.log for results.')
+
+
+

http://git-wip-us.apache.org/repos/asf/ambari/blob/58b0b501/ambari-server/src/main/python/ambari_server/setupActions.py
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/python/ambari_server/setupActions.py b/ambari-server/src/main/python/ambari_server/setupActions.py
index 686ac9a..324ef69 100644
--- a/ambari-server/src/main/python/ambari_server/setupActions.py
+++ b/ambari-server/src/main/python/ambari_server/setupActions.py
@@ -36,6 +36,7 @@ SETUP_GANGLIA_HTTPS_ACTION = "setup-ganglia-https"
 ENCRYPT_PASSWORDS_ACTION = "encrypt-passwords"
 SETUP_SECURITY_ACTION = "setup-security"
 UPDATE_HOST_NAMES_ACTION = "update-host-names"
+CHECK_DATABASE_ACTION = "check-database"
 BACKUP_ACTION = "backup"
 RESTORE_ACTION = "restore"
 SETUP_JCE_ACTION = "setup-jce"

http://git-wip-us.apache.org/repos/asf/ambari/blob/58b0b501/ambari-server/src/test/java/org/apache/ambari/server/checks/CheckDatabaseHelperTest.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/test/java/org/apache/ambari/server/checks/CheckDatabaseHelperTest.java b/ambari-server/src/test/java/org/apache/ambari/server/checks/CheckDatabaseHelperTest.java
new file mode 100644
index 0000000..e329ab7
--- /dev/null
+++ b/ambari-server/src/test/java/org/apache/ambari/server/checks/CheckDatabaseHelperTest.java
@@ -0,0 +1,292 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.ambari.server.checks;
+
+
+import com.google.inject.AbstractModule;
+import com.google.inject.Guice;
+import com.google.inject.Injector;
+import org.apache.ambari.server.api.services.AmbariMetaInfo;
+import org.apache.ambari.server.orm.DBAccessor;
+import org.apache.ambari.server.stack.StackManagerFactory;
+import org.apache.ambari.server.state.Clusters;
+import org.apache.ambari.server.state.ServiceInfo;
+import org.apache.ambari.server.state.stack.OsFamily;
+import org.easymock.EasyMockSupport;
+import org.junit.Test;
+
+import javax.persistence.EntityManager;
+import java.sql.Connection;
+import java.sql.ResultSet;
+import java.sql.Statement;
+import java.util.HashMap;
+import java.util.Map;
+
+import static org.easymock.EasyMock.expect;
+
+public class CheckDatabaseHelperTest {
+
+  @Test
+  public void testCheckForNotMappedConfigs() throws Exception {
+    EasyMockSupport easyMockSupport = new EasyMockSupport();
+    final AmbariMetaInfo mockAmbariMetainfo = easyMockSupport.createNiceMock(AmbariMetaInfo.class);
+    final DBAccessor mockDBDbAccessor = easyMockSupport.createNiceMock(DBAccessor.class);
+    final Connection mockConnection = easyMockSupport.createNiceMock(Connection.class);
+    final ResultSet mockResultSet = easyMockSupport.createNiceMock(ResultSet.class);
+    final Statement mockStatement = easyMockSupport.createNiceMock(Statement.class);
+
+    final StackManagerFactory mockStackManagerFactory = easyMockSupport.createNiceMock(StackManagerFactory.class);
+    final EntityManager mockEntityManager = easyMockSupport.createNiceMock(EntityManager.class);
+    final Clusters mockClusters = easyMockSupport.createNiceMock(Clusters.class);
+    final OsFamily mockOSFamily = easyMockSupport.createNiceMock(OsFamily.class);
+    final Injector mockInjector = Guice.createInjector(new AbstractModule() {
+      @Override
+      protected void configure() {
+        bind(AmbariMetaInfo.class).toInstance(mockAmbariMetainfo);
+        bind(StackManagerFactory.class).toInstance(mockStackManagerFactory);
+        bind(EntityManager.class).toInstance(mockEntityManager);
+        bind(DBAccessor.class).toInstance(mockDBDbAccessor);
+        bind(Clusters.class).toInstance(mockClusters);
+        bind(OsFamily.class).toInstance(mockOSFamily);
+      }
+    });
+
+
+    expect(mockDBDbAccessor.getConnection()).andReturn(mockConnection);
+    expect(mockConnection.createStatement(ResultSet.TYPE_SCROLL_SENSITIVE, ResultSet.CONCUR_UPDATABLE)).andReturn(mockStatement);
+    expect(mockStatement.executeQuery("select type_name from clusterconfig where type_name not in (select type_name from clusterconfigmapping)")).andReturn(mockResultSet);
+
+    CheckDatabaseHelper checkDatabaseHelper = new CheckDatabaseHelper(mockDBDbAccessor, mockInjector, null);
+
+
+    easyMockSupport.replayAll();
+
+    mockAmbariMetainfo.init();
+    checkDatabaseHelper.init();
+    checkDatabaseHelper.checkForNotMappedConfigsToCluster();
+
+    easyMockSupport.verifyAll();
+  }
+
+  @Test
+  public void testCheckForConfigsSelectedMoreThanOnce() throws Exception {
+    EasyMockSupport easyMockSupport = new EasyMockSupport();
+    final AmbariMetaInfo mockAmbariMetainfo = easyMockSupport.createNiceMock(AmbariMetaInfo.class);
+    final DBAccessor mockDBDbAccessor = easyMockSupport.createNiceMock(DBAccessor.class);
+    final Connection mockConnection = easyMockSupport.createNiceMock(Connection.class);
+    final ResultSet mockResultSet = easyMockSupport.createNiceMock(ResultSet.class);
+    final Statement mockStatement = easyMockSupport.createNiceMock(Statement.class);
+
+    final StackManagerFactory mockStackManagerFactory = easyMockSupport.createNiceMock(StackManagerFactory.class);
+    final EntityManager mockEntityManager = easyMockSupport.createNiceMock(EntityManager.class);
+    final Clusters mockClusters = easyMockSupport.createNiceMock(Clusters.class);
+    final OsFamily mockOSFamily = easyMockSupport.createNiceMock(OsFamily.class);
+    final Injector mockInjector = Guice.createInjector(new AbstractModule() {
+      @Override
+      protected void configure() {
+        bind(AmbariMetaInfo.class).toInstance(mockAmbariMetainfo);
+        bind(StackManagerFactory.class).toInstance(mockStackManagerFactory);
+        bind(EntityManager.class).toInstance(mockEntityManager);
+        bind(DBAccessor.class).toInstance(mockDBDbAccessor);
+        bind(Clusters.class).toInstance(mockClusters);
+        bind(OsFamily.class).toInstance(mockOSFamily);
+      }
+    });
+
+
+    expect(mockDBDbAccessor.getConnection()).andReturn(mockConnection);
+    expect(mockConnection.createStatement(ResultSet.TYPE_SCROLL_SENSITIVE, ResultSet.CONCUR_UPDATABLE)).andReturn(mockStatement);
+    expect(mockStatement.executeQuery("select type_name from clusterconfigmapping group by type_name having sum(selected) > 1")).andReturn(mockResultSet);
+
+    CheckDatabaseHelper checkDatabaseHelper = new CheckDatabaseHelper(mockDBDbAccessor, mockInjector, null);
+
+
+    easyMockSupport.replayAll();
+
+    mockAmbariMetainfo.init();
+    checkDatabaseHelper.init();
+    checkDatabaseHelper.checkForConfigsSelectedMoreThanOnce();
+
+    easyMockSupport.verifyAll();
+  }
+
+  @Test
+  public void testCheckForHostsWithoutState() throws Exception {
+    EasyMockSupport easyMockSupport = new EasyMockSupport();
+    final AmbariMetaInfo mockAmbariMetainfo = easyMockSupport.createNiceMock(AmbariMetaInfo.class);
+    final DBAccessor mockDBDbAccessor = easyMockSupport.createNiceMock(DBAccessor.class);
+    final Connection mockConnection = easyMockSupport.createNiceMock(Connection.class);
+    final ResultSet mockResultSet = easyMockSupport.createNiceMock(ResultSet.class);
+    final Statement mockStatement = easyMockSupport.createNiceMock(Statement.class);
+
+    final StackManagerFactory mockStackManagerFactory = easyMockSupport.createNiceMock(StackManagerFactory.class);
+    final EntityManager mockEntityManager = easyMockSupport.createNiceMock(EntityManager.class);
+    final Clusters mockClusters = easyMockSupport.createNiceMock(Clusters.class);
+    final OsFamily mockOSFamily = easyMockSupport.createNiceMock(OsFamily.class);
+    final Injector mockInjector = Guice.createInjector(new AbstractModule() {
+      @Override
+      protected void configure() {
+        bind(AmbariMetaInfo.class).toInstance(mockAmbariMetainfo);
+        bind(StackManagerFactory.class).toInstance(mockStackManagerFactory);
+        bind(EntityManager.class).toInstance(mockEntityManager);
+        bind(DBAccessor.class).toInstance(mockDBDbAccessor);
+        bind(Clusters.class).toInstance(mockClusters);
+        bind(OsFamily.class).toInstance(mockOSFamily);
+      }
+    });
+
+
+    expect(mockDBDbAccessor.getConnection()).andReturn(mockConnection);
+    expect(mockConnection.createStatement(ResultSet.TYPE_SCROLL_SENSITIVE, ResultSet.CONCUR_UPDATABLE)).andReturn(mockStatement);
+    expect(mockStatement.executeQuery("select host_name from hosts where host_id not in (select host_id from hoststate)")).andReturn(mockResultSet);
+
+    CheckDatabaseHelper checkDatabaseHelper = new CheckDatabaseHelper(mockDBDbAccessor, mockInjector, null);
+
+
+    easyMockSupport.replayAll();
+
+    mockAmbariMetainfo.init();
+    checkDatabaseHelper.init();
+    checkDatabaseHelper.checkForHostsWithoutState();
+
+    easyMockSupport.verifyAll();
+  }
+
+  @Test
+  public void testCheckHostComponentStatesCountEqualsHostComponentsDesiredStates() throws Exception {
+    EasyMockSupport easyMockSupport = new EasyMockSupport();
+    final AmbariMetaInfo mockAmbariMetainfo = easyMockSupport.createNiceMock(AmbariMetaInfo.class);
+    final DBAccessor mockDBDbAccessor = easyMockSupport.createNiceMock(DBAccessor.class);
+    final Connection mockConnection = easyMockSupport.createNiceMock(Connection.class);
+    final ResultSet mockResultSet = easyMockSupport.createNiceMock(ResultSet.class);
+    final Statement mockStatement = easyMockSupport.createNiceMock(Statement.class);
+
+    final StackManagerFactory mockStackManagerFactory = easyMockSupport.createNiceMock(StackManagerFactory.class);
+    final EntityManager mockEntityManager = easyMockSupport.createNiceMock(EntityManager.class);
+    final Clusters mockClusters = easyMockSupport.createNiceMock(Clusters.class);
+    final OsFamily mockOSFamily = easyMockSupport.createNiceMock(OsFamily.class);
+    final Injector mockInjector = Guice.createInjector(new AbstractModule() {
+      @Override
+      protected void configure() {
+        bind(AmbariMetaInfo.class).toInstance(mockAmbariMetainfo);
+        bind(StackManagerFactory.class).toInstance(mockStackManagerFactory);
+        bind(EntityManager.class).toInstance(mockEntityManager);
+        bind(DBAccessor.class).toInstance(mockDBDbAccessor);
+        bind(Clusters.class).toInstance(mockClusters);
+        bind(OsFamily.class).toInstance(mockOSFamily);
+      }
+    });
+
+
+    expect(mockDBDbAccessor.getConnection()).andReturn(mockConnection);
+    expect(mockConnection.createStatement(ResultSet.TYPE_SCROLL_SENSITIVE, ResultSet.CONCUR_UPDATABLE)).andReturn(mockStatement);
+    expect(mockStatement.executeQuery("select count(*) from hostcomponentstate")).andReturn(mockResultSet);
+    expect(mockStatement.executeQuery("select count(*) from hostcomponentdesiredstate")).andReturn(mockResultSet);
+    expect(mockStatement.executeQuery("select count(*) FROM hostcomponentstate hcs " +
+            "JOIN hostcomponentdesiredstate hcds ON hcs.service_name = hcds.service_name AND " +
+            "hcs.component_name = hcds.component_name AND hcs.host_id = hcds.host_id")).andReturn(mockResultSet);
+
+    CheckDatabaseHelper checkDatabaseHelper = new CheckDatabaseHelper(mockDBDbAccessor, mockInjector, null);
+
+
+    easyMockSupport.replayAll();
+
+    mockAmbariMetainfo.init();
+    checkDatabaseHelper.init();
+    checkDatabaseHelper.checkHostComponentStatesCountEqualsHostComponentsDesiredStates();
+
+    easyMockSupport.verifyAll();
+  }
+
+  @Test
+  public void testCheckServiceConfigs() throws Exception {
+    EasyMockSupport easyMockSupport = new EasyMockSupport();
+    final AmbariMetaInfo mockAmbariMetainfo = easyMockSupport.createNiceMock(AmbariMetaInfo.class);
+    final DBAccessor mockDBDbAccessor = easyMockSupport.createNiceMock(DBAccessor.class);
+    final Connection mockConnection = easyMockSupport.createNiceMock(Connection.class);
+    final ResultSet mockResultSet = easyMockSupport.createNiceMock(ResultSet.class);
+    final ResultSet stackResultSet = easyMockSupport.createNiceMock(ResultSet.class);
+    final ResultSet serviceConfigResultSet = easyMockSupport.createNiceMock(ResultSet.class);
+    final Statement mockStatement = easyMockSupport.createNiceMock(Statement.class);
+    final ServiceInfo mockHDFSServiceInfo = easyMockSupport.createNiceMock(ServiceInfo.class);
+
+    final StackManagerFactory mockStackManagerFactory = easyMockSupport.createNiceMock(StackManagerFactory.class);
+    final EntityManager mockEntityManager = easyMockSupport.createNiceMock(EntityManager.class);
+    final Clusters mockClusters = easyMockSupport.createNiceMock(Clusters.class);
+    final OsFamily mockOSFamily = easyMockSupport.createNiceMock(OsFamily.class);
+    final Injector mockInjector = Guice.createInjector(new AbstractModule() {
+      @Override
+      protected void configure() {
+        bind(AmbariMetaInfo.class).toInstance(mockAmbariMetainfo);
+        bind(StackManagerFactory.class).toInstance(mockStackManagerFactory);
+        bind(EntityManager.class).toInstance(mockEntityManager);
+        bind(DBAccessor.class).toInstance(mockDBDbAccessor);
+        bind(Clusters.class).toInstance(mockClusters);
+        bind(OsFamily.class).toInstance(mockOSFamily);
+      }
+    });
+
+    Map<String, ServiceInfo> services = new HashMap<>();
+    services.put("HDFS", mockHDFSServiceInfo);
+
+    Map<String, Map<String, Map<String, String>>> configAttributes = new HashMap<>();
+    configAttributes.put("core-site", new HashMap<String, Map<String, String>>());
+
+    expect(mockHDFSServiceInfo.getConfigTypeAttributes()).andReturn(configAttributes);
+    expect(mockAmbariMetainfo.getServices("HDP", "2.2")).andReturn(services);
+    expect(serviceConfigResultSet.next()).andReturn(true);
+    expect(serviceConfigResultSet.getString("service_name")).andReturn("HDFS");
+    expect(serviceConfigResultSet.getString("type_name")).andReturn("core-site");
+    expect(stackResultSet.next()).andReturn(true);
+    expect(stackResultSet.getString("stack_name")).andReturn("HDP");
+    expect(stackResultSet.getString("stack_version")).andReturn("2.2");
+    expect(mockDBDbAccessor.getConnection()).andReturn(mockConnection);
+    expect(mockConnection.createStatement(ResultSet.TYPE_SCROLL_SENSITIVE, ResultSet.CONCUR_UPDATABLE)).andReturn(mockStatement);
+    expect(mockStatement.executeQuery("select service_name from clusterservices where service_name not in (select service_name from serviceconfig where group_id is null)")).andReturn(mockResultSet);
+    expect(mockStatement.executeQuery("select service_name from serviceconfig where service_config_id not in (select service_config_id from serviceconfigmapping) and group_id is null")).andReturn(mockResultSet);
+    expect(mockStatement.executeQuery("select s.stack_name, s.stack_version from clusters c join stack s on c.desired_stack_id = s.stack_id")).andReturn(stackResultSet);
+    expect(mockStatement.executeQuery("select cs.service_name, type_name, sc.version from clusterservices cs " +
+            "join serviceconfig sc on cs.service_name=sc.service_name " +
+            "join serviceconfigmapping scm on sc.service_config_id=scm.service_config_id " +
+            "join clusterconfig cc on scm.config_id=cc.config_id " +
+            "where sc.group_id is null " +
+            "group by cs.service_name, type_name, sc.version")).andReturn(serviceConfigResultSet);
+    expect(mockStatement.executeQuery("select cs.service_name,cc.type_name from clusterservices cs " +
+            "join serviceconfig sc on cs.service_name=sc.service_name " +
+            "join serviceconfigmapping scm on sc.service_config_id=scm.service_config_id " +
+            "join clusterconfig cc on scm.config_id=cc.config_id " +
+            "join clusterconfigmapping ccm on cc.type_name=ccm.type_name and cc.version_tag=ccm.version_tag " +
+            "where sc.group_id is null and sc.service_config_id = (select max(service_config_id) from serviceconfig sc2 where sc2.service_name=sc.service_name) " +
+            "group by cs.service_name,cc.type_name " +
+            "having sum(ccm.selected) < 1")).andReturn(mockResultSet);
+
+    CheckDatabaseHelper checkDatabaseHelper = new CheckDatabaseHelper(mockDBDbAccessor, mockInjector, null);
+
+
+    easyMockSupport.replayAll();
+
+    mockAmbariMetainfo.init();
+    checkDatabaseHelper.init();
+    checkDatabaseHelper.checkServiceConfigs();
+
+    easyMockSupport.verifyAll();
+  }
+
+
+}
+

http://git-wip-us.apache.org/repos/asf/ambari/blob/58b0b501/ambari-server/src/test/python/TestAmbariServer.py
----------------------------------------------------------------------
diff --git a/ambari-server/src/test/python/TestAmbariServer.py b/ambari-server/src/test/python/TestAmbariServer.py
index fdc375b..511700b 100644
--- a/ambari-server/src/test/python/TestAmbariServer.py
+++ b/ambari-server/src/test/python/TestAmbariServer.py
@@ -94,6 +94,7 @@ with patch("platform.linux_distribution", return_value = os_distro_value):
         from ambari_server_main import get_ulimit_open_files, ULIMIT_OPEN_FILES_KEY, ULIMIT_OPEN_FILES_DEFAULT
         from ambari_server.serverClassPath import ServerClassPath
         from ambari_server.hostUpdate import update_host_names
+        from ambari_server.checkDatabase import check_database
 
 CURR_AMBARI_VERSION = "2.0.0"
 
@@ -6816,6 +6817,42 @@ MIIFHjCCAwYCCQDpHKOBI+Lt0zANBgkqhkiG9w0BAQUFADBRMQswCQYDVQQGEwJV
 
     pass
 
+  @patch.object(ServerClassPath, "get_full_ambari_classpath_escaped_for_shell", new = MagicMock(return_value = 'test' + os.pathsep + 'path12'))
+  @patch("ambari_server.serverUtils.is_server_runing")
+  @patch("ambari_commons.os_utils.run_os_command")
+  @patch("ambari_server.setupSecurity.generate_env")
+  @patch("ambari_server.setupSecurity.ensure_can_start_under_current_user")
+  @patch("ambari_server.serverConfiguration.read_ambari_user")
+  @patch("ambari_server.dbConfiguration.ensure_jdbc_driver_is_installed")
+  @patch("ambari_server.serverConfiguration.parse_properties_file")
+  @patch("ambari_server.serverConfiguration.get_ambari_properties")
+  @patch("ambari_server.serverConfiguration.get_java_exe_path")
+  def test_check_database(self, getJavaExePathMock,
+                             getAmbariPropertiesMock, parsePropertiesFileMock, ensureDriverInstalledMock, readAmbariUserMock,
+                             ensureCanStartUnderCurrentUserMock, generateEnvMock, runOSCommandMock, isServerRunningMock):
+    properties = Properties()
+    properties.process_pair("server.jdbc.database", "embedded")
+
+    getJavaExePathMock.return_value = "/path/to/java"
+    getAmbariPropertiesMock.return_value = properties
+    readAmbariUserMock.return_value = "test_user"
+    ensureCanStartUnderCurrentUserMock.return_value = "test_user"
+    generateEnvMock.return_value = {}
+    runOSCommandMock.return_value = (0, "", "")
+    isServerRunningMock.return_value = (False, 1)
+
+    check_database(properties)
+
+    self.assertTrue(getJavaExePathMock.called)
+    self.assertTrue(readAmbariUserMock.called)
+    self.assertTrue(ensureCanStartUnderCurrentUserMock.called)
+    self.assertTrue(generateEnvMock.called)
+
+    self.assertEquals(runOSCommandMock.call_args[0][0], '/path/to/java -cp test:path12 org.apache.ambari.server.checks.CheckDatabaseHelper'
+                                                        ' > /var/log/ambari-server/ambari-server.log 2>&1')
+
+    pass
+
   @not_for_platform(PLATFORM_WINDOWS)
   @patch.object(OSCheck, "os_distribution", new = MagicMock(return_value = os_distro_value))
   @patch.object(_ambari_server_, "is_server_runing")