This is an automated email from the ASF dual-hosted git repository.

prasanthj pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/hive.git


The following commit(s) were added to refs/heads/master by this push:
     new acec83f  HIVE-21254: Pre-upgrade tool should handle exceptions and 
skip db/tables (Prasanth Jayachandran reviewed by Jason Dere, Eugene Koifman, 
Ashutosh Chauhan)
acec83f is described below

commit acec83f3b7718250e6317ec5890a5ad7a014f10e
Author: Prasanth Jayachandran <prasan...@apache.org>
AuthorDate: Tue Feb 19 23:06:21 2019 -0800

    HIVE-21254: Pre-upgrade tool should handle exceptions and skip db/tables 
(Prasanth Jayachandran reviewed by Jason Dere, Eugene Koifman, Ashutosh Chauhan)
---
 .../hadoop/hive/upgrade/acid/PreUpgradeTool.java   |  93 ++++++++---
 .../hive/upgrade/acid/TestPreUpgradeTool.java      | 172 ++++++++++++++++-----
 2 files changed, 207 insertions(+), 58 deletions(-)

diff --git 
a/upgrade-acid/pre-upgrade/src/main/java/org/apache/hadoop/hive/upgrade/acid/PreUpgradeTool.java
 
b/upgrade-acid/pre-upgrade/src/main/java/org/apache/hadoop/hive/upgrade/acid/PreUpgradeTool.java
index 04782a6..0e3e3e2 100644
--- 
a/upgrade-acid/pre-upgrade/src/main/java/org/apache/hadoop/hive/upgrade/acid/PreUpgradeTool.java
+++ 
b/upgrade-acid/pre-upgrade/src/main/java/org/apache/hadoop/hive/upgrade/acid/PreUpgradeTool.java
@@ -25,6 +25,7 @@ import org.apache.commons.cli.HelpFormatter;
 import org.apache.commons.cli.Option;
 import org.apache.commons.cli.Options;
 import org.apache.commons.cli.ParseException;
+import org.apache.commons.lang3.exception.ExceptionUtils;
 import org.apache.hadoop.fs.ContentSummary;
 import org.apache.hadoop.fs.FileStatus;
 import org.apache.hadoop.fs.FileSystem;
@@ -54,6 +55,7 @@ import org.apache.hadoop.hive.ql.io.orc.OrcFile;
 import org.apache.hadoop.hive.ql.io.orc.Reader;
 import org.apache.hadoop.hive.serde.serdeConstants;
 import org.apache.hadoop.hive.shims.HadoopShims;
+import org.apache.hadoop.security.AccessControlException;
 import org.apache.hadoop.security.UserGroupInformation;
 import org.apache.hive.common.util.HiveVersionInfo;
 import org.apache.thrift.TException;
