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

[4/4] git commit: AMBARI-4716. Run Ambari Server Upgrade via code rather than DDL/DML. (mpapirkovskyy)

AMBARI-4716. Run Ambari Server Upgrade via code rather than DDL/DML. (mpapirkovskyy)


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

Branch: refs/heads/trunk
Commit: fea7b6222311a48604c5a96d9478c53fbd7ce26f
Parents: c02c7bf
Author: Myroslav Papirkovskyy <mp...@hortonworks.com>
Authored: Fri Feb 21 21:02:27 2014 +0200
Committer: Myroslav Papirkovskyy <mp...@hortonworks.com>
Committed: Fri Feb 21 21:03:40 2014 +0200

----------------------------------------------------------------------
 ambari-server/pom.xml                           |  19 +-
 .../server/configuration/Configuration.java     |  20 +-
 .../server/controller/ControllerModule.java     |   5 +-
 .../apache/ambari/server/orm/DBAccessor.java    | 319 ++++++++++++
 .../ambari/server/orm/DBAccessorImpl.java       | 455 +++++++++++++++++
 .../orm/dao/HostComponentDesiredStateDAO.java   |  13 +
 .../server/orm/dao/HostComponentStateDAO.java   |  13 +
 .../dao/ServiceComponentDesiredStateDAO.java    |  14 +
 .../server/orm/dao/ServiceDesiredStateDAO.java  |  14 +
 .../ambari/server/orm/helpers/ScriptRunner.java | 254 ++++++++++
 .../server/orm/helpers/dbms/DbmsHelper.java     |  72 +++
 .../server/orm/helpers/dbms/DerbyHelper.java    |  52 ++
 .../orm/helpers/dbms/GenericDbmsHelper.java     | 273 +++++++++++
 .../server/orm/helpers/dbms/MySqlHelper.java    |  49 ++
 .../server/orm/helpers/dbms/OracleHelper.java   |  46 ++
 .../server/orm/helpers/dbms/PostgresHelper.java |  46 ++
 .../server/upgrade/AbstractUpgradeCatalog.java  | 192 ++++++++
 .../server/upgrade/SchemaUpgradeHelper.java     | 211 ++++++++
 .../server/upgrade/StackUpgradeHelper.java      | 159 ++++++
 .../ambari/server/upgrade/StackUpgradeUtil.java | 142 ++++++
 .../ambari/server/upgrade/UpgradeCatalog.java   |  55 +++
 .../server/upgrade/UpgradeCatalog150.java       | 487 +++++++++++++++++++
 .../apache/ambari/server/utils/DateUtils.java   |  13 +
 .../ambari/server/utils/VersionUtils.java       |  14 +
 ambari-server/src/main/python/ambari-server.py  | 469 ++++--------------
 .../upgrade/ddl/Ambari-DDL-MySQL-UPGRADE.sql    |  95 ----
 .../upgrade/ddl/Ambari-DDL-Oracle-UPGRADE.sql   | 134 -----
 .../ddl/Ambari-DDL-Postgres-UPGRADE-1.3.0.sql   | 250 ----------
 .../main/resources/upgrade/ddl/quartz.mysql.sql |  53 ++
 .../resources/upgrade/ddl/quartz.oracle.sql     |  55 +++
 .../resources/upgrade/ddl/quartz.postgres.sql   |  53 ++
 .../dml/Ambari-DML-Oracle-FIX_LOCAL_REPO.sql    |  45 --
 .../dml/Ambari-DML-Postgres-FIX_LOCAL_REPO.sql  |  44 --
 .../ambari/server/orm/DBAccessorImplTest.java   | 253 ++++++++++
 .../server/upgrade/UpgradeCatalogTest.java      | 105 ++++
 .../src/test/python/TestAmbariServer.py         | 226 ++++-----
 ambari-server/src/test/python/ambari.properties |   1 +
 37 files changed, 3617 insertions(+), 1103 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/ambari/blob/fea7b622/ambari-server/pom.xml
----------------------------------------------------------------------
diff --git a/ambari-server/pom.xml b/ambari-server/pom.xml
index bc83dd8..0da58d1 100644
--- a/ambari-server/pom.xml
+++ b/ambari-server/pom.xml
@@ -350,19 +350,7 @@
               <directory>/var/lib/ambari-server/resources/upgrade/ddl</directory>
               <sources>
                 <source>
-                  <location>target/classes/upgrade/ddl/Ambari-DDL-Postgres-UPGRADE-1.3.0.sql</location>
-                </source>
-                <source>
-                  <location>src/main/resources/upgrade/ddl/Ambari-DDL-Postgres-UPGRADE-1.3.0.Fix.sql</location>
-                </source>
-                <source>
-                  <location>src/main/resources/upgrade/ddl/Ambari-DDL-Postgres-UPGRADE-1.3.0.Check.sql</location>
-                </source>
-                <source>
-                  <location>target/classes/upgrade/ddl/Ambari-DDL-Oracle-UPGRADE.sql</location>
-                </source>
-                <source>
-                  <location>target/classes/upgrade/ddl/Ambari-DDL-MySQL-UPGRADE.sql</location>
+                  <location>src/main/resources/upgrade/ddl</location>
                 </source>
               </sources>
             </mapping>
@@ -618,6 +606,11 @@
       <artifactId>guice-servlet</artifactId>
     </dependency>
     <dependency>
+      <groupId>com.google.inject.extensions</groupId>
+      <artifactId>guice-multibindings</artifactId>
+      <version>3.0</version>
+    </dependency>
+    <dependency>
       <groupId>org.apache.derby</groupId>
       <artifactId>derby</artifactId>
     </dependency>

