You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@sentry.apache.org by co...@apache.org on 2016/06/24 06:00:45 UTC

[16/44] sentry git commit: SENTRY-1287: Create sentry-service-server module(Colin Ma, reviewed by Dapeng Sun)

http://git-wip-us.apache.org/repos/asf/sentry/blob/e72e6eac/sentry-service/sentry-service-server/src/main/java/org/apache/sentry/provider/db/tools/SentrySchemaTool.java
----------------------------------------------------------------------
diff --git a/sentry-service/sentry-service-server/src/main/java/org/apache/sentry/provider/db/tools/SentrySchemaTool.java b/sentry-service/sentry-service-server/src/main/java/org/apache/sentry/provider/db/tools/SentrySchemaTool.java
new file mode 100644
index 0000000..d75e24b
--- /dev/null
+++ b/sentry-service/sentry-service-server/src/main/java/org/apache/sentry/provider/db/tools/SentrySchemaTool.java
@@ -0,0 +1,595 @@
+/**
+ * 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.sentry.provider.db.tools;
+
+import java.io.BufferedReader;
+import java.io.BufferedWriter;
+import java.io.File;
+import java.io.FileReader;
+import java.io.FileWriter;
+import java.io.IOException;
+import java.io.PrintStream;
+import java.net.MalformedURLException;
+import java.sql.Connection;
+import java.sql.DriverManager;
+import java.sql.ResultSet;
+import java.sql.SQLException;
+import java.sql.Statement;
+import java.util.ArrayList;
+import java.util.IllegalFormatException;
+import java.util.List;
+
+import org.apache.commons.cli.CommandLine;
+import org.apache.commons.cli.CommandLineParser;
+import org.apache.commons.cli.GnuParser;
+import org.apache.commons.cli.HelpFormatter;
+import org.apache.commons.cli.Option;
+import org.apache.commons.cli.OptionBuilder;
+import org.apache.commons.cli.OptionGroup;
+import org.apache.commons.cli.Options;
+import org.apache.commons.cli.ParseException;
+import org.apache.commons.io.output.NullOutputStream;
+import org.apache.hadoop.conf.Configuration;
+import org.apache.hive.beeline.BeeLine;
+import org.apache.sentry.Command;
+import org.apache.sentry.core.common.exception.SentryUserException;
+import org.apache.sentry.core.common.exception.SentrySiteConfigurationException;
+import org.apache.sentry.provider.db.service.persistent.SentryStoreSchemaInfo;
+import org.apache.sentry.provider.db.tools.SentrySchemaHelper.NestedScriptParser;
+import org.apache.sentry.service.thrift.SentryService;
+import org.apache.sentry.service.thrift.ServiceConstants;
+
+public class SentrySchemaTool {
+  private static final String SENTRY_SCRIP_DIR = File.separatorChar + "scripts"
+      + File.separatorChar + "sentrystore" + File.separatorChar + "upgrade";
+  private String userName = null;
+  private String passWord = null;
+  private String connectionURL = null;
+  private String driver = null;
+  private boolean dryRun = false;
+  private String dbOpts = null;
+  private boolean verbose = false;
+  private final Configuration sentryConf;
+  private final String dbType;
+  private final SentryStoreSchemaInfo sentryStoreSchemaInfo;
+
+  public SentrySchemaTool(Configuration sentryConf, String dbType)
+      throws SentryUserException, IOException {
+    this(System.getenv("SENTRY_HOME") + SENTRY_SCRIP_DIR, sentryConf, dbType);
+  }
+
+  public SentrySchemaTool(String sentryScripPath, Configuration sentryConf,
+      String dbType) throws SentryUserException, IOException {
+    if (sentryScripPath == null || sentryScripPath.isEmpty()) {
+      throw new SentryUserException("No Sentry script dir provided");
+    }
+    this.sentryConf = sentryConf;
+    this.dbType = dbType;
+    this.sentryStoreSchemaInfo = new SentryStoreSchemaInfo(sentryScripPath,
+        dbType);
+    userName = sentryConf.get(ServiceConstants.ServerConfig.SENTRY_STORE_JDBC_USER,
+        ServiceConstants.ServerConfig.SENTRY_STORE_JDBC_USER_DEFAULT);
+    //Password will be read from Credential provider specified using property
+    // CREDENTIAL_PROVIDER_PATH("hadoop.security.credential.provider.path" in sentry-site.xml
+    // it falls back to reading directly from sentry-site.xml
+    char[] passTmp = sentryConf.getPassword(ServiceConstants.ServerConfig.SENTRY_STORE_JDBC_PASS);
+    if(passTmp != null) {
+      passWord = new String(passTmp);
+    } else {
+      throw new SentrySiteConfigurationException("Error reading " + ServiceConstants.ServerConfig.SENTRY_STORE_JDBC_PASS);
+    }
+
+    try {
+      connectionURL = getValidConfVar(ServiceConstants.ServerConfig.SENTRY_STORE_JDBC_URL);
+      if(dbType.equalsIgnoreCase(SentrySchemaHelper.DB_DERBY)) {
+        driver = sentryConf.get(ServiceConstants.ServerConfig.SENTRY_STORE_JDBC_DRIVER,
+            ServiceConstants.ServerConfig.SENTRY_STORE_JDBC_DRIVER_DEFAULT);
+      } else {
+        driver = getValidConfVar(ServiceConstants.ServerConfig.SENTRY_STORE_JDBC_DRIVER);
+      }
+      // load required JDBC driver
+      Class.forName(driver);
+    } catch (IOException e) {
+      throw new SentryUserException("Missing property: " + e.getMessage());
+    } catch (ClassNotFoundException e) {
+      throw new SentryUserException("Failed to load driver", e);
+    }
+  }
+
+  public Configuration getConfiguration() {
+    return sentryConf;
+  }
+
+  public void setUserName(String userName) {
+    this.userName = userName;
+  }
+
+  public void setPassWord(String passWord) {
+    this.passWord = passWord;
+  }
+
+  public void setDryRun(boolean dryRun) {
+    this.dryRun = dryRun;
+  }
+
+  public void setVerbose(boolean verbose) {
+    this.verbose = verbose;
+  }
+
+  public String getDbOpts() {
+    return dbOpts;
+  }
+
+  public void setDbOpts(String dbOpts) {
+    this.dbOpts = dbOpts;
+  }
+
+  private static void printAndExit(Options cmdLineOptions) {
+    HelpFormatter formatter = new HelpFormatter();
+    formatter.printHelp("schemaTool", cmdLineOptions);
+    System.exit(1);
+  }
+
+  /***
+   * Print Hive version and schema version
+   * @throws SentryUserException
+   */
+  public void showInfo() throws SentryUserException {
+    Connection sentryStoreConn = getConnectionToMetastore(true);
+    System.out.println("Sentry distribution version:\t "
+        + SentryStoreSchemaInfo.getSentryVersion());
+    System.out.println("SentryStore schema version:\t "
+        + getMetaStoreSchemaVersion(sentryStoreConn));
+  }
+
+  // read schema version from sentry store
+  private String getMetaStoreSchemaVersion(Connection sentryStoreConn)
+      throws SentryUserException {
+    String versionQuery;
+    if (SentrySchemaHelper.getDbCommandParser(dbType).needsQuotedIdentifier()) {
+      versionQuery = "select t.\"SCHEMA_VERSION\" from \"SENTRY_VERSION\" t";
+    } else {
+      versionQuery = "select t.SCHEMA_VERSION from SENTRY_VERSION t";
+    }
+    try (Statement stmt = sentryStoreConn.createStatement();
+      ResultSet res = stmt.executeQuery(versionQuery)) {
+      if (!res.next()) {
+        throw new SentryUserException("Didn't find version data in sentry store");
+      }
+      String currentSchemaVersion = res.getString(1);
+      sentryStoreConn.close();
+      return currentSchemaVersion;
+    } catch (SQLException e) {
+      throw new SentryUserException("Failed to get schema version.", e);
+    }
+  }
+
+  // test the connection sentry store using the config property
+  private void testConnectionToMetastore() throws SentryUserException {
+    try (Connection conn = getConnectionToMetastore(true)) {
+      conn.close();
+    } catch (SQLException e) {
+      throw new SentryUserException("Failed to close sentry store connection", e);
+    }
+  }
+
+  /***
+   * get JDBC connection to sentry store db
+   *
+   * @param printInfo print connection parameters
+   * @return
+   * @throws SentryUserException
+   */
+  private Connection getConnectionToMetastore(boolean printInfo)
+      throws SentryUserException {
+    if (printInfo) {
+      System.out.println("Sentry store connection URL:\t " + connectionURL);
+      System.out.println("Sentry store Connection Driver :\t " + driver);
+      System.out.println("Sentry store connection User:\t " + userName);
+    }
+    if (userName == null || userName.isEmpty()) {
+      throw new SentryUserException("UserName empty ");
+    }
+    try {
+      // Connect using the JDBC URL and user/pass from conf
+      return DriverManager.getConnection(connectionURL, userName, passWord);
+    } catch (SQLException e) {
+      throw new SentryUserException("Failed to make connection to Sentry store.", e);
+    }
+  }
+
+  /**
+   * check if the current schema version in sentry store matches the Hive version
+   * @throws SentryUserException
+   */
+  public void verifySchemaVersion() throws SentryUserException {
+    // don't check version if its a dry run
+    if (dryRun) {
+      return;
+    }
+    String newSchemaVersion =
+        getMetaStoreSchemaVersion(getConnectionToMetastore(false));
+    // verify that the new version is added to schema
+    if (!sentryStoreSchemaInfo.getSentrySchemaVersion().equalsIgnoreCase(
+        newSchemaVersion)) {
+      throw new SentryUserException("Found unexpected schema version "
+          + newSchemaVersion);
+    }
+  }
+
+  /**
+   * Perform sentry store schema upgrade. extract the current schema version from sentry store
+   * @throws SentryUserException
+   */
+  public void doUpgrade() throws SentryUserException {
+    String fromVersion = getMetaStoreSchemaVersion(getConnectionToMetastore(false));
+    if (fromVersion == null || fromVersion.isEmpty()) {
+      throw new SentryUserException(
+          "Schema version not stored in the sentry store. "
+              +
+          "Metastore schema is too old or corrupt. Try specifying the version manually");
+    }
+    doUpgrade(fromVersion);
+  }
+
+  /**
+   * Perform sentry store schema upgrade
+   *
+   * @param fromSchemaVer
+   *          Existing version of the sentry store. If null, then read from the sentry store
+   * @throws SentryUserException
+   */
+  public void doUpgrade(String fromSchemaVer) throws SentryUserException {
+    if (sentryStoreSchemaInfo.getSentrySchemaVersion().equals(fromSchemaVer)) {
+      System.out.println("No schema upgrade required from version " + fromSchemaVer);
+      return;
+    }
+    // Find the list of scripts to execute for this upgrade
+    List<String> upgradeScripts =
+        sentryStoreSchemaInfo.getUpgradeScripts(fromSchemaVer);
+    testConnectionToMetastore();
+    System.out.println("Starting upgrade sentry store schema from version " +
+ fromSchemaVer + " to "
+        + sentryStoreSchemaInfo.getSentrySchemaVersion());
+    String scriptDir = sentryStoreSchemaInfo.getSentryStoreScriptDir();
+    try {
+      for (String scriptFile : upgradeScripts) {
+        System.out.println("Upgrade script " + scriptFile);
+        if (!dryRun) {
+          runBeeLine(scriptDir, scriptFile);
+          System.out.println("Completed " + scriptFile);
+        }
+      }
+    } catch (IOException eIO) {
+      throw new SentryUserException(
+          "Upgrade FAILED! Metastore state would be inconsistent !!", eIO);
+    }
+
+    // Revalidated the new version after upgrade
+    verifySchemaVersion();
+  }
+
+  /**
+   * Initialize the sentry store schema to current version
+   *
+   * @throws SentryUserException
+   */
+  public void doInit() throws SentryUserException {
+    doInit(sentryStoreSchemaInfo.getSentrySchemaVersion());
+
+    // Revalidated the new version after upgrade
+    verifySchemaVersion();
+  }
+
+  /**
+   * Initialize the sentry store schema
+   *
+   * @param toVersion
+   *          If null then current hive version is used
+   * @throws SentryUserException
+   */
+  public void doInit(String toVersion) throws SentryUserException {
+    testConnectionToMetastore();
+    System.out.println("Starting sentry store schema initialization to " + toVersion);
+
+    String initScriptDir = sentryStoreSchemaInfo.getSentryStoreScriptDir();
+    String initScriptFile = sentryStoreSchemaInfo.generateInitFileName(toVersion);
+
+    try {
+      System.out.println("Initialization script " + initScriptFile);
+      if (!dryRun) {
+        runBeeLine(initScriptDir, initScriptFile);
+        System.out.println("Initialization script completed");
+      }
+    } catch (IOException e) {
+      throw new SentryUserException("Schema initialization FAILED!"
+          + " Metastore state would be inconsistent !!", e);
+    }
+  }
+
+  // Flatten the nested upgrade script into a buffer
+  public static String buildCommand(NestedScriptParser dbCommandParser,
+        String scriptDir, String scriptFile) throws IllegalFormatException, IOException {
+
+    BufferedReader bfReader =
+        new BufferedReader(new FileReader(scriptDir + File.separatorChar + scriptFile));
+    String currLine;
+    StringBuilder sb = new StringBuilder();
+    String currentCommand = null;
+    while ((currLine = bfReader.readLine()) != null) {
+      currLine = currLine.trim();
+      if (currLine.isEmpty()) {
+        continue; // skip empty lines
+      }
+
+      if (currentCommand == null) {
+        currentCommand = currLine;
+      } else {
+        currentCommand = currentCommand + " " + currLine;
+      }
+      if (dbCommandParser.isPartialCommand(currLine)) {
+        // if its a partial line, continue collecting the pieces
+        continue;
+      }
+
+      // if this is a valid executable command then add it to the buffer
+      if (!dbCommandParser.isNonExecCommand(currentCommand)) {
+        currentCommand = dbCommandParser.cleanseCommand(currentCommand);
+
+        if (dbCommandParser.isNestedScript(currentCommand)) {
+          // if this is a nested sql script then flatten it
+          String currScript = dbCommandParser.getScriptName(currentCommand);
+          sb.append(buildCommand(dbCommandParser, scriptDir, currScript));
+        } else {
+          // Now we have a complete statement, process it
+          // write the line to buffer
+          sb.append(currentCommand);
+          sb.append(System.getProperty("line.separator"));
+        }
+      }
+      currentCommand = null;
+    }
+    bfReader.close();
+    return sb.toString();
+  }
+
+  // run beeline on the given sentry store scrip, flatten the nested scripts into single file
+  private void runBeeLine(String scriptDir, String scriptFile) throws IOException {
+    NestedScriptParser dbCommandParser =
+        SentrySchemaHelper.getDbCommandParser(dbType);
+    dbCommandParser.setDbOpts(getDbOpts());
+    // expand the nested script
+    String sqlCommands = buildCommand(dbCommandParser, scriptDir, scriptFile);
+    File tmpFile = File.createTempFile("schematool", ".sql");
+    tmpFile.deleteOnExit();
+
+    // write out the buffer into a file. Add beeline commands for autocommit and close
+    try (FileWriter fstream = new FileWriter(tmpFile.getPath());
+      BufferedWriter out = new BufferedWriter(fstream)) {
+
+      out.write("!set Silent " + verbose + System.getProperty("line.separator"));
+      out.write("!autocommit on" + System.getProperty("line.separator"));
+      out.write("!set Isolation TRANSACTION_READ_COMMITTED"
+          + System.getProperty("line.separator"));
+      out.write("!set AllowMultiLineCommand false"
+          + System.getProperty("line.separator"));
+      out.write(sqlCommands);
+      out.write("!closeall" + System.getProperty("line.separator"));
+      out.close();
+    }
+    runBeeLine(tmpFile.getPath());
+  }
+
+  // Generate the beeline args per hive conf and execute the given script
+  public void runBeeLine(String sqlScriptFile) throws IOException {
+    List<String> argList = new ArrayList<String>();
+    argList.add("-u");
+    argList.add(connectionURL);
+    argList.add("-d");
+    argList
+        .add(driver);
+    argList.add("-n");
+    argList.add(userName);
+    argList.add("-p");
+    argList.add(passWord);
+    argList.add("-f");
+    argList.add(sqlScriptFile);
+
+    BeeLine beeLine = new BeeLine();
+    if (!verbose) {
+      beeLine.setOutputStream(new PrintStream(new NullOutputStream()));
+      // beeLine.getOpts().setSilent(true);
+    }
+    // beeLine.getOpts().setAllowMultiLineCommand(false);
+    // beeLine.getOpts().setIsolation("TRANSACTION_READ_COMMITTED");
+    int status = beeLine.begin(argList.toArray(new String[0]), null);
+    if (status != 0) {
+      throw new IOException("Schema script failed, errorcode " + status);
+    }
+  }
+
+  private String getValidConfVar(String confVar) throws IOException {
+    String confVarKey = confVar;
+    String confVarValue = sentryConf.get(confVarKey);
+    if (confVarValue == null || confVarValue.isEmpty()) {
+      throw new IOException("Empty " + confVar);
+    }
+    return confVarValue;
+  }
+
+  // Create the required command line options
+  @SuppressWarnings("static-access")
+  private static void initOptions(Options cmdLineOptions) {
+    Option help = new Option("help", "print this message");
+    Option upgradeOpt = new Option("upgradeSchema", "Schema upgrade");
+    Option upgradeFromOpt = OptionBuilder.withArgName("upgradeFrom").hasArg().
+                withDescription("Schema upgrade from a version").
+                create("upgradeSchemaFrom");
+    Option initOpt = new Option("initSchema", "Schema initialization");
+    Option initToOpt = OptionBuilder.withArgName("initTo").hasArg().
+                withDescription("Schema initialization to a version").
+                create("initSchemaTo");
+    Option infoOpt = new Option("info", "Show config and schema details");
+
+    OptionGroup optGroup = new OptionGroup();
+    optGroup.addOption(upgradeOpt).addOption(initOpt).
+                addOption(help).addOption(upgradeFromOpt).
+                addOption(initToOpt).addOption(infoOpt);
+    optGroup.setRequired(true);
+
+    Option userNameOpt = OptionBuilder.withArgName("user")
+                .hasArg()
+                .withDescription("Override config file user name")
+                .create("userName");
+    Option passwdOpt = OptionBuilder.withArgName("password")
+                .hasArg()
+                 .withDescription("Override config file password")
+                 .create("passWord");
+    Option dbTypeOpt = OptionBuilder.withArgName("databaseType")
+                .hasArg().withDescription("Metastore database type [" +
+                SentrySchemaHelper.DB_DERBY + "," +
+                SentrySchemaHelper.DB_MYSQL + "," +
+                SentrySchemaHelper.DB_ORACLE + "," +
+                SentrySchemaHelper.DB_POSTGRACE + "," +
+                SentrySchemaHelper.DB_DB2 + "]")
+                .create("dbType");
+    Option dbOpts = OptionBuilder.withArgName("databaseOpts")
+                .hasArgs().withDescription("Backend DB specific options")
+                .create("dbOpts");
+
+    Option dryRunOpt = new Option("dryRun", "list SQL scripts (no execute)");
+    Option verboseOpt = new Option("verbose", "only print SQL statements");
+
+    Option configOpt = OptionBuilder.withArgName("confName").hasArgs()
+        .withDescription("Sentry Service configuration file").isRequired(true)
+        .create(ServiceConstants.ServiceArgs.CONFIG_FILE_LONG);
+
+    cmdLineOptions.addOption(help);
+    cmdLineOptions.addOption(dryRunOpt);
+    cmdLineOptions.addOption(userNameOpt);
+    cmdLineOptions.addOption(passwdOpt);
+    cmdLineOptions.addOption(dbTypeOpt);
+    cmdLineOptions.addOption(verboseOpt);
+    cmdLineOptions.addOption(dbOpts);
+    cmdLineOptions.addOption(configOpt);
+    cmdLineOptions.addOptionGroup(optGroup);
+  }
+
+  public static class CommandImpl implements Command {
+    @Override
+    public void run(String[] args) throws Exception {
+      CommandLineParser parser = new GnuParser();
+      CommandLine line = null;
+      String dbType = null;
+      String schemaVer = null;
+      Options cmdLineOptions = new Options();
+      String configFileName = null;
+
+      // Argument handling
+      initOptions(cmdLineOptions);
+      try {
+        line = parser.parse(cmdLineOptions, args);
+      } catch (ParseException e) {
+        System.err.println("SentrySchemaTool:Parsing failed.  Reason: "
+            + e.getLocalizedMessage());
+        printAndExit(cmdLineOptions);
+      }
+
+      if (line.hasOption("help")) {
+        HelpFormatter formatter = new HelpFormatter();
+        formatter.printHelp("schemaTool", cmdLineOptions);
+        return;
+      }
+
+      if (line.hasOption("dbType")) {
+        dbType = line.getOptionValue("dbType");
+        if (!dbType.equalsIgnoreCase(SentrySchemaHelper.DB_DERBY)
+            && !dbType.equalsIgnoreCase(SentrySchemaHelper.DB_MYSQL)
+            && !dbType.equalsIgnoreCase(SentrySchemaHelper.DB_POSTGRACE)
+            && !dbType.equalsIgnoreCase(SentrySchemaHelper.DB_ORACLE)
+            && !dbType.equalsIgnoreCase(SentrySchemaHelper.DB_DB2)) {
+          System.err.println("Unsupported dbType " + dbType);
+          printAndExit(cmdLineOptions);
+        }
+      } else {
+        System.err.println("no dbType supplied");
+        printAndExit(cmdLineOptions);
+      }
+      if (line.hasOption(ServiceConstants.ServiceArgs.CONFIG_FILE_LONG)) {
+        configFileName = line
+            .getOptionValue(ServiceConstants.ServiceArgs.CONFIG_FILE_LONG);
+      } else {
+        System.err.println("no config file specified");
+        printAndExit(cmdLineOptions);
+      }
+      try {
+        SentrySchemaTool schemaTool = new SentrySchemaTool(
+            SentryService.loadConfig(configFileName), dbType);
+
+        if (line.hasOption("userName")) {
+          schemaTool.setUserName(line.getOptionValue("userName"));
+        }
+        if (line.hasOption("passWord")) {
+          schemaTool.setPassWord(line.getOptionValue("passWord"));
+        }
+        if (line.hasOption("dryRun")) {
+          schemaTool.setDryRun(true);
+        }
+        if (line.hasOption("verbose")) {
+          schemaTool.setVerbose(true);
+        }
+        if (line.hasOption("dbOpts")) {
+          schemaTool.setDbOpts(line.getOptionValue("dbOpts"));
+        }
+
+        if (line.hasOption("info")) {
+          schemaTool.showInfo();
+        } else if (line.hasOption("upgradeSchema")) {
+          schemaTool.doUpgrade();
+        } else if (line.hasOption("upgradeSchemaFrom")) {
+          schemaVer = line.getOptionValue("upgradeSchemaFrom");
+          schemaTool.doUpgrade(schemaVer);
+        } else if (line.hasOption("initSchema")) {
+          schemaTool.doInit();
+        } else if (line.hasOption("initSchemaTo")) {
+          schemaVer = line.getOptionValue("initSchemaTo");
+          schemaTool.doInit(schemaVer);
+        } else {
+          System.err.println("no valid option supplied");
+          printAndExit(cmdLineOptions);
+        }
+      } catch (SentryUserException e) {
+        System.err.println(e);
+        if (line.hasOption("verbose")) {
+          e.printStackTrace();
+        }
+        System.err.println("*** Sentry schemaTool failed ***");
+        System.exit(1);
+      } catch (MalformedURLException e) {
+        System.err.println(e);
+        if (line.hasOption("verbose")) {
+          e.printStackTrace();
+        }
+        System.err.println("*** Sentry schemaTool failed ***");
+        System.exit(1);
+      }
+      System.out.println("Sentry schemaTool completed");
+    }
+  }
+
+}