@@ -223,39 +225,74 @@ public class PreUpgradeTool {
     boolean isAcidEnabled = isAcidEnabled(conf);
     IMetaStoreClient hms = getHMS(conf);
     LOG.debug("Looking for databases");
-    List<String> databases = hms.getAllDatabases();//TException
-    LOG.debug("Found " + databases.size() + " databases to process");
+    String exceptionMsg = null;
+    List<String> databases;
     List<String> compactions = new ArrayList<>();
     final CompactionMetaInfo compactionMetaInfo = new CompactionMetaInfo();
     ValidTxnList txns = null;
     Hive db = null;
-    if(execute) {
-      db = Hive.get(conf);
-    }
+    try {
+      databases = hms.getAllDatabases();//TException
+      LOG.debug("Found " + databases.size() + " databases to process");
+      if (execute) {
+        db = Hive.get(conf);
+      }
 
-    for(String dbName : databases) {
-      List<String> tables = hms.getAllTables(dbName);
-      LOG.debug("found " + tables.size() + " tables in " + dbName);
-      for(String tableName : tables) {
-        Table t = hms.getTable(dbName, tableName);
-        LOG.debug("processing table " + Warehouse.getQualifiedName(t));
-        if(isAcidEnabled) {
-          //if acid is off, there can't be any acid tables - nothing to compact
-          if(txns == null) {
+      for (String dbName : databases) {
+        try {
+          List<String> tables = hms.getAllTables(dbName);
+          LOG.debug("found " + tables.size() + " tables in " + dbName);
+          for (String tableName : tables) {
+            try {
+              Table t = hms.getTable(dbName, tableName);
+              LOG.debug("processing table " + Warehouse.getQualifiedName(t));
+              if (isAcidEnabled) {
+                //if acid is off, there can't be any acid tables - nothing to 
compact
+                if (txns == null) {
           /*
            This API changed from 2.x to 3.0.  so this won't even compile with 
3.0
            but it doesn't need to since we only run this preUpgrade
           */
-            TxnStore txnHandler = TxnUtils.getTxnStore(conf);
-            txns = 
TxnUtils.createValidCompactTxnList(txnHandler.getOpenTxnsInfo());
+                  TxnStore txnHandler = TxnUtils.getTxnStore(conf);
+                  txns = 
TxnUtils.createValidCompactTxnList(txnHandler.getOpenTxnsInfo());
+                }
+                List<String> compactionCommands =
+                  getCompactionCommands(t, conf, hms, compactionMetaInfo, 
execute, db, txns);
+                compactions.addAll(compactionCommands);
+              }
+              /*todo: handle renaming files somewhere*/
+            } catch (Exception e) {
+              if (isAccessControlException(e)) {
+                // this could be external table with 0 permission for hive user
+                exceptionMsg = "Unable to access " + dbName + "." + tableName 
+ ". Pre-upgrade tool requires read-access " +
+                  "to databases and tables to determine if a table has to be 
compacted. " +
+                  "Set " + 
HiveConf.ConfVars.HIVE_METASTORE_AUTHORIZATION_AUTH_READS.varname + " config to 
" +
+                  "false to allow read-access to databases and tables and 
retry the pre-upgrade tool again..";
+              }
+              throw e;
+            }
           }
-          List<String> compactionCommands =
-              getCompactionCommands(t, conf, hms, compactionMetaInfo, execute, 
db, txns);
-          compactions.addAll(compactionCommands);
+        } catch (Exception e) {
+          if (exceptionMsg == null && isAccessControlException(e)) {
+            // we may not have access to read all tables from this db
+            exceptionMsg = "Unable to access " + dbName + ". Pre-upgrade tool 
requires read-access " +
+              "to databases and tables to determine if a table has to be 
compacted. " +
+              "Set " + 
HiveConf.ConfVars.HIVE_METASTORE_AUTHORIZATION_AUTH_READS.varname + " config to 
" +
+              "false to allow read-access to databases and tables and retry 
the pre-upgrade tool again..";
+          }
+          throw e;
         }
-        /*todo: handle renaming files somewhere*/
       }
+    } catch (Exception e) {
+      if (exceptionMsg == null && isAccessControlException(e)) {
+        exceptionMsg = "Unable to get databases. Pre-upgrade tool requires 
read-access " +
+          "to databases and tables to determine if a table has to be 
compacted. " +
+          "Set " + 
HiveConf.ConfVars.HIVE_METASTORE_AUTHORIZATION_AUTH_READS.varname + " config to 
" +
+          "false to allow read-access to databases and tables and retry the 
pre-upgrade tool again..";
+      }
+      throw new HiveException(exceptionMsg, e);
     }
+
     makeCompactionScript(compactions, scriptLocation, compactionMetaInfo);
 
     if(execute) {
@@ -306,6 +343,22 @@ public class PreUpgradeTool {
     }
   }
 
+  private boolean isAccessControlException(final Exception e) {
+    // hadoop security AccessControlException
+    if ((e instanceof MetaException && e.getCause() instanceof 
AccessControlException) ||
+      ExceptionUtils.getRootCause(e) instanceof AccessControlException) {
+      return true;
+    }
+
+    // java security AccessControlException
+    if ((e instanceof MetaException && e.getCause() instanceof 
java.security.AccessControlException) ||
+      ExceptionUtils.getRootCause(e) instanceof 
java.security.AccessControlException) {
+      return true;
+    }
+
+    // metastore in some cases sets the AccessControlException as message 
instead of wrapping the exception
+    return e instanceof MetaException && 
e.getMessage().startsWith("java.security.AccessControlException: Permission 
denied");
+  }
 
   /**
    * Generates a set compaction commands to run on pre Hive 3 cluster
diff --git 
a/upgrade-acid/pre-upgrade/src/test/java/org/apache/hadoop/hive/upgrade/acid/TestPreUpgradeTool.java
 
b/upgrade-acid/pre-upgrade/src/test/java/org/apache/hadoop/hive/upgrade/acid/TestPreUpgradeTool.java
index fe4b08b..90230d5d 100644
--- 
a/upgrade-acid/pre-upgrade/src/test/java/org/apache/hadoop/hive/upgrade/acid/TestPreUpgradeTool.java
+++ 
b/upgrade-acid/pre-upgrade/src/test/java/org/apache/hadoop/hive/upgrade/acid/TestPreUpgradeTool.java
@@ -34,6 +34,7 @@ import org.apache.hadoop.hive.ql.exec.mr.MapRedTask;
 import org.apache.hadoop.hive.ql.io.AcidUtils;
 import org.apache.hadoop.hive.ql.io.HiveInputFormat;
 import org.apache.hadoop.hive.ql.metadata.Hive;
+import org.apache.hadoop.hive.ql.metadata.HiveException;
 import org.apache.hadoop.hive.ql.metadata.Table;
 import org.apache.hadoop.hive.ql.processors.CommandProcessorResponse;
 import org.apache.hadoop.hive.ql.session.SessionState;
@@ -46,8 +47,13 @@ import org.junit.Test;
 import org.junit.rules.TestName;
 
 import java.io.File;
+import java.nio.file.Files;
+import java.nio.file.attribute.FileAttribute;
+import java.nio.file.attribute.PosixFilePermission;
+import java.nio.file.attribute.PosixFilePermissions;
 import java.util.ArrayList;
 import java.util.List;
+import java.util.Set;
 import java.util.concurrent.atomic.AtomicBoolean;
 
 public class TestPreUpgradeTool {
@@ -72,41 +78,45 @@ public class TestPreUpgradeTool {
     runStatementOnDriver("drop table if exists TFlat");
     runStatementOnDriver("drop table if exists TFlatText");
 
-    runStatementOnDriver("create table TAcid (a int, b int) clustered by (b) 
into 2 buckets stored as orc TBLPROPERTIES ('transactional'='true')");
-    runStatementOnDriver("create table TAcidPart (a int, b int) partitioned by 
(p tinyint)  clustered by (b) into 2 buckets  stored" +
-        " as orc TBLPROPERTIES ('transactional'='true')");
-    //on 2.x these are guaranteed to not be acid
-    runStatementOnDriver("create table TFlat (a int, b int) stored as orc 
tblproperties('transactional'='false')");
-    runStatementOnDriver("create table TFlatText (a int, b int) stored as 
textfile tblproperties('transactional'='false')");
+    try {
+      runStatementOnDriver(
+        "create table TAcid (a int, b int) clustered by (b) into 2 buckets 
stored as orc TBLPROPERTIES ('transactional'='true')");
+      runStatementOnDriver(
+        "create table TAcidPart (a int, b int) partitioned by (p tinyint)  
clustered by (b) into 2 buckets  stored" +
+          " as orc TBLPROPERTIES ('transactional'='true')");
+      //on 2.x these are guaranteed to not be acid
+      runStatementOnDriver("create table TFlat (a int, b int) stored as orc 
tblproperties('transactional'='false')");
+      runStatementOnDriver(
+        "create table TFlatText (a int, b int) stored as textfile 
tblproperties('transactional'='false')");
 
 
-    //this needs major compaction
-    runStatementOnDriver("insert into TAcid" + makeValuesClause(data));
-    runStatementOnDriver("update TAcid set a = 1 where b = 2");
+      //this needs major compaction
+      runStatementOnDriver("insert into TAcid" + makeValuesClause(data));
+      runStatementOnDriver("update TAcid set a = 1 where b = 2");
 
-    //this table needs to be converted to CRUD Acid
-    runStatementOnDriver("insert into TFlat" + makeValuesClause(data));
+      //this table needs to be converted to CRUD Acid
+      runStatementOnDriver("insert into TFlat" + makeValuesClause(data));
 
-    //this table needs to be converted to MM
-    runStatementOnDriver("insert into TFlatText" + makeValuesClause(data));
+      //this table needs to be converted to MM
+      runStatementOnDriver("insert into TFlatText" + makeValuesClause(data));
 
-    //p=10 needs major compaction
-    runStatementOnDriver("insert into TAcidPart partition(p)" + 
makeValuesClause(dataPart));
-    runStatementOnDriver("update TAcidPart set a = 1 where b = 2 and p = 10");
+      //p=10 needs major compaction
+      runStatementOnDriver("insert into TAcidPart partition(p)" + 
makeValuesClause(dataPart));
+      runStatementOnDriver("update TAcidPart set a = 1 where b = 2 and p = 
10");
 
-    //todo: add partitioned table that needs conversion to MM/Acid
+      //todo: add partitioned table that needs conversion to MM/Acid
 
-    //todo: rename files case
-    String[] args = {"-location", getTestDataDir(), "-execute"};
-    PreUpgradeTool.callback = new PreUpgradeTool.Callback() {
-      @Override
-      void onWaitForCompaction() throws MetaException {
-        runWorker(hiveConf);
-      }
-    };
-    PreUpgradeTool.pollIntervalMs = 1;
-    PreUpgradeTool.hiveConf = hiveConf;
-    PreUpgradeTool.main(args);
+      //todo: rename files case
+      String[] args = {"-location", getTestDataDir(), "-execute"};
+      PreUpgradeTool.callback = new PreUpgradeTool.Callback() {
+        @Override
+        void onWaitForCompaction() throws MetaException {
+          runWorker(hiveConf);
+        }
+      };
+      PreUpgradeTool.pollIntervalMs = 1;
+      PreUpgradeTool.hiveConf = hiveConf;
+      PreUpgradeTool.main(args);
     /*
     todo: parse
     
target/tmp/org.apache.hadoop.hive.upgrade.acid.TestPreUpgradeTool-1527286256834/compacts_1527286277624.sql
@@ -115,19 +125,99 @@ public class TestPreUpgradeTool {
 ALTER TABLE default.tacidpart PARTITION(p=10Y) COMPACT 'major';
     * */
 
-    TxnStore txnHandler = TxnUtils.getTxnStore(hiveConf);
+      TxnStore txnHandler = TxnUtils.getTxnStore(hiveConf);
+
+      ShowCompactResponse resp = txnHandler.showCompact(new 
ShowCompactRequest());
+      Assert.assertEquals(2, resp.getCompactsSize());
+      for (ShowCompactResponseElement e : resp.getCompacts()) {
+        Assert.assertEquals(e.toString(), TxnStore.CLEANING_RESPONSE, 
e.getState());
+      }
 
-    ShowCompactResponse resp = txnHandler.showCompact(new 
ShowCompactRequest());
-    Assert.assertEquals(2, resp.getCompactsSize());
-    for(ShowCompactResponseElement e : resp.getCompacts()) {
-      Assert.assertEquals(e.toString(), TxnStore.CLEANING_RESPONSE, 
e.getState());
+      String[] args2 = {"-location", getTestDataDir()};
+      PreUpgradeTool.main(args2);
+      /*
+       * todo: parse compacts script - make sure there is nothing in it
+       * */
+    } finally {
+      runStatementOnDriver("drop table if exists TAcid");
+      runStatementOnDriver("drop table if exists TAcidPart");
+      runStatementOnDriver("drop table if exists TFlat");
+      runStatementOnDriver("drop table if exists TFlatText");
     }
+  }
 
-    String[] args2 = {"-location", getTestDataDir()};
-    PreUpgradeTool.main(args2);
-    /*
-    * todo: parse compacts script - make sure there is nothing in it
-    * */
+  @Test
+  public void testUpgradeExternalTableNoReadPermissionForDatabase() throws 
Exception {
+    int[][] data = {{1,2}, {3, 4}, {5, 6}};
+
+    runStatementOnDriver("drop database if exists test cascade");
+    runStatementOnDriver("drop table if exists TExternal");
+
+    runStatementOnDriver("create database test");
+    runStatementOnDriver("create table test.TExternal (a int, b int) stored as 
orc tblproperties" +
+      "('transactional'='false')");
+
+    //this needs major compaction
+    runStatementOnDriver("insert into test.TExternal" + 
makeValuesClause(data));
+
+    String dbDir = getWarehouseDir() + "/test.db";
+    File dbPath = new File(dbDir);
+    try {
+      Set<PosixFilePermission> perms = 
PosixFilePermissions.fromString("-w-------");
+      Files.setPosixFilePermissions(dbPath.toPath(), perms);
+      String[] args = {"-location", getTestDataDir(), "-execute"};
+      PreUpgradeTool.pollIntervalMs = 1;
+      PreUpgradeTool.hiveConf = hiveConf;
+      Exception expected = null;
+      try {
+        PreUpgradeTool.main(args);
+      } catch (Exception e) {
+        expected = e;
+      }
+
+      Assert.assertNotNull(expected);
+      Assert.assertTrue(expected instanceof HiveException);
+      Assert.assertTrue(expected.getMessage().contains("Pre-upgrade tool 
requires " +
+        "read-access to databases and tables to determine if a table has to be 
compacted."));
+    } finally {
+      Set<PosixFilePermission> perms = 
PosixFilePermissions.fromString("rwxrw----");
+      Files.setPosixFilePermissions(dbPath.toPath(), perms);
+    }
+  }
+
+  @Test
+  public void testUpgradeExternalTableNoReadPermissionForTable() throws 
Exception {
+    int[][] data = {{1,2}, {3, 4}, {5, 6}};
+    runStatementOnDriver("drop table if exists TExternal");
+
+    runStatementOnDriver("create table TExternal (a int, b int) stored as orc 
tblproperties('transactional'='false')");
+
+    //this needs major compaction
+    runStatementOnDriver("insert into TExternal" + makeValuesClause(data));
+
+    String tableDir = getWarehouseDir() + "/texternal";
+    File tablePath = new File(tableDir);
+    try {
+      Set<PosixFilePermission> perms = 
PosixFilePermissions.fromString("-w-------");
+      Files.setPosixFilePermissions(tablePath.toPath(), perms);
+      String[] args = {"-location", getTestDataDir(), "-execute"};
+      PreUpgradeTool.pollIntervalMs = 1;
+      PreUpgradeTool.hiveConf = hiveConf;
+      Exception expected = null;
+      try {
+        PreUpgradeTool.main(args);
+      } catch (Exception e) {
+        expected = e;
+      }
+
+      Assert.assertNotNull(expected);
+      Assert.assertTrue(expected instanceof HiveException);
+      Assert.assertTrue(expected.getMessage().contains("Pre-upgrade tool 
requires" +
+        " read-access to databases and tables to determine if a table has to 
be compacted."));
+    } finally {
+      Set<PosixFilePermission> perms = 
PosixFilePermissions.fromString("rwxrw----");
+      Files.setPosixFilePermissions(tablePath.toPath(), perms);
+    }
   }
 
   private static void runWorker(HiveConf hiveConf) throws MetaException {
@@ -203,6 +293,12 @@ ALTER TABLE default.tacidpart PARTITION(p=10Y) COMPACT 
'major';
     hiveConf
         .setVar(HiveConf.ConfVars.HIVE_AUTHORIZATION_MANAGER,
             
"org.apache.hadoop.hive.ql.security.authorization.plugin.sqlstd.SQLStdHiveAuthorizerFactory");
+    hiveConf
+      .setVar(HiveConf.ConfVars.METASTORE_PRE_EVENT_LISTENERS,
+        
"org.apache.hadoop.hive.ql.security.authorization.AuthorizationPreEventListener");
+    hiveConf
+      .setVar(HiveConf.ConfVars.HIVE_METASTORE_AUTHORIZATION_MANAGER,
+        
"org.apache.hadoop.hive.ql.security.authorization.StorageBasedAuthorizationProvider");
     hiveConf.setBoolVar(HiveConf.ConfVars.MERGE_CARDINALITY_VIOLATION_CHECK, 
true);
     hiveConf.setBoolVar(HiveConf.ConfVars.HIVESTATSCOLAUTOGATHER, false);
     TxnDbUtil.setConfValues(hiveConf);

Reply via email to