parser.accepts("get-quota", "Retrieve some quota already enforced on the servers")
.withRequiredArg()
.describedAs("quota-type")
.ofType(String.class);
OptionSet options = parser.parse(args);
if(options.has("help")) {
printHelp(System.out, parser);
System.exit(0);
}
Set<String> missing = CmdUtils.missing(options, "url", "node");
if(missing.size() > 0) {
// Not the most elegant way to do this
// basically check if only "node" is missing for these set of
// options; all these can live without explicit node ids
if(!(missing.equals(ImmutableSet.of("node"))
&& (options.has("add-stores") || options.has("delete-store")
|| options.has("ro-metadata") || options.has("set-metadata")
|| options.has("update-store-defs") || options.has("set-metadata-pair")
|| options.has("get-metadata") || options.has("check-metadata"))
|| options.has("truncate") || options.has("clear-rebalancing-metadata")
|| options.has("async") || options.has("native-backup") || options.has("rollback")
|| options.has("verify-metadata-version") || options.has("reserve-memory")
|| options.has("purge-slops") || options.has("show-routing-plan")
|| options.has("query-key") || options.has("set-quota")
|| options.has("unset-quota") || options.has("get-quota"))) {
System.err.println("Missing required arguments: " + Joiner.on(", ").join(missing));
printHelp(System.err, parser);
System.exit(1);
}
}
try {
String url = (String) options.valueOf("url");
Integer nodeId = CmdUtils.valueOf(options, "node", -1);
int parallelism = CmdUtils.valueOf(options, "restore", 5);
Integer zoneId = CmdUtils.valueOf(options, "zone", -1);
AdminClient adminClient = new AdminClient(url,
new AdminClientConfig(),
new ClientConfig());
List<String> storeNames = null;
if(options.has("store") && options.has("stores")) {
throw new VoldemortException("Must not specify both --stores and --store options");
} else if(options.has("stores")) {
storeNames = (List<String>) options.valuesOf("stores");
} else if(options.has("store")) {
storeNames = Arrays.asList((String) options.valueOf("store"));
}
String outputDir = null;
if(options.has("outdir")) {
outputDir = (String) options.valueOf("outdir");
}
if(options.has("add-stores")) {
String storesXml = (String) options.valueOf("add-stores");
executeAddStores(adminClient, storesXml, nodeId);
} else if(options.has("async")) {
String asyncKey = (String) options.valueOf("async");
List<Integer> asyncIds = null;
if(options.hasArgument("async-id"))
asyncIds = (List<Integer>) options.valuesOf("async-id");
executeAsync(nodeId, adminClient, asyncKey, asyncIds);
} else if(options.has("check-metadata")) {
String metadataKey = (String) options.valueOf("check-metadata");
executeCheckMetadata(adminClient, metadataKey);
} else if(options.has("delete-partitions")) {
System.out.println("Starting delete-partitions");
List<Integer> partitionIdList = (List<Integer>) options.valuesOf("delete-partitions");
executeDeletePartitions(nodeId, adminClient, partitionIdList, storeNames);
System.out.println("Finished delete-partitions");
} else if(options.has("ro-metadata")) {
String type = (String) options.valueOf("ro-metadata");
executeROMetadata(nodeId, adminClient, storeNames, type);
} else if(options.has("reserve-memory")) {
if(!options.has("stores")) {
Utils.croak("Specify the list of stores to reserve memory");
}
long reserveMB = (Long) options.valueOf("reserve-memory");
adminClient.quotaMgmtOps.reserveMemory(nodeId, storeNames, reserveMB);
} else if(options.has("get-metadata")) {
String metadataKey = ALL_METADATA;
if(options.hasArgument("get-metadata")) {
metadataKey = (String) options.valueOf("get-metadata");
}
executeGetMetadata(nodeId, adminClient, metadataKey, outputDir);
} else if(options.has("mirror-from-url")) {
if(!options.has("mirror-node")) {
Utils.croak("Specify the mirror node to fetch from");
}
if(nodeId == -1) {
System.err.println("Cannot run mirroring without node id");
System.exit(1);
}
Integer mirrorNodeId = CmdUtils.valueOf(options, "mirror-node", -1);
if(mirrorNodeId == -1) {
System.err.println("Cannot run mirroring without mirror node id");
System.exit(1);
}
adminClient.restoreOps.mirrorData(nodeId,
mirrorNodeId,
(String) options.valueOf("mirror-from-url"),
storeNames);
} else if(options.has("clear-rebalancing-metadata")) {
executeClearRebalancing(nodeId, adminClient);
} else if(options.has("prune-job")) {
if(storeNames == null) {
Utils.croak("Must specify --stores to run the prune job");
}
executePruneJob(nodeId, adminClient, storeNames);
} else if(options.has("fetch-keys")) {
boolean useAscii = options.has("ascii");
System.out.println("Starting fetch keys");
List<Integer> partitionIdList = null;
if(options.hasArgument("fetch-keys"))
partitionIdList = (List<Integer>) options.valuesOf("fetch-keys");
executeFetchKeys(nodeId,
adminClient,
partitionIdList,
outputDir,
storeNames,
useAscii,
options.has("fetch-orphaned"));
} else if(options.has("repair-job")) {
executeRepairJob(nodeId, adminClient);
} else if(options.has("set-metadata-pair")) {
List<String> metadataKeyPair = (List<String>) options.valuesOf("set-metadata-pair");
if(metadataKeyPair.size() != 2) {
throw new VoldemortException("Missing set-metadata-pair keys (only two keys are needed and allowed)");
}
if(!options.has("set-metadata-value-pair")) {
throw new VoldemortException("Missing set-metadata-value-pair");
} else {
List<String> metadataValuePair = (List<String>) options.valuesOf("set-metadata-value-pair");
if(metadataValuePair.size() != 2) {
throw new VoldemortException("Missing set-metadata--value-pair values (only two values are needed and allowed)");
}
if(metadataKeyPair.contains(MetadataStore.CLUSTER_KEY)
&& metadataKeyPair.contains(MetadataStore.STORES_KEY)) {
ClusterMapper clusterMapper = new ClusterMapper();
StoreDefinitionsMapper storeDefsMapper = new StoreDefinitionsMapper();
// original metadata
Integer nodeIdToGetStoreXMLFrom = nodeId;
if(nodeId < 0) {
Collection<Node> nodes = adminClient.getAdminClientCluster().getNodes();
if(nodes.isEmpty()) {
throw new VoldemortException("No nodes in this cluster");
} else {
nodeIdToGetStoreXMLFrom = nodes.iterator().next().getId();
}
}
Versioned<String> storesXML = adminClient.metadataMgmtOps.getRemoteMetadata(nodeIdToGetStoreXMLFrom,
MetadataStore.STORES_KEY);
List<StoreDefinition> oldStoreDefs = storeDefsMapper.readStoreList(new StringReader(storesXML.getValue()));
String clusterXMLPath = metadataValuePair.get(metadataKeyPair.indexOf(MetadataStore.CLUSTER_KEY));
clusterXMLPath = clusterXMLPath.replace("~",
System.getProperty("user.home"));
if(!Utils.isReadableFile(clusterXMLPath))
throw new VoldemortException("Cluster xml file path incorrect");
Cluster cluster = clusterMapper.readCluster(new File(clusterXMLPath));
String storesXMLPath = metadataValuePair.get(metadataKeyPair.indexOf(MetadataStore.STORES_KEY));
storesXMLPath = storesXMLPath.replace("~", System.getProperty("user.home"));
if(!Utils.isReadableFile(storesXMLPath))
throw new VoldemortException("Stores definition xml file path incorrect");
List<StoreDefinition> newStoreDefs = storeDefsMapper.readStoreList(new File(storesXMLPath));
StoreDefinitionUtils.validateSchemasAsNeeded(newStoreDefs);
executeSetMetadataPair(nodeId,
adminClient,
MetadataStore.CLUSTER_KEY,
clusterMapper.writeCluster(cluster),
MetadataStore.STORES_KEY,
storeDefsMapper.writeStoreList(newStoreDefs));
executeUpdateMetadataVersionsOnStores(adminClient,
oldStoreDefs,
newStoreDefs);
} else {
throw new VoldemortException("set-metadata-pair keys should be <cluster.xml, stores.xml>");
}
}
} else if(options.has("set-metadata")) {
String metadataKey = (String) options.valueOf("set-metadata");
if(!options.has("set-metadata-value")) {
throw new VoldemortException("Missing set-metadata-value");
} else {
String metadataValue = (String) options.valueOf("set-metadata-value");
if(metadataKey.compareTo(MetadataStore.CLUSTER_KEY) == 0
|| metadataKey.compareTo(MetadataStore.REBALANCING_SOURCE_CLUSTER_XML) == 0) {
if(!Utils.isReadableFile(metadataValue))
throw new VoldemortException("Cluster xml file path incorrect");
ClusterMapper mapper = new ClusterMapper();
Cluster newCluster = mapper.readCluster(new File(metadataValue));
if(options.has("auto")) {
executeSetMetadata(nodeId,
adminClient,
metadataKey,
mapper.writeCluster(newCluster));
} else {
if(confirmMetadataUpdate(nodeId,
adminClient,
mapper.writeCluster(newCluster))) {
executeSetMetadata(nodeId,
adminClient,
metadataKey,
mapper.writeCluster(newCluster));
} else {
System.out.println("New metadata has not been set");
}
}
} else if(metadataKey.compareTo(MetadataStore.SERVER_STATE_KEY) == 0) {
VoldemortState newState = VoldemortState.valueOf(metadataValue);
executeSetMetadata(nodeId,
adminClient,
MetadataStore.SERVER_STATE_KEY,
newState.toString());
} else if(metadataKey.compareTo(MetadataStore.STORES_KEY) == 0) {
if(!Utils.isReadableFile(metadataValue))
throw new VoldemortException("Stores definition xml file path incorrect");
StoreDefinitionsMapper mapper = new StoreDefinitionsMapper();
List<StoreDefinition> newStoreDefs = mapper.readStoreList(new File(metadataValue));
StoreDefinitionUtils.validateSchemasAsNeeded(newStoreDefs);
// original metadata
Integer nodeIdToGetStoreXMLFrom = nodeId;
if(nodeId < 0) {
Collection<Node> nodes = adminClient.getAdminClientCluster().getNodes();
if(nodes.isEmpty()) {
throw new VoldemortException("No nodes in this cluster");
} else {
nodeIdToGetStoreXMLFrom = nodes.iterator().next().getId();
}
}
Versioned<String> storesXML = adminClient.metadataMgmtOps.getRemoteMetadata(nodeIdToGetStoreXMLFrom,
MetadataStore.STORES_KEY);
List<StoreDefinition> oldStoreDefs = mapper.readStoreList(new StringReader(storesXML.getValue()));
if(options.has("auto")) {
executeSetMetadata(nodeId,
adminClient,
MetadataStore.STORES_KEY,
mapper.writeStoreList(newStoreDefs));
executeUpdateMetadataVersionsOnStores(adminClient,
oldStoreDefs,
newStoreDefs);
} else {
if(confirmMetadataUpdate(nodeId, adminClient, storesXML.getValue())) {
executeSetMetadata(nodeId,
adminClient,
MetadataStore.STORES_KEY,
mapper.writeStoreList(newStoreDefs));
if(nodeId >= 0) {
System.err.println("WARNING: Metadata version update of stores goes to all servers, "
+ "although this set-metadata oprations only goes to node "
+ nodeId);
}
executeUpdateMetadataVersionsOnStores(adminClient,
oldStoreDefs,
newStoreDefs);
} else {
System.out.println("New metadata has not been set");
}
}
} else if(metadataKey.compareTo(MetadataStore.REBALANCING_STEAL_INFO) == 0) {
if(!Utils.isReadableFile(metadataValue))
throw new VoldemortException("Rebalancing steal info file path incorrect");
String rebalancingStealInfoJsonString = FileUtils.readFileToString(new File(metadataValue));
RebalancerState state = RebalancerState.create(rebalancingStealInfoJsonString);
executeSetMetadata(nodeId,
adminClient,
MetadataStore.REBALANCING_STEAL_INFO,
state.toJsonString());
} else {
throw new VoldemortException("Incorrect metadata key");
}
}
} else if(options.has("update-store-defs")) {
if(!options.has("update-store-value")) {
throw new VoldemortException("Missing update-store-value for update-store-defs");
} else {
String storesXmlValue = (String) options.valueOf("update-store-value");
if(!Utils.isReadableFile(storesXmlValue))
throw new VoldemortException("Stores definition xml file path incorrect");
StoreDefinitionsMapper mapper = new StoreDefinitionsMapper();
List<StoreDefinition> newStoreDefs = mapper.readStoreList(new File(storesXmlValue));
StoreDefinitionUtils.validateSchemasAsNeeded(newStoreDefs);
if(options.has("auto")) {
executeUpdateStoreDefinitions(nodeId, adminClient, newStoreDefs);
} else {
if(confirmMetadataUpdate(nodeId, adminClient, newStoreDefs)) {
executeUpdateStoreDefinitions(nodeId, adminClient, newStoreDefs);
if(nodeId >= 0) {
System.err.println("WARNING: Metadata version update of stores goes to all servers, "
+ "although this set-metadata oprations only goes to node "
+ nodeId);
}
} else {
System.out.println("New metadata has not been set");
}
}
System.out.println("The store definitions have been successfully updated.");
}
} else if(options.has("native-backup")) {
if(!options.has("backup-dir")) {
Utils.croak("A backup directory must be specified with backup-dir option");
}
String backupDir = (String) options.valueOf("backup-dir");
String storeName = (String) options.valueOf("native-backup");
int timeout = CmdUtils.valueOf(options, "backup-timeout", 30);
adminClient.storeMntOps.nativeBackup(nodeId,
storeName,
backupDir,
timeout,
options.has("backup-verify"),
options.has("backup-incremental"));
} else if(options.has("rollback")) {
if(!options.has("version")) {
Utils.croak("A read-only push version must be specified with rollback option");
}
String storeName = (String) options.valueOf("rollback");
long pushVersion = (Long) options.valueOf("version");
executeRollback(nodeId, storeName, pushVersion, adminClient);
} else if(options.has("query-key")) {
String key = (String) options.valueOf("query-key");
String keyFormat = (String) options.valueOf("query-key-format");
if(keyFormat == null) {
keyFormat = "hex";
}
if(!keyFormat.equals("hex") && !keyFormat.equals("readable")) {
throw new VoldemortException("--query-key-format must be hex or readable");
}
executeQueryKey(nodeId, adminClient, storeNames, key, keyFormat);
} else if(options.has("restore")) {
if(nodeId == -1) {
System.err.println("Cannot run restore without node id");
System.exit(1);
}
System.out.println("Starting restore");
adminClient.restoreOps.restoreDataFromReplications(nodeId, parallelism, zoneId);
System.out.println("Finished restore");
} else if(options.has("delete-store")) {
String storeName = (String) options.valueOf("delete-store");
executeDeleteStore(adminClient, storeName, nodeId);
} else if(options.has("truncate")) {
String storeName = (String) options.valueOf("truncate");
executeTruncateStore(nodeId, adminClient, storeName);
} else if(options.has("update-entries")) {
String inputDir = (String) options.valueOf("update-entries");
executeUpdateEntries(nodeId, adminClient, storeNames, inputDir);
} else if(options.has("fetch-entries")) {
boolean useAscii = options.has("ascii");
System.out.println("Starting fetch entries");
List<Integer> partitionIdList = null;
if(options.hasArgument("fetch-entries"))
partitionIdList = (List<Integer>) options.valuesOf("fetch-entries");
executeFetchEntries(nodeId,
adminClient,
partitionIdList,
outputDir,
storeNames,
useAscii,
options.has("fetch-orphaned"));
} else if(options.has("purge-slops")) {
List<Integer> nodesToPurge = null;
if(options.has("nodes")) {
nodesToPurge = (List<Integer>) options.valuesOf("nodes");
}
if(nodesToPurge == null && zoneId == -1 && storeNames == null) {
Utils.croak("Must specify atleast one of --nodes, --zone-id or --stores with --purge-slops");
}
executePurgeSlops(adminClient, nodesToPurge, zoneId, storeNames);
} else if(options.has("synchronize-metadata-version")) {
synchronizeMetadataVersion(adminClient, nodeId);
} else if(options.has("verify-metadata-version")) {
checkMetadataVersion(adminClient);
} else if(options.has("show-routing-plan")) {
if(!options.has("store")) {
Utils.croak("Must specify the store the keys belong to using --store ");
}
String storeName = (String) options.valueOf("store");
List<String> keysToRoute = (List<String>) options.valuesOf("show-routing-plan");
if(keysToRoute == null || keysToRoute.size() == 0) {
Utils.croak("Must specify comma separated keys list in hex format");
}
executeShowRoutingPlan(adminClient, storeName, keysToRoute);
} else if(options.has("set-quota")) {
String quotaType = (String) options.valueOf("set-quota");
Set<String> validQuotaTypes = QuotaUtils.validQuotaTypes();
if(!validQuotaTypes.contains(quotaType)) {
Utils.croak("Specify a valid quota type from :" + validQuotaTypes);
}
if(!options.has("store")) {
Utils.croak("Must specify the store to enforce the quota on. ");
}
if(!options.has("quota-value")) {
Utils.croak("Must specify the value of the quota being set");
}
String storeName = (String) options.valueOf("store");
String quotaValue = (String) options.valueOf("quota-value");
executeSetQuota(adminClient, storeName, quotaType, quotaValue);
} else if(options.has("unset-quota")) {
String quotaType = (String) options.valueOf("unset-quota");
Set<String> validQuotaTypes = QuotaUtils.validQuotaTypes();
if(!validQuotaTypes.contains(quotaType)) {
Utils.croak("Specify a valid quota type from :" + validQuotaTypes);
}
if(!options.has("store")) {
Utils.croak("Must specify the store to enforce the quota on. ");
}
String storeName = (String) options.valueOf("store");
executeUnsetQuota(adminClient, storeName, quotaType);
} else if(options.has("get-quota")) {
String quotaType = (String) options.valueOf("get-quota");
Set<String> validQuotaTypes = QuotaUtils.validQuotaTypes();
if(!validQuotaTypes.contains(quotaType)) {
Utils.croak("Specify a valid quota type from :" + validQuotaTypes);
}
if(!options.has("store")) {
Utils.croak("Must specify the store to enforce the quota on. ");
}
String storeName = (String) options.valueOf("store");
executeGetQuota(adminClient, storeName, quotaType);
} else {
Utils.croak("At least one of (delete-partitions, restore, add-node, fetch-entries, "
+ "fetch-keys, add-stores, delete-store, update-entries, get-metadata, ro-metadata, "