http://git-wip-us.apache.org/repos/asf/ambari/blob/fea7b622/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 9fe104c..56bb58c 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
@@ -97,6 +97,7 @@ public class Configuration {
   public static final String POSTGRES_DB_NAME = "postgres";
   public static final String ORACLE_DB_NAME = "oracle";
   public static final String MYSQL_DB_NAME = "mysql";
+  public static final String DERBY_DB_NAME = "derby";
   public static final String OJDBC_JAR_NAME_KEY = "db.oracle.jdbc.name";
   public static final String OJDBC_JAR_NAME_DEFAULT = "ojdbc6.jar";
   public static final String MYSQL_JAR_NAME_KEY = "db.mysql.jdbc.name";
@@ -224,7 +225,7 @@ public class Configuration {
       "/var/lib/ambari-server/resources/custom_action_definitions";
 
   private static final long SERVER_EC_CACHE_SIZE_DEFAULT = 10000L;
-  private static final String SERVER_JDBC_USER_NAME_DEFAULT = "ambari-server";
+  private static final String SERVER_JDBC_USER_NAME_DEFAULT = "ambari";
   private static final String SERVER_JDBC_USER_PASSWD_DEFAULT = "bigdata";
   private static final String SERVER_JDBC_RCA_USER_NAME_DEFAULT = "mapred";
   private static final String SERVER_JDBC_RCA_USER_PASSWD_DEFAULT = "mapred";
@@ -235,7 +236,7 @@ public class Configuration {
   private static final String SRVR_CRT_PASS_LEN_DEFAULT = "50";
   private static final String PASSPHRASE_ENV_DEFAULT = "AMBARI_PASSPHRASE";
   private static final String RESOURCES_DIR_DEFAULT =
-      "/var/share/ambari/resources/";
+      "/var/lib/ambari-server/resources/";
   private static final String ANONYMOUS_AUDIT_NAME_KEY = "anonymous.audit.name";
   private static final String CLIENT_SECURITY_DEFAULT = "local";
   private static final int CLIENT_API_PORT_DEFAULT = 8080;
@@ -601,11 +602,19 @@ public class Configuration {
   }
 
   public String getDatabaseDriver() {
-    return properties.getProperty(SERVER_JDBC_DRIVER_KEY, JDBC_LOCAL_DRIVER);
+    if (getPersistenceType() != PersistenceType.IN_MEMORY) {
+      return properties.getProperty(SERVER_JDBC_DRIVER_KEY, JDBC_LOCAL_DRIVER);
+    } else {
+      return JDBC_IN_MEMROY_DRIVER;
+    }
   }
 
   public String getDatabaseUrl() {
-    return properties.getProperty(SERVER_JDBC_URL_KEY, getLocalDatabaseUrl());
+    if (getPersistenceType() != PersistenceType.IN_MEMORY) {
+      return properties.getProperty(SERVER_JDBC_URL_KEY, getLocalDatabaseUrl());
+    } else {
+      return JDBC_IN_MEMORY_URL;
+    }
   }
 
   public String getLocalDatabaseUrl() {
@@ -929,4 +938,7 @@ public class Configuration {
     }
   }
 
+  public String getResourceDirPath() {
+    return properties.getProperty(RESOURCES_DIR_KEY, RESOURCES_DIR_DEFAULT);
+  }
 }

http://git-wip-us.apache.org/repos/asf/ambari/blob/fea7b622/ambari-server/src/main/java/org/apache/ambari/server/controller/ControllerModule.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/controller/ControllerModule.java b/ambari-server/src/main/java/org/apache/ambari/server/controller/ControllerModule.java
index adb78c3..ae57af2 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/controller/ControllerModule.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/controller/ControllerModule.java
@@ -37,6 +37,7 @@ import org.apache.ambari.server.controller.internal.HostComponentResourceProvide
 import org.apache.ambari.server.controller.internal.HostResourceProvider;
 import org.apache.ambari.server.controller.internal.ServiceResourceProvider;
 import org.apache.ambari.server.controller.spi.ResourceProvider;
+import org.apache.ambari.server.orm.DBAccessorImpl;
 import org.apache.ambari.server.orm.PersistenceType;
 import org.apache.ambari.server.scheduler.ExecutionScheduler;
 import org.apache.ambari.server.scheduler.ExecutionSchedulerImpl;
@@ -70,13 +71,12 @@ import org.apache.ambari.server.state.scheduler.RequestExecutionImpl;
 import org.apache.ambari.server.state.svccomphost.ServiceComponentHostImpl;
 import org.springframework.security.crypto.password.PasswordEncoder;
 import org.springframework.security.crypto.password.StandardPasswordEncoder;
-
 import java.security.SecureRandom;
 import java.util.Map;
 import java.util.Map.Entry;
 import java.util.Properties;
-
 import com.google.gson.GsonBuilder;
+import org.apache.ambari.server.orm.DBAccessor;
 import static org.eclipse.persistence.config.PersistenceUnitProperties.CREATE_JDBC_DDL_FILE;
 import static org.eclipse.persistence.config.PersistenceUnitProperties.CREATE_ONLY;
 import static org.eclipse.persistence.config.PersistenceUnitProperties.CREATE_OR_EXTEND;
@@ -247,6 +247,7 @@ public class ControllerModule extends AbstractModule {
     install(new FactoryModuleBuilder().build(RequestFactory.class));
 
     bind(HostRoleCommandFactory.class).to(HostRoleCommandFactoryImpl.class);
+    bind(DBAccessor.class).to(DBAccessorImpl.class);
   }
 
 }

http://git-wip-us.apache.org/repos/asf/ambari/blob/fea7b622/ambari-server/src/main/java/org/apache/ambari/server/orm/DBAccessor.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/orm/DBAccessor.java b/ambari-server/src/main/java/org/apache/ambari/server/orm/DBAccessor.java
new file mode 100644
index 0000000..3b3d2e5
--- /dev/null
+++ b/ambari-server/src/main/java/org/apache/ambari/server/orm/DBAccessor.java
@@ -0,0 +1,319 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.ambari.server.orm;
+
+import org.eclipse.persistence.sessions.DatabaseSession;
+
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.sql.SQLException;
+import java.util.List;
+
+/**
+ * Interface for schema manipulation
+ * Note: IF NOT EXISTS is default for all supported DDL statements
+ */
+public interface DBAccessor {
+
+  /**
+   * Create new table
+   * @param tableName
+   * @param columnInfo
+   * @param primaryKeyColumns
+   * @throws SQLException
+   */
+  public void createTable(String tableName, List<DBColumnInfo> columnInfo,
+                          String... primaryKeyColumns) throws SQLException;
+
+  /**
+   * Create new index
+   * @param indexName
+   * @param tableName
+   * @param columnNames
+   * @throws SQLException
+   */
+  public void createIndex(String indexName, String tableName,
+                          String... columnNames) throws SQLException;
+
+
+  /**
+   * Add foreign key for a relation
+   * @param tableName
+   * @param constraintName
+   * @param keyColumn
+   * @param referenceColumn
+   * @throws SQLException
+   */
+  public void addFKConstraint(String tableName,
+                              String constraintName,
+                              String keyColumn,
+                              String referenceTableName,
+                              String referenceColumn,
+                              boolean ignoreFailure) throws SQLException;
+
+  /**
+   * Add foreign key for a relation
+   * @param tableName
+   * @param constraintName
+   * @param keyColumn
+   * @param referenceColumn
+   * @throws SQLException
+   */
+  public void addFKConstraint(String tableName,
+                              String constraintName,
+                              String[] keyColumns,
+                              String referenceTableName,
+                              String[] referenceColumns,
+                              boolean ignoreFailure) throws SQLException;
+
+  /**
+   * Add column to existing table
+   * @param tableName
+   * @param columnInfo
+   * @throws SQLException
+   */
+  public void addColumn(String tableName,
+                        DBColumnInfo columnInfo) throws SQLException;
+
+  /**
+   * Rename existing column
+   * @param tableName
+   * @param oldColumnName
+   * @param columnInfo
+   * @throws SQLException
+   */
+  void renameColumn(String tableName, String oldColumnName,
+                    DBColumnInfo columnInfo) throws SQLException;
+
+  /**
+   * Alter column from existing table, only supports varchar extension <br/>
+   * Use following sequence for more complex stuff: <br/>
+   * <li/>{@link #addColumn(String, org.apache.ambari.server.orm.DBAccessor.DBColumnInfo)}
+   * <li/>{@link #updateTable(String, String, Object, String)}
+   * <li/>{@link #dropColumn(String, String)}
+   * <li/>{@link #renameColumn(String, String, org.apache.ambari.server.orm.DBAccessor.DBColumnInfo)}
+   * @param tableName
+   * @param columnInfo
+   * @throws SQLException
+   */
+  public void alterColumn(String tableName,
+                          DBColumnInfo columnInfo) throws SQLException;
+
+  /**
+   * Insert row into table
+   *
+   * @param tableName
+   * @param columnNames
+   * @param values
+   * @param ignoreFailure
+   * @return
+   * @throws SQLException
+   */
+  boolean insertRow(String tableName, String[] columnNames, String[] values, boolean ignoreFailure) throws SQLException;
+
+  /**
+   * Simple update operation on table
+   * @param tableName
+   * @param columnName
+   * @param value
+   * @param whereClause
+   * @return
+   * @throws SQLException
+   */
+  public int updateTable(String tableName, String columnName, Object value,
+                         String whereClause) throws SQLException;
+
+  /**
+   * Helper method to run third party scripts like Quartz DDL
+   * @param filePath
+   * @throws SQLException
+   */
+  public void executeScript(String filePath) throws SQLException, IOException;
+
+
+  /**
+   * Execute ad-hoc query on DB.
+   * @param query
+   * @throws SQLException
+   */
+  public void executeQuery(String query) throws SQLException;
+
+  /**
+   * Execute query on DB
+   * @param query
+   * @param ignoreFailure
+   * @throws SQLException
+   */
+  void executeQuery(String query, boolean ignoreFailure) throws SQLException;
+
+  /**
+   * Drop table from schema
+   * @param tableName
+   * @throws SQLException
+   */
+  public void dropTable(String tableName) throws SQLException;
+
+  /**
+   * Delete all table data
+   * @param tableName
+   * @throws SQLException
+   */
+  public void truncateTable(String tableName) throws SQLException;
+
+  /**
+   * Drop a column from table
+   * @param tableName
+   * @param columnName
+   * @throws SQLException
+   */
+  public void dropColumn(String tableName, String columnName) throws SQLException;
+
+  /**
+   * Drop sequence
+   * @param sequenceName
+   * @throws SQLException
+   */
+  public void dropSequence(String sequenceName) throws SQLException;
+
+  /**
+   * Drop a constraint from table
+   * @param tableName
+   * @param constraintName
+   * @throws SQLException
+   */
+  public void dropConstraint(String tableName, String constraintName) throws SQLException;
+
+  /**
+   * Verify if table exists by looking at metadata.
+   * @param tableName
+   * @return
+   * @throws SQLException
+   */
+  public boolean tableExists(String tableName) throws SQLException;
+
+  /**
+   * Verify if table has any data
+   * @param tableName
+   * @return
+   * @throws SQLException
+   */
+  public boolean tableHasData(String tableName) throws SQLException;
+
+  /**
+   * Verify if table already has a column defined.
+   * @param tableName
+   * @param columnName
+   * @return
+   * @throws SQLException
+   */
+  public boolean tableHasColumn(String tableName, String columnName) throws SQLException;
+
+  /**
+   * Verify if table already has a FK constraint.
+   * @param tableName
+   * @param refTableName
+   * @param columnName
+   * @param refColumnName
+   * @return
+   * @throws SQLException
+   */
+  public boolean tableHasForeignKey(String tableName, String refTableName,
+             String columnName, String refColumnName) throws SQLException;
+
+  /**
+   * Get a new DB session
+   * @return
+   */
+  public DatabaseSession getNewDatabaseSession();
+
+  /**
+   * Capture column type
+   */
+  public class DBColumnInfo {
+    private String name;
+    private Class type;
+//    private DBColumnType type;
+    private Integer length;
+    private Object defaultValue;
+    private boolean isNullable;
+
+    public DBColumnInfo(String name, Class type, Integer length) {
+      this(name, type, length, null, false);
+    }
+
+    public DBColumnInfo(String name, Class type, Integer length,
+                        Object defaultValue, boolean nullable) {
+      this.name = name;
+      this.type = type;
+      this.length = length;
+      this.defaultValue = defaultValue;
+      isNullable = nullable;
+    }
+
+    public String getName() {
+      return name;
+    }
+
+    public void setName(String name) {
+      this.name = name;
+    }
+
+    public Class getType() {
+      return type;
+    }
+
+    public void setType(Class type) {
+      this.type = type;
+    }
+
+    public Integer getLength() {
+      return length;
+    }
+
+    public void setLength(Integer length) {
+      this.length = length;
+    }
+
+    public Object getDefaultValue() {
+      return defaultValue;
+    }
+
+    public void setDefaultValue(Object defaultValue) {
+      this.defaultValue = defaultValue;
+    }
+
+    public boolean isNullable() {
+      return isNullable;
+    }
+
+    public void setNullable(boolean nullable) {
+      isNullable = nullable;
+    }
+
+    public enum DBColumnType {
+      VARCHAR,
+      CHAR,
+      INT,
+      LONG,
+      BOOL,
+      TIME,
+      BLOB
+    }
+  }
+
+}

http://git-wip-us.apache.org/repos/asf/ambari/blob/fea7b622/ambari-server/src/main/java/org/apache/ambari/server/orm/DBAccessorImpl.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/orm/DBAccessorImpl.java b/ambari-server/src/main/java/org/apache/ambari/server/orm/DBAccessorImpl.java
new file mode 100644
index 0000000..e30d4f1
--- /dev/null
+++ b/ambari-server/src/main/java/org/apache/ambari/server/orm/DBAccessorImpl.java
@@ -0,0 +1,455 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.ambari.server.orm;
+
+import com.google.inject.Inject;
+import org.apache.ambari.server.configuration.Configuration;
+import org.apache.ambari.server.orm.helpers.ScriptRunner;
+import org.apache.ambari.server.orm.helpers.dbms.*;
+import org.eclipse.persistence.internal.helper.DBPlatformHelper;
+import org.eclipse.persistence.internal.sessions.DatabaseSessionImpl;
+import org.eclipse.persistence.logging.AbstractSessionLog;
+import org.eclipse.persistence.logging.SessionLogEntry;
+import org.eclipse.persistence.platform.database.*;
+import org.eclipse.persistence.sessions.DatabaseLogin;
+import org.eclipse.persistence.sessions.DatabaseSession;
+import org.eclipse.persistence.sessions.Login;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.io.BufferedReader;
+import java.io.FileReader;
+import java.io.IOException;
+import java.sql.Connection;
+import java.sql.DatabaseMetaData;
+import java.sql.DriverManager;
+import java.sql.ResultSet;
+import java.sql.SQLException;
+import java.sql.Statement;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
+
+public class DBAccessorImpl implements DBAccessor {
+  private static final Logger LOG = LoggerFactory.getLogger(DBAccessorImpl.class);
+  private final DatabasePlatform databasePlatform;
+  private final Connection connection;
+  private final DbmsHelper dbmsHelper;
+  private Configuration configuration;
+  private DatabaseMetaData databaseMetaData;
+
+  @Inject
+  public DBAccessorImpl(Configuration configuration) {
+    this.configuration = configuration;
+
+    try {
+      Class.forName(configuration.getDatabaseDriver());
+
+      connection = DriverManager.getConnection(configuration.getDatabaseUrl(),
+        configuration.getDatabaseUser(),
+        configuration.getDatabasePassword());
+
+      //TODO create own mapping and platform classes for supported databases
+      String vendorName = connection.getMetaData().getDatabaseProductName() +
+        connection.getMetaData().getDatabaseMajorVersion();
+      String dbPlatform = DBPlatformHelper.getDBPlatform(vendorName, new AbstractSessionLog() {
+        @Override
+        public void log(SessionLogEntry sessionLogEntry) {
+          LOG.debug(sessionLogEntry.getMessage());
+        }
+      });
+      this.databasePlatform = (DatabasePlatform) Class.forName(dbPlatform).newInstance();
+      this.dbmsHelper = loadHelper(databasePlatform);
+    } catch (Exception e) {
+      String message = "Error while creating database accessor ";
+      LOG.error(message, e);
+      throw new RuntimeException(e);
+    }
+  }
+
+  protected DbmsHelper loadHelper(DatabasePlatform databasePlatform) {
+    if (databasePlatform instanceof OraclePlatform) {
+      return new OracleHelper(databasePlatform);
+    }else if (databasePlatform instanceof MySQLPlatform) {
+      return new MySqlHelper(databasePlatform);
+    }else if (databasePlatform instanceof PostgreSQLPlatform) {
+      return new PostgresHelper(databasePlatform);
+    }else if (databasePlatform instanceof DerbyPlatform) {
+      return new DerbyHelper(databasePlatform);
+    } else {
+      return new GenericDbmsHelper(databasePlatform);
+    }
+  }
+
+  protected Connection getConnection() {
+    return connection;
+  }
+
+  @Override
+  public void createTable(String tableName, List<DBColumnInfo> columnInfo,
+                          String... primaryKeyColumns) throws SQLException {
+    if (!tableExists(tableName)) {
+      String query = dbmsHelper.getCreateTableStatement(tableName, columnInfo, Arrays.asList(primaryKeyColumns));
+
+      executeQuery(query);
+    }
+  }
+
+  private DatabaseMetaData getDatabaseMetaData() throws SQLException {
+    if (databaseMetaData == null) {
+      databaseMetaData = connection.getMetaData();
+    }
+
+    return databaseMetaData;
+  }
+
+  @Override
+  public boolean tableExists(String tableName) throws SQLException {
+    boolean result = false;
+    DatabaseMetaData metaData = getDatabaseMetaData();
+    String schemaFilter = null;
+    if (getDbType().equals(Configuration.ORACLE_DB_NAME)) {
+      // Optimization to not query everything
+      schemaFilter = configuration.getDatabaseUser();
+    }
+
+    ResultSet res = metaData.getTables(null, schemaFilter,
+      tableName.toUpperCase(), new String[] { "TABLE" });
+
+    if (res != null) {
+      try {
+        if (res.next()) {
+          return res.getString("TABLE_NAME") != null && res.getString
+            ("TABLE_NAME").equalsIgnoreCase(tableName);
+        }
+      } finally {
+        res.close();
+      }
+    }
+
+    return result;
+  }
+
+  protected String getDbType() {
+    String dbUrl = configuration.getDatabaseUrl();
+    String dbType;
+
+    if (dbUrl.contains(Configuration.POSTGRES_DB_NAME)) {
+      dbType = Configuration.POSTGRES_DB_NAME;
+    } else if (dbUrl.contains(Configuration.ORACLE_DB_NAME)) {
+      dbType = Configuration.ORACLE_DB_NAME;
+    } else if (dbUrl.contains(Configuration.MYSQL_DB_NAME)) {
+      dbType = Configuration.MYSQL_DB_NAME;
+    } else if (dbUrl.contains(Configuration.DERBY_DB_NAME)) {
+      dbType = Configuration.DERBY_DB_NAME;
+    } else {
+      throw new RuntimeException("Unable to determine database type.");
+    }
+
+    return dbType;
+  }
+
+  @Override
+  public boolean tableHasData(String tableName) throws SQLException {
+    String query = "SELECT count(*) from " + tableName;
+    Statement statement = getConnection().createStatement();
+    ResultSet rs = statement.executeQuery(query);
+    boolean retVal = false;
+    if (rs != null) {
+      if (rs.next()) {
+        return rs.getInt(0) > 0;
+      }
+    }
+    return retVal;
+  }
+
+  @Override
+  public boolean tableHasColumn(String tableName, String columnName) throws SQLException {
+    boolean result = false;
+    DatabaseMetaData metaData = getDatabaseMetaData();
+    String schemaFilter = null;
+    if (getDbType().equals(Configuration.ORACLE_DB_NAME)) {
+      // Optimization to not query everything
+      schemaFilter = configuration.getDatabaseUser();
+    }
+
+    ResultSet rs = metaData.getColumns(null, schemaFilter,
+        tableName.toUpperCase(), columnName.toUpperCase());
+
+    if (rs != null) {
+      try {
+        if (rs.next()) {
+          return rs.getString("COLUMN_NAME") != null && rs.getString
+            ("COLUMN_NAME").equalsIgnoreCase(columnName);
+        }
+      } finally {
+        rs.close();
+      }
+    }
+
+    return result;
+  }
+
+  @Override
+  public boolean tableHasForeignKey(String tableName, String refTableName,
+              String columnName, String refColumnName) throws SQLException {
+    boolean result = false;
+    DatabaseMetaData metaData = getDatabaseMetaData();
+    String schemaFilter = null;
+    if (getDbType().equals(Configuration.ORACLE_DB_NAME)) {
+      // Optimization to not query everything
+      schemaFilter = configuration.getDatabaseUser();
+    }
+
+    ResultSet rs = metaData.getCrossReference(null, schemaFilter, tableName,
+      null, schemaFilter, refTableName);
+
+    if (rs != null) {
+      try {
+        if (rs.next()) {
+          String refColumn = rs.getString("FKCOLUMN_NAME");
+          result = refColumn != null && refColumn.equalsIgnoreCase(refColumnName);
+        }
+      } finally {
+        rs.close();
+      }
+    }
+
+    return result;
+  }
+
+  @Override
+  public void createIndex(String indexName, String tableName,
+                          String... columnNames) throws SQLException {
+    String query = dbmsHelper.getCreateIndexStatement(indexName, tableName, columnNames);
+
+    executeQuery(query);
+  }
+
+  @Override
+  public void addFKConstraint(String tableName, String constraintName,
+                              String keyColumn, String referenceTableName,
+                              String referenceColumn, boolean ignoreFailure) throws SQLException {
+
+    if (!tableHasForeignKey(tableName, referenceTableName, keyColumn, referenceColumn)) {
+
+      String query = dbmsHelper.getAddForeignKeyStatement(tableName, constraintName,
+        Collections.singletonList(keyColumn),
+        referenceTableName,
+        Collections.singletonList(referenceColumn)
+      );
+
+      try {
+        executeQuery(query);
+      } catch (SQLException e) {
+        LOG.warn("Add FK constraint failed" +
+          ", constraintName = " + constraintName +
+          ", tableName = " + tableName, e);
+        if (!ignoreFailure) {
+          throw e;
+        }
+      }
+    }
+  }
+
+  @Override
+  public void addFKConstraint(String tableName, String constraintName,
+                              String[] keyColumns, String referenceTableName,
+                              String[] referenceColumns, boolean ignoreFailure) throws SQLException {
+    String query = dbmsHelper.getAddForeignKeyStatement(tableName, constraintName,
+        Arrays.asList(keyColumns),
+        referenceTableName,
+        Arrays.asList(referenceColumns)
+    );
+
+    try {
+      executeQuery(query);
+    } catch (SQLException e) {
+      LOG.warn("Add FK constraint failed" +
+              ", constraintName = " + constraintName +
+              ", tableName = " + tableName, e);
+      if (!ignoreFailure) {
+        throw e;
+      }
+    }
+  }
+
+  @Override
+  public void renameColumn(String tableName, String oldColumnName,
+                           DBColumnInfo columnInfo) throws SQLException {
+    //it is mandatory to specify type in column change clause for mysql
+    String renameColumnStatement = dbmsHelper.getRenameColumnStatement(tableName, oldColumnName, columnInfo);
+    executeQuery(renameColumnStatement);
+
+  }
+
+  @Override
+  public void addColumn(String tableName, DBColumnInfo columnInfo) throws SQLException {
+    if (!tableHasColumn(tableName, columnInfo.getName())) {
+      //TODO workaround for default values, possibly we will have full support later
+      if (columnInfo.getDefaultValue() != null) {
+        columnInfo.setNullable(true);
+      }
+      String query = dbmsHelper.getAddColumnStatement(tableName, columnInfo);
+      executeQuery(query);
+
+      if (columnInfo.getDefaultValue() != null) {
+        updateTable(tableName, columnInfo.getName(), columnInfo.getDefaultValue(), "");
+      }
+    }
+  }
+
+  @Override
+  public void alterColumn(String tableName, DBColumnInfo columnInfo) throws SQLException {
+    //varchar extension only (derby limitation, but not too much for others),
+    //use addColumn-update-drop-rename for more
+    String statement = dbmsHelper.getAlterColumnStatement(tableName, columnInfo);
+    executeQuery(statement);
+  }
+
+  @Override
+  public boolean insertRow(String tableName, String[] columnNames, String[] values, boolean ignoreFailure) throws SQLException {
+    StringBuilder builder = new StringBuilder();
+    builder.append("INSERT INTO ").append(tableName).append("(");
+    if (columnNames.length != values.length) {
+      throw new IllegalArgumentException("number of columns should be equal to number of values");
+    }
+
+    for (int i = 0; i < columnNames.length; i++) {
+      builder.append(columnNames[i]);
+      if(i!=columnNames.length-1){
+        builder.append(",");
+      }
+    }
+
+    builder.append(") VALUES(");
+
+    for (int i = 0; i < values.length; i++) {
+      builder.append(values[i]);
+      if(i!=values.length-1){
+        builder.append(",");
+      }
+    }
+
+    builder.append(")");
+
+    Statement statement = getConnection().createStatement();
+    int rowsUpdated = 0;
+    String query = builder.toString();
+    try {
+      rowsUpdated = statement.executeUpdate(query);
+    } catch (SQLException e) {
+      LOG.warn("Unable to execute query: " + query, e);
+      if (!ignoreFailure) {
+        throw e;
+      }
+    }
+
+    return rowsUpdated != 0;
+  }
+
+
+  @Override
+  public int updateTable(String tableName, String columnName, Object value,
+                         String whereClause) throws SQLException {
+
+    StringBuilder query = new StringBuilder
+      (String.format("UPDATE %s SET %s = ", tableName, columnName));
+
+    // Only String and number supported.
+    // Taken from: org.eclipse.persistence.internal.databaseaccess.appendParameterInternal
+    Object dbValue = databasePlatform.convertToDatabaseType(value);
+    String valueString = value.toString();
+    if (dbValue instanceof String) {
+      valueString = "'" + value.toString() + "'";
+    }
+
+    query.append(valueString);
+    query.append(" ");
+    query.append(whereClause);
+
+    Statement statement = getConnection().createStatement();
+
+    return statement.executeUpdate(query.toString());
+  }
+
+  @Override
+  public void executeQuery(String query) throws SQLException {
+    executeQuery(query, false);
+  }
+
+  @Override
+  public void executeQuery(String query, boolean ignoreFailure) throws SQLException {
+    Statement statement = getConnection().createStatement();
+    try {
+      statement.execute(query);
+    } catch (SQLException e) {
+      LOG.warn("Error executing query: "+query, e);
+      if (!ignoreFailure) {
+        throw e;
+      }
+    }
+  }
+
+  @Override
+  public void dropTable(String tableName) throws SQLException {
+    String query = dbmsHelper.getDropTableStatement(tableName);
+    executeQuery(query);
+  }
+
+  @Override
+  public void truncateTable(String tableName) throws SQLException {
+    String query = "DELETE FROM " + tableName;
+    executeQuery(query);
+  }
+
+  @Override
+  public void dropColumn(String tableName, String columnName) throws SQLException {
+    throw new UnsupportedOperationException("Drop column not supported");
+  }
+
+  @Override
+  public void dropSequence(String sequenceName) throws SQLException {
+    executeQuery(dbmsHelper.getDropSequenceStatement(sequenceName));
+  }
+
+  @Override
+  public void dropConstraint(String tableName, String constraintName) throws SQLException {
+    String query = dbmsHelper.getDropConstraintStatement(tableName, constraintName);
+
+    executeQuery(query);
+  }
+
+  @Override
+  /**
+   * Execute script with autocommit and error tolerance, like psql and sqlplus do by default
+   */
+  public void executeScript(String filePath) throws SQLException, IOException {
+    BufferedReader br = new BufferedReader(new FileReader(filePath));
+    ScriptRunner scriptRunner = new ScriptRunner(getConnection(), true, false);
+    scriptRunner.runScript(br);
+  }
+
+  @Override
+  public DatabaseSession getNewDatabaseSession() {
+    Login login = new DatabaseLogin();
+    login.setUserName(configuration.getDatabaseUser());
+    login.setPassword(configuration.getDatabasePassword());
+    return new DatabaseSessionImpl(login);
+  }
+}

http://git-wip-us.apache.org/repos/asf/ambari/blob/fea7b622/ambari-server/src/main/java/org/apache/ambari/server/orm/dao/HostComponentDesiredStateDAO.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/orm/dao/HostComponentDesiredStateDAO.java b/ambari-server/src/main/java/org/apache/ambari/server/orm/dao/HostComponentDesiredStateDAO.java
index f98df0f..f8b43a8 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/orm/dao/HostComponentDesiredStateDAO.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/orm/dao/HostComponentDesiredStateDAO.java
@@ -26,6 +26,9 @@ import org.apache.ambari.server.orm.entities.HostComponentDesiredStateEntity;
 import org.apache.ambari.server.orm.entities.HostComponentDesiredStateEntityPK;
 
 import javax.persistence.EntityManager;
+import javax.persistence.NoResultException;
+import javax.persistence.TypedQuery;
+import java.util.List;
 
 @Singleton
 public class HostComponentDesiredStateDAO {
@@ -62,4 +65,14 @@ public class HostComponentDesiredStateDAO {
     remove(findByPK(primaryKey));
   }
 
+  @Transactional
+  public List<HostComponentDesiredStateEntity> findAll() {
+    TypedQuery<HostComponentDesiredStateEntity> query = entityManagerProvider.get()
+      .createQuery("SELECT hcd from HostComponentDesiredStateEntity hcd", HostComponentDesiredStateEntity.class);
+    try {
+      return query.getResultList();
+    } catch (NoResultException ignored) {
+    }
+    return null;
+  }
 }

http://git-wip-us.apache.org/repos/asf/ambari/blob/fea7b622/ambari-server/src/main/java/org/apache/ambari/server/orm/dao/HostComponentStateDAO.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/orm/dao/HostComponentStateDAO.java b/ambari-server/src/main/java/org/apache/ambari/server/orm/dao/HostComponentStateDAO.java
index 06d97d9..697d5f0 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/orm/dao/HostComponentStateDAO.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/orm/dao/HostComponentStateDAO.java
@@ -26,6 +26,9 @@ import org.apache.ambari.server.orm.entities.HostComponentStateEntity;
 import org.apache.ambari.server.orm.entities.HostComponentStateEntityPK;
 
 import javax.persistence.EntityManager;
+import javax.persistence.NoResultException;
+import javax.persistence.TypedQuery;
+import java.util.List;
 
 @Singleton
 public class HostComponentStateDAO {
@@ -62,4 +65,14 @@ public class HostComponentStateDAO {
     remove(findByPK(primaryKey));
   }
 
+  @Transactional
+  public List<HostComponentStateEntity> findAll() {
+    TypedQuery<HostComponentStateEntity> query = entityManagerProvider.get()
+      .createQuery("SELECT hsc from HostComponentStateEntity hsc", HostComponentStateEntity.class);
+    try {
+      return query.getResultList();
+    } catch (NoResultException ignored) {
+    }
+    return null;
+  }
 }

http://git-wip-us.apache.org/repos/asf/ambari/blob/fea7b622/ambari-server/src/main/java/org/apache/ambari/server/orm/dao/ServiceComponentDesiredStateDAO.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/orm/dao/ServiceComponentDesiredStateDAO.java b/ambari-server/src/main/java/org/apache/ambari/server/orm/dao/ServiceComponentDesiredStateDAO.java
index f062690..d1cea2e 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/orm/dao/ServiceComponentDesiredStateDAO.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/orm/dao/ServiceComponentDesiredStateDAO.java
@@ -26,6 +26,9 @@ import org.apache.ambari.server.orm.entities.ServiceComponentDesiredStateEntityP
 import org.apache.ambari.server.orm.entities.ServiceComponentDesiredStateEntity;
 
 import javax.persistence.EntityManager;
+import javax.persistence.NoResultException;
+import javax.persistence.TypedQuery;
+import java.util.List;
 
 @Singleton
 public class ServiceComponentDesiredStateDAO {
@@ -62,4 +65,15 @@ public class ServiceComponentDesiredStateDAO {
     remove(findByPK(primaryKey));
   }
 
+  @Transactional
+  public List<ServiceComponentDesiredStateEntity> findAll() {
+    TypedQuery<ServiceComponentDesiredStateEntity> query =
+      entityManagerProvider.get().
+        createQuery("SELECT scd from ServiceComponentDesiredStateEntity scd", ServiceComponentDesiredStateEntity.class);
+    try {
+      return query.getResultList();
+    } catch (NoResultException ignored) {
+    }
+    return null;
+  }
 }

http://git-wip-us.apache.org/repos/asf/ambari/blob/fea7b622/ambari-server/src/main/java/org/apache/ambari/server/orm/dao/ServiceDesiredStateDAO.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/orm/dao/ServiceDesiredStateDAO.java b/ambari-server/src/main/java/org/apache/ambari/server/orm/dao/ServiceDesiredStateDAO.java
index b6224f0..bd47213 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/orm/dao/ServiceDesiredStateDAO.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/orm/dao/ServiceDesiredStateDAO.java
@@ -26,6 +26,9 @@ import org.apache.ambari.server.orm.entities.ServiceDesiredStateEntity;
 import org.apache.ambari.server.orm.entities.ServiceDesiredStateEntityPK;
 
 import javax.persistence.EntityManager;
+import javax.persistence.NoResultException;
+import javax.persistence.TypedQuery;
+import java.util.List;
 
 @Singleton
 public class ServiceDesiredStateDAO {
@@ -62,4 +65,15 @@ public class ServiceDesiredStateDAO {
     remove(findByPK(primaryKey));
   }
 
+  @Transactional
+  public List<ServiceDesiredStateEntity> findAll() {
+    TypedQuery<ServiceDesiredStateEntity> query =
+      entityManagerProvider.get().
+        createQuery("SELECT sd from ServiceDesiredStateEntity sd", ServiceDesiredStateEntity.class);
+    try {
+      return query.getResultList();
+    } catch (NoResultException ignored) {
+    }
+    return null;
+  }
 }

http://git-wip-us.apache.org/repos/asf/ambari/blob/fea7b622/ambari-server/src/main/java/org/apache/ambari/server/orm/helpers/ScriptRunner.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/orm/helpers/ScriptRunner.java b/ambari-server/src/main/java/org/apache/ambari/server/orm/helpers/ScriptRunner.java
new file mode 100644
index 0000000..6ab0cda
--- /dev/null
+++ b/ambari-server/src/main/java/org/apache/ambari/server/orm/helpers/ScriptRunner.java
@@ -0,0 +1,254 @@
+/*
+ * Slightly modified version of the com.ibatis.common.jdbc.ScriptRunner class
+ * from the iBATIS Apache project. Only removed dependency on Resource class
+ * and a constructor
+ *
+ *
+ *
+ *  Copyright 2004 Clinton Begin
+ *
+ *  Licensed under the Apache License, Version 2.0 (the "License");
+ *  you may not use this file except in compliance with the License.
+ *  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+
+package org.apache.ambari.server.orm.helpers;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.io.IOException;
+import java.io.LineNumberReader;
+import java.io.PrintWriter;
+import java.io.Reader;
+import java.sql.*;
+
+/**
+ * Tool to run database scripts
+ * TODO replace logging, deal with licence properly or rewrite completely
+ */
+public class ScriptRunner {
+  private static final Logger LOG = LoggerFactory.getLogger(ScriptRunner.class);
+
+  private static final String DEFAULT_DELIMITER = ";";
+
+  private Connection connection;
+
+  private boolean stopOnError;
+  private boolean autoCommit;
+
+  private PrintWriter logWriter = new PrintWriter(System.out);
+  private PrintWriter errorLogWriter = new PrintWriter(System.err);
+
+  private String delimiter = DEFAULT_DELIMITER;
+  private boolean fullLineDelimiter = false;
+
+  /**
+   * Default constructor
+   */
+  public ScriptRunner(Connection connection, boolean autoCommit,
+                      boolean stopOnError) {
+    this.connection = connection;
+    this.autoCommit = autoCommit;
+    this.stopOnError = stopOnError;
+  }
+
+  public void setDelimiter(String delimiter, boolean fullLineDelimiter) {
+    this.delimiter = delimiter;
+    this.fullLineDelimiter = fullLineDelimiter;
+  }
+
+  /**
+   * Setter for logWriter property
+   *
+   * @param logWriter
+   *            - the new value of the logWriter property
+   */
+  public void setLogWriter(PrintWriter logWriter) {
+    this.logWriter = logWriter;
+  }
+
+  /**
+   * Setter for errorLogWriter property
+   *
+   * @param errorLogWriter
+   *            - the new value of the errorLogWriter property
+   */
+  public void setErrorLogWriter(PrintWriter errorLogWriter) {
+    this.errorLogWriter = errorLogWriter;
+  }
+
+  /**
+   * Runs an SQL script (read in using the Reader parameter)
+   *
+   * @param reader
+   *            - the source of the script
+   */
+  public void runScript(Reader reader) throws IOException, SQLException {
+    try {
+      boolean originalAutoCommit = connection.getAutoCommit();
+      try {
+        if (originalAutoCommit != this.autoCommit) {
+          connection.setAutoCommit(this.autoCommit);
+        }
+        runScript(connection, reader);
+      } finally {
+        connection.setAutoCommit(originalAutoCommit);
+      }
+    } catch (IOException e) {
+      throw e;
+    } catch (SQLException e) {
+      throw e;
+    } catch (Exception e) {
+      throw new RuntimeException("Error running script.  Cause: " + e, e);
+    }
+  }
+
+  /**
+   * Runs an SQL script (read in using the Reader parameter) using the
+   * connection passed in
+   *
+   * @param conn
+   *            - the connection to use for the script
+   * @param reader
+   *            - the source of the script
+   * @throws SQLException
+   *             if any SQL errors occur
+   * @throws IOException
+   *             if there is an error reading from the Reader
+   */
+  private void runScript(Connection conn, Reader reader) throws IOException,
+    SQLException {
+    StringBuffer command = null;
+    try {
+      LineNumberReader lineReader = new LineNumberReader(reader);
+      String line = null;
+      while ((line = lineReader.readLine()) != null) {
+        if (command == null) {
+          command = new StringBuffer();
+        }
+        String trimmedLine = line.trim();
+        if (trimmedLine.startsWith("--")) {
+          println(trimmedLine);
+        } else if (trimmedLine.length() < 1
+          || trimmedLine.startsWith("//")) {
+          // Do nothing
+        } else if (trimmedLine.length() < 1
+          || trimmedLine.startsWith("--")) {
+          // Do nothing
+        } else if (!fullLineDelimiter
+          && trimmedLine.endsWith(getDelimiter())
+          || fullLineDelimiter
+          && trimmedLine.equals(getDelimiter())) {
+          command.append(line.substring(0, line
+            .lastIndexOf(getDelimiter())));
+          command.append(" ");
+          Statement statement = conn.createStatement();
+
+          println(command);
+
+          boolean hasResults = false;
+          if (stopOnError) {
+            hasResults = statement.execute(command.toString());
+          } else {
+            try {
+              statement.execute(command.toString());
+            } catch (SQLException e) {
+              e.fillInStackTrace();
+              printlnError("Error executing: " + command);
+              printlnError(e);
+            }
+          }
+
+          if (autoCommit && !conn.getAutoCommit()) {
+            conn.commit();
+          }
+
+          ResultSet rs = statement.getResultSet();
+          if (hasResults && rs != null) {
+            ResultSetMetaData md = rs.getMetaData();
+            int cols = md.getColumnCount();
+            for (int i = 0; i < cols; i++) {
+              String name = md.getColumnLabel(i);
+              print(name + "\t");
+            }
+            println("");
+            while (rs.next()) {
+              for (int i = 0; i < cols; i++) {
+                String value = rs.getString(i);
+                print(value + "\t");
+              }
+              println("");
+            }
+          }
+
+          command = null;
+          try {
+            statement.close();
+          } catch (Exception e) {
+            // Ignore to workaround a bug in Jakarta DBCP
+          }
+          Thread.yield();
+        } else {
+          command.append(line);
+          command.append(" ");
+        }
+      }
+      if (!autoCommit) {
+        conn.commit();
+      }
+    } catch (SQLException e) {
+      e.fillInStackTrace();
+      printlnError("Error executing: " + command);
+      printlnError(e);
+      throw e;
+    } catch (IOException e) {
+      e.fillInStackTrace();
+      printlnError("Error executing: " + command);
+      printlnError(e);
+      throw e;
+    } finally {
+      conn.rollback();
+      flush();
+    }
+  }
+
+  private String getDelimiter() {
+    return delimiter;
+  }
+
+  private void print(Object o) {
+    if (logWriter != null) {
+      System.out.print(o);
+    }
+  }
+
+  private void println(Object o) {
+    if (logWriter != null) {
+      logWriter.println(o);
+    }
+  }
+
+  private void printlnError(Object o) {
+    if (errorLogWriter != null) {
+      errorLogWriter.println(o);
+    }
+  }
+
+  private void flush() {
+    if (logWriter != null) {
+      logWriter.flush();
+    }
+    if (errorLogWriter != null) {
+      errorLogWriter.flush();
+    }
+  }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/ambari/blob/fea7b622/ambari-server/src/main/java/org/apache/ambari/server/orm/helpers/dbms/DbmsHelper.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/orm/helpers/dbms/DbmsHelper.java b/ambari-server/src/main/java/org/apache/ambari/server/orm/helpers/dbms/DbmsHelper.java
new file mode 100644
index 0000000..2e66006
--- /dev/null
+++ b/ambari-server/src/main/java/org/apache/ambari/server/orm/helpers/dbms/DbmsHelper.java
@@ -0,0 +1,72 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.ambari.server.orm.helpers.dbms;
+
+import org.apache.ambari.server.orm.DBAccessor;
+
+import java.util.List;
+
+public interface DbmsHelper {
+
+  /**
+   * Check if column type can be modified directly
+   * @return
+   */
+  boolean supportsColumnTypeChange();
+
+  /**
+   * Generate rename column statement
+   * @param tableName
+   * @param oldName
+   * @param columnInfo definition of new column
+   * @return
+   */
+  String getRenameColumnStatement(String tableName, String oldName, DBAccessor.DBColumnInfo columnInfo);
+
+  /**
+   * Generate alter column statement
+   * @param tableName
+   * @param columnInfo
+   * @return
+   */
+  String getAlterColumnStatement(String tableName, DBAccessor.DBColumnInfo columnInfo);
+
+  String getCreateTableStatement(String tableName,
+                                 List<DBAccessor.DBColumnInfo> columns,
+                                 List<String> primaryKeyColumns);
+
+  String getCreateIndexStatement(String indexName, String tableName,
+                                 String... columnNames);
+
+  String getAddForeignKeyStatement(String tableName, String constraintName,
+                                   List<String> keyColumns,
+                                   String referenceTableName,
+                                   List<String> referenceColumns);
+
+  String getAddColumnStatement(String tableName, DBAccessor.DBColumnInfo columnInfo);
+
+  String getRenameColumnStatement(String tableName, String oldColumnName,
+                                  String newColumnName);
+
+  String getDropTableStatement(String tableName);
+
+  String getDropConstraintStatement(String tableName, String constraintName);
+
+  String getDropSequenceStatement(String sequenceName);
+}

http://git-wip-us.apache.org/repos/asf/ambari/blob/fea7b622/ambari-server/src/main/java/org/apache/ambari/server/orm/helpers/dbms/DerbyHelper.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/orm/helpers/dbms/DerbyHelper.java b/ambari-server/src/main/java/org/apache/ambari/server/orm/helpers/dbms/DerbyHelper.java
new file mode 100644
index 0000000..00d4b86
--- /dev/null
+++ b/ambari-server/src/main/java/org/apache/ambari/server/orm/helpers/dbms/DerbyHelper.java
@@ -0,0 +1,52 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.ambari.server.orm.helpers.dbms;
+
+import org.apache.ambari.server.orm.DBAccessor;
+import org.eclipse.persistence.platform.database.DatabasePlatform;
+
+public class DerbyHelper extends GenericDbmsHelper {
+  public DerbyHelper(DatabasePlatform databasePlatform) {
+    super(databasePlatform);
+  }
+
+  @Override
+  public boolean supportsColumnTypeChange() {
+    return false; //type change is dramatically limited to varchar length increase only, almost useless
+  }
+
+  @Override
+  public String getRenameColumnStatement(String tableName, String oldName, DBAccessor.DBColumnInfo columnInfo) {
+    StringBuilder builder = new StringBuilder();
+
+    builder.append("RENAME COLUMN ").append(tableName).append(".").append(oldName);
+    builder.append(" TO ").append(columnInfo.getName());
+
+    return builder.toString();
+  }
+
+  @Override
+  public StringBuilder writeColumnModifyString(StringBuilder builder, DBAccessor.DBColumnInfo columnInfo) {
+    builder.append(" ALTER COLUMN ").append(columnInfo.getName())
+      .append(" SET DATA TYPE ");
+    writeColumnType(builder, columnInfo);
+
+    return builder;
+  }
+}

http://git-wip-us.apache.org/repos/asf/ambari/blob/fea7b622/ambari-server/src/main/java/org/apache/ambari/server/orm/helpers/dbms/GenericDbmsHelper.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/orm/helpers/dbms/GenericDbmsHelper.java b/ambari-server/src/main/java/org/apache/ambari/server/orm/helpers/dbms/GenericDbmsHelper.java
new file mode 100644
index 0000000..5f484a8
--- /dev/null
+++ b/ambari-server/src/main/java/org/apache/ambari/server/orm/helpers/dbms/GenericDbmsHelper.java
@@ -0,0 +1,273 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.ambari.server.orm.helpers.dbms;
+
+import org.apache.ambari.server.orm.DBAccessor;
+import org.eclipse.persistence.internal.databaseaccess.FieldTypeDefinition;
+import org.eclipse.persistence.internal.databaseaccess.Platform;
+import org.eclipse.persistence.internal.sessions.AbstractSession;
+import org.eclipse.persistence.platform.database.DatabasePlatform;
+import org.eclipse.persistence.tools.schemaframework.FieldDefinition;
+import org.eclipse.persistence.tools.schemaframework.ForeignKeyConstraint;
+import org.eclipse.persistence.tools.schemaframework.TableDefinition;
+
+import java.io.IOException;
+import java.io.StringWriter;
+import java.io.Writer;
+import java.util.List;
+
+public class GenericDbmsHelper implements DbmsHelper {
+  protected final DatabasePlatform databasePlatform;
+
+  public GenericDbmsHelper(DatabasePlatform databasePlatform) {
+    this.databasePlatform = databasePlatform;
+  }
+
+  @Override
+  public boolean supportsColumnTypeChange() {
+    return false;
+  }
+
+  @Override
+  public String getRenameColumnStatement(String tableName, String oldName, DBAccessor.DBColumnInfo columnInfo) {
+    StringBuilder stringBuilder = new StringBuilder();
+
+    writeAlterTableClause(stringBuilder, tableName);
+    writeColumnRenameString(stringBuilder, oldName, columnInfo);
+
+    return stringBuilder.toString();
+  }
+
+  @Override
+  public String getAlterColumnStatement(String tableName, DBAccessor.DBColumnInfo columnInfo) {
+    StringBuilder stringBuilder = new StringBuilder();
+    writeAlterTableClause(stringBuilder, tableName);
+    writeColumnModifyString(stringBuilder, columnInfo);
+
+
+    return stringBuilder.toString();
+  }
+
+  public StringBuilder writeAlterTableClause(StringBuilder builder, String tableName) {
+    builder.append("ALTER TABLE ").append(tableName).append(" ");
+    return builder;
+  }
+
+  public StringBuilder writeColumnModifyString(StringBuilder builder, DBAccessor.DBColumnInfo columnInfo) {
+    throw new UnsupportedOperationException("Column type modification not supported for generic DB");
+  }
+
+  public StringBuilder writeColumnRenameString(StringBuilder builder, String oldName, DBAccessor.DBColumnInfo newColumnInfo) {
+    throw new UnsupportedOperationException("Column rename not supported for generic DB");
+  }
+
+  public StringBuilder writeColumnType(StringBuilder builder, DBAccessor.DBColumnInfo columnInfo) {
+    FieldTypeDefinition fieldType;
+
+    fieldType = databasePlatform.getFieldTypeDefinition(columnInfo.getType());
+
+    if (fieldType == null) {
+      throw new IllegalArgumentException("Unable to convert data type");
+    }
+
+    FieldDefinition definition = convertToFieldDefinition(columnInfo);
+
+    StringWriter writer = new StringWriter();
+
+    try {
+      databasePlatform.printFieldTypeSize(writer, definition, fieldType, false); //Ambari doesn't use identity fields
+    } catch (IOException ignored) {
+      // no writing to file
+    }
+
+    builder.append(writer.toString());
+
+    return builder;
+  }
+
+  /**
+   * get create table statement
+   * @param tableName
+   * @param columns
+   * @param primaryKeyColumns
+   * @return
+   */
+  @Override
+  public String getCreateTableStatement(String tableName,
+                                        List<DBAccessor.DBColumnInfo> columns,
+                                        List<String> primaryKeyColumns) {
+    Writer stringWriter = new StringWriter();
+    writeCreateTableStatement(stringWriter, tableName, columns, primaryKeyColumns);
+    return stringWriter.toString();
+  }
+
+
+  /**
+   * Write create table statement to writer
+   * TODO default Value of column not supported
+   */
+  public Writer writeCreateTableStatement(Writer writer, String tableName,
+                                          List<DBAccessor.DBColumnInfo> columns,
+                                          List<String> primaryKeyColumns) {
+    //TODO validateNames(String tableName, List<DBAccessor.DBColumnInfo> columns)
+    //TODO validatePKNames(List<DBAccessor.DBColumnInfo> columns, String... primaryKeyColumns)
+
+    TableDefinition tableDefinition = new TableDefinition();
+    tableDefinition.setName(tableName);
+    for (DBAccessor.DBColumnInfo columnInfo : columns) {
+      //TODO case-sensitive for now
+      int length = columnInfo.getLength() != null ? columnInfo.getLength() : 0;
+
+      if (primaryKeyColumns.contains(columnInfo.getName())) {
+        tableDefinition.addIdentityField(columnInfo.getName(), columnInfo.getType(), length);
+      } else {
+        FieldDefinition fieldDefinition = convertToFieldDefinition(columnInfo);
+        tableDefinition.addField(fieldDefinition);
+      }
+    }
+
+    //TODO possibly move code to avoid unnecessary dependencies and allow extension
+    tableDefinition.buildCreationWriter(createStubAbstractSessionFromPlatform(databasePlatform), writer);
+
+    return writer;
+  }
+
+  public FieldDefinition convertToFieldDefinition(DBAccessor.DBColumnInfo columnInfo) {
+    int length = columnInfo.getLength() != null ? columnInfo.getLength() : 0;
+    FieldDefinition fieldDefinition = new FieldDefinition(columnInfo.getName(), columnInfo.getType(), length);
+    fieldDefinition.setShouldAllowNull(columnInfo.isNullable());
+    return fieldDefinition;
+  }
+
+  /**
+   * get create index statement
+   * @param indexName
+   * @param tableName
+   * @param columnNames
+   * @return
+   */
+  @Override
+  public String getCreateIndexStatement(String indexName, String tableName,
+                                        String... columnNames) {
+    //TODO validateColumnNames()
+    String createIndex = databasePlatform.buildCreateIndex(tableName, indexName, columnNames);
+    return createIndex;
+  }
+
+
+  @Override
+  public String getAddForeignKeyStatement(String tableName, String constraintName,
+                                          List<String> keyColumns,
+                                          String referenceTableName,
+                                          List<String> referenceColumns) {
+    ForeignKeyConstraint foreignKeyConstraint = new ForeignKeyConstraint();
+    foreignKeyConstraint.setName(constraintName);
+    foreignKeyConstraint.setTargetTable(referenceTableName);
+    foreignKeyConstraint.setSourceFields(keyColumns);
+    foreignKeyConstraint.setTargetFields(referenceColumns);
+
+    TableDefinition tableDefinition = new TableDefinition();
+    tableDefinition.setName(tableName);
+
+    Writer writer = new StringWriter();
+    tableDefinition.buildConstraintCreationWriter(createStubAbstractSessionFromPlatform(databasePlatform),
+        foreignKeyConstraint, writer);
+
+    return writer.toString();
+
+  }
+
+  @Override
+  public String getAddColumnStatement(String tableName, DBAccessor.DBColumnInfo columnInfo) {
+    Writer writer = new StringWriter();
+
+    TableDefinition tableDefinition = new TableDefinition();
+    tableDefinition.setName(tableName);
+    tableDefinition.buildAddFieldWriter(createStubAbstractSessionFromPlatform(databasePlatform),
+        convertToFieldDefinition(columnInfo), writer);
+
+    return writer.toString();
+  }
+
+
+  @Override
+  public String getRenameColumnStatement(String tableName, String oldColumnName,
+                                         String newColumnName) {
+
+    throw new UnsupportedOperationException("Rename operation not supported.");
+  }
+
+  @Override
+  public String getDropTableStatement(String tableName) {
+    Writer writer = new StringWriter();
+
+    TableDefinition tableDefinition = new TableDefinition();
+    tableDefinition.setName(tableName);
+    tableDefinition.buildDeletionWriter
+        (createStubAbstractSessionFromPlatform(databasePlatform), writer);
+
+    return writer.toString();
+  }
+
+  @Override
+  public String getDropConstraintStatement(String tableName, String constraintName) {
+    Writer writer = new StringWriter();
+
+    ForeignKeyConstraint foreignKeyConstraint = new ForeignKeyConstraint();
+    foreignKeyConstraint.setName(constraintName);
+    foreignKeyConstraint.setTargetTable(tableName);
+
+    TableDefinition tableDefinition = new TableDefinition();
+    tableDefinition.setName(tableName);
+    tableDefinition.buildConstraintDeletionWriter(
+        createStubAbstractSessionFromPlatform(databasePlatform),
+        foreignKeyConstraint, writer);
+
+    return writer.toString();
+  }
+
+  @Override
+  public String getDropSequenceStatement(String sequenceName) {
+    StringWriter writer = new StringWriter();
+    String defaultStmt = String.format("DROP sequence %s", sequenceName);
+
+    try {
+      Writer w = databasePlatform.buildSequenceObjectDeletionWriter(writer, sequenceName);
+      return w != null ? w.toString() : defaultStmt;
+    } catch (IOException e) {
+      e.printStackTrace();
+    }
+    return defaultStmt;
+  }
+
+  public AbstractSession createStubAbstractSessionFromPlatform
+      (final DatabasePlatform databasePlatform) {
+    return new AbstractSession() {
+      @Override
+      public Platform getDatasourcePlatform() {
+        return databasePlatform;
+      }
+
+      @Override
+      public DatabasePlatform getPlatform() {
+        return databasePlatform;
+      }
+    };
+  }
+}

http://git-wip-us.apache.org/repos/asf/ambari/blob/fea7b622/ambari-server/src/main/java/org/apache/ambari/server/orm/helpers/dbms/MySqlHelper.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/orm/helpers/dbms/MySqlHelper.java b/ambari-server/src/main/java/org/apache/ambari/server/orm/helpers/dbms/MySqlHelper.java
new file mode 100644
index 0000000..817ca9b
--- /dev/null
+++ b/ambari-server/src/main/java/org/apache/ambari/server/orm/helpers/dbms/MySqlHelper.java
@@ -0,0 +1,49 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.ambari.server.orm.helpers.dbms;
+
+import org.apache.ambari.server.orm.DBAccessor;
+import org.eclipse.persistence.platform.database.DatabasePlatform;
+
+public class MySqlHelper extends GenericDbmsHelper {
+  public MySqlHelper(DatabasePlatform databasePlatform) {
+    super(databasePlatform);
+  }
+
+  @Override
+  public boolean supportsColumnTypeChange() {
+    return true;
+  }
+
+  @Override
+  public StringBuilder writeColumnRenameString(StringBuilder builder, String oldName, DBAccessor.DBColumnInfo newColumnInfo) {
+
+    builder.append(" CHANGE ").append(oldName).append(" ").append(newColumnInfo.getName()).append(" ");
+    writeColumnType(builder, newColumnInfo);
+
+    return builder;
+  }
+
+  @Override
+  public StringBuilder writeColumnModifyString(StringBuilder builder, DBAccessor.DBColumnInfo columnInfo) {
+    builder.append(" MODIFY ").append(columnInfo.getName()).append(" ");
+    writeColumnType(builder, columnInfo);
+    return builder;
+  }
+}

http://git-wip-us.apache.org/repos/asf/ambari/blob/fea7b622/ambari-server/src/main/java/org/apache/ambari/server/orm/helpers/dbms/OracleHelper.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/orm/helpers/dbms/OracleHelper.java b/ambari-server/src/main/java/org/apache/ambari/server/orm/helpers/dbms/OracleHelper.java
new file mode 100644
index 0000000..aebfb62
--- /dev/null
+++ b/ambari-server/src/main/java/org/apache/ambari/server/orm/helpers/dbms/OracleHelper.java
@@ -0,0 +1,46 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.ambari.server.orm.helpers.dbms;
+
+import org.apache.ambari.server.orm.DBAccessor;
+import org.eclipse.persistence.platform.database.DatabasePlatform;
+
+public class OracleHelper extends GenericDbmsHelper {
+  public OracleHelper(DatabasePlatform databasePlatform) {
+    super(databasePlatform);
+  }
+
+  @Override
+  public boolean supportsColumnTypeChange() {
+    return true;
+  }
+
+  @Override
+  public StringBuilder writeColumnRenameString(StringBuilder builder, String oldName, DBAccessor.DBColumnInfo newColumnInfo) {
+    builder.append(" RENAME COLUMN ").append(oldName).append(" TO ").append(newColumnInfo.getName());
+    return builder;
+  }
+
+  @Override
+  public StringBuilder writeColumnModifyString(StringBuilder builder, DBAccessor.DBColumnInfo columnInfo) {
+    builder.append(" MODIFY ").append(columnInfo.getName()).append(" ");
+    writeColumnType(builder, columnInfo);
+    return builder;
+  }
+}

http://git-wip-us.apache.org/repos/asf/ambari/blob/fea7b622/ambari-server/src/main/java/org/apache/ambari/server/orm/helpers/dbms/PostgresHelper.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/orm/helpers/dbms/PostgresHelper.java b/ambari-server/src/main/java/org/apache/ambari/server/orm/helpers/dbms/PostgresHelper.java
new file mode 100644
index 0000000..38e837e
--- /dev/null
+++ b/ambari-server/src/main/java/org/apache/ambari/server/orm/helpers/dbms/PostgresHelper.java
@@ -0,0 +1,46 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.ambari.server.orm.helpers.dbms;
+
+import org.apache.ambari.server.orm.DBAccessor;
+import org.eclipse.persistence.platform.database.DatabasePlatform;
+
+public class PostgresHelper extends GenericDbmsHelper {
+  public PostgresHelper(DatabasePlatform databasePlatform) {
+    super(databasePlatform);
+  }
+
+  @Override
+  public boolean supportsColumnTypeChange() {
+    return true;
+  }
+
+  @Override
+  public StringBuilder writeColumnRenameString(StringBuilder builder, String oldName, DBAccessor.DBColumnInfo newColumnInfo) {
+    builder.append(" RENAME COLUMN ").append(oldName).append(" TO ").append(newColumnInfo.getName());
+    return builder;
+  }
+
+  @Override
+  public StringBuilder writeColumnModifyString(StringBuilder builder, DBAccessor.DBColumnInfo columnInfo) {
+    builder.append(" ALTER COLUMN ").append(columnInfo.getName()).append(" TYPE ");
+    writeColumnType(builder, columnInfo);
+    return builder;
+  }
+}

http://git-wip-us.apache.org/repos/asf/ambari/blob/fea7b622/ambari-server/src/main/java/org/apache/ambari/server/upgrade/AbstractUpgradeCatalog.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/upgrade/AbstractUpgradeCatalog.java b/ambari-server/src/main/java/org/apache/ambari/server/upgrade/AbstractUpgradeCatalog.java
new file mode 100644
index 0000000..dfdfa85
--- /dev/null
+++ b/ambari-server/src/main/java/org/apache/ambari/server/upgrade/AbstractUpgradeCatalog.java
@@ -0,0 +1,192 @@
+/*
+ * 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.upgrade;
+
+import com.google.inject.Inject;
+import com.google.inject.Injector;
+import com.google.inject.Provider;
+import org.apache.ambari.server.AmbariException;
+import org.apache.ambari.server.configuration.Configuration;
+import org.apache.ambari.server.orm.DBAccessor;
+import org.apache.ambari.server.utils.VersionUtils;
+import org.apache.commons.io.FileUtils;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import javax.persistence.EntityManager;
+import java.io.File;
+import java.io.IOException;
+import java.sql.SQLException;
+import java.util.Comparator;
+import java.util.HashMap;
+import java.util.Map;
+
+public abstract class AbstractUpgradeCatalog implements UpgradeCatalog {
+  @Inject
+  protected DBAccessor dbAccessor;
+  @Inject
+  protected Configuration configuration;
+  @Inject
+  protected StackUpgradeUtil stackUpgradeUtil;
+
+  private Injector injector;
+  private static final Logger LOG = LoggerFactory.getLogger
+    (AbstractUpgradeCatalog.class);
+  private static final Map<String, UpgradeCatalog> upgradeCatalogMap =
+    new HashMap<String, UpgradeCatalog>();
+
+  @Inject
+  public AbstractUpgradeCatalog(Injector injector) {
+    this.injector = injector;
+    registerCatalog(this);
+  }
+
+  /**
+   * Every subclass needs to register itself
+   */
+  protected void registerCatalog(UpgradeCatalog upgradeCatalog) {
+    upgradeCatalogMap.put(upgradeCatalog.getTargetVersion(), upgradeCatalog);
+  }
+
+  @Override
+  public String getSourceVersion() {
+    return null;
+  }
+
+  protected static UpgradeCatalog getUpgradeCatalog(String version) {
+    return upgradeCatalogMap.get(version);
+  }
+
+  protected static class VersionComparator implements Comparator<UpgradeCatalog> {
+
+    @Override
+    public int compare(UpgradeCatalog upgradeCatalog1,
+                       UpgradeCatalog upgradeCatalog2) {
+      return VersionUtils.compareVersions(upgradeCatalog1.getTargetVersion(),
+        upgradeCatalog2.getTargetVersion(), 3);
+    }
+  }
+
+  /**
+   * Read server version file
+   * @return
+   */
+  protected String getAmbariServerVersion() {
+    String versionFilePath = configuration.getServerVersionFilePath();
+    try {
+      return FileUtils.readFileToString(new File(versionFilePath));
+    } catch (IOException e) {
+      e.printStackTrace();
+    }
+    return null;
+  }
+
+  /**
+   * Update metainfo to new version.
+   */
+  protected int updateMetaInfoVersion(String version) {
+    String ambariServerVersion = getAmbariServerVersion();
+    int rows = 0;
+
+    if (ambariServerVersion != null) {
+      try {
+        dbAccessor.executeQuery("INSERT INTO metainfo ('metainfo_key', " +
+          "'metainfo_value') VALUES ('version', '${ambariVersion}')");
+
+        rows = dbAccessor.updateTable("metainfo", "metainfo_value",
+          ambariServerVersion, String.format("WHERE metainfo_key = '%s'", version));
+      } catch (SQLException e) {
+        LOG.error("Failed updating metainfo table.", e);
+      }
+    }
+
+    return rows;
+  }
+
+  protected String getDbType() {
+    String dbUrl = configuration.getDatabaseUrl();
+    String dbType;
+
+    if (dbUrl.contains(Configuration.POSTGRES_DB_NAME)) {
+      dbType = Configuration.POSTGRES_DB_NAME;
+    } else if (dbUrl.contains(Configuration.ORACLE_DB_NAME)) {
+      dbType = Configuration.ORACLE_DB_NAME;
+    } else if (dbUrl.contains(Configuration.MYSQL_DB_NAME)) {
+      dbType = Configuration.MYSQL_DB_NAME;
+    } else {
+      throw new RuntimeException("Unable to determine database type.");
+    }
+
+    return dbType;
+  }
+
+  protected Provider<EntityManager> getEntityManagerProvider() {
+    return injector.getProvider(EntityManager.class);
+  }
+
+  protected void executeInTransaction(Runnable func) {
+    EntityManager entityManager = getEntityManagerProvider().get();
+    if (entityManager.getTransaction().isActive()) { //already started, reuse
+      func.run();
+    } else {
+      entityManager.getTransaction().begin();
+      try {
+        func.run();
+        entityManager.getTransaction().commit();
+      } catch (Exception e) {
+        entityManager.getTransaction().rollback();
+        throw new RuntimeException(e);
+      }
+
+    }
+  }
+
+  protected void changePostgresSearchPath() throws SQLException {
+    String dbUser = configuration.getDatabaseUser();
+    String dbName = configuration.getServerDBName();
+
+    dbAccessor.executeQuery(String.format("ALTER SCHEMA %s OWNER TO %s;", dbName, dbUser));
+
+    dbAccessor.executeQuery(String.format("ALTER ROLE %s SET search_path to '%s';", dbUser, dbName));
+  }
+
+  protected void grantAllPostgresPrivileges() throws SQLException {
+    String query = "GRANT ALL PRIVILEGES ON DATABASE ambari TO " +
+      configuration.getDatabaseUser();
+
+    dbAccessor.executeQuery(query);
+  }
+
+  @Override
+  public void upgradeSchema() throws AmbariException, SQLException {
+    if (getDbType().equals(Configuration.POSTGRES_DB_NAME)) {
+      changePostgresSearchPath();
+    }
+
+    this.executeDDLUpdates();
+  }
+
+  protected abstract void executeDDLUpdates() throws AmbariException, SQLException;
+
+  @Override
+  public String toString() {
+    return "{ " + this.getClass().getCanonicalName() +": " +
+      "sourceVersion = " + getSourceVersion() + ", " +
+      "targetVersion = " + getTargetVersion() + " }";
+  }
+}

http://git-wip-us.apache.org/repos/asf/ambari/blob/fea7b622/ambari-server/src/main/java/org/apache/ambari/server/upgrade/SchemaUpgradeHelper.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/upgrade/SchemaUpgradeHelper.java b/ambari-server/src/main/java/org/apache/ambari/server/upgrade/SchemaUpgradeHelper.java
new file mode 100644
index 0000000..5875cdb
--- /dev/null
+++ b/ambari-server/src/main/java/org/apache/ambari/server/upgrade/SchemaUpgradeHelper.java
@@ -0,0 +1,211 @@
+/*
+ * 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.upgrade;
+
+import com.google.inject.Guice;
+import com.google.inject.Inject;
+import com.google.inject.Injector;
+import com.google.inject.multibindings.Multibinder;
+import com.google.inject.persist.PersistService;
+import org.apache.ambari.server.AmbariException;
+import org.apache.ambari.server.configuration.Configuration;
+import org.apache.ambari.server.controller.ControllerModule;
+import org.apache.ambari.server.orm.dao.MetainfoDAO;
+import org.apache.ambari.server.orm.entities.MetainfoEntity;
+import org.apache.ambari.server.utils.VersionUtils;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import java.sql.SQLException;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.InputMismatchException;
+import java.util.List;
+import java.util.Set;
+
+public class SchemaUpgradeHelper {
+  private static final Logger LOG = LoggerFactory.getLogger
+    (SchemaUpgradeHelper.class);
+
+  private Set<UpgradeCatalog> allUpgradeCatalogs;
+  private MetainfoDAO metainfoDAO;
+  private PersistService persistService;
+
+  @Inject
+  public SchemaUpgradeHelper(Set<UpgradeCatalog> allUpgradeCatalogs, MetainfoDAO metainfoDAO,
+                             PersistService persistService) {
+    this.allUpgradeCatalogs = allUpgradeCatalogs;
+    this.metainfoDAO = metainfoDAO;
+    this.persistService = persistService;
+  }
+
+  private void startPersistenceService() {
+    persistService.start();
+  }
+
+  private void stopPersistenceService() {
+    persistService.stop();
+  }
+
+  public Set<UpgradeCatalog> getAllUpgradeCatalogs() {
+    return allUpgradeCatalogs;
+  }
+
+  private String readSourceVersion() {
+    String sourceVersion = null;
+
+    MetainfoEntity metainfoEntity = metainfoDAO.findByKey
+      (Configuration.SERVER_VERSION_KEY);
+
+    if (metainfoEntity != null) {
+      String version = metainfoEntity.getMetainfoValue();
+      if (version != null) {
+        sourceVersion = VersionUtils.getVersionSubstring(version);
+      }
+    }
+
+    return sourceVersion;
+  }
+
+  /**
+   * Return a set Upgrade catalogs to be applied to upgrade from
+   * @sourceVersion to @targetVersion
+   *
+   * @param sourceVersion
+   * @param targetVersion
+   * @return
+   * @throws org.apache.ambari.server.AmbariException
+   */
+  protected List<UpgradeCatalog> getUpgradePath(String sourceVersion,
+                                                       String targetVersion) throws AmbariException {
+
+    List<UpgradeCatalog> upgradeCatalogs = new ArrayList<UpgradeCatalog>();
+    List<UpgradeCatalog> candidateCatalogs = new ArrayList<UpgradeCatalog>(allUpgradeCatalogs);
+
+    Collections.sort(candidateCatalogs, new AbstractUpgradeCatalog.VersionComparator());
+
+    for (UpgradeCatalog upgradeCatalog : candidateCatalogs) {
+      if (sourceVersion == null || VersionUtils.compareVersions(sourceVersion,
+        upgradeCatalog.getTargetVersion(), 3) < 0) {
+        // catalog version is newer than source
+        if (VersionUtils.compareVersions(upgradeCatalog.getTargetVersion(),
+          targetVersion, 3) <= 0) {
+          // catalog version is older or equal to target
+          upgradeCatalogs.add(upgradeCatalog);
+        }
+      }
+    }
+
+    LOG.info("Upgrade path: " + upgradeCatalogs);
+
+    return upgradeCatalogs;
+  }
+
+  /**
+   * Extension of main controller module
+   */
+  public static class UpgradeHelperModule extends ControllerModule {
+    public UpgradeHelperModule() throws Exception {
+
+    }
+
+    @Override
+    protected void configure() {
+      super.configure();
+      // Add binding to each newly created catalog
+      Multibinder<UpgradeCatalog> catalogBinder =
+        Multibinder.newSetBinder(binder(), UpgradeCatalog.class);
+      catalogBinder.addBinding().to(UpgradeCatalog150.class);
+    }
+  }
+
+  private void executeUpgrade(List<UpgradeCatalog> upgradeCatalogs) throws AmbariException {
+    LOG.info("Executing DDL upgrade...");
+
+    if (upgradeCatalogs != null && !upgradeCatalogs.isEmpty()) {
+      for (UpgradeCatalog upgradeCatalog : upgradeCatalogs) {
+        try {
+          upgradeCatalog.upgradeSchema();
+        } catch (AmbariException e) {
+          LOG.error("Upgrade failed. ", e);
+          throw e;
+        } catch (SQLException e) {
+          LOG.error("Upgrade failed. ", e);
+          throw new AmbariException(e.getMessage());
+        }
+      }
+    }
+  }
+
+  private void executeDMLUpdates(List<UpgradeCatalog> upgradeCatalogs) throws AmbariException {
+    LOG.info("Execution DML changes.");
+
+    if (upgradeCatalogs != null && !upgradeCatalogs.isEmpty()) {
+      for (UpgradeCatalog upgradeCatalog : upgradeCatalogs) {
+        try {
+          upgradeCatalog.executeDMLUpdates();
+        } catch (AmbariException e) {
+          LOG.error("Upgrade failed. ", e);
+          throw e;
+        } catch (SQLException e) {
+          LOG.error("Upgrade failed. ", e);
+          throw new AmbariException(e.getMessage());
+        }
+      }
+    }
+  }
+
+  /**
+   * Upgrade Ambari DB schema to the target version passed in as the only
+   * argument.
+   * @param args args[0] = target version to upgrade to.
+   */
+  public static void main(String[] args) throws Exception {
+    if (args.length == 0) {
+      throw new InputMismatchException("Need to provide target version.");
+    }
+
+    String targetVersion = args[0];
+    LOG.info("Upgrading schema to target version = " + targetVersion);
+
+    UpgradeCatalog targetUpgradeCatalog = AbstractUpgradeCatalog
+      .getUpgradeCatalog(targetVersion);
+
+    LOG.debug("Target upgrade catalog. " + targetUpgradeCatalog);
+
+    Injector injector = Guice.createInjector(new UpgradeHelperModule());
+
+    SchemaUpgradeHelper schemaUpgradeHelper = injector.getInstance(SchemaUpgradeHelper.class);
+
+    // Read source version from DB
+    String sourceVersion = schemaUpgradeHelper.readSourceVersion();
+    LOG.info("Upgrading schema from source version = " + sourceVersion);
+
+    List<UpgradeCatalog> upgradeCatalogs =
+      schemaUpgradeHelper.getUpgradePath(sourceVersion, targetVersion);
+
+    schemaUpgradeHelper.executeUpgrade(upgradeCatalogs);
+
+    schemaUpgradeHelper.startPersistenceService();
+
+    schemaUpgradeHelper.executeDMLUpdates(upgradeCatalogs);
+
+    LOG.info("Upgrade successful.");
+
+    schemaUpgradeHelper.stopPersistenceService();
+  }
+}