HDFS-11162. Block Storage: add command line tool. Contributed by Chen Liang.
This commit is contained in:
parent
6b5dee9c38
commit
a9f92c4666
|
@ -25,13 +25,19 @@ public final class CBlockConfigKeys {
|
||||||
"dfs.cblock.enabled";
|
"dfs.cblock.enabled";
|
||||||
public static final String DFS_CBLOCK_SERVICERPC_ADDRESS_KEY =
|
public static final String DFS_CBLOCK_SERVICERPC_ADDRESS_KEY =
|
||||||
"dfs.cblock.servicerpc-address";
|
"dfs.cblock.servicerpc-address";
|
||||||
public static final int DFS_CBLOCK_RPCSERVICE_PORT_DEFAULT =
|
public static final String DFS_CBLOCK_SERVICERPC_PORT_KEY =
|
||||||
|
"dfs.cblock.servicerpc.port";
|
||||||
|
public static final int DFS_CBLOCK_SERVICERPC_PORT_DEFAULT =
|
||||||
9810;
|
9810;
|
||||||
|
public static final String DFS_CBLOCK_SERVICERPC_HOSTNAME_KEY =
|
||||||
|
"dfs.cblock.servicerpc.hostname";
|
||||||
|
public static final String DFS_CBLOCK_SERVICERPC_HOSTNAME_DEFAULT =
|
||||||
|
"0.0.0.0";
|
||||||
public static final String DFS_CBLOCK_RPCSERVICE_IP_DEFAULT =
|
public static final String DFS_CBLOCK_RPCSERVICE_IP_DEFAULT =
|
||||||
"0.0.0.0";
|
"0.0.0.0";
|
||||||
public static final String DFS_CBLOCK_SERVICERPC_ADDRESS_DEFAULT =
|
public static final String DFS_CBLOCK_SERVICERPC_ADDRESS_DEFAULT =
|
||||||
DFS_CBLOCK_RPCSERVICE_IP_DEFAULT
|
DFS_CBLOCK_SERVICERPC_HOSTNAME_DEFAULT
|
||||||
+ ":" + DFS_CBLOCK_RPCSERVICE_PORT_DEFAULT;
|
+ ":" + DFS_CBLOCK_SERVICERPC_PORT_DEFAULT;
|
||||||
|
|
||||||
public static final String DFS_CBLOCK_JSCSIRPC_ADDRESS_KEY =
|
public static final String DFS_CBLOCK_JSCSIRPC_ADDRESS_KEY =
|
||||||
"dfs.cblock.jscsi-address";
|
"dfs.cblock.jscsi-address";
|
||||||
|
|
|
@ -0,0 +1,284 @@
|
||||||
|
/*
|
||||||
|
* 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.hadoop.cblock.cli;
|
||||||
|
|
||||||
|
import org.apache.commons.cli.BasicParser;
|
||||||
|
import org.apache.commons.cli.CommandLine;
|
||||||
|
import org.apache.commons.cli.HelpFormatter;
|
||||||
|
import org.apache.commons.cli.Option;
|
||||||
|
import org.apache.commons.cli.OptionBuilder;
|
||||||
|
import org.apache.commons.cli.Options;
|
||||||
|
import org.apache.commons.cli.ParseException;
|
||||||
|
import org.apache.hadoop.cblock.client.CBlockVolumeClient;
|
||||||
|
import org.apache.hadoop.cblock.meta.VolumeInfo;
|
||||||
|
import org.apache.hadoop.cblock.protocolPB.CBlockServiceProtocolPB;
|
||||||
|
import org.apache.hadoop.conf.Configured;
|
||||||
|
import org.apache.hadoop.ipc.ProtobufRpcEngine;
|
||||||
|
import org.apache.hadoop.ipc.RPC;
|
||||||
|
import org.apache.hadoop.ozone.OzoneConfiguration;
|
||||||
|
import org.apache.hadoop.util.Tool;
|
||||||
|
import org.apache.hadoop.util.ToolRunner;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.PrintStream;
|
||||||
|
import java.net.InetSocketAddress;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.regex.Matcher;
|
||||||
|
import java.util.regex.Pattern;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The command line tool class.
|
||||||
|
*/
|
||||||
|
public class CBlockCli extends Configured implements Tool {
|
||||||
|
|
||||||
|
private static final String CREATE_VOLUME = "createVolume";
|
||||||
|
|
||||||
|
private static final String DELETE_VOLUME = "deleteVolume";
|
||||||
|
|
||||||
|
private static final String INFO_VOLUME = "infoVolume";
|
||||||
|
|
||||||
|
private static final String LIST_VOLUME = "listVolume";
|
||||||
|
|
||||||
|
private static final String SERVER_ADDR = "serverAddr";
|
||||||
|
|
||||||
|
private static final String HELP = "help";
|
||||||
|
|
||||||
|
private static final Logger LOG =
|
||||||
|
LoggerFactory.getLogger(CBlockCli.class);
|
||||||
|
private OzoneConfiguration conf;
|
||||||
|
|
||||||
|
private PrintStream printStream;
|
||||||
|
|
||||||
|
private Options options;
|
||||||
|
|
||||||
|
private BasicParser parser;
|
||||||
|
|
||||||
|
private CBlockVolumeClient localProxy;
|
||||||
|
|
||||||
|
public CBlockCli(OzoneConfiguration conf, PrintStream printStream)
|
||||||
|
throws IOException {
|
||||||
|
this.printStream = printStream;
|
||||||
|
this.conf = conf;
|
||||||
|
this.options = getOptions();
|
||||||
|
this.parser = new BasicParser();
|
||||||
|
}
|
||||||
|
|
||||||
|
public CBlockCli(OzoneConfiguration conf) throws IOException{
|
||||||
|
this(conf, System.out);
|
||||||
|
}
|
||||||
|
|
||||||
|
private CommandLine parseArgs(String[] argv)
|
||||||
|
throws ParseException {
|
||||||
|
return parser.parse(options, argv);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static Options getOptions() {
|
||||||
|
Options options = new Options();
|
||||||
|
Option serverAddress = OptionBuilder
|
||||||
|
.withArgName("serverAddress>:<serverPort")
|
||||||
|
.withLongOpt(SERVER_ADDR)
|
||||||
|
.withValueSeparator(':')
|
||||||
|
.hasArgs(2)
|
||||||
|
.withDescription("specify server address:port")
|
||||||
|
.create("s");
|
||||||
|
options.addOption(serverAddress);
|
||||||
|
|
||||||
|
// taking 4 args: userName, volumeName, volumeSize, blockSize
|
||||||
|
Option createVolume = OptionBuilder
|
||||||
|
.withArgName("user> <volume> <volumeSize in [GB/TB]> <blockSize")
|
||||||
|
.withLongOpt(CREATE_VOLUME)
|
||||||
|
.withValueSeparator(' ')
|
||||||
|
.hasArgs(4)
|
||||||
|
.withDescription("create a fresh new volume")
|
||||||
|
.create("c");
|
||||||
|
options.addOption(createVolume);
|
||||||
|
|
||||||
|
// taking 2 args: userName, volumeName
|
||||||
|
Option deleteVolume = OptionBuilder
|
||||||
|
.withArgName("user> <volume")
|
||||||
|
.withLongOpt(DELETE_VOLUME)
|
||||||
|
.hasArgs(2)
|
||||||
|
.withDescription("delete a volume")
|
||||||
|
.create("d");
|
||||||
|
options.addOption(deleteVolume);
|
||||||
|
|
||||||
|
// taking 2 args: userName, volumeName
|
||||||
|
Option infoVolume = OptionBuilder
|
||||||
|
.withArgName("user> <volume")
|
||||||
|
.withLongOpt(INFO_VOLUME)
|
||||||
|
.hasArgs(2)
|
||||||
|
.withDescription("info a volume")
|
||||||
|
.create("i");
|
||||||
|
options.addOption(infoVolume);
|
||||||
|
|
||||||
|
// taking 1 arg: userName
|
||||||
|
Option listVolume = OptionBuilder
|
||||||
|
.withArgName("user")
|
||||||
|
.withLongOpt(LIST_VOLUME)
|
||||||
|
.hasOptionalArgs(1)
|
||||||
|
.withDescription("list all volumes")
|
||||||
|
.create("l");
|
||||||
|
options.addOption(listVolume);
|
||||||
|
|
||||||
|
Option help = OptionBuilder
|
||||||
|
.withLongOpt(HELP)
|
||||||
|
.withDescription("help")
|
||||||
|
.create("h");
|
||||||
|
options.addOption(help);
|
||||||
|
|
||||||
|
return options;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int run(String[] args) throws ParseException, IOException {
|
||||||
|
CommandLine commandLine = parseArgs(args);
|
||||||
|
if (commandLine.hasOption("s")) {
|
||||||
|
String[] serverAddrArgs = commandLine.getOptionValues("s");
|
||||||
|
LOG.info("server address" + Arrays.toString(serverAddrArgs));
|
||||||
|
String serverHost = serverAddrArgs[0];
|
||||||
|
int serverPort = Integer.parseInt(serverAddrArgs[1]);
|
||||||
|
InetSocketAddress serverAddress =
|
||||||
|
new InetSocketAddress(serverHost, serverPort);
|
||||||
|
this.localProxy = new CBlockVolumeClient(conf, serverAddress);
|
||||||
|
} else {
|
||||||
|
this.localProxy = new CBlockVolumeClient(conf);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (commandLine.hasOption("h")) {
|
||||||
|
LOG.info("help");
|
||||||
|
help();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (commandLine.hasOption("c")) {
|
||||||
|
String[] createArgs = commandLine.getOptionValues("c");
|
||||||
|
LOG.info("create volume:" + Arrays.toString(createArgs));
|
||||||
|
createVolume(createArgs);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (commandLine.hasOption("d")) {
|
||||||
|
String[] deleteArgs = commandLine.getOptionValues("d");
|
||||||
|
LOG.info("delete args:" + Arrays.toString(deleteArgs));
|
||||||
|
deleteVolume(deleteArgs);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (commandLine.hasOption("l")) {
|
||||||
|
String[] listArg = commandLine.getOptionValues("l");
|
||||||
|
LOG.info("list args:" + Arrays.toString(listArg));
|
||||||
|
listVolume(listArg);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (commandLine.hasOption("i")) {
|
||||||
|
String[] infoArgs = commandLine.getOptionValues("i");
|
||||||
|
LOG.info("info args:" + Arrays.toString(infoArgs));
|
||||||
|
infoVolume(infoArgs);
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void main(String[] argv) throws Exception {
|
||||||
|
OzoneConfiguration cblockConf = new OzoneConfiguration();
|
||||||
|
RPC.setProtocolEngine(cblockConf, CBlockServiceProtocolPB.class,
|
||||||
|
ProtobufRpcEngine.class);
|
||||||
|
int res = 0;
|
||||||
|
Tool shell = new CBlockCli(cblockConf, System.out);
|
||||||
|
try {
|
||||||
|
ToolRunner.run(shell, argv);
|
||||||
|
} catch (Exception ex) {
|
||||||
|
LOG.error(ex.toString());
|
||||||
|
res = 1;
|
||||||
|
}
|
||||||
|
System.exit(res);
|
||||||
|
}
|
||||||
|
|
||||||
|
private long parseSize(String volumeSizeArgs) throws IOException {
|
||||||
|
long multiplier = 1;
|
||||||
|
|
||||||
|
Pattern p = Pattern.compile("([0-9]+)([a-zA-Z]+)");
|
||||||
|
Matcher m = p.matcher(volumeSizeArgs);
|
||||||
|
|
||||||
|
if (!m.find()) {
|
||||||
|
throw new IOException("Invalid volume size args " + volumeSizeArgs);
|
||||||
|
}
|
||||||
|
|
||||||
|
int size = Integer.parseInt(m.group(1));
|
||||||
|
String s = m.group(2);
|
||||||
|
|
||||||
|
if (s.equalsIgnoreCase("GB")) {
|
||||||
|
multiplier = 1024L * 1024 * 1024;
|
||||||
|
} else if (s.equalsIgnoreCase("TB")) {
|
||||||
|
multiplier = 1024L * 1024 * 1024 * 1024;
|
||||||
|
} else {
|
||||||
|
throw new IOException("Invalid volume size args " + volumeSizeArgs);
|
||||||
|
}
|
||||||
|
return size * multiplier;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void createVolume(String[] createArgs) throws IOException {
|
||||||
|
String userName = createArgs[0];
|
||||||
|
String volumeName = createArgs[1];
|
||||||
|
long volumeSize = parseSize(createArgs[2]);
|
||||||
|
int blockSize = Integer.parseInt(createArgs[3])*1024;
|
||||||
|
localProxy.createVolume(userName, volumeName, volumeSize, blockSize);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void deleteVolume(String[] deleteArgs) throws IOException {
|
||||||
|
String userName = deleteArgs[0];
|
||||||
|
String volumeName = deleteArgs[1];
|
||||||
|
boolean force = false;
|
||||||
|
if (deleteArgs.length > 2) {
|
||||||
|
force = Boolean.parseBoolean(deleteArgs[2]);
|
||||||
|
}
|
||||||
|
localProxy.deleteVolume(userName, volumeName, force);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void infoVolume(String[] infoArgs) throws IOException {
|
||||||
|
String userName = infoArgs[0];
|
||||||
|
String volumeName = infoArgs[1];
|
||||||
|
VolumeInfo volumeInfo = localProxy.infoVolume(userName, volumeName);
|
||||||
|
printStream.println(volumeInfo.toString());
|
||||||
|
}
|
||||||
|
|
||||||
|
private void listVolume(String[] listArgs) throws IOException {
|
||||||
|
StringBuilder stringBuilder = new StringBuilder();
|
||||||
|
List<VolumeInfo> volumeResponse;
|
||||||
|
if (listArgs == null) {
|
||||||
|
volumeResponse = localProxy.listVolume(null);
|
||||||
|
} else {
|
||||||
|
volumeResponse = localProxy.listVolume(listArgs[0]);
|
||||||
|
}
|
||||||
|
for (int i = 0; i<volumeResponse.size(); i++) {
|
||||||
|
stringBuilder.append(
|
||||||
|
String.format("%s:%s\t%d\t%d", volumeResponse.get(i).getUserName(),
|
||||||
|
volumeResponse.get(i).getVolumeName(),
|
||||||
|
volumeResponse.get(i).getVolumeSize(),
|
||||||
|
volumeResponse.get(i).getBlockSize()));
|
||||||
|
if (i < volumeResponse.size() - 1) {
|
||||||
|
stringBuilder.append("\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
printStream.println(stringBuilder);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void help() {
|
||||||
|
HelpFormatter formatter = new HelpFormatter();
|
||||||
|
formatter.printHelp(100, "cblock", "", options, "");
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,18 @@
|
||||||
|
/**
|
||||||
|
* 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.hadoop.cblock.cli;
|
|
@ -0,0 +1,135 @@
|
||||||
|
/*
|
||||||
|
* 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.hadoop.cblock.client;
|
||||||
|
|
||||||
|
import com.google.protobuf.ServiceException;
|
||||||
|
import org.apache.hadoop.cblock.meta.VolumeInfo;
|
||||||
|
import org.apache.hadoop.cblock.proto.CBlockServiceProtocol;
|
||||||
|
import org.apache.hadoop.cblock.protocol.proto.CBlockServiceProtocolProtos;
|
||||||
|
import org.apache.hadoop.cblock.protocolPB.CBlockServiceProtocolPB;
|
||||||
|
import org.apache.hadoop.classification.InterfaceAudience;
|
||||||
|
import org.apache.hadoop.ipc.ProtobufHelper;
|
||||||
|
import org.apache.hadoop.ipc.ProtocolTranslator;
|
||||||
|
import org.apache.hadoop.ipc.RPC;
|
||||||
|
|
||||||
|
import java.io.Closeable;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The client side implement of CBlockServiceProtocol.
|
||||||
|
*/
|
||||||
|
@InterfaceAudience.Private
|
||||||
|
public final class CBlockServiceProtocolClientSideTranslatorPB
|
||||||
|
implements CBlockServiceProtocol, ProtocolTranslator, Closeable {
|
||||||
|
|
||||||
|
private final CBlockServiceProtocolPB rpcProxy;
|
||||||
|
|
||||||
|
public CBlockServiceProtocolClientSideTranslatorPB(
|
||||||
|
CBlockServiceProtocolPB rpcProxy) {
|
||||||
|
this.rpcProxy = rpcProxy;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void close() throws IOException {
|
||||||
|
RPC.stopProxy(rpcProxy);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void createVolume(String userName, String volumeName,
|
||||||
|
long volumeSize, int blockSize) throws IOException {
|
||||||
|
CBlockServiceProtocolProtos.CreateVolumeRequestProto.Builder req =
|
||||||
|
CBlockServiceProtocolProtos.CreateVolumeRequestProto.newBuilder();
|
||||||
|
req.setUserName(userName);
|
||||||
|
req.setVolumeName(volumeName);
|
||||||
|
req.setVolumeSize(volumeSize);
|
||||||
|
req.setBlockSize(blockSize);
|
||||||
|
try {
|
||||||
|
rpcProxy.createVolume(null, req.build());
|
||||||
|
} catch (ServiceException e) {
|
||||||
|
throw ProtobufHelper.getRemoteException(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void deleteVolume(String userName, String volumeName, boolean force)
|
||||||
|
throws IOException {
|
||||||
|
CBlockServiceProtocolProtos.DeleteVolumeRequestProto.Builder req =
|
||||||
|
CBlockServiceProtocolProtos.DeleteVolumeRequestProto.newBuilder();
|
||||||
|
req.setUserName(userName);
|
||||||
|
req.setVolumeName(volumeName);
|
||||||
|
req.setForce(force);
|
||||||
|
try {
|
||||||
|
rpcProxy.deleteVolume(null, req.build());
|
||||||
|
} catch (ServiceException e) {
|
||||||
|
throw ProtobufHelper.getRemoteException(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Object getUnderlyingProxyObject() {
|
||||||
|
return rpcProxy;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public VolumeInfo infoVolume(String userName, String volumeName)
|
||||||
|
throws IOException {
|
||||||
|
CBlockServiceProtocolProtos.InfoVolumeRequestProto.Builder req =
|
||||||
|
CBlockServiceProtocolProtos.InfoVolumeRequestProto.newBuilder();
|
||||||
|
req.setUserName(userName);
|
||||||
|
req.setVolumeName(volumeName);
|
||||||
|
try {
|
||||||
|
CBlockServiceProtocolProtos.InfoVolumeResponseProto resp =
|
||||||
|
rpcProxy.infoVolume(null, req.build());
|
||||||
|
return new VolumeInfo(resp.getVolumeInfo().getUserName(),
|
||||||
|
resp.getVolumeInfo().getVolumeName(),
|
||||||
|
resp.getVolumeInfo().getVolumeSize(),
|
||||||
|
resp.getVolumeInfo().getBlockSize(),
|
||||||
|
resp.getVolumeInfo().getUsage());
|
||||||
|
} catch (ServiceException e) {
|
||||||
|
throw ProtobufHelper.getRemoteException(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<VolumeInfo> listVolume(String userName) throws IOException {
|
||||||
|
CBlockServiceProtocolProtos.ListVolumeRequestProto.Builder req =
|
||||||
|
CBlockServiceProtocolProtos.ListVolumeRequestProto.newBuilder();
|
||||||
|
if (userName != null) {
|
||||||
|
req.setUserName(userName);
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
CBlockServiceProtocolProtos.ListVolumeResponseProto resp =
|
||||||
|
rpcProxy.listVolume(null, req.build());
|
||||||
|
List<VolumeInfo> respList = new ArrayList<>();
|
||||||
|
for (CBlockServiceProtocolProtos.VolumeInfoProto entry :
|
||||||
|
resp.getVolumeEntryList()) {
|
||||||
|
VolumeInfo volumeInfo = new VolumeInfo(
|
||||||
|
entry.getUserName(), entry.getVolumeName(), entry.getVolumeSize(),
|
||||||
|
entry.getBlockSize());
|
||||||
|
respList.add(volumeInfo);
|
||||||
|
}
|
||||||
|
return respList;
|
||||||
|
} catch (ServiceException e) {
|
||||||
|
throw ProtobufHelper.getRemoteException(e);
|
||||||
|
} catch (Exception e) {
|
||||||
|
throw new IOException("got" + e.getCause() + " " + e.getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,96 @@
|
||||||
|
/*
|
||||||
|
* 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.hadoop.cblock.client;
|
||||||
|
|
||||||
|
import org.apache.hadoop.cblock.meta.VolumeInfo;
|
||||||
|
import org.apache.hadoop.cblock.protocolPB.CBlockServiceProtocolPB;
|
||||||
|
import org.apache.hadoop.io.retry.RetryPolicies;
|
||||||
|
import org.apache.hadoop.ipc.RPC;
|
||||||
|
import org.apache.hadoop.net.NetUtils;
|
||||||
|
import org.apache.hadoop.ozone.OzoneConfiguration;
|
||||||
|
import org.apache.hadoop.security.UserGroupInformation;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.net.InetSocketAddress;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.concurrent.TimeUnit;
|
||||||
|
|
||||||
|
import static org.apache.hadoop.cblock.CBlockConfigKeys.DFS_CBLOCK_SERVICERPC_HOSTNAME_DEFAULT;
|
||||||
|
import static org.apache.hadoop.cblock.CBlockConfigKeys.DFS_CBLOCK_SERVICERPC_HOSTNAME_KEY;
|
||||||
|
import static org.apache.hadoop.cblock.CBlockConfigKeys.DFS_CBLOCK_SERVICERPC_PORT_DEFAULT;
|
||||||
|
import static org.apache.hadoop.cblock.CBlockConfigKeys.DFS_CBLOCK_SERVICERPC_PORT_KEY;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Implementation of client used by CBlock command line tool.
|
||||||
|
*/
|
||||||
|
public class CBlockVolumeClient {
|
||||||
|
private final CBlockServiceProtocolClientSideTranslatorPB cblockClient;
|
||||||
|
private final OzoneConfiguration conf;
|
||||||
|
|
||||||
|
public CBlockVolumeClient(OzoneConfiguration conf) throws IOException {
|
||||||
|
this.conf = conf;
|
||||||
|
long version = RPC.getProtocolVersion(CBlockServiceProtocolPB.class);
|
||||||
|
String serverAddress = conf.get(DFS_CBLOCK_SERVICERPC_HOSTNAME_KEY,
|
||||||
|
DFS_CBLOCK_SERVICERPC_HOSTNAME_DEFAULT);
|
||||||
|
int serverPort = conf.getInt(DFS_CBLOCK_SERVICERPC_PORT_KEY,
|
||||||
|
DFS_CBLOCK_SERVICERPC_PORT_DEFAULT);
|
||||||
|
InetSocketAddress address = new InetSocketAddress(
|
||||||
|
serverAddress, serverPort);
|
||||||
|
// currently the largest supported volume is about 8TB, which might take
|
||||||
|
// > 20 seconds to finish creating containers. thus set timeout to 30 sec.
|
||||||
|
cblockClient = new CBlockServiceProtocolClientSideTranslatorPB(
|
||||||
|
RPC.getProtocolProxy(CBlockServiceProtocolPB.class, version,
|
||||||
|
address, UserGroupInformation.getCurrentUser(), conf,
|
||||||
|
NetUtils.getDefaultSocketFactory(conf), 30000, RetryPolicies
|
||||||
|
.retryUpToMaximumCountWithFixedSleep(300, 1, TimeUnit
|
||||||
|
.SECONDS)).getProxy());
|
||||||
|
}
|
||||||
|
|
||||||
|
public CBlockVolumeClient(OzoneConfiguration conf,
|
||||||
|
InetSocketAddress serverAddress) throws IOException {
|
||||||
|
this.conf = conf;
|
||||||
|
long version = RPC.getProtocolVersion(CBlockServiceProtocolPB.class);
|
||||||
|
cblockClient = new CBlockServiceProtocolClientSideTranslatorPB(
|
||||||
|
RPC.getProtocolProxy(CBlockServiceProtocolPB.class, version,
|
||||||
|
serverAddress, UserGroupInformation.getCurrentUser(), conf,
|
||||||
|
NetUtils.getDefaultSocketFactory(conf), 30000, RetryPolicies
|
||||||
|
.retryUpToMaximumCountWithFixedSleep(300, 1, TimeUnit
|
||||||
|
.SECONDS)).getProxy());
|
||||||
|
}
|
||||||
|
|
||||||
|
public void createVolume(String userName, String volumeName,
|
||||||
|
long volumeSize, int blockSize) throws IOException {
|
||||||
|
cblockClient.createVolume(userName, volumeName,
|
||||||
|
volumeSize, blockSize);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void deleteVolume(String userName, String volumeName, boolean force)
|
||||||
|
throws IOException {
|
||||||
|
cblockClient.deleteVolume(userName, volumeName, force);
|
||||||
|
}
|
||||||
|
|
||||||
|
public VolumeInfo infoVolume(String userName, String volumeName)
|
||||||
|
throws IOException {
|
||||||
|
return cblockClient.infoVolume(userName, volumeName);
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<VolumeInfo> listVolume(String userName)
|
||||||
|
throws IOException {
|
||||||
|
return cblockClient.listVolume(userName);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,18 @@
|
||||||
|
/**
|
||||||
|
* 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.hadoop.cblock.client;
|
|
@ -0,0 +1,224 @@
|
||||||
|
/*
|
||||||
|
* 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.hadoop.cblock;
|
||||||
|
|
||||||
|
import org.apache.hadoop.cblock.cli.CBlockCli;
|
||||||
|
import org.apache.hadoop.cblock.meta.VolumeDescriptor;
|
||||||
|
import org.apache.hadoop.cblock.util.MockStorageClient;
|
||||||
|
import org.apache.hadoop.ozone.OzoneConfiguration;
|
||||||
|
import org.apache.hadoop.scm.client.ScmClient;
|
||||||
|
import org.junit.After;
|
||||||
|
import org.junit.AfterClass;
|
||||||
|
import org.junit.BeforeClass;
|
||||||
|
import org.junit.Test;
|
||||||
|
|
||||||
|
import java.io.ByteArrayOutputStream;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.PrintStream;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import static org.apache.hadoop.cblock.CBlockConfigKeys.DFS_CBLOCK_SERVICE_LEVELDB_PATH_KEY;
|
||||||
|
import static org.junit.Assert.assertEquals;
|
||||||
|
import static org.junit.Assert.assertTrue;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A testing class for cblock command line tool.
|
||||||
|
*/
|
||||||
|
public class TestCBlockCLI {
|
||||||
|
private static final long GB = 1 * 1024 * 1024 * 1024L;
|
||||||
|
private static final int KB = 1024;
|
||||||
|
private static CBlockCli cmd;
|
||||||
|
private static OzoneConfiguration conf;
|
||||||
|
private static CBlockManager cBlockManager;
|
||||||
|
private static ByteArrayOutputStream outContent;
|
||||||
|
private static PrintStream testPrintOut;
|
||||||
|
|
||||||
|
@BeforeClass
|
||||||
|
public static void setup() throws IOException {
|
||||||
|
outContent = new ByteArrayOutputStream();
|
||||||
|
ScmClient storageClient = new MockStorageClient();
|
||||||
|
conf = new OzoneConfiguration();
|
||||||
|
conf.set(DFS_CBLOCK_SERVICE_LEVELDB_PATH_KEY, "/tmp/testCblockCli.dat");
|
||||||
|
cBlockManager = new CBlockManager(conf, storageClient);
|
||||||
|
cBlockManager.start();
|
||||||
|
testPrintOut = new PrintStream(outContent);
|
||||||
|
cmd = new CBlockCli(conf, testPrintOut);
|
||||||
|
}
|
||||||
|
|
||||||
|
@AfterClass
|
||||||
|
public static void clean() {
|
||||||
|
cBlockManager.stop();
|
||||||
|
cBlockManager.join();
|
||||||
|
cBlockManager.clean();
|
||||||
|
}
|
||||||
|
|
||||||
|
@After
|
||||||
|
public void reset() {
|
||||||
|
outContent.reset();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test the help command.
|
||||||
|
* @throws Exception
|
||||||
|
*/
|
||||||
|
@Test
|
||||||
|
public void testCliHelp() throws Exception {
|
||||||
|
PrintStream initialStdOut = System.out;
|
||||||
|
System.setOut(testPrintOut);
|
||||||
|
String[] args = {"-h"};
|
||||||
|
cmd.run(args);
|
||||||
|
String helpPrints =
|
||||||
|
"usage: cblock\n" +
|
||||||
|
" -c,--createVolume <user> <volume> <volumeSize in [GB/TB]> " +
|
||||||
|
"<blockSize> create a fresh new volume\n" +
|
||||||
|
" -d,--deleteVolume <user> <volume> " +
|
||||||
|
" delete a volume\n" +
|
||||||
|
" -h,--help " +
|
||||||
|
" help\n" +
|
||||||
|
" -i,--infoVolume <user> <volume> " +
|
||||||
|
" info a volume\n" +
|
||||||
|
" -l,--listVolume <user> " +
|
||||||
|
" list all volumes\n" +
|
||||||
|
" -s,--serverAddr <serverAddress>:<serverPort> " +
|
||||||
|
" specify server address:port\n";
|
||||||
|
assertEquals(helpPrints, outContent.toString());
|
||||||
|
outContent.reset();
|
||||||
|
System.setOut(initialStdOut);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test volume listing command.
|
||||||
|
* @throws Exception
|
||||||
|
*/
|
||||||
|
@Test
|
||||||
|
public void testCliList() throws Exception {
|
||||||
|
String userName0 = "userTestCliList0";
|
||||||
|
String userName1 = "userTestCliList1";
|
||||||
|
String userTestNotExist = "userTestNotExist";
|
||||||
|
String volumeName0 = "volumeTest0";
|
||||||
|
String volumeName1 = "volumeTest1";
|
||||||
|
String volumeSize0 = "30GB";
|
||||||
|
String volumeSize1 = "40GB";
|
||||||
|
String blockSize = Integer.toString(4);
|
||||||
|
String[] argsCreate0 =
|
||||||
|
{"-c", userName0, volumeName0, volumeSize0, blockSize};
|
||||||
|
cmd.run(argsCreate0);
|
||||||
|
String[] argsCreate1 =
|
||||||
|
{"-c", userName0, volumeName1, volumeSize1, blockSize};
|
||||||
|
cmd.run(argsCreate1);
|
||||||
|
String[] argsCreate2 =
|
||||||
|
{"-c", userName1, volumeName0, volumeSize0, blockSize};
|
||||||
|
cmd.run(argsCreate2);
|
||||||
|
String[] argsList0 = {"-l"};
|
||||||
|
cmd.run(argsList0);
|
||||||
|
String[] outExpected1 = {
|
||||||
|
"userTestCliList1:volumeTest0\t32212254720\t4096\n",
|
||||||
|
"userTestCliList0:volumeTest0\t32212254720\t4096\n",
|
||||||
|
"userTestCliList0:volumeTest1\t42949672960\t4096\n"};
|
||||||
|
int length = 0;
|
||||||
|
for (String str : outExpected1) {
|
||||||
|
assertTrue(outContent.toString().contains(str));
|
||||||
|
length += str.length();
|
||||||
|
}
|
||||||
|
assertEquals(length, outContent.toString().length());
|
||||||
|
outContent.reset();
|
||||||
|
|
||||||
|
String[] argsList1 = {"-l", userName1};
|
||||||
|
cmd.run(argsList1);
|
||||||
|
String outExpected2 = "userTestCliList1:volumeTest0\t32212254720\t4096\n";
|
||||||
|
assertEquals(outExpected2, outContent.toString());
|
||||||
|
outContent.reset();
|
||||||
|
|
||||||
|
String[] argsList2 = {"-l", userTestNotExist};
|
||||||
|
cmd.run(argsList2);
|
||||||
|
String outExpected3 = "\n";
|
||||||
|
assertEquals(outExpected3, outContent.toString());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test create volume command.
|
||||||
|
* @throws Exception
|
||||||
|
*/
|
||||||
|
@Test
|
||||||
|
public void testCliCreate() throws Exception {
|
||||||
|
String userName = "userTestCliCreate";
|
||||||
|
String volumeName = "volumeTest";
|
||||||
|
String volumeSize = "30GB";
|
||||||
|
String blockSize = "4";
|
||||||
|
String[] argsCreate = {"-c", userName, volumeName, volumeSize, blockSize};
|
||||||
|
cmd.run(argsCreate);
|
||||||
|
List<VolumeDescriptor> allVolumes = cBlockManager.getAllVolumes(userName);
|
||||||
|
assertEquals(1, allVolumes.size());
|
||||||
|
VolumeDescriptor volume = allVolumes.get(0);
|
||||||
|
assertEquals(userName, volume.getUserName());
|
||||||
|
assertEquals(volumeName, volume.getVolumeName());
|
||||||
|
long volumeSizeB = volume.getVolumeSize();
|
||||||
|
assertEquals(30, (int)(volumeSizeB/ GB));
|
||||||
|
assertEquals(4, volume.getBlockSize()/ KB);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test delete volume command.
|
||||||
|
* @throws Exception
|
||||||
|
*/
|
||||||
|
@Test
|
||||||
|
public void testCliDelete() throws Exception {
|
||||||
|
String userName = "userTestCliDelete";
|
||||||
|
String volumeName = "volumeTest";
|
||||||
|
String volumeSize = "30GB";
|
||||||
|
String blockSize = "4";
|
||||||
|
String[] argsCreate = {"-c", userName, volumeName, volumeSize, blockSize};
|
||||||
|
cmd.run(argsCreate);
|
||||||
|
List<VolumeDescriptor> allVolumes = cBlockManager.getAllVolumes(userName);
|
||||||
|
assertEquals(1, allVolumes.size());
|
||||||
|
VolumeDescriptor volume = allVolumes.get(0);
|
||||||
|
assertEquals(userName, volume.getUserName());
|
||||||
|
assertEquals(volumeName, volume.getVolumeName());
|
||||||
|
long volumeSizeB = volume.getVolumeSize();
|
||||||
|
assertEquals(30, (int)(volumeSizeB/ GB));
|
||||||
|
assertEquals(4, volume.getBlockSize()/ KB);
|
||||||
|
|
||||||
|
String[] argsDelete = {"-d", userName, volumeName};
|
||||||
|
cmd.run(argsDelete);
|
||||||
|
allVolumes = cBlockManager.getAllVolumes(userName);
|
||||||
|
assertEquals(0, allVolumes.size());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test info volume command.
|
||||||
|
* @throws Exception
|
||||||
|
*/
|
||||||
|
@Test
|
||||||
|
public void testCliInfoVolume() throws Exception {
|
||||||
|
String userName0 = "userTestCliInfo";
|
||||||
|
String volumeName0 = "volumeTest0";
|
||||||
|
String volumeSize = "8000GB";
|
||||||
|
String blockSize = "4";
|
||||||
|
String[] argsCreate0 = {
|
||||||
|
"-c", userName0, volumeName0, volumeSize, blockSize};
|
||||||
|
cmd.run(argsCreate0);
|
||||||
|
String[] argsInfo = {"-i", userName0, volumeName0};
|
||||||
|
cmd.run(argsInfo);
|
||||||
|
// TODO : the usage field is not implemented yet, always 0 now.
|
||||||
|
String outExpected = " userName:userTestCliInfo " +
|
||||||
|
"volumeName:volumeTest0 " +
|
||||||
|
"volumeSize:8589934592000 " +
|
||||||
|
"blockSize:4096 (sizeInBlocks:2097152000) usageInBlocks:0\n";
|
||||||
|
assertEquals(outExpected, outContent.toString());
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue