Skip to content

Commit b5d69a1

Browse files
committed
Added feature to transfer table owner detail with -to.
1 parent 3117657 commit b5d69a1

File tree

11 files changed

+126
-3
lines changed

11 files changed

+126
-3
lines changed

README.md

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -758,7 +758,7 @@ After running the `setup.sh` script, `hms-mirror` will be available in the `$PAT
758758
### Assumptions
759759
760760
1. This process will only 'migrate' EXTERNAL and MANAGED (non-ACID/Transactional) table METADATA (not data, except with [SQL](#sql) and [EXPORT_IMPORT](#export-import) ).
761-
2. MANAGED tables replicated to the **RIGHT** cluster will be converted to "EXTERNAL" tables for the 'metadata' stage. They will be tagged as 'legacy managed' in the **RIGHT** cluster and will NOT be assigned the `external.table.purge=true` flag, yet. Once the table's data has been migrated, the table will be adjusted to be purgeable via `external.table.purge=true` to match the classic `MANAGED` table behavior.
761+
2. MANAGED tables replicated to the **RIGHT** cluster will be converted to "EXTERNAL" tables for the 'metadata' stage. They will be tagged as 'legacy managed' in the **RIGHT** cluster. They will be assigned the `external.table.purge=true` flag, to continue the behaviors of the legacy managed tables.
762762
1. The **RIGHT** cluster has 'line of sight' to the **LEFT** cluster.
763763
2. The **RIGHT** cluster has been configured to access the **LEFT** cluster storage. See [link clusters](#linking-clusters-storage-layers). This is the same configuration required to support `distcp` from the **RIGHT** cluster to the **LEFT** cluster.
764764
3. The movement of metadata/data is from the **LEFT** cluster to the **RIGHT** cluster.
@@ -779,7 +779,7 @@ When you do need to move data, `hms-mirror` create a workbook of 'source' and 't
779779
780780
```
781781
usage: hms-mirror <options>
782-
version:1.5.3.1.0-SNAPSHOT
782+
version: *******
783783
Hive Metastore Migration Utility
784784
-accept,--accept Accept ALL confirmations
785785
and silence prompts
@@ -1059,6 +1059,22 @@ Hive Metastore Migration Utility
10591059
double-quote the
10601060
expression on the
10611061
commandline.
1062+
-to,--transfer-ownership If available (supported)
1063+
on LEFT cluster, extract
1064+
and transfer the tables
1065+
owner to the RIGHT
1066+
cluster. Note: This will
1067+
make an 'exta' SQL call
1068+
on the LEFT cluster to
1069+
determine the ownership.
1070+
This won't be supported
1071+
on CDH 5 and some other
1072+
legacy Hive platforms.
1073+
Beware the cost of this
1074+
extra call for EVERY
1075+
table, as it may slow
1076+
down the process for a
1077+
large volume of tables.
10621078
-v,--views-only Process VIEWs ONLY
10631079
-wd,--warehouse-directory <warehouse-path> The warehouse directory
10641080
path. Should not include

pom.xml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@
2222

2323
<groupId>com.cloudera.utils.hadoop</groupId>
2424
<artifactId>hms-mirror</artifactId>
25-
<version>1.5.3.1.3-SNAPSHOT</version>
25+
<version>1.5.3.2.0-SNAPSHOT</version>
2626
<name>hms-mirror</name>
2727

2828
<url>https://github.com/dstreev/hms_mirror</url>

src/main/java/com/cloudera/utils/hadoop/hms/Mirror.java

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -396,6 +396,10 @@ public long init(String[] args) {
396396
config.setCopyAvroSchemaUrls(Boolean.TRUE);
397397
}
398398