http://git-wip-us.apache.org/repos/asf/sentry/blob/e72e6eac/sentry-service/sentry-service-server/src/main/java/org/apache/sentry/service/thrift/GSSCallback.java
----------------------------------------------------------------------
diff --git a/sentry-service/sentry-service-server/src/main/java/org/apache/sentry/service/thrift/GSSCallback.java b/sentry-service/sentry-service-server/src/main/java/org/apache/sentry/service/thrift/GSSCallback.java
new file mode 100644
index 0000000..b668b95
--- /dev/null
+++ b/sentry-service/sentry-service-server/src/main/java/org/apache/sentry/service/thrift/GSSCallback.java
@@ -0,0 +1,110 @@
+/**
+ * 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.sentry.service.thrift;
+
+import java.util.Arrays;
+import java.util.List;
+
+import javax.security.auth.callback.Callback;
+import javax.security.auth.callback.UnsupportedCallbackException;
+import javax.security.sasl.AuthorizeCallback;
+
+import org.apache.hadoop.conf.Configuration;
+import org.apache.hadoop.security.SaslRpcServer;
+import org.apache.sentry.core.common.exception.ConnectionDeniedException;
+import org.apache.sentry.service.thrift.ServiceConstants.ServerConfig;
+
+public class GSSCallback extends SaslRpcServer.SaslGssCallbackHandler {
+
+  private final Configuration conf;
+  public GSSCallback(Configuration conf) {
+    super();
+    this.conf = conf;
+  }
+
+  boolean comparePrincipals(String principal1, String principal2) {
+    String[] principalParts1 = SaslRpcServer.splitKerberosName(principal1);
+    String[] principalParts2 = SaslRpcServer.splitKerberosName(principal2);
+    if (principalParts1.length == 0 || principalParts2.length == 0) {
+      return false;
+    }
+    if (principalParts1.length == principalParts2.length) {
+      for (int i=0; i < principalParts1.length; i++) {
+        if (!principalParts1[i].equals(principalParts2[i])) {
+          return false;
+        }
+      }
+      return true;
+    } else {
+      return false;
+    }
+  }
+
+  boolean allowConnect(String principal) {
+    String allowedPrincipals = conf.get(ServerConfig.ALLOW_CONNECT);
+    if (allowedPrincipals == null) {
+      return false;
+    }
+    String principalShortName = getShortName(principal);
+    List<String> items = Arrays.asList(allowedPrincipals.split("\\s*,\\s*"));
+    for (String item : items) {
+      if (comparePrincipals(item, principalShortName)) {
+        return true;
+      }
+    }
+    return false;
+  }
+
+  private String getShortName(String principal) {
+    String parts[] = SaslRpcServer.splitKerberosName(principal);
+    return parts[0];
+  }
+
+  @Override
+  public void handle(Callback[] callbacks)
+  throws UnsupportedCallbackException, ConnectionDeniedException {
+    AuthorizeCallback ac = null;
+    for (Callback callback : callbacks) {
+      if (callback instanceof AuthorizeCallback) {
+        ac = (AuthorizeCallback) callback;
+      } else {
+        throw new UnsupportedCallbackException(callback,
+            "Unrecognized SASL GSSAPI Callback");
+      }
+    }
+    if (ac != null) {
+      String authid = ac.getAuthenticationID();
+      String authzid = ac.getAuthorizationID();
+
+      if (allowConnect(authid)) {
+        if (authid.equals(authzid)) {
+          ac.setAuthorized(true);
+        } else {
+          ac.setAuthorized(false);
+        }
+        if (ac.isAuthorized()) {
+          ac.setAuthorizedID(authzid);
+        }
+      } else {
+        throw new ConnectionDeniedException(ac,
+            "Connection to sentry service denied due to lack of client credentials",
+            authid);
+      }
+    }
+  }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/sentry/blob/e72e6eac/sentry-service/sentry-service-server/src/main/java/org/apache/sentry/service/thrift/KerberosConfiguration.java
----------------------------------------------------------------------
diff --git a/sentry-service/sentry-service-server/src/main/java/org/apache/sentry/service/thrift/KerberosConfiguration.java b/sentry-service/sentry-service-server/src/main/java/org/apache/sentry/service/thrift/KerberosConfiguration.java
new file mode 100644
index 0000000..41e4fe4
--- /dev/null
+++ b/sentry-service/sentry-service-server/src/main/java/org/apache/sentry/service/thrift/KerberosConfiguration.java
@@ -0,0 +1,107 @@
+/**
+ * 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.sentry.service.thrift;
+
+import java.io.File;
+import java.util.HashMap;
+import java.util.Map;
+
+import javax.security.auth.login.AppConfigurationEntry;
+
+public class KerberosConfiguration extends javax.security.auth.login.Configuration {
+  private String principal;
+  private String keytab;
+  private boolean isInitiator;
+  private static final boolean IBM_JAVA =  System.getProperty("java.vendor").contains("IBM");
+
+  private KerberosConfiguration(String principal, File keytab,
+      boolean client) {
+    this.principal = principal;
+    this.keytab = keytab.getAbsolutePath();
+    this.isInitiator = client;
+  }
+
+  public static javax.security.auth.login.Configuration createClientConfig(String principal,
+      File keytab) {
+    return new KerberosConfiguration(principal, keytab, true);
+  }
+
+  public static javax.security.auth.login.Configuration createServerConfig(String principal,
+      File keytab) {
+    return new KerberosConfiguration(principal, keytab, false);
+  }
+
+  private static String getKrb5LoginModuleName() {
+    return (IBM_JAVA ? "com.ibm.security.auth.module.Krb5LoginModule"
+            : "com.sun.security.auth.module.Krb5LoginModule");
+  }
+
+  @Override
+  public AppConfigurationEntry[] getAppConfigurationEntry(String name) {
+    Map<String, String> options = new HashMap<String, String>();
+
+    if (IBM_JAVA) {
+      // IBM JAVA's UseKeytab covers both keyTab and useKeyTab options
+      options.put("useKeytab",keytab.startsWith("file://") ? keytab : "file://" + keytab);
+
+      options.put("principal", principal);
+      options.put("refreshKrb5Config", "true");
+
+      // Both "initiator" and "acceptor"
+      options.put("credsType", "both");
+    } else {
+      options.put("keyTab", keytab);
+      options.put("principal", principal);
+      options.put("useKeyTab", "true");
+      options.put("storeKey", "true");
+      options.put("doNotPrompt", "true");
+      options.put("useTicketCache", "true");
+      options.put("renewTGT", "true");
+      options.put("refreshKrb5Config", "true");
+      options.put("isInitiator", Boolean.toString(isInitiator));
+    }
+
+    String ticketCache = System.getenv("KRB5CCNAME");
+    if (IBM_JAVA) {
+      // If cache is specified via env variable, it takes priority
+      if (ticketCache != null) {
+        // IBM JAVA only respects system property so copy ticket cache to system property
+        // The first value searched when "useDefaultCcache" is true.
+        System.setProperty("KRB5CCNAME", ticketCache);
+      } else {
+    	ticketCache = System.getProperty("KRB5CCNAME");
+      }
+
+      if (ticketCache != null) {
+        options.put("useDefaultCcache", "true");
+        options.put("renewTGT", "true");
+      }
+    } else {
+      if (ticketCache != null) {
+        options.put("ticketCache", ticketCache);
+      }
+    }
+    options.put("debug", "true");
+
+    return new AppConfigurationEntry[]{
+        new AppConfigurationEntry(getKrb5LoginModuleName(),
+            AppConfigurationEntry.LoginModuleControlFlag.REQUIRED,
+            options)};
+  }
+}
+

http://git-wip-us.apache.org/repos/asf/sentry/blob/e72e6eac/sentry-service/sentry-service-server/src/main/java/org/apache/sentry/service/thrift/ProcessorFactory.java
----------------------------------------------------------------------
diff --git a/sentry-service/sentry-service-server/src/main/java/org/apache/sentry/service/thrift/ProcessorFactory.java b/sentry-service/sentry-service-server/src/main/java/org/apache/sentry/service/thrift/ProcessorFactory.java
new file mode 100644
index 0000000..a3bb6ab
--- /dev/null
+++ b/sentry-service/sentry-service-server/src/main/java/org/apache/sentry/service/thrift/ProcessorFactory.java
@@ -0,0 +1,31 @@
+/**
+ * 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.sentry.service.thrift;
+
+import org.apache.hadoop.conf.Configuration;
+import org.apache.thrift.TMultiplexedProcessor;
+
+public abstract class ProcessorFactory {
+  protected final Configuration conf;
+
+  public ProcessorFactory(Configuration conf) {
+    this.conf = conf;
+  }
+
+  public abstract boolean register(TMultiplexedProcessor processor) throws Exception;
+}

http://git-wip-us.apache.org/repos/asf/sentry/blob/e72e6eac/sentry-service/sentry-service-server/src/main/java/org/apache/sentry/service/thrift/SentryKerberosContext.java
----------------------------------------------------------------------
diff --git a/sentry-service/sentry-service-server/src/main/java/org/apache/sentry/service/thrift/SentryKerberosContext.java b/sentry-service/sentry-service-server/src/main/java/org/apache/sentry/service/thrift/SentryKerberosContext.java
new file mode 100644
index 0000000..f54f161
--- /dev/null
+++ b/sentry-service/sentry-service-server/src/main/java/org/apache/sentry/service/thrift/SentryKerberosContext.java
@@ -0,0 +1,157 @@
+/**
+ * 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.sentry.service.thrift;
+
+import java.io.File;
+import java.util.HashSet;
+import java.util.Set;
+
+import javax.security.auth.Subject;
+import javax.security.auth.kerberos.KerberosPrincipal;
+import javax.security.auth.kerberos.KerberosTicket;
+import javax.security.auth.login.LoginContext;
+import javax.security.auth.login.LoginException;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.google.common.collect.Sets;
+
+public class SentryKerberosContext implements Runnable {
+  private static final float TICKET_RENEW_WINDOW = 0.80f;
+  private static final Logger LOGGER = LoggerFactory
+      .getLogger(SentryKerberosContext.class);
+  private LoginContext loginContext;
+  private Subject subject;
+  private final javax.security.auth.login.Configuration kerberosConfig;
+  @Deprecated
+  private Thread renewerThread;
+  @Deprecated
+  private boolean shutDownRenewer = false;
+
+  public SentryKerberosContext(String principal, String keyTab, boolean autoRenewTicket)
+      throws LoginException {
+    subject = new Subject(false, Sets.newHashSet(new KerberosPrincipal(principal)),
+          new HashSet<Object>(), new HashSet<Object>());
+    kerberosConfig = KerberosConfiguration.createClientConfig(principal, new File(keyTab));
+    loginWithNewContext();
+    if (autoRenewTicket) {
+      startRenewerThread();
+    }
+  }
+
+  private void loginWithNewContext() throws LoginException {
+    LOGGER.info("Logging in with new Context");
+    logoutSubject();
+    loginContext = new LoginContext("", subject, null, kerberosConfig);
+    loginContext.login();
+    subject = loginContext.getSubject();
+  }
+  
+  private void logoutSubject() {
+    if (loginContext != null) {
+      try {
+        loginContext.logout();
+      } catch (LoginException e) {
+        LOGGER.warn("Error logging out the subject", e);
+      }        
+    }
+    loginContext = null;
+  }
+  
+  public Subject getSubject() {
+    return subject;
+  }
+
+  /**
+   * Get the Kerberos TGT
+   * @return the user's TGT or null if none was found
+   */
+  @Deprecated
+  private KerberosTicket getTGT() {
+    Set<KerberosTicket> tickets = subject.getPrivateCredentials(KerberosTicket.class);
+    for(KerberosTicket ticket: tickets) {
+      KerberosPrincipal server = ticket.getServer();
+      if (server.getName().equals("krbtgt/" + server.getRealm() +
+          "@" + server.getRealm())) {
+        return ticket;
+      }
+    }
+    return null;
+  }
+
+  @Deprecated
+  private long getRefreshTime(KerberosTicket tgt) {
+    long start = tgt.getStartTime().getTime();
+    long end = tgt.getEndTime().getTime();
+    LOGGER.debug("Ticket start time: " + start);
+    LOGGER.debug("Ticket End time: " + end);
+    return start + (long) ((end - start) * TICKET_RENEW_WINDOW);
+  }
+
+  /***
+   * Ticket renewer thread
+   * wait till 80% time interval left on the ticket and then renew it
+   */
+  @Deprecated
+  @Override
+  public void run() {
+    try {
+      LOGGER.info("Sentry Ticket renewer thread started");
+      while (!shutDownRenewer) {
+        KerberosTicket tgt = getTGT();
+        if (tgt == null) {
+          LOGGER.warn("No ticket found in the cache");
+          return;
+        }
+        long nextRefresh = getRefreshTime(tgt);
+        while (System.currentTimeMillis() < nextRefresh) {
+          Thread.sleep(1000);
+          if (shutDownRenewer) {
+            return;
+          }
+        }
+        loginWithNewContext();
+        LOGGER.debug("Renewed ticket");
+      }
+    } catch (InterruptedException e1) {
+      LOGGER.warn("Sentry Ticket renewer thread interrupted", e1);
+      return;
+    } catch (LoginException e) {
+      LOGGER.warn("Failed to renew ticket", e);
+    } finally {
+      logoutSubject();
+      LOGGER.info("Sentry Ticket renewer thread finished");
+    }
+  }
+
+  @Deprecated
+  public void startRenewerThread() {
+    renewerThread = new Thread(this);
+    renewerThread.start();
+  }
+
+  public void shutDown() throws LoginException {
+    if (renewerThread != null) {
+      shutDownRenewer = true;
+    } else {
+      logoutSubject();
+    }
+  }
+}

http://git-wip-us.apache.org/repos/asf/sentry/blob/e72e6eac/sentry-service/sentry-service-server/src/main/java/org/apache/sentry/service/thrift/SentryService.java
----------------------------------------------------------------------
diff --git a/sentry-service/sentry-service-server/src/main/java/org/apache/sentry/service/thrift/SentryService.java b/sentry-service/sentry-service-server/src/main/java/org/apache/sentry/service/thrift/SentryService.java
new file mode 100644
index 0000000..5783649
--- /dev/null
+++ b/sentry-service/sentry-service-server/src/main/java/org/apache/sentry/service/thrift/SentryService.java
@@ -0,0 +1,426 @@
+/**
+ * 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.sentry.service.thrift;
+
+import java.io.File;
+import java.io.IOException;
+import java.lang.reflect.Constructor;
+import java.net.InetSocketAddress;
+import java.net.MalformedURLException;
+import java.net.ServerSocket;
+import java.security.PrivilegedExceptionAction;
+import java.util.ArrayList;
+import java.util.EventListener;
+import java.util.List;
+import java.util.concurrent.Callable;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+import java.util.concurrent.Future;
+import java.util.concurrent.ThreadFactory;
+
+import javax.security.auth.Subject;
+
+import org.apache.commons.cli.CommandLine;
+import org.apache.commons.cli.CommandLineParser;
+import org.apache.commons.cli.GnuParser;
+import org.apache.commons.cli.HelpFormatter;
+import org.apache.commons.cli.Options;
+import org.apache.hadoop.conf.Configuration;
+import org.apache.hadoop.net.NetUtils;
+import org.apache.hadoop.security.SaslRpcServer;
+import org.apache.hadoop.security.SaslRpcServer.AuthMethod;
+import org.apache.hadoop.security.SecurityUtil;
+import org.apache.sentry.Command;
+import org.apache.sentry.provider.db.service.thrift.SentryHealthCheckServletContextListener;
+import org.apache.sentry.provider.db.service.thrift.SentryMetricsServletContextListener;
+import org.apache.sentry.provider.db.service.thrift.SentryWebServer;
+import org.apache.sentry.service.thrift.ServiceConstants.ConfUtilties;
+import org.apache.sentry.service.thrift.ServiceConstants.ServerConfig;
+import org.apache.thrift.TMultiplexedProcessor;
+import org.apache.thrift.protocol.TBinaryProtocol;
+import org.apache.thrift.server.TServer;
+import org.apache.thrift.server.TServerEventHandler;
+import org.apache.thrift.server.TThreadPoolServer;
+import org.apache.thrift.transport.TSaslServerTransport;
+import org.apache.thrift.transport.TServerSocket;
+import org.apache.thrift.transport.TServerTransport;
+import org.apache.thrift.transport.TTransportFactory;
+import org.eclipse.jetty.util.MultiException;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.google.common.base.Preconditions;
+
+public class SentryService implements Callable {
+
+  private static final Logger LOGGER = LoggerFactory
+      .getLogger(SentryService.class);
+
+  private static enum Status {
+    NOT_STARTED(), STARTED();
+  }
+
+  private final Configuration conf;
+  private final InetSocketAddress address;
+  private final int maxThreads;
+  private final int minThreads;
+  private boolean kerberos;
+  private final String principal;
+  private final String[] principalParts;
+  private final String keytab;
+  private final ExecutorService serviceExecutor;
+  private Future serviceStatus;
+  private TServer thriftServer;
+  private Status status;
+  private int webServerPort;
+  private SentryWebServer sentryWebServer;
+  private long maxMessageSize;
+
+  public SentryService(Configuration conf) {
+    this.conf = conf;
+    int port = conf
+        .getInt(ServerConfig.RPC_PORT, ServerConfig.RPC_PORT_DEFAULT);
+    if (port == 0) {
+      port = findFreePort();
+      conf.setInt(ServerConfig.RPC_PORT, port);
+    }
+    this.address = NetUtils.createSocketAddr(
+        conf.get(ServerConfig.RPC_ADDRESS, ServerConfig.RPC_ADDRESS_DEFAULT),
+        port);
+    LOGGER.info("Configured on address " + address);
+    kerberos = ServerConfig.SECURITY_MODE_KERBEROS.equalsIgnoreCase(
+        conf.get(ServerConfig.SECURITY_MODE, ServerConfig.SECURITY_MODE_KERBEROS).trim());
+    maxThreads = conf.getInt(ServerConfig.RPC_MAX_THREADS,
+        ServerConfig.RPC_MAX_THREADS_DEFAULT);
+    minThreads = conf.getInt(ServerConfig.RPC_MIN_THREADS,
+        ServerConfig.RPC_MIN_THREADS_DEFAULT);
+    maxMessageSize = conf.getLong(ServerConfig.SENTRY_POLICY_SERVER_THRIFT_MAX_MESSAGE_SIZE,
+        ServerConfig.SENTRY_POLICY_SERVER_THRIFT_MAX_MESSAGE_SIZE_DEFAULT);
+    if (kerberos) {
+      // Use Hadoop libraries to translate the _HOST placeholder with actual hostname
+      try {
+        String rawPrincipal = Preconditions.checkNotNull(conf.get(ServerConfig.PRINCIPAL), ServerConfig.PRINCIPAL + " is required");
+        principal = SecurityUtil.getServerPrincipal(rawPrincipal, address.getAddress());
+      } catch(IOException io) {
+        throw new RuntimeException("Can't translate kerberos principal'", io);
+      }
+      LOGGER.info("Using kerberos principal: " + principal);
+
+      principalParts = SaslRpcServer.splitKerberosName(principal);
+      Preconditions.checkArgument(principalParts.length == 3,
+          "Kerberos principal should have 3 parts: " + principal);
+      keytab = Preconditions.checkNotNull(conf.get(ServerConfig.KEY_TAB),
+          ServerConfig.KEY_TAB + " is required");
+      File keytabFile = new File(keytab);
+      Preconditions.checkState(keytabFile.isFile() && keytabFile.canRead(),
+          "Keytab " + keytab + " does not exist or is not readable.");
+    } else {
+      principal = null;
+      principalParts = null;
+      keytab = null;
+    }
+    serviceExecutor = Executors.newSingleThreadExecutor(new ThreadFactory() {
+      private int count = 0;
+
+      @Override
+      public Thread newThread(Runnable r) {
+        return new Thread(r, SentryService.class.getSimpleName() + "-"
+            + (count++));
+      }
+    });
+    webServerPort = conf.getInt(ServerConfig.SENTRY_WEB_PORT, ServerConfig.SENTRY_WEB_PORT_DEFAULT);
+    status = Status.NOT_STARTED;
+  }
+
+  @Override
+  public String call() throws Exception {
+    SentryKerberosContext kerberosContext = null;
+    try {
+      status = Status.STARTED;
+      if (kerberos) {
+        Boolean autoRenewTicket = conf.getBoolean(ServerConfig.SENTRY_KERBEROS_TGT_AUTORENEW, ServerConfig.SENTRY_KERBEROS_TGT_AUTORENEW_DEFAULT);
+        kerberosContext = new SentryKerberosContext(principal, keytab, autoRenewTicket);
+        Subject.doAs(kerberosContext.getSubject(), new PrivilegedExceptionAction<Void>() {
+          @Override
+          public Void run() throws Exception {
+            runServer();
+            return null;
+          }
+        });
+      } else {
+        runServer();
+      }
+    } catch (Exception t) {
+      LOGGER.error("Error starting server", t);
+      throw new Exception("Error starting server", t);
+    } finally {
+      if (kerberosContext != null) {
+        kerberosContext.shutDown();
+      }
+      status = Status.NOT_STARTED;
+    }
+    return null;
+  }
+
+  private void runServer() throws Exception {
+    Iterable<String> processorFactories = ConfUtilties.CLASS_SPLITTER
+        .split(conf.get(ServerConfig.PROCESSOR_FACTORIES,
+            ServerConfig.PROCESSOR_FACTORIES_DEFAULT).trim());
+    TMultiplexedProcessor processor = new TMultiplexedProcessor();
+    boolean registeredProcessor = false;
+    for (String processorFactory : processorFactories) {
+      Class<?> clazz = conf.getClassByName(processorFactory);
+      if (!ProcessorFactory.class.isAssignableFrom(clazz)) {
+        throw new IllegalArgumentException("Processor Factory "
+            + processorFactory + " is not a "
+            + ProcessorFactory.class.getName());
+      }
+      try {
+        Constructor<?> constructor = clazz
+            .getConstructor(Configuration.class);
+        LOGGER.info("ProcessorFactory being used: " + clazz.getCanonicalName());
+        ProcessorFactory factory = (ProcessorFactory) constructor
+            .newInstance(conf);
+        boolean registerStatus = factory.register(processor);
+        if (!registerStatus) {
+          LOGGER.error("Failed to register " + clazz.getCanonicalName());
+        }
+        registeredProcessor = registerStatus || registeredProcessor;
+      } catch (Exception e) {
+        throw new IllegalStateException("Could not create "
+            + processorFactory, e);
+      }
+    }
+    if (!registeredProcessor) {
+      throw new IllegalStateException(
+          "Failed to register any processors from " + processorFactories);
+    }
+    TServerTransport serverTransport = new TServerSocket(address);
+    TTransportFactory transportFactory = null;
+    if (kerberos) {
+      TSaslServerTransport.Factory saslTransportFactory = new TSaslServerTransport.Factory();
+      saslTransportFactory.addServerDefinition(AuthMethod.KERBEROS
+          .getMechanismName(), principalParts[0], principalParts[1],
+          ServerConfig.SASL_PROPERTIES, new GSSCallback(conf));
+      transportFactory = saslTransportFactory;
+    } else {
+      transportFactory = new TTransportFactory();
+    }
+    TThreadPoolServer.Args args = new TThreadPoolServer.Args(
+        serverTransport).processor(processor)
+        .transportFactory(transportFactory)
+        .protocolFactory(new TBinaryProtocol.Factory(true, true, maxMessageSize, maxMessageSize))
+        .minWorkerThreads(minThreads).maxWorkerThreads(maxThreads);
+    thriftServer = new TThreadPoolServer(args);
+    LOGGER.info("Serving on " + address);
+    startSentryWebServer();
+    thriftServer.serve();
+  }
+
+  private void startSentryWebServer() throws Exception{
+    Boolean sentryReportingEnable = conf.getBoolean(ServerConfig.SENTRY_WEB_ENABLE,
+        ServerConfig.SENTRY_WEB_ENABLE_DEFAULT);
+    if(sentryReportingEnable) {
+      List<EventListener> listenerList = new ArrayList<EventListener>();
+      listenerList.add(new SentryHealthCheckServletContextListener());
+      listenerList.add(new SentryMetricsServletContextListener());
+      sentryWebServer = new SentryWebServer(listenerList, webServerPort, conf);
+      sentryWebServer.start();
+    }
+
+  }
+
+  private void stopSentryWebServer() throws Exception{
+    if( sentryWebServer != null) {
+      sentryWebServer.stop();
+      sentryWebServer = null;
+    }
+  }
+
+  public InetSocketAddress getAddress() {
+    return address;
+  }
+
+  public synchronized boolean isRunning() {
+    return status == Status.STARTED && thriftServer != null
+        && thriftServer.isServing();
+  }
+
+  public synchronized void start() throws Exception{
+    if (status != Status.NOT_STARTED) {
+      throw new IllegalStateException("Cannot start when " + status);
+    }
+    LOGGER.info("Attempting to start...");
+    serviceStatus = serviceExecutor.submit(this);
+  }
+
+  public synchronized void stop() throws Exception{
+    MultiException exception = null;
+    LOGGER.info("Attempting to stop...");
+    if (isRunning()) {
+      LOGGER.info("Attempting to stop sentry thrift service...");
+      try {
+        thriftServer.stop();
+        thriftServer = null;
+        status = Status.NOT_STARTED;
+      } catch (Exception e) {
+        LOGGER.error("Error while stopping sentry thrift service", e);
+        exception = addMultiException(exception,e);
+      }
+    } else {
+      thriftServer = null;
+      status = Status.NOT_STARTED;
+      LOGGER.info("Sentry thrift service is already stopped...");
+    }
+    if (isWebServerRunning()) {
+      try {
+        LOGGER.info("Attempting to stop sentry web service...");
+        stopSentryWebServer();
+      } catch (Exception e) {
+        LOGGER.error("Error while stopping sentry web service", e);
+        exception = addMultiException(exception,e);
+      }
+    } else {
+      LOGGER.info("Sentry web service is already stopped...");
+    }
+    if (exception != null) {
+      exception.ifExceptionThrow();
+    }
+    LOGGER.info("Stopped...");
+  }
+
+  // wait for the service thread to finish execution
+  public synchronized void waitOnFuture() throws ExecutionException, InterruptedException {
+    LOGGER.info("Waiting on future.get()");
+      serviceStatus.get();
+  }
+
+  private MultiException addMultiException(MultiException exception, Exception e) {
+    MultiException newException = exception;
+    if (newException == null) {
+      newException = new MultiException();
+    }
+    newException.add(e);
+    return newException;
+  }
+
+  private boolean isWebServerRunning() {
+    return sentryWebServer != null
+        && sentryWebServer.isAlive();
+  }
+
+  private static int findFreePort() {
+    int attempts = 0;
+    while (attempts++ <= 1000) {
+      try {
+        ServerSocket s = new ServerSocket(0);
+        int port = s.getLocalPort();
+        s.close();
+        return port;
+      } catch (IOException e) {
+        // ignore and retry
+      }
+    }
+    throw new IllegalStateException("Unable to find a port after 1000 attempts");
+  }
+
+  public static Configuration loadConfig(String configFileName)
+      throws MalformedURLException {
+    File configFile = null;
+    if (configFileName == null) {
+      throw new IllegalArgumentException("Usage: "
+          + ServiceConstants.ServiceArgs.CONFIG_FILE_LONG
+          + " path/to/sentry-service.xml");
+    } else if (!((configFile = new File(configFileName)).isFile() && configFile
+        .canRead())) {
+      throw new IllegalArgumentException("Cannot read configuration file "
+          + configFile);
+    }
+    Configuration conf = new Configuration(false);
+    conf.addResource(configFile.toURI().toURL());
+    return conf;
+  }
+
+  public static class CommandImpl implements Command {
+    @Override
+    public void run(String[] args) throws Exception {
+      CommandLineParser parser = new GnuParser();
+      Options options = new Options();
+      options.addOption(ServiceConstants.ServiceArgs.CONFIG_FILE_SHORT,
+          ServiceConstants.ServiceArgs.CONFIG_FILE_LONG,
+          true, "Sentry Service configuration file");
+      CommandLine commandLine = parser.parse(options, args);
+      String configFileName = commandLine.getOptionValue(ServiceConstants.
+          ServiceArgs.CONFIG_FILE_LONG);
+      File configFile = null;
+      if (configFileName == null || commandLine.hasOption("h") || commandLine.hasOption("help")) {
+        // print usage
+        HelpFormatter formatter = new HelpFormatter();
+        formatter.printHelp("sentry --command service", options);
+        System.exit(-1);
+      } else if(!((configFile = new File(configFileName)).isFile() && configFile.canRead())) {
+        throw new IllegalArgumentException("Cannot read configuration file " + configFile);
+      }
+      Configuration serverConf = loadConfig(configFileName);
+      final SentryService server = new SentryService(serverConf);
+      server.start();
+      Runtime.getRuntime().addShutdownHook(new Thread() {
+        @Override
+        public void run() {
+          LOGGER.info("ShutdownHook shutting down server");
+          try {
+            server.stop();
+          } catch (Throwable t) {
+            LOGGER.error("Error stopping SentryService", t);
+          }
+        }
+      });
+
+      // Let's wait on the service to stop
+      try {
+        server.waitOnFuture();
+      } finally {
+        server.serviceExecutor.shutdown();
+      }
+    }
+  }
+
+  public Configuration getConf() {
+    return conf;
+  }
+
+  /**
+   * Add Thrift event handler to underlying thrift threadpool server
+   * @param eventHandler
+   */
+  public void setThriftEventHandler(TServerEventHandler eventHandler) throws IllegalStateException {
+    if (thriftServer == null) {
+      throw new IllegalStateException("Server is not initialized or stopped");
+    }
+    thriftServer.setServerEventHandler(eventHandler);
+  }
+
+  public TServerEventHandler getThriftEventHandler() throws IllegalStateException {
+    if (thriftServer == null) {
+      throw new IllegalStateException("Server is not initialized or stopped");
+    }
+    return thriftServer.getEventHandler();
+  }
+}

