HDFS-11162. Block Storage: add command line tool. Contributed by Chen Liang.

This commit is contained in:
Anu Engineer 2017-03-21 15:06:18 -07:00
parent 6b5dee9c38
commit a9f92c4666
7 changed files with 784 additions and 3 deletions

View File

@ -25,13 +25,19 @@ public final class CBlockConfigKeys {
"dfs.cblock.enabled";
public static final String DFS_CBLOCK_SERVICERPC_ADDRESS_KEY =
"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;
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 =
"0.0.0.0";
public static final String DFS_CBLOCK_SERVICERPC_ADDRESS_DEFAULT =
DFS_CBLOCK_RPCSERVICE_IP_DEFAULT
+ ":" + DFS_CBLOCK_RPCSERVICE_PORT_DEFAULT;
DFS_CBLOCK_SERVICERPC_HOSTNAME_DEFAULT
+ ":" + DFS_CBLOCK_SERVICERPC_PORT_DEFAULT;
public static final String DFS_CBLOCK_JSCSIRPC_ADDRESS_KEY =
"dfs.cblock.jscsi-address";

View File

@ -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, "");
}
}

View File

@ -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;

View File

@ -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());
}
}
}

View File

@ -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);
}
}

View File

@ -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;

View File

@ -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());
}
}