AMBARI-19824. Add consistency checker for blueprint tables (magyari_sandor)
Project: http://git-wip-us.apache.org/repos/asf/ambari/repo Commit: http://git-wip-us.apache.org/repos/asf/ambari/commit/4ad3a2b3 Tree: http://git-wip-us.apache.org/repos/asf/ambari/tree/4ad3a2b3 Diff: http://git-wip-us.apache.org/repos/asf/ambari/diff/4ad3a2b3 Branch: refs/heads/branch-dev-patch-upgrade Commit: 4ad3a2b3611a38aeea3d64411feec8776a6af554 Parents: 779995d Author: Sandor Magyari <[email protected]> Authored: Thu Feb 2 00:11:15 2017 +0100 Committer: Sandor Magyari <[email protected]> Committed: Fri Feb 3 13:47:01 2017 +0200 ---------------------------------------------------------------------- .../checks/DatabaseConsistencyCheckHelper.java | 78 ++++++++++++++++++++ .../DatabaseConsistencyCheckHelperTest.java | 58 +++++++++++++++ 2 files changed, 136 insertions(+) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/ambari/blob/4ad3a2b3/ambari-server/src/main/java/org/apache/ambari/server/checks/DatabaseConsistencyCheckHelper.java ---------------------------------------------------------------------- diff --git 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 index ea5fa15..7aa8652 100644 --- 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 @@ -137,6 +137,7 @@ public class DatabaseConsistencyCheckHelper { checkForHostsWithoutState(); checkHostComponentStates(); checkServiceConfigs(); + checkTopologyTables(); LOG.info("******************************* Check database completed *******************************"); } @@ -342,6 +343,83 @@ public class DatabaseConsistencyCheckHelper { } } + + /** + * This method checks that for each row in topology_request there is at least one row in topology_logical_request, + * topology_host_request, topology_host_task, topology_logical_task. + * */ + public static void checkTopologyTables() { + LOG.info("Checking Topology tables"); + + String SELECT_REQUEST_COUNT_QUERY = "select count(tpr.id) from topology_request tpr"; + + String SELECT_JOINED_COUNT_QUERY = "select count(DISTINCT tpr.id) from topology_request tpr join " + + "topology_logical_request tlr on tpr.id = tlr.request_id join topology_host_request thr on tlr.id = " + + "thr.logical_request_id join topology_host_task tht on thr.id = tht.host_request_id join topology_logical_task " + + "tlt on tht.id = tlt.host_task_id"; + + int topologyRequestCount = 0; + int topologyRequestTablesJoinedCount = 0; + + ResultSet rs = null; + Statement statement = null; + + if (connection == null) { + if (dbAccessor == null) { + dbAccessor = injector.getInstance(DBAccessor.class); + } + connection = dbAccessor.getConnection(); + } + + try { + statement = connection.createStatement(ResultSet.TYPE_SCROLL_SENSITIVE, ResultSet.CONCUR_UPDATABLE); + + rs = statement.executeQuery(SELECT_REQUEST_COUNT_QUERY); + if (rs != null) { + while (rs.next()) { + topologyRequestCount = rs.getInt(1); + } + } + + rs = statement.executeQuery(SELECT_JOINED_COUNT_QUERY); + if (rs != null) { + while (rs.next()) { + topologyRequestTablesJoinedCount = rs.getInt(1); + } + } + + if (topologyRequestCount != topologyRequestTablesJoinedCount) { + LOG.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."); + errorsFound = true; + } + + + } catch (SQLException e) { + LOG.error("Exception occurred during topology request tables check: ", e); + } finally { + if (rs != null) { + try { + rs.close(); + } catch (SQLException e) { + LOG.error("Exception occurred during result set closing procedure: ", e); + } + } + + if (statement != null) { + try { + statement.close(); + } catch (SQLException e) { + LOG.error("Exception occurred during statement closing procedure: ", e); + } + } + } + + } + + + /** * This method checks if count of host component states equals count * of desired host component states. According to ambari logic these http://git-wip-us.apache.org/repos/asf/ambari/blob/4ad3a2b3/ambari-server/src/test/java/org/apache/ambari/server/checks/DatabaseConsistencyCheckHelperTest.java ---------------------------------------------------------------------- diff --git a/ambari-server/src/test/java/org/apache/ambari/server/checks/DatabaseConsistencyCheckHelperTest.java b/ambari-server/src/test/java/org/apache/ambari/server/checks/DatabaseConsistencyCheckHelperTest.java index cf0854d..f73562d 100644 --- a/ambari-server/src/test/java/org/apache/ambari/server/checks/DatabaseConsistencyCheckHelperTest.java +++ b/ambari-server/src/test/java/org/apache/ambari/server/checks/DatabaseConsistencyCheckHelperTest.java @@ -172,6 +172,64 @@ public class DatabaseConsistencyCheckHelperTest { } @Test + public void testCheckTopologyTablesAreConsistent() throws Exception { + testCheckTopologyTablesConsistent(2); + Assert.assertTrue(!DatabaseConsistencyCheckHelper.ifErrorsFound()); + } + + @Test + public void testCheckTopologyTablesAreNotConsistent() throws Exception { + testCheckTopologyTablesConsistent(1); + Assert.assertTrue(DatabaseConsistencyCheckHelper.ifErrorsFound()); + } + + private void testCheckTopologyTablesConsistent(int resultCount) throws Exception { + EasyMockSupport easyMockSupport = new EasyMockSupport(); + + final DBAccessor mockDBDbAccessor = easyMockSupport.createNiceMock(DBAccessor.class); + final Connection mockConnection = easyMockSupport.createNiceMock(Connection.class); + final ResultSet mockCountResultSet = easyMockSupport.createNiceMock(ResultSet.class); + final ResultSet mockJoinResultSet = 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(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(mockConnection.createStatement(ResultSet.TYPE_SCROLL_SENSITIVE, ResultSet.CONCUR_UPDATABLE)).andReturn(mockStatement); + expect(mockCountResultSet.next()).andReturn(true).once(); + expect(mockCountResultSet.getInt(1)).andReturn(2); + expect(mockJoinResultSet.next()).andReturn(true).once(); + expect(mockJoinResultSet.getInt(1)).andReturn(resultCount); + expect(mockStatement.executeQuery("select count(tpr.id) from topology_request tpr")).andReturn(mockCountResultSet); + expect(mockStatement.executeQuery("select count(DISTINCT tpr.id) from topology_request tpr join " + + "topology_logical_request tlr on tpr.id = tlr.request_id join topology_host_request thr on tlr.id = thr.logical_request_id join topology_host_task tht on thr.id = tht.host_request_id join topology_logical_task tlt on tht.id = tlt.host_task_id")).andReturn(mockJoinResultSet); + + DatabaseConsistencyCheckHelper.setInjector(mockInjector); + DatabaseConsistencyCheckHelper.setConnection(mockConnection); + + easyMockSupport.replayAll(); + + + DatabaseConsistencyCheckHelper.checkTopologyTables(); + + easyMockSupport.verifyAll(); + + } + + @Test public void testCheckHostComponentStatesCountEqualsHostComponentsDesiredStates() throws Exception { EasyMockSupport easyMockSupport = new EasyMockSupport();