399+
if (cmd.hasOption("to")) {
400+
config.setTransferOwnership(Boolean.TRUE);
401+
}
402+
399403
String dataStrategyStr = cmd.getOptionValue("d");
400404
// default is SCHEMA_ONLY
401405
if (dataStrategyStr != null) {
@@ -1381,6 +1385,15 @@ private Options getOptions() {
13811385
asmOption.setRequired(Boolean.FALSE);
13821386
options.addOption(asmOption);
13831387

1388+
Option transferOwnershipOption = new Option("to", "transfer-ownership", false,
1389+
"If available (supported) on LEFT cluster, extract and transfer the tables owner to the " +
1390+
"RIGHT cluster. Note: This will make an 'exta' SQL call on the LEFT cluster to determine " +
1391+
"the ownership. This won't be supported on CDH 5 and some other legacy Hive platforms. " +
1392+
"Beware the cost of this extra call for EVERY table, as it may slow down the process for " +
1393+
"a large volume of tables.");
1394+
transferOwnershipOption.setRequired(Boolean.FALSE);
1395+
options.addOption(transferOwnershipOption);
1396+
13841397
OptionGroup dbAdjustOptionGroup = new OptionGroup();
13851398

13861399
Option dbPrefixOption = new Option("dbp", "db-prefix", true,

src/main/java/com/cloudera/utils/hadoop/hms/mirror/Cluster.java

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -287,6 +287,7 @@ public void getTables(Config config, DBMirror dbMirror) throws SQLException {
287287
}
288288
}
289289

290+
290291
public void getTableDefinition(Config config, String database, TableMirror tableMirror) throws SQLException {
291292
// The connection should already be in the database;
292293
Connection conn = null;
@@ -358,6 +359,33 @@ public void getTableDefinition(Config config, String database, TableMirror table
358359
}
359360
}
360361

362+
if (config.getTransferOwnership()) {
363+
try {
364+
String ownerStatement = MessageFormat.format(MirrorConf.SHOW_TABLE_EXTENDED, tableMirror.getName());
365+
resultSet = stmt.executeQuery(ownerStatement);
366+
String owner = null;
367+
while (resultSet.next()) {
368+
369+
if (resultSet.getString(1).startsWith("owner")) {
370+
String[] ownerLine = resultSet.getString(1).split(":");
371+
try {
372+
owner = ownerLine[1];
373+
} catch (Throwable t) {
374+
// Parsing issue.
375+
LOG.error("Couldn't parse 'owner' value from: " + resultSet.getString(1) +
376+
" for table: " + tableMirror.getDbName() + "." + tableMirror.getName());
377+
}
378+
break;
379+
}
380+
}
381+
if (owner != null) {
382+
et.setOwner(owner);
383+
}
384+
} catch (SQLException sed) {
385+
// Failed to gather owner details.
386+
}
387+
}
388+
361389
LOG.debug(getEnvironment() + ":" + database + "." + et.getName() +
362390
": Loaded Table Definition");
363391
} catch (SQLException throwables) {

src/main/java/com/cloudera/utils/hadoop/hms/mirror/Config.java

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -140,6 +140,7 @@ public class Config {
140140
private String tblExcludeRegEx = null;
141141

142142
private TransferConfig transfer = new TransferConfig();
143+
private Boolean transferOwnership = Boolean.FALSE;
143144
@JsonIgnore
144145
private ScheduledExecutorService transferThreadPool;
145146
@JsonIgnore
@@ -1066,6 +1067,14 @@ public void setTransfer(TransferConfig transfer) {
10661067
this.transfer = transfer;
10671068
}
10681069

1070+
public Boolean getTransferOwnership() {
1071+
return transferOwnership;
1072+
}
1073+
1074+
public void setTransferOwnership(Boolean transferOwnership) {
1075+
this.transferOwnership = transferOwnership;
1076+
}
1077+
10691078
public Map<Environment, Cluster> getClusters() {
10701079
return clusters;
10711080
}

src/main/java/com/cloudera/utils/hadoop/hms/mirror/EnvironmentTable.java

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,8 @@ public class EnvironmentTable {
2727
private CreateStrategy createStrategy = CreateStrategy.NOTHING;
2828
private List<String> definition = new ArrayList<String>();
2929
private final Boolean partitioned = Boolean.FALSE;
30+
private String owner = null;
31+
3032
private List<String> partitions = new ArrayList<String>();
3133
private List<String> actions = new ArrayList<String>();
3234
private Map<String, String> addProperties = new TreeMap<String, String>();
@@ -88,6 +90,14 @@ public List<String> getPartitions() {
8890
return partitions;
8991
}
9092

93+
public String getOwner() {
94+
return owner;
95+
}
96+
97+
public void setOwner(String owner) {
98+
this.owner = owner;
99+
}
100+
91101
public void setPartitions(List<String> partitions) {
92102
this.partitions = partitions;
93103
}

src/main/java/com/cloudera/utils/hadoop/hms/mirror/MirrorConf.java

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,9 @@ public class MirrorConf {
2121

2222
public static final String SHOW_TABLES = "SHOW TABLES";
2323
public static final String SHOW_VIEWS = "SHOW VIEWS";
24+
public static final String SHOW_TABLE_EXTENDED = "SHOW TABLE EXTENDED LIKE {0}";
2425
public static final String SHOW_CREATE_TABLE = "SHOW CREATE TABLE {0}";
26+
public static final String DESCRIBE_FORMATTED_TABLE = "DESCRIBE FORMATTED {0}";
2527
public static final String SHOW_PARTITIONS = "SHOW PARTITIONS {0}.{1}";
2628
public static final String MSCK_REPAIR_TABLE = "MSCK REPAIR TABLE {0}";
2729
public static final String MSCK_REPAIR_TABLE_DESC = "MSCK Repair Table";
@@ -55,6 +57,8 @@ public class MirrorConf {
5557
public static final String DROP_VIEW = "DROP VIEW IF EXISTS {0}";
5658
public static final String RENAME_TABLE_DESC = "Rename table";
5759
public static final String RENAME_TABLE = " ALTER TABLE {0} RENAME TO {1}";
60+
public static final String SET_OWNER_DESC = "Set table owner";
61+
public static final String SET_OWNER = "ALTER TABLE {0} SET OWNER USER {1}";
5862
public static final String EXPORT_TABLE =
5963
"EXPORT TABLE {0} TO \"{1}\"";
6064
public static final String IMPORT_EXTERNAL_TABLE =

src/main/java/com/cloudera/utils/hadoop/hms/mirror/TableMirror.java

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -972,6 +972,10 @@ public Boolean buildoutDUMPSql(Config config, DBMirror dbMirror) {
972972

973973
createTbl = this.getCreateStatement(Environment.LEFT);
974974
let.addSql(TableUtils.CREATE_DESC, createTbl);
975+
if (!config.getCluster(Environment.LEFT).getLegacyHive() && config.getTransferOwnership() && let.getOwner() != null) {
976+
String ownerSql = MessageFormat.format(MirrorConf.SET_OWNER, let.getName(), let.getOwner());
977+
let.addSql(MirrorConf.SET_OWNER_DESC, ownerSql);
978+
}
975979

976980
// If partitioned, !ACID, repair
977981
if (let.getPartitioned() && !TableUtils.isACID(let) &&
@@ -1028,6 +1032,10 @@ public Boolean buildoutSCHEMA_ONLYSql(Config config, DBMirror dbMirror) {
10281032
ret.addSql(TableUtils.USE_DESC, useDb);
10291033
String createStmt2 = getCreateStatement(Environment.RIGHT);
10301034
ret.addSql(TableUtils.CREATE_DESC, createStmt2);
1035+
if (!config.getCluster(Environment.RIGHT).getLegacyHive() && config.getTransferOwnership() && let.getOwner() != null) {
1036+
String ownerSql = MessageFormat.format(MirrorConf.SET_OWNER, ret.getName(), let.getOwner());
1037+
ret.addSql(MirrorConf.SET_OWNER_DESC, ownerSql);
1038+
}
10311039
break;
10321040
}
10331041

@@ -1154,6 +1162,10 @@ public Boolean buildoutSQLSql(Config config, DBMirror dbMirror) {
11541162
case CREATE:
11551163
String createStmt2 = getCreateStatement(Environment.RIGHT);
11561164
ret.addSql(TableUtils.CREATE_DESC, createStmt2);
1165+
if (!config.getCluster(Environment.RIGHT).getLegacyHive() && config.getTransferOwnership() && let.getOwner() != null) {
1166+
String ownerSql = MessageFormat.format(MirrorConf.SET_OWNER, ret.getName(), let.getOwner());
1167+
ret.addSql(MirrorConf.SET_OWNER_DESC, ownerSql);
1168+
}
11571169
break;
11581170
}
11591171

@@ -1189,6 +1201,10 @@ public Boolean buildoutSTORAGEMIGRATIONSql(Config config, DBMirror dbMirror) {
11891201
// Create table with New Location
11901202
String createStmt2 = getCreateStatement(Environment.RIGHT);
11911203
let.addSql(TableUtils.CREATE_DESC, createStmt2);
1204+
if (!config.getCluster(Environment.LEFT).getLegacyHive() && config.getTransferOwnership() && let.getOwner() != null) {
1205+
String ownerSql = MessageFormat.format(MirrorConf.SET_OWNER, let.getName(), let.getOwner());
1206+
let.addSql(MirrorConf.SET_OWNER_DESC, ownerSql);
1207+
}
11921208

11931209
// Drop Renamed Table.
11941210
String dropOriginalTable = MessageFormat.format(MirrorConf.DROP_TABLE, let.getName());
@@ -1266,6 +1282,10 @@ public Boolean buildoutIntermediateSql(Config config, DBMirror dbMirror) {
12661282
case CREATE:
12671283
String createStmt2 = getCreateStatement(Environment.RIGHT);
12681284
ret.addSql(TableUtils.CREATE_DESC, createStmt2);
1285+
if (!config.getCluster(Environment.RIGHT).getLegacyHive() && config.getTransferOwnership() && let.getOwner() != null) {
1286+
String ownerSql = MessageFormat.format(MirrorConf.SET_OWNER, ret.getName(), let.getOwner());
1287+
ret.addSql(MirrorConf.SET_OWNER_DESC, ownerSql);
1288+
}
12691289
if (let.getPartitioned()) {
12701290
if (config.getTransfer().getCommonStorage() != null) {
12711291
if (!TableUtils.isACID(let) || (TableUtils.isACID(let) && config.getMigrateACID().isDowngrade())) {

src/test/java/com/cloudera/utils/hadoop/hms/LegacySchemaMigrationTest.java

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -219,6 +219,26 @@ public void test_so_leg() {
219219
assertTrue("Return Code Failure: " + rtn + " doesn't match: " + check, rtn == check);
220220
}
221221

222+
@Test
223+
public void test_so_owner_leg() {
224+
String nameofCurrMethod = new Throwable()
225+
.getStackTrace()[0]
226+
.getMethodName();
227+
228+
String outputDir = outputDirBase + nameofCurrMethod;
229+
230+
String[] args = new String[]{"-db", DataState.getInstance().getWorking_db(),
231+
"-to",
232+
"-o", outputDir, "-cfg", DataState.getInstance().getConfiguration()};
233+
args = toExecute(args, execArgs, Boolean.FALSE);
234+
235+
long rtn = 0;
236+
Mirror mirror = new Mirror();
237+
rtn = mirror.go(args);
238+
int check = 0;
239+
assertTrue("Return Code Failure: " + rtn + " doesn't match: " + check, rtn == check);
240+
}
241+
222242
@Test
223243
public void test_so_distcp_leg() {
224244
String nameofCurrMethod = new Throwable()

src/test/java/com/cloudera/utils/hadoop/hms/MirrorTestBase.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,7 @@ public Boolean dataSetup01() {
9090
dataset = getDataset(2, 2000, null);
9191
}
9292
build_n_populate(CREATE_EXTERNAL_TBL, TBL_INSERT, dataset, leftSql,new String[]{"ext_part_02"});
93+
build_n_populate(CREATE_LEGACY_MNGD_TBL, TBL_INSERT, dataset, leftSql,new String[]{"legacy_mngd_01"});
9394

9495
Mirror cfgMirror = new Mirror();
9596
long rtn = cfgMirror.setupSqlLeft(args, leftSql);

0 commit comments

Comments
 (0)