http://git-wip-us.apache.org/repos/asf/sentry/blob/e72e6eac/sentry-service/sentry-service-server/src/main/java/org/apache/sentry/service/thrift/SentryServiceFactory.java
----------------------------------------------------------------------
diff --git a/sentry-service/sentry-service-server/src/main/java/org/apache/sentry/service/thrift/SentryServiceFactory.java b/sentry-service/sentry-service-server/src/main/java/org/apache/sentry/service/thrift/SentryServiceFactory.java
new file mode 100644
index 0000000..1685702
--- /dev/null
+++ b/sentry-service/sentry-service-server/src/main/java/org/apache/sentry/service/thrift/SentryServiceFactory.java
@@ -0,0 +1,28 @@
+/**
+ * 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.sentry.service.thrift;
+import org.apache.hadoop.conf.Configuration;
+
+public class SentryServiceFactory {
+
+  public SentryService create(Configuration conf) throws Exception {
+    return new SentryService(conf);
+  }
+
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/sentry/blob/e72e6eac/sentry-service/sentry-service-server/src/main/resources/001-SENTRY-327.derby.sql
----------------------------------------------------------------------
diff --git a/sentry-service/sentry-service-server/src/main/resources/001-SENTRY-327.derby.sql b/sentry-service/sentry-service-server/src/main/resources/001-SENTRY-327.derby.sql
new file mode 100644
index 0000000..04353d1
--- /dev/null
+++ b/sentry-service/sentry-service-server/src/main/resources/001-SENTRY-327.derby.sql
@@ -0,0 +1,2 @@
+-- SENTRY-327
+ALTER TABLE SENTRY_DB_PRIVILEGE ADD COLUMN WITH_GRANT_OPTION CHAR(1) NOT NULL DEFAULT 'N';

http://git-wip-us.apache.org/repos/asf/sentry/blob/e72e6eac/sentry-service/sentry-service-server/src/main/resources/001-SENTRY-327.mysql.sql
----------------------------------------------------------------------
diff --git a/sentry-service/sentry-service-server/src/main/resources/001-SENTRY-327.mysql.sql b/sentry-service/sentry-service-server/src/main/resources/001-SENTRY-327.mysql.sql
new file mode 100644
index 0000000..7d96bc0
--- /dev/null
+++ b/sentry-service/sentry-service-server/src/main/resources/001-SENTRY-327.mysql.sql
@@ -0,0 +1,2 @@
+-- SENTRY-327
+ALTER TABLE `SENTRY_DB_PRIVILEGE` ADD `WITH_GRANT_OPTION` CHAR(1) NOT NULL DEFAULT 'N';

http://git-wip-us.apache.org/repos/asf/sentry/blob/e72e6eac/sentry-service/sentry-service-server/src/main/resources/001-SENTRY-327.oracle.sql
----------------------------------------------------------------------
diff --git a/sentry-service/sentry-service-server/src/main/resources/001-SENTRY-327.oracle.sql b/sentry-service/sentry-service-server/src/main/resources/001-SENTRY-327.oracle.sql
new file mode 100644
index 0000000..f42ccdf
--- /dev/null
+++ b/sentry-service/sentry-service-server/src/main/resources/001-SENTRY-327.oracle.sql
@@ -0,0 +1,2 @@
+-- SENTRY-327
+ALTER TABLE SENTRY_DB_PRIVILEGE ADD WITH_GRANT_OPTION CHAR(1) DEFAULT 'N' NOT NULL;

http://git-wip-us.apache.org/repos/asf/sentry/blob/e72e6eac/sentry-service/sentry-service-server/src/main/resources/001-SENTRY-327.postgres.sql
----------------------------------------------------------------------
diff --git a/sentry-service/sentry-service-server/src/main/resources/001-SENTRY-327.postgres.sql b/sentry-service/sentry-service-server/src/main/resources/001-SENTRY-327.postgres.sql
new file mode 100644
index 0000000..1b670ec
--- /dev/null
+++ b/sentry-service/sentry-service-server/src/main/resources/001-SENTRY-327.postgres.sql
@@ -0,0 +1,2 @@
+-- SENTRY-327
+ALTER TABLE "SENTRY_DB_PRIVILEGE" ADD COLUMN "WITH_GRANT_OPTION" CHAR(1) NOT NULL DEFAULT 'N';

http://git-wip-us.apache.org/repos/asf/sentry/blob/e72e6eac/sentry-service/sentry-service-server/src/main/resources/002-SENTRY-339.derby.sql
----------------------------------------------------------------------
diff --git a/sentry-service/sentry-service-server/src/main/resources/002-SENTRY-339.derby.sql b/sentry-service/sentry-service-server/src/main/resources/002-SENTRY-339.derby.sql
new file mode 100644
index 0000000..647e9e2
--- /dev/null
+++ b/sentry-service/sentry-service-server/src/main/resources/002-SENTRY-339.derby.sql
@@ -0,0 +1,13 @@
+-- SENTRY-339
+DROP INDEX SENTRYPRIVILEGENAME;
+CREATE UNIQUE INDEX SENTRYPRIVILEGENAME ON SENTRY_DB_PRIVILEGE ("SERVER_NAME",DB_NAME,"TABLE_NAME",URI,"ACTION",WITH_GRANT_OPTION);
+
+ALTER TABLE SENTRY_DB_PRIVILEGE DROP COLUMN PRIVILEGE_NAME;
+
+ALTER TABLE SENTRY_DB_PRIVILEGE ALTER COLUMN DB_NAME SET DEFAULT '__NULL__';
+ALTER TABLE SENTRY_DB_PRIVILEGE ALTER COLUMN TABLE_NAME SET DEFAULT '__NULL__';
+ALTER TABLE SENTRY_DB_PRIVILEGE ALTER COLUMN URI SET DEFAULT '__NULL__';
+
+UPDATE SENTRY_DB_PRIVILEGE SET DB_NAME = DEFAULT WHERE DB_NAME is null;
+UPDATE SENTRY_DB_PRIVILEGE SET TABLE_NAME = DEFAULT WHERE TABLE_NAME is null;
+UPDATE SENTRY_DB_PRIVILEGE SET URI = DEFAULT WHERE URI is null;

http://git-wip-us.apache.org/repos/asf/sentry/blob/e72e6eac/sentry-service/sentry-service-server/src/main/resources/002-SENTRY-339.mysql.sql
----------------------------------------------------------------------
diff --git a/sentry-service/sentry-service-server/src/main/resources/002-SENTRY-339.mysql.sql b/sentry-service/sentry-service-server/src/main/resources/002-SENTRY-339.mysql.sql
new file mode 100644
index 0000000..cd4ec7c
--- /dev/null
+++ b/sentry-service/sentry-service-server/src/main/resources/002-SENTRY-339.mysql.sql
@@ -0,0 +1,13 @@
+-- SENTRY-339
+ALTER TABLE `SENTRY_DB_PRIVILEGE` DROP INDEX `SENTRY_DB_PRIV_PRIV_NAME_UNIQ`;
+ALTER TABLE `SENTRY_DB_PRIVILEGE` ADD UNIQUE `SENTRY_DB_PRIV_PRIV_NAME_UNIQ` (`SERVER_NAME`,`DB_NAME`,`TABLE_NAME`,`URI`(250),`ACTION`,`WITH_GRANT_OPTION`);
+ALTER TABLE `SENTRY_DB_PRIVILEGE` DROP `PRIVILEGE_NAME`;
+
+ALTER TABLE SENTRY_DB_PRIVILEGE ALTER COLUMN DB_NAME SET DEFAULT '__NULL__';
+ALTER TABLE SENTRY_DB_PRIVILEGE ALTER COLUMN TABLE_NAME SET DEFAULT '__NULL__';
+ALTER TABLE SENTRY_DB_PRIVILEGE ALTER COLUMN URI SET DEFAULT '__NULL__';
+
+UPDATE SENTRY_DB_PRIVILEGE SET DB_NAME = DEFAULT WHERE DB_NAME is null;
+UPDATE SENTRY_DB_PRIVILEGE SET TABLE_NAME = DEFAULT WHERE TABLE_NAME is null;
+UPDATE SENTRY_DB_PRIVILEGE SET URI = DEFAULT WHERE URI is null;
+

http://git-wip-us.apache.org/repos/asf/sentry/blob/e72e6eac/sentry-service/sentry-service-server/src/main/resources/002-SENTRY-339.oracle.sql
----------------------------------------------------------------------
diff --git a/sentry-service/sentry-service-server/src/main/resources/002-SENTRY-339.oracle.sql b/sentry-service/sentry-service-server/src/main/resources/002-SENTRY-339.oracle.sql
new file mode 100644
index 0000000..f5f596d
--- /dev/null
+++ b/sentry-service/sentry-service-server/src/main/resources/002-SENTRY-339.oracle.sql
@@ -0,0 +1,13 @@
+-- SENTRY-339
+ALTER TABLE SENTRY_DB_PRIVILEGE DROP CONSTRAINT "SENTRY_DB_PRIV_PRIV_NAME_UNIQ" DROP INDEX;
+ALTER TABLE SENTRY_DB_PRIVILEGE ADD CONSTRAINT "SENTRY_DB_PRIV_PRIV_NAME_UNIQ" UNIQUE ("SERVER_NAME","DB_NAME","TABLE_NAME","URI","ACTION","WITH_GRANT_OPTION");
+ALTER TABLE SENTRY_DB_PRIVILEGE DROP COLUMN PRIVILEGE_NAME;
+
+ALTER TABLE SENTRY_DB_PRIVILEGE MODIFY DB_NAME DEFAULT '__NULL__';
+ALTER TABLE SENTRY_DB_PRIVILEGE MODIFY TABLE_NAME DEFAULT '__NULL__';
+ALTER TABLE SENTRY_DB_PRIVILEGE MODIFY URI DEFAULT '__NULL__';
+
+UPDATE SENTRY_DB_PRIVILEGE SET DB_NAME = DEFAULT WHERE DB_NAME is null;
+UPDATE SENTRY_DB_PRIVILEGE SET TABLE_NAME = DEFAULT WHERE TABLE_NAME is null;
+UPDATE SENTRY_DB_PRIVILEGE SET URI = DEFAULT WHERE URI is null;
+

http://git-wip-us.apache.org/repos/asf/sentry/blob/e72e6eac/sentry-service/sentry-service-server/src/main/resources/002-SENTRY-339.postgres.sql
----------------------------------------------------------------------
diff --git a/sentry-service/sentry-service-server/src/main/resources/002-SENTRY-339.postgres.sql b/sentry-service/sentry-service-server/src/main/resources/002-SENTRY-339.postgres.sql
new file mode 100644
index 0000000..458e447
--- /dev/null
+++ b/sentry-service/sentry-service-server/src/main/resources/002-SENTRY-339.postgres.sql
@@ -0,0 +1,13 @@
+-- SENTRY-339
+ALTER TABLE "SENTRY_DB_PRIVILEGE" DROP CONSTRAINT "SENTRY_DB_PRIV_PRIV_NAME_UNIQ";
+ALTER TABLE "SENTRY_DB_PRIVILEGE" ADD CONSTRAINT "SENTRY_DB_PRIV_PRIV_NAME_UNIQ" UNIQUE ("SERVER_NAME","DB_NAME","TABLE_NAME","URI", "ACTION","WITH_GRANT_OPTION");
+ALTER TABLE "SENTRY_DB_PRIVILEGE" DROP COLUMN "PRIVILEGE_NAME";
+
+ALTER TABLE "SENTRY_DB_PRIVILEGE" ALTER COLUMN "DB_NAME" SET DEFAULT '__NULL__';
+AlTER TABLE "SENTRY_DB_PRIVILEGE" ALTER COLUMN "TABLE_NAME" SET DEFAULT '__NULL__';
+ALTER TABLE "SENTRY_DB_PRIVILEGE" ALTER COLUMN "URI" SET DEFAULT '__NULL__';
+
+UPDATE "SENTRY_DB_PRIVILEGE" SET "DB_NAME" = DEFAULT where "DB_NAME" is null;
+UPDATE "SENTRY_DB_PRIVILEGE" SET "TABLE_NAME" = DEFAULT where "TABLE_NAME" is null;
+UPDATE "SENTRY_DB_PRIVILEGE" SET "URI" = DEFAULT where "URI" is null;
+

http://git-wip-us.apache.org/repos/asf/sentry/blob/e72e6eac/sentry-service/sentry-service-server/src/main/resources/003-SENTRY-380.derby.sql
----------------------------------------------------------------------
diff --git a/sentry-service/sentry-service-server/src/main/resources/003-SENTRY-380.derby.sql b/sentry-service/sentry-service-server/src/main/resources/003-SENTRY-380.derby.sql
new file mode 100644
index 0000000..f27b358
--- /dev/null
+++ b/sentry-service/sentry-service-server/src/main/resources/003-SENTRY-380.derby.sql
@@ -0,0 +1,7 @@
+-- SENTRY-380
+ALTER TABLE SENTRY_DB_PRIVILEGE DROP GRANTOR_PRINCIPAL;
+ALTER TABLE SENTRY_ROLE DROP GRANTOR_PRINCIPAL;
+ALTER TABLE SENTRY_GROUP DROP GRANTOR_PRINCIPAL;
+
+ALTER TABLE SENTRY_ROLE_DB_PRIVILEGE_MAP ADD GRANTOR_PRINCIPAL VARCHAR(128);
+ALTER TABLE SENTRY_ROLE_GROUP_MAP ADD GRANTOR_PRINCIPAL VARCHAR(128);

http://git-wip-us.apache.org/repos/asf/sentry/blob/e72e6eac/sentry-service/sentry-service-server/src/main/resources/003-SENTRY-380.mysql.sql
----------------------------------------------------------------------
diff --git a/sentry-service/sentry-service-server/src/main/resources/003-SENTRY-380.mysql.sql b/sentry-service/sentry-service-server/src/main/resources/003-SENTRY-380.mysql.sql
new file mode 100644
index 0000000..8e0a633
--- /dev/null
+++ b/sentry-service/sentry-service-server/src/main/resources/003-SENTRY-380.mysql.sql
@@ -0,0 +1,7 @@
+-- SENTRY-380
+ALTER TABLE `SENTRY_DB_PRIVILEGE` DROP `GRANTOR_PRINCIPAL`;
+ALTER TABLE `SENTRY_ROLE` DROP `GRANTOR_PRINCIPAL`;
+ALTER TABLE `SENTRY_GROUP` DROP `GRANTOR_PRINCIPAL`;
+
+ALTER TABLE `SENTRY_ROLE_DB_PRIVILEGE_MAP` ADD `GRANTOR_PRINCIPAL` VARCHAR(128) CHARACTER SET utf8 COLLATE utf8_bin;
+ALTER TABLE `SENTRY_ROLE_GROUP_MAP` ADD `GRANTOR_PRINCIPAL` VARCHAR(128) CHARACTER SET utf8 COLLATE utf8_bin;
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/sentry/blob/e72e6eac/sentry-service/sentry-service-server/src/main/resources/003-SENTRY-380.oracle.sql
----------------------------------------------------------------------
diff --git a/sentry-service/sentry-service-server/src/main/resources/003-SENTRY-380.oracle.sql b/sentry-service/sentry-service-server/src/main/resources/003-SENTRY-380.oracle.sql
new file mode 100644
index 0000000..d07d20e
--- /dev/null
+++ b/sentry-service/sentry-service-server/src/main/resources/003-SENTRY-380.oracle.sql
@@ -0,0 +1,7 @@
+-- SENTRY-380
+ALTER TABLE "SENTRY_DB_PRIVILEGE" DROP COLUMN "GRANTOR_PRINCIPAL";
+ALTER TABLE "SENTRY_ROLE" DROP COLUMN "GRANTOR_PRINCIPAL";
+ALTER TABLE "SENTRY_GROUP" DROP COLUMN "GRANTOR_PRINCIPAL";
+
+ALTER TABLE "SENTRY_ROLE_DB_PRIVILEGE_MAP" ADD "GRANTOR_PRINCIPAL" VARCHAR2(128);
+ALTER TABLE "SENTRY_ROLE_GROUP_MAP" ADD "GRANTOR_PRINCIPAL" VARCHAR2(128);

http://git-wip-us.apache.org/repos/asf/sentry/blob/e72e6eac/sentry-service/sentry-service-server/src/main/resources/003-SENTRY-380.postgres.sql
----------------------------------------------------------------------
diff --git a/sentry-service/sentry-service-server/src/main/resources/003-SENTRY-380.postgres.sql b/sentry-service/sentry-service-server/src/main/resources/003-SENTRY-380.postgres.sql
new file mode 100644
index 0000000..95a2ef1
--- /dev/null
+++ b/sentry-service/sentry-service-server/src/main/resources/003-SENTRY-380.postgres.sql
@@ -0,0 +1,7 @@
+-- SENTRY-380
+ALTER TABLE "SENTRY_DB_PRIVILEGE" DROP "GRANTOR_PRINCIPAL";
+ALTER TABLE "SENTRY_ROLE" DROP "GRANTOR_PRINCIPAL";
+ALTER TABLE "SENTRY_GROUP" DROP "GRANTOR_PRINCIPAL";
+
+ALTER TABLE "SENTRY_ROLE_DB_PRIVILEGE_MAP" ADD "GRANTOR_PRINCIPAL" character varying(128);
+ALTER TABLE "SENTRY_ROLE_GROUP_MAP" ADD "GRANTOR_PRINCIPAL" character varying(128);

http://git-wip-us.apache.org/repos/asf/sentry/blob/e72e6eac/sentry-service/sentry-service-server/src/main/resources/004-SENTRY-74.derby.sql
----------------------------------------------------------------------
diff --git a/sentry-service/sentry-service-server/src/main/resources/004-SENTRY-74.derby.sql b/sentry-service/sentry-service-server/src/main/resources/004-SENTRY-74.derby.sql
new file mode 100644
index 0000000..da1f4d6
--- /dev/null
+++ b/sentry-service/sentry-service-server/src/main/resources/004-SENTRY-74.derby.sql
@@ -0,0 +1,4 @@
+-- SENTRY-74
+ALTER TABLE SENTRY_DB_PRIVILEGE ADD COLUMN COLUMN_NAME VARCHAR(4000) DEFAULT '__NULL__';
+DROP INDEX SENTRYPRIVILEGENAME;
+CREATE UNIQUE INDEX SENTRYPRIVILEGENAME ON SENTRY_DB_PRIVILEGE ("SERVER_NAME",DB_NAME,"TABLE_NAME","COLUMN_NAME",URI,"ACTION",WITH_GRANT_OPTION);

http://git-wip-us.apache.org/repos/asf/sentry/blob/e72e6eac/sentry-service/sentry-service-server/src/main/resources/004-SENTRY-74.mysql.sql
----------------------------------------------------------------------
diff --git a/sentry-service/sentry-service-server/src/main/resources/004-SENTRY-74.mysql.sql b/sentry-service/sentry-service-server/src/main/resources/004-SENTRY-74.mysql.sql
new file mode 100644
index 0000000..1419ca3
--- /dev/null
+++ b/sentry-service/sentry-service-server/src/main/resources/004-SENTRY-74.mysql.sql
@@ -0,0 +1,4 @@
+-- SENTRY-74
+ALTER TABLE `SENTRY_DB_PRIVILEGE` ADD `COLUMN_NAME` VARCHAR(128) DEFAULT '__NULL__';
+ALTER TABLE `SENTRY_DB_PRIVILEGE` DROP INDEX `SENTRY_DB_PRIV_PRIV_NAME_UNIQ`;
+ALTER TABLE `SENTRY_DB_PRIVILEGE` ADD UNIQUE `SENTRY_DB_PRIV_PRIV_NAME_UNIQ` (`SERVER_NAME`,`DB_NAME`,`TABLE_NAME`,`COLUMN_NAME`,`URI`(250),`ACTION`,`WITH_GRANT_OPTION`);

http://git-wip-us.apache.org/repos/asf/sentry/blob/e72e6eac/sentry-service/sentry-service-server/src/main/resources/004-SENTRY-74.oracle.sql
----------------------------------------------------------------------
diff --git a/sentry-service/sentry-service-server/src/main/resources/004-SENTRY-74.oracle.sql b/sentry-service/sentry-service-server/src/main/resources/004-SENTRY-74.oracle.sql
new file mode 100644
index 0000000..a70ae0a
--- /dev/null
+++ b/sentry-service/sentry-service-server/src/main/resources/004-SENTRY-74.oracle.sql
@@ -0,0 +1,4 @@
+-- SENTRY-74
+ALTER TABLE SENTRY_DB_PRIVILEGE ADD COLUMN_NAME VARCHAR2(128) DEFAULT '__NULL__';
+ALTER TABLE SENTRY_DB_PRIVILEGE DROP CONSTRAINT "SENTRY_DB_PRIV_PRIV_NAME_UNIQ" DROP INDEX;
+ALTER TABLE SENTRY_DB_PRIVILEGE ADD CONSTRAINT "SENTRY_DB_PRIV_PRIV_NAME_UNIQ" UNIQUE ("SERVER_NAME","DB_NAME","TABLE_NAME","COLUMN_NAME","URI","ACTION","WITH_GRANT_OPTION");

http://git-wip-us.apache.org/repos/asf/sentry/blob/e72e6eac/sentry-service/sentry-service-server/src/main/resources/004-SENTRY-74.postgres.sql
----------------------------------------------------------------------
diff --git a/sentry-service/sentry-service-server/src/main/resources/004-SENTRY-74.postgres.sql b/sentry-service/sentry-service-server/src/main/resources/004-SENTRY-74.postgres.sql
new file mode 100644
index 0000000..81bdfa3
--- /dev/null
+++ b/sentry-service/sentry-service-server/src/main/resources/004-SENTRY-74.postgres.sql
@@ -0,0 +1,4 @@
+-- SENTRY-74
+ALTER TABLE "SENTRY_DB_PRIVILEGE" ADD COLUMN "COLUMN_NAME" character varying(128) DEFAULT '__NULL__';
+ALTER TABLE "SENTRY_DB_PRIVILEGE" DROP CONSTRAINT "SENTRY_DB_PRIV_PRIV_NAME_UNIQ";
+ALTER TABLE "SENTRY_DB_PRIVILEGE" ADD CONSTRAINT "SENTRY_DB_PRIV_PRIV_NAME_UNIQ" UNIQUE ("SERVER_NAME","DB_NAME","TABLE_NAME","COLUMN_NAME","URI", "ACTION","WITH_GRANT_OPTION");

http://git-wip-us.apache.org/repos/asf/sentry/blob/e72e6eac/sentry-service/sentry-service-server/src/main/resources/005-SENTRY-398.derby.sql
----------------------------------------------------------------------
diff --git a/sentry-service/sentry-service-server/src/main/resources/005-SENTRY-398.derby.sql b/sentry-service/sentry-service-server/src/main/resources/005-SENTRY-398.derby.sql
new file mode 100644
index 0000000..c038b81
--- /dev/null
+++ b/sentry-service/sentry-service-server/src/main/resources/005-SENTRY-398.derby.sql
@@ -0,0 +1,43 @@
+-- Table SENTRY_GM_PRIVILEGE for classes [org.apache.sentry.provider.db.service.model.MSentryGMPrivilege]
+CREATE TABLE SENTRY_GM_PRIVILEGE
+(
+    GM_PRIVILEGE_ID BIGINT NOT NULL,
+    "ACTION" VARCHAR(40),
+    COMPONENT_NAME VARCHAR(400),
+    CREATE_TIME BIGINT NOT NULL,
+    WITH_GRANT_OPTION CHAR(1) NOT NULL DEFAULT 'N',
+    RESOURCE_NAME_0 VARCHAR(400) DEFAULT '__NULL__',
+    RESOURCE_NAME_1 VARCHAR(400) DEFAULT '__NULL__',
+    RESOURCE_NAME_2 VARCHAR(400) DEFAULT '__NULL__',
+    RESOURCE_NAME_3 VARCHAR(400) DEFAULT '__NULL__',
+    RESOURCE_TYPE_0 VARCHAR(400) DEFAULT '__NULL__',
+    RESOURCE_TYPE_1 VARCHAR(400) DEFAULT '__NULL__',
+    RESOURCE_TYPE_2 VARCHAR(400) DEFAULT '__NULL__',
+    RESOURCE_TYPE_3 VARCHAR(400) DEFAULT '__NULL__',
+    "SCOPE" VARCHAR(40),
+    SERVICE_NAME VARCHAR(400)
+);
+-- Primary key(GM_PRIVILEGE_ID)
+ALTER TABLE SENTRY_GM_PRIVILEGE ADD CONSTRAINT SENTRY_GM_PRIVILEGE_PK PRIMARY KEY (GM_PRIVILEGE_ID);
+
+-- Constraints for table SENTRY_GM_PRIVILEGE for class(es) [org.apache.sentry.provider.db.service.model.MSentryGMPrivilege]
+CREATE UNIQUE INDEX GM_PRIVILEGE_INDEX ON SENTRY_GM_PRIVILEGE (COMPONENT_NAME,SERVICE_NAME,RESOURCE_NAME_0,RESOURCE_TYPE_0,RESOURCE_NAME_1,RESOURCE_TYPE_1,RESOURCE_NAME_2,RESOURCE_TYPE_2,RESOURCE_NAME_3,RESOURCE_TYPE_3,"ACTION",WITH_GRANT_OPTION);
+
+-- Table SENTRY_ROLE_GM_PRIVILEGE_MAP for join relationship
+CREATE TABLE SENTRY_ROLE_GM_PRIVILEGE_MAP
+(
+    ROLE_ID BIGINT NOT NULL,
+    GM_PRIVILEGE_ID BIGINT NOT NULL
+);
+ALTER TABLE SENTRY_ROLE_GM_PRIVILEGE_MAP ADD CONSTRAINT SENTRY_ROLE_GM_PRIVILEGE_MAP_PK PRIMARY KEY (ROLE_ID,GM_PRIVILEGE_ID);
+
+-- Constraints for table SENTRY_ROLE_GM_PRIVILEGE_MAP
+CREATE INDEX SENTRY_ROLE_GM_PRIVILEGE_MAP_N50 ON SENTRY_ROLE_GM_PRIVILEGE_MAP (ROLE_ID);
+
+CREATE INDEX SENTRY_ROLE_GM_PRIVILEGE_MAP_N49 ON SENTRY_ROLE_GM_PRIVILEGE_MAP (GM_PRIVILEGE_ID);
+
+ALTER TABLE SENTRY_ROLE_GM_PRIVILEGE_MAP ADD CONSTRAINT SENTRY_ROLE_GM_PRIVILEGE_MAP_FK2 FOREIGN KEY (GM_PRIVILEGE_ID) REFERENCES SENTRY_GM_PRIVILEGE (GM_PRIVILEGE_ID);
+
+ALTER TABLE SENTRY_ROLE_GM_PRIVILEGE_MAP ADD CONSTRAINT SENTRY_ROLE_GM_PRIVILEGE_MAP_FK1 FOREIGN KEY (ROLE_ID) REFERENCES SENTRY_ROLE (ROLE_ID);
+
+

http://git-wip-us.apache.org/repos/asf/sentry/blob/e72e6eac/sentry-service/sentry-service-server/src/main/resources/005-SENTRY-398.mysql.sql
----------------------------------------------------------------------
diff --git a/sentry-service/sentry-service-server/src/main/resources/005-SENTRY-398.mysql.sql b/sentry-service/sentry-service-server/src/main/resources/005-SENTRY-398.mysql.sql
new file mode 100644
index 0000000..920737f
--- /dev/null
+++ b/sentry-service/sentry-service-server/src/main/resources/005-SENTRY-398.mysql.sql
@@ -0,0 +1,62 @@
+-- Table SENTRY_GM_PRIVILEGE for classes [org.apache.sentry.provider.db.service.model.MSentryGMPrivilege]
+CREATE TABLE `SENTRY_GM_PRIVILEGE`
+(
+    `GM_PRIVILEGE_ID` BIGINT NOT NULL,
+    `ACTION` VARCHAR(32) CHARACTER SET utf8 COLLATE utf8_bin NOT NULL,
+    `COMPONENT_NAME` VARCHAR(32) CHARACTER SET utf8 COLLATE utf8_bin NOT NULL,
+    `CREATE_TIME` BIGINT NOT NULL,
+    `WITH_GRANT_OPTION` CHAR(1) NOT NULL DEFAULT 'N',
+    `RESOURCE_NAME_0` VARCHAR(64) CHARACTER SET utf8 COLLATE utf8_bin DEFAULT '__NULL__',
+    `RESOURCE_NAME_1` VARCHAR(64) CHARACTER SET utf8 COLLATE utf8_bin DEFAULT '__NULL__',
+    `RESOURCE_NAME_2` VARCHAR(64) CHARACTER SET utf8 COLLATE utf8_bin DEFAULT '__NULL__',
+    `RESOURCE_NAME_3` VARCHAR(64) CHARACTER SET utf8 COLLATE utf8_bin DEFAULT '__NULL__',
+    `RESOURCE_TYPE_0` VARCHAR(64) CHARACTER SET utf8 COLLATE utf8_bin DEFAULT '__NULL__',
+    `RESOURCE_TYPE_1` VARCHAR(64) CHARACTER SET utf8 COLLATE utf8_bin DEFAULT '__NULL__',
+    `RESOURCE_TYPE_2` VARCHAR(64) CHARACTER SET utf8 COLLATE utf8_bin DEFAULT '__NULL__',
+    `RESOURCE_TYPE_3` VARCHAR(64) CHARACTER SET utf8 COLLATE utf8_bin DEFAULT '__NULL__',
+    `SCOPE` VARCHAR(128) CHARACTER SET utf8 COLLATE utf8_bin NOT NULL,
+    `SERVICE_NAME` VARCHAR(64) BINARY CHARACTER SET utf8 COLLATE utf8_bin NOT NULL
+) ENGINE=INNODB DEFAULT CHARSET=utf8;
+
+ALTER TABLE `SENTRY_GM_PRIVILEGE`
+  ADD CONSTRAINT `SENTRY_GM_PRIVILEGE_PK` PRIMARY KEY (`GM_PRIVILEGE_ID`);
+-- Constraints for table SENTRY_GM_PRIVILEGE for class(es) [org.apache.sentry.provider.db.service.model.MSentryGMPrivilege]
+ALTER TABLE `SENTRY_GM_PRIVILEGE`
+  ADD UNIQUE `GM_PRIVILEGE_UNIQUE` (`COMPONENT_NAME`,`SERVICE_NAME`,`RESOURCE_NAME_0`,`RESOURCE_TYPE_0`,`RESOURCE_NAME_1`,`RESOURCE_TYPE_1`,`RESOURCE_NAME_2`,`RESOURCE_TYPE_2`,`RESOURCE_NAME_3`,`RESOURCE_TYPE_3`,`ACTION`,`WITH_GRANT_OPTION`);
+
+ALTER TABLE `SENTRY_GM_PRIVILEGE`
+  ADD INDEX `SENTRY_GM_PRIV_COMP_IDX` (`COMPONENT_NAME`);
+
+ALTER TABLE `SENTRY_GM_PRIVILEGE`
+  ADD INDEX `SENTRY_GM_PRIV_SERV_IDX` (`SERVICE_NAME`);
+
+ALTER TABLE `SENTRY_GM_PRIVILEGE`
+  ADD INDEX `SENTRY_GM_PRIV_RES0_IDX` (`RESOURCE_NAME_0`,`RESOURCE_TYPE_0`);
+
+ALTER TABLE `SENTRY_GM_PRIVILEGE`
+  ADD INDEX `SENTRY_GM_PRIV_RES1_IDX` (`RESOURCE_NAME_1`,`RESOURCE_TYPE_1`);
+
+ALTER TABLE `SENTRY_GM_PRIVILEGE`
+  ADD INDEX `SENTRY_GM_PRIV_RES2_IDX` (`RESOURCE_NAME_2`,`RESOURCE_TYPE_2`);
+
+ALTER TABLE `SENTRY_GM_PRIVILEGE`
+  ADD INDEX `SENTRY_GM_PRIV_RES3_IDX` (`RESOURCE_NAME_3`,`RESOURCE_TYPE_3`);
+
+-- Table SENTRY_ROLE_GM_PRIVILEGE_MAP for join relationship
+CREATE TABLE `SENTRY_ROLE_GM_PRIVILEGE_MAP`
+(
+    `ROLE_ID` BIGINT NOT NULL,
+    `GM_PRIVILEGE_ID` BIGINT NOT NULL
+) ENGINE=INNODB DEFAULT CHARSET=utf8;
+
+ALTER TABLE `SENTRY_ROLE_GM_PRIVILEGE_MAP`
+  ADD CONSTRAINT `SENTRY_ROLE_GM_PRIVILEGE_MAP_PK` PRIMARY KEY (`ROLE_ID`,`GM_PRIVILEGE_ID`);
+
+-- Constraints for table SENTRY_ROLE_GM_PRIVILEGE_MAP
+ALTER TABLE `SENTRY_ROLE_GM_PRIVILEGE_MAP`
+  ADD CONSTRAINT `SEN_RLE_GM_PRV_MAP_SN_RLE_FK`
+  FOREIGN KEY (`ROLE_ID`) REFERENCES `SENTRY_ROLE`(`ROLE_ID`);
+
+ALTER TABLE `SENTRY_ROLE_GM_PRIVILEGE_MAP`
+  ADD CONSTRAINT `SEN_RL_GM_PRV_MAP_SN_DB_PRV_FK`
+  FOREIGN KEY (`GM_PRIVILEGE_ID`) REFERENCES `SENTRY_GM_PRIVILEGE`(`GM_PRIVILEGE_ID`);

http://git-wip-us.apache.org/repos/asf/sentry/blob/e72e6eac/sentry-service/sentry-service-server/src/main/resources/005-SENTRY-398.oracle.sql
----------------------------------------------------------------------
diff --git a/sentry-service/sentry-service-server/src/main/resources/005-SENTRY-398.oracle.sql b/sentry-service/sentry-service-server/src/main/resources/005-SENTRY-398.oracle.sql
new file mode 100644
index 0000000..412bc45
--- /dev/null
+++ b/sentry-service/sentry-service-server/src/main/resources/005-SENTRY-398.oracle.sql
@@ -0,0 +1,55 @@
+-- Table SENTRY_GM_PRIVILEGE for classes [org.apache.sentry.provider.db.service.model.MSentryGMPrivilege]
+CREATE TABLE "SENTRY_GM_PRIVILEGE" (
+  "GM_PRIVILEGE_ID" NUMBER NOT NULL,
+  "COMPONENT_NAME" VARCHAR2(32) NOT NULL,
+  "CREATE_TIME" NUMBER NOT NULL,
+  "WITH_GRANT_OPTION" CHAR(1) DEFAULT 'N' NOT NULL,
+  "RESOURCE_NAME_0" VARCHAR2(64) DEFAULT '__NULL__',
+  "RESOURCE_NAME_1" VARCHAR2(64) DEFAULT '__NULL__',
+  "RESOURCE_NAME_2" VARCHAR2(64) DEFAULT '__NULL__',
+  "RESOURCE_NAME_3" VARCHAR2(64) DEFAULT '__NULL__',
+  "RESOURCE_TYPE_0" VARCHAR2(64) DEFAULT '__NULL__',
+  "RESOURCE_TYPE_1" VARCHAR2(64) DEFAULT '__NULL__',
+  "RESOURCE_TYPE_2" VARCHAR2(64) DEFAULT '__NULL__',
+  "RESOURCE_TYPE_3" VARCHAR2(64) DEFAULT '__NULL__',
+  "ACTION" VARCHAR2(32) NOT NULL,
+  "SCOPE" VARCHAR2(128) NOT NULL,
+  "SERVICE_NAME" VARCHAR2(64) NOT NULL
+);
+
+ALTER TABLE "SENTRY_GM_PRIVILEGE"
+  ADD CONSTRAINT "SENTRY_GM_PRIV_PK" PRIMARY KEY ("GM_PRIVILEGE_ID");
+-- Constraints for table SENTRY_GM_PRIVILEGE for class(es) [org.apache.sentry.provider.db.service.model.MSentryGMPrivilege]
+ALTER TABLE "SENTRY_GM_PRIVILEGE"
+  ADD CONSTRAINT "SENTRY_GM_PRIV_PRIV_NAME_UNIQ" UNIQUE ("COMPONENT_NAME","SERVICE_NAME","RESOURCE_NAME_0","RESOURCE_NAME_1","RESOURCE_NAME_2",
+  "RESOURCE_NAME_3","RESOURCE_TYPE_0","RESOURCE_TYPE_1","RESOURCE_TYPE_2","RESOURCE_TYPE_3","ACTION","WITH_GRANT_OPTION");
+
+CREATE INDEX "SENTRY_GM_PRIV_COMP_IDX" ON "SENTRY_GM_PRIVILEGE" ("COMPONENT_NAME");
+
+CREATE INDEX "SENTRY_GM_PRIV_SERV_IDX" ON "SENTRY_GM_PRIVILEGE" ("SERVICE_NAME");
+
+CREATE INDEX "SENTRY_GM_PRIV_RES0_IDX" ON "SENTRY_GM_PRIVILEGE" ("RESOURCE_NAME_0","RESOURCE_TYPE_0");
+
+CREATE INDEX "SENTRY_GM_PRIV_RES1_IDX" ON "SENTRY_GM_PRIVILEGE" ("RESOURCE_NAME_1","RESOURCE_TYPE_1");
+
+CREATE INDEX "SENTRY_GM_PRIV_RES2_IDX" ON "SENTRY_GM_PRIVILEGE" ("RESOURCE_NAME_2","RESOURCE_TYPE_2");
+
+CREATE INDEX "SENTRY_GM_PRIV_RES3_IDX" ON "SENTRY_GM_PRIVILEGE" ("RESOURCE_NAME_3","RESOURCE_TYPE_3");
+
+-- Table SENTRY_ROLE_GM_PRIVILEGE_MAP for join relationship
+CREATE TABLE "SENTRY_ROLE_GM_PRIVILEGE_MAP" (
+  "ROLE_ID" NUMBER NOT NULL,
+  "GM_PRIVILEGE_ID" NUMBER NOT NULL
+);
+
+ALTER TABLE "SENTRY_ROLE_GM_PRIVILEGE_MAP"
+  ADD CONSTRAINT "SEN_RLE_GM_PRIV_MAP_PK" PRIMARY KEY ("ROLE_ID","GM_PRIVILEGE_ID");
+
+-- Constraints for table SENTRY_ROLE_GM_PRIVILEGE_MAP
+ALTER TABLE "SENTRY_ROLE_GM_PRIVILEGE_MAP"
+  ADD CONSTRAINT "SEN_RLE_GM_PRV_MAP_SN_RLE_FK"
+  FOREIGN KEY ("ROLE_ID") REFERENCES "SENTRY_ROLE"("ROLE_ID") INITIALLY DEFERRED;
+
+ALTER TABLE "SENTRY_ROLE_GM_PRIVILEGE_MAP"
+  ADD CONSTRAINT "SEN_RL_GM_PRV_MAP_SN_DB_PRV_FK"
+  FOREIGN KEY ("GM_PRIVILEGE_ID") REFERENCES "SENTRY_GM_PRIVILEGE"("GM_PRIVILEGE_ID") INITIALLY DEFERRED;

http://git-wip-us.apache.org/repos/asf/sentry/blob/e72e6eac/sentry-service/sentry-service-server/src/main/resources/005-SENTRY-398.postgres.sql
----------------------------------------------------------------------
diff --git a/sentry-service/sentry-service-server/src/main/resources/005-SENTRY-398.postgres.sql b/sentry-service/sentry-service-server/src/main/resources/005-SENTRY-398.postgres.sql
new file mode 100644
index 0000000..e9e1655
--- /dev/null
+++ b/sentry-service/sentry-service-server/src/main/resources/005-SENTRY-398.postgres.sql
@@ -0,0 +1,54 @@
+-- Table SENTRY_GM_PRIVILEGE for classes [org.apache.sentry.provider.db.service.model.MSentryGMPrivilege]
+CREATE TABLE "SENTRY_GM_PRIVILEGE" (
+  "GM_PRIVILEGE_ID" BIGINT NOT NULL,
+  "COMPONENT_NAME" character varying(32) NOT NULL,
+  "CREATE_TIME" BIGINT NOT NULL,
+  "WITH_GRANT_OPTION" CHAR(1) NOT NULL DEFAULT 'N',
+  "RESOURCE_NAME_0" character varying(64) DEFAULT '__NULL__',
+  "RESOURCE_NAME_1" character varying(64) DEFAULT '__NULL__',
+  "RESOURCE_NAME_2" character varying(64) DEFAULT '__NULL__',
+  "RESOURCE_NAME_3" character varying(64) DEFAULT '__NULL__',
+  "RESOURCE_TYPE_0" character varying(64) DEFAULT '__NULL__',
+  "RESOURCE_TYPE_1" character varying(64) DEFAULT '__NULL__',
+  "RESOURCE_TYPE_2" character varying(64) DEFAULT '__NULL__',
+  "RESOURCE_TYPE_3" character varying(64) DEFAULT '__NULL__',
+  "ACTION" character varying(32) NOT NULL,
+  "SCOPE" character varying(128) NOT NULL,
+  "SERVICE_NAME" character varying(64) NOT NULL
+);
+ALTER TABLE ONLY "SENTRY_GM_PRIVILEGE"
+  ADD CONSTRAINT "SENTRY_GM_PRIV_PK" PRIMARY KEY ("GM_PRIVILEGE_ID");
+-- Constraints for table SENTRY_GM_PRIVILEGE for class(es) [org.apache.sentry.provider.db.service.model.MSentryGMPrivilege]
+ALTER TABLE ONLY "SENTRY_GM_PRIVILEGE"
+  ADD CONSTRAINT "SENTRY_GM_PRIV_PRIV_NAME_UNIQ" UNIQUE ("COMPONENT_NAME","SERVICE_NAME","RESOURCE_NAME_0","RESOURCE_NAME_1","RESOURCE_NAME_2",
+  "RESOURCE_NAME_3","RESOURCE_TYPE_0","RESOURCE_TYPE_1","RESOURCE_TYPE_2","RESOURCE_TYPE_3","ACTION","WITH_GRANT_OPTION");
+
+CREATE INDEX "SENTRY_GM_PRIV_COMP_IDX" ON "SENTRY_GM_PRIVILEGE" USING btree ("COMPONENT_NAME");
+
+CREATE INDEX "SENTRY_GM_PRIV_SERV_IDX" ON "SENTRY_GM_PRIVILEGE" USING btree ("SERVICE_NAME");
+
+CREATE INDEX "SENTRY_GM_PRIV_RES0_IDX" ON "SENTRY_GM_PRIVILEGE" USING btree ("RESOURCE_NAME_0","RESOURCE_TYPE_0");
+
+CREATE INDEX "SENTRY_GM_PRIV_RES1_IDX" ON "SENTRY_GM_PRIVILEGE" USING btree ("RESOURCE_NAME_1","RESOURCE_TYPE_1");
+
+CREATE INDEX "SENTRY_GM_PRIV_RES2_IDX" ON "SENTRY_GM_PRIVILEGE" USING btree ("RESOURCE_NAME_2","RESOURCE_TYPE_2");
+
+CREATE INDEX "SENTRY_GM_PRIV_RES3_IDX" ON "SENTRY_GM_PRIVILEGE" USING btree ("RESOURCE_NAME_3","RESOURCE_TYPE_3");
+
+-- Table SENTRY_ROLE_GM_PRIVILEGE_MAP for join relationship
+CREATE TABLE "SENTRY_ROLE_GM_PRIVILEGE_MAP" (
+  "ROLE_ID" BIGINT NOT NULL,
+  "GM_PRIVILEGE_ID" BIGINT NOT NULL
+);
+
+ALTER TABLE "SENTRY_ROLE_GM_PRIVILEGE_MAP"
+  ADD CONSTRAINT "SENTRY_ROLE_GM_PRIVILEGE_MAP_PK" PRIMARY KEY ("ROLE_ID","GM_PRIVILEGE_ID");
+
+-- Constraints for table SENTRY_ROLE_GM_PRIVILEGE_MAP
+ALTER TABLE ONLY "SENTRY_ROLE_GM_PRIVILEGE_MAP"
+  ADD CONSTRAINT "SEN_RLE_GM_PRV_MAP_SN_RLE_FK"
+  FOREIGN KEY ("ROLE_ID") REFERENCES "SENTRY_ROLE"("ROLE_ID") DEFERRABLE;
+
+ALTER TABLE ONLY "SENTRY_ROLE_GM_PRIVILEGE_MAP"
+  ADD CONSTRAINT "SEN_RL_GM_PRV_MAP_SN_DB_PRV_FK"
+  FOREIGN KEY ("GM_PRIVILEGE_ID") REFERENCES "SENTRY_GM_PRIVILEGE"("GM_PRIVILEGE_ID") DEFERRABLE;

http://git-wip-us.apache.org/repos/asf/sentry/blob/e72e6eac/sentry-service/sentry-service-server/src/main/resources/006-SENTRY-711.derby.sql
----------------------------------------------------------------------
diff --git a/sentry-service/sentry-service-server/src/main/resources/006-SENTRY-711.derby.sql b/sentry-service/sentry-service-server/src/main/resources/006-SENTRY-711.derby.sql
new file mode 100644
index 0000000..807a62b
--- /dev/null
+++ b/sentry-service/sentry-service-server/src/main/resources/006-SENTRY-711.derby.sql
@@ -0,0 +1,27 @@
+CREATE TABLE SENTRY_USER
+(
+    USER_ID BIGINT NOT NULL generated always as identity (start with 1),
+    CREATE_TIME BIGINT NOT NULL,
+    USER_NAME VARCHAR(128)
+);
+
+ALTER TABLE SENTRY_USER ADD CONSTRAINT SENTRY_USER_PK PRIMARY KEY (USER_ID);
+
+CREATE UNIQUE INDEX SENTRYUSERNAME ON SENTRY_USER (USER_NAME);
+
+CREATE TABLE SENTRY_ROLE_USER_MAP
+(
+    USER_ID BIGINT NOT NULL,
+    ROLE_ID BIGINT NOT NULL,
+    GRANTOR_PRINCIPAL VARCHAR(128)
+);
+
+ALTER TABLE SENTRY_ROLE_USER_MAP ADD CONSTRAINT SENTRY_ROLE_USER_MAP_PK PRIMARY KEY (USER_ID,ROLE_ID);
+
+CREATE INDEX SENTRY_ROLE_USER_MAP_N49 ON SENTRY_ROLE_USER_MAP (USER_ID);
+
+CREATE INDEX SENTRY_ROLE_USER_MAP_N50 ON SENTRY_ROLE_USER_MAP (ROLE_ID);
+
+ALTER TABLE SENTRY_ROLE_USER_MAP ADD CONSTRAINT SENTRY_ROLE_USER_MAP_FK2 FOREIGN KEY (ROLE_ID) REFERENCES SENTRY_ROLE (ROLE_ID) ;
+
+ALTER TABLE SENTRY_ROLE_USER_MAP ADD CONSTRAINT SENTRY_ROLE_USER_MAP_FK1 FOREIGN KEY (USER_ID) REFERENCES SENTRY_USER (USER_ID) ;
\ No newline at end of file