mirror of
https://github.com/gluster/gluster-block.git
synced 2026-02-05 12:45:33 +01:00
If the configshell_fb package version is low, or checking the CONFIGSHELL_VERSION fails, the create_io_timeout capability will be disabled: gluster-blockd[12934]: Traceback (most recent call last): gluster-blockd[12934]: File "<string>", line 1, in <module> gluster-blockd[12934]: ImportError: cannot import name __version__ WARNING: io timeout needs atleast configshell >=1.1.25 and tcmu-runner >= 1.5.0, so disabling its capability [at capabilities.c+179 :<gbSetCapabilties>] The old code will always set the io_timeout to _DEF value even in this case when the create_io_timeout capability is disabled. This will finally cause the gluster-block create fails even we won't specify or care about the io-timeout option. This fix will disable the io_timeout option as default and only we the create_io_timeout capability is enabled will we set the _DEF for it. Reviewed-by: Prasanna Kumar Kalever <prasanna.kalever@redhat.com> Signed-off-by: Xiubo Li <xiubli@redhat.com>
1271 lines
36 KiB
C
1271 lines
36 KiB
C
/*
|
|
Copyright (c) 2016 Red Hat, Inc. <http://www.redhat.com>
|
|
This file is part of gluster-block.
|
|
|
|
This file is licensed to you under your choice of the GNU Lesser
|
|
General Public License, version 3 or any later version (LGPLv3 or
|
|
later), or the GNU General Public License, version 2 (GPLv2), in all
|
|
cases as published by the Free Software Foundation.
|
|
*/
|
|
|
|
|
|
# include "common.h"
|
|
# include "block.h"
|
|
# include "config.h"
|
|
|
|
# include <arpa/inet.h>
|
|
|
|
# define GB_CREATE_HELP_STR "gluster-block create <volname/blockname> " \
|
|
"[ha <count>] [auth <enable|disable>] " \
|
|
"[prealloc <full|no>] [storage <filename>] " \
|
|
"[ring-buffer <size-in-MB-units>] " \
|
|
"[block-size <size-in-Byte-units>] " \
|
|
"[io-timeout <N-in-Second>] " \
|
|
"<HOST1[,HOST2,...]> [size] [--json*]"
|
|
# define GB_DELETE_HELP_STR "gluster-block delete <volname/blockname> " \
|
|
"[unlink-storage <yes|no>] [force] [--json*]"
|
|
# define GB_RELOAD_HELP_STR "gluster-block reload <volname/blockname> " \
|
|
"[force] [--json*]"
|
|
# define GB_MODIFY_HELP_STR "gluster-block modify <volname/blockname> " \
|
|
"[auth <enable|disable>] [size <size> " \
|
|
"[force]] [--json*]"
|
|
# define GB_REPLACE_HELP_STR "gluster-block replace <volname/blockname> " \
|
|
"<old-node> <new-node> [force] [--json*]"
|
|
# define GB_GENCONF_HELP_STR "gluster-block genconfig <volname[,volume2,volume3,...]> "\
|
|
"enable-tpg <host> [--json*]"
|
|
# define GB_INFO_HELP_STR "gluster-block info <volname/blockname> [--json*]"
|
|
# define GB_LIST_HELP_STR "gluster-block list <volname> [--json*]"
|
|
|
|
|
|
# define GB_ARGCHECK_OR_RETURN(argcount, count, cmd, helpstr) \
|
|
do { \
|
|
if (argcount != count) { \
|
|
MSG(stderr, "Inadequate arguments for %s:\n%s", cmd, helpstr); \
|
|
return -1; \
|
|
} \
|
|
} while(0)
|
|
|
|
extern const char *argp_program_version;
|
|
|
|
struct timeval TIMEOUT; /* cli process to daemon cli thread timeout */
|
|
static size_t cliOptTimeout;
|
|
|
|
gbProcessCtx gbCtx = GB_CLI_MODE; /* set process mode */
|
|
|
|
typedef enum clioperations {
|
|
CREATE_CLI = 1,
|
|
LIST_CLI = 2,
|
|
INFO_CLI = 3,
|
|
DELETE_CLI = 4,
|
|
MODIFY_CLI = 5,
|
|
MODIFY_SIZE_CLI = 6,
|
|
REPLACE_CLI = 7,
|
|
GENCONF_CLI = 8,
|
|
RELOAD_CLI = 9
|
|
} clioperations;
|
|
|
|
|
|
gbConfig *
|
|
glusterBlockCLILoadConfig(void)
|
|
{
|
|
gbConfig *cfg = NULL;
|
|
|
|
if (GB_ALLOC(cfg) < 0) {
|
|
LOG("cli", GB_LOG_ERROR,
|
|
"Alloc GB config failed for configPath: %s!", GB_DEF_CONFIGPATH);
|
|
return NULL;
|
|
}
|
|
|
|
if (GB_STRDUP(cfg->configPath, GB_DEF_CONFIGPATH) < 0) {
|
|
LOG("cli", GB_LOG_ERROR,
|
|
"failed to copy configPath: %s", GB_DEF_CONFIGPATH);
|
|
goto freeConfig;
|
|
}
|
|
|
|
if (glusterBlockLoadConfig(cfg, false)) {
|
|
LOG("cli", GB_LOG_ERROR,
|
|
"Loading GB config failed for configPath: %s!", GB_DEF_CONFIGPATH);
|
|
goto freeConfigPath;
|
|
}
|
|
|
|
return cfg;
|
|
|
|
freeConfigPath:
|
|
GB_FREE(cfg->configPath);
|
|
freeConfig:
|
|
GB_FREE(cfg);
|
|
|
|
return NULL;
|
|
}
|
|
|
|
|
|
static int
|
|
glusterBlockCliRPC_1(void *cobj, clioperations opt)
|
|
{
|
|
CLIENT *clnt = NULL;
|
|
int ret = -1;
|
|
int sockfd = RPC_ANYSOCK;
|
|
struct sockaddr_un saun = {0,};
|
|
blockCreateCli *create_obj;
|
|
blockDeleteCli *delete_obj;
|
|
blockReloadCli *reload_obj;
|
|
blockInfoCli *info_obj;
|
|
blockListCli *list_obj;
|
|
blockModifyCli *modify_obj;
|
|
blockModifySizeCli *modify_size_obj;
|
|
blockReplaceCli *replace_obj;
|
|
blockGenConfigCli *genconfig_obj;
|
|
blockResponse reply = {0,};
|
|
char errMsg[2048] = {0};
|
|
gbConfig *conf = NULL;
|
|
char *cli_timeout;
|
|
|
|
|
|
if (strlen(GB_UNIX_ADDRESS) > SUN_PATH_MAX) {
|
|
snprintf (errMsg, sizeof (errMsg), "%s: path length is more than "
|
|
"SUN_PATH_MAX: (%zu > %zu chars)", GB_UNIX_ADDRESS,
|
|
strlen(GB_UNIX_ADDRESS), SUN_PATH_MAX);
|
|
goto out;
|
|
}
|
|
|
|
saun.sun_family = AF_UNIX;
|
|
GB_STRCPYSTATIC(saun.sun_path, GB_UNIX_ADDRESS);
|
|
|
|
#ifndef HAVE_LIBTIRPC
|
|
if ((sockfd = socket(AF_UNIX, SOCK_STREAM, 0)) < 0) {
|
|
snprintf (errMsg, sizeof (errMsg), "%s: socket creation failed (%s)",
|
|
GB_UNIX_ADDRESS, strerror (errno));
|
|
goto out;
|
|
}
|
|
|
|
if (connect(sockfd, (struct sockaddr *) &saun,
|
|
sizeof(struct sockaddr_un)) < 0) {
|
|
if (errno == ENOENT || errno == ECONNREFUSED) {
|
|
snprintf (errMsg, sizeof (errMsg), "Connection failed. Please check if "
|
|
"gluster-block daemon is operational.");
|
|
} else {
|
|
snprintf (errMsg, sizeof (errMsg), "%s: connect failed (%s)",
|
|
GB_UNIX_ADDRESS, strerror (errno));
|
|
}
|
|
goto out;
|
|
}
|
|
#endif /* HAVE_LIBTIRPC */
|
|
|
|
clnt = clntunix_create((struct sockaddr_un *) &saun,
|
|
GLUSTER_BLOCK_CLI, GLUSTER_BLOCK_CLI_VERS,
|
|
&sockfd, 0, 0);
|
|
if (!clnt) {
|
|
snprintf (errMsg, sizeof (errMsg), "%s, unix addr %s",
|
|
clnt_spcreateerror("client create failed"), GB_UNIX_ADDRESS);
|
|
goto out;
|
|
}
|
|
|
|
conf = glusterBlockCLILoadConfig();
|
|
if (!conf) {
|
|
LOG("cli", GB_LOG_ERROR, "glusterBlockCLILoadConfig() failed");
|
|
goto out;
|
|
}
|
|
|
|
/* follow precedence */
|
|
if (conf->GB_CLI_TIMEOUT) {
|
|
TIMEOUT.tv_sec = conf->GB_CLI_TIMEOUT;
|
|
} else if (cliOptTimeout) {
|
|
TIMEOUT.tv_sec = cliOptTimeout;
|
|
} else if ((cli_timeout = getenv("GB_CLI_TIMEOUT"))) {
|
|
sscanf(cli_timeout, "%lu", &TIMEOUT.tv_sec);
|
|
} else {
|
|
TIMEOUT.tv_sec = CLI_TIMEOUT_DEF;
|
|
}
|
|
LOG("cli", GB_LOG_DEBUG, "cli timeout now is %lu", TIMEOUT.tv_sec);
|
|
|
|
switch(opt) {
|
|
case CREATE_CLI:
|
|
create_obj = cobj;
|
|
if (block_create_cli_1(create_obj, &reply, clnt) != RPC_SUCCESS) {
|
|
LOG("cli", GB_LOG_ERROR,
|
|
"%s block %s create on volume %s with hosts %s failed",
|
|
clnt_sperror(clnt, "block_create_cli_1"), create_obj->block_name,
|
|
create_obj->volume, create_obj->block_hosts);
|
|
goto out;
|
|
}
|
|
break;
|
|
case DELETE_CLI:
|
|
delete_obj = cobj;
|
|
if (block_delete_cli_1(delete_obj, &reply, clnt) != RPC_SUCCESS) {
|
|
LOG("cli", GB_LOG_ERROR, "%s block %s delete on volume %s failed",
|
|
clnt_sperror(clnt, "block_delete_cli_1"),
|
|
delete_obj->block_name, delete_obj->volume);
|
|
goto out;
|
|
}
|
|
break;
|
|
case RELOAD_CLI:
|
|
reload_obj = cobj;
|
|
if (block_reload_cli_1(reload_obj, &reply, clnt) != RPC_SUCCESS) {
|
|
LOG("cli", GB_LOG_ERROR, "%s block %s reload on volume %s failed",
|
|
clnt_sperror(clnt, "block_reload_cli_1"),
|
|
reload_obj->block_name, reload_obj->volume);
|
|
goto out;
|
|
}
|
|
break;
|
|
case INFO_CLI:
|
|
info_obj = cobj;
|
|
if (block_info_cli_1(info_obj, &reply, clnt) != RPC_SUCCESS) {
|
|
LOG("cli", GB_LOG_ERROR, "%s block %s info on volume %s failed",
|
|
clnt_sperror(clnt, "block_info_cli_1"),
|
|
info_obj->block_name, info_obj->volume);
|
|
goto out;
|
|
}
|
|
break;
|
|
case LIST_CLI:
|
|
list_obj = cobj;
|
|
if (block_list_cli_1(list_obj, &reply, clnt) != RPC_SUCCESS) {
|
|
LOG("cli", GB_LOG_ERROR, "%s block list on volume %s failed",
|
|
clnt_sperror(clnt, "block_list_cli_1"), list_obj->volume);
|
|
goto out;
|
|
}
|
|
break;
|
|
case MODIFY_CLI:
|
|
modify_obj = cobj;
|
|
if (block_modify_cli_1(modify_obj, &reply, clnt) != RPC_SUCCESS) {
|
|
LOG("cli", GB_LOG_ERROR, "%s block modify auth on volume %s failed",
|
|
clnt_sperror(clnt, "block_modify_cli_1"), modify_obj->volume);
|
|
goto out;
|
|
}
|
|
break;
|
|
case MODIFY_SIZE_CLI:
|
|
modify_size_obj = cobj;
|
|
if (block_modify_size_cli_1(modify_size_obj, &reply, clnt) != RPC_SUCCESS) {
|
|
LOG("cli", GB_LOG_ERROR, "%s block modify size on volume %s failed",
|
|
clnt_sperror(clnt, "block_modify_size_cli_1"), modify_size_obj->volume);
|
|
goto out;
|
|
}
|
|
break;
|
|
case REPLACE_CLI:
|
|
replace_obj = cobj;
|
|
if (block_replace_cli_1(replace_obj, &reply, clnt) != RPC_SUCCESS) {
|
|
LOG("cli", GB_LOG_ERROR, "%s block %s replace on volume %s failed",
|
|
clnt_sperror(clnt, "block_replace_cli_1"), replace_obj->block_name,
|
|
replace_obj->volume);
|
|
goto out;
|
|
}
|
|
break;
|
|
case GENCONF_CLI:
|
|
genconfig_obj = cobj;
|
|
if (block_gen_config_cli_1(genconfig_obj, &reply, clnt) != RPC_SUCCESS) {
|
|
LOG("cli", GB_LOG_ERROR, "%s genconfig on volume %s failed",
|
|
clnt_sperror(clnt, "block_gen_config_cli_1"), genconfig_obj->volume);
|
|
goto out;
|
|
}
|
|
break;
|
|
}
|
|
|
|
out:
|
|
if (reply.out) {
|
|
ret = reply.exit;
|
|
if (!ret) {
|
|
MSG(stdout, "%s", reply.out);
|
|
} else {
|
|
MSG(stderr, "%s", reply.out);
|
|
}
|
|
} else if (errMsg[0]) {
|
|
LOG("cli", GB_LOG_ERROR, "%s", errMsg);
|
|
MSG(stderr, "%s", errMsg);
|
|
} else {
|
|
MSG(stderr, "Did not receive any response from gluster-block daemon."
|
|
" Please check log files to find the reason");
|
|
ret = -1;
|
|
}
|
|
|
|
if (clnt) {
|
|
if (reply.out && !clnt_freeres(clnt, (xdrproc_t)xdr_blockResponse,
|
|
(char *)&reply)) {
|
|
LOG("cli", GB_LOG_ERROR, "%s",
|
|
clnt_sperror(clnt, "clnt_freeres failed"));
|
|
}
|
|
clnt_destroy (clnt);
|
|
}
|
|
|
|
if (sockfd != RPC_ANYSOCK) {
|
|
close (sockfd);
|
|
}
|
|
|
|
if (conf) {
|
|
GB_FREE(conf->configPath);
|
|
GB_FREE(conf);
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
|
|
|
|
static void
|
|
glusterBlockHelp(void)
|
|
{
|
|
MSG(stdout,
|
|
PACKAGE_NAME" ("PACKAGE_VERSION")\n"
|
|
"usage:\n"
|
|
" gluster-block [timeout <seconds>] <command> <volname[/blockname]> [<args>] [--json*]\n"
|
|
"\n"
|
|
"commands:\n"
|
|
" create <volname/blockname> [ha <count>]\n"
|
|
" [auth <enable|disable>]\n"
|
|
" [prealloc <full|no>]\n"
|
|
" [storage <filename>]\n"
|
|
" [ring-buffer <size-in-MB-units>]\n"
|
|
" [block-size <size-in-Byte-units>]\n"
|
|
" [io-timeout <N-in-Second>]\n"
|
|
" <host1[,host2,...]> [size]\n"
|
|
" create block device [defaults: ha 1, auth disable, prealloc full, size in bytes,\n"
|
|
" ring-buffer and block-size default size dependends on kernel,\n"
|
|
" io-timeout 43s]\n"
|
|
"\n"
|
|
" list <volname>\n"
|
|
" list available block devices.\n"
|
|
"\n"
|
|
" info <volname/blockname>\n"
|
|
" details about block device.\n"
|
|
"\n"
|
|
" delete <volname/blockname> [unlink-storage <yes|no>] [force]\n"
|
|
" delete block device.\n"
|
|
"\n"
|
|
" modify <volname/blockname> [auth <enable|disable>] [size <size> [force]]\n"
|
|
" modify block device.\n"
|
|
"\n"
|
|
" replace <volname/blockname> <old-node> <new-node> [force]\n"
|
|
" replace operations.\n"
|
|
"\n"
|
|
" reload <volname/blockname> [force]\n"
|
|
" reload a block device.\n"
|
|
"\n"
|
|
" genconfig <volname[,volume2,volume3,...]> enable-tpg <host>\n"
|
|
" generate the block volumes target configuration.\n"
|
|
"\n"
|
|
" help\n"
|
|
" show this message and exit.\n"
|
|
"\n"
|
|
" version\n"
|
|
" show version info and exit.\n"
|
|
"\n"
|
|
"common cli options: (fixed formats)\n"
|
|
" timeout <seconds>\n"
|
|
" it is the time in seconds that cli can wait for daemon to respond.\n"
|
|
" [default: timeout 300]\n"
|
|
" --json*\n"
|
|
" used to request the output result in json format [default: plain text]\n"
|
|
" supported JSON formats: --json|--json-plain|--json-spaced|--json-pretty\n"
|
|
);
|
|
}
|
|
|
|
static bool
|
|
glusterBlockIsNameAcceptable(char *name)
|
|
{
|
|
int i = 0;
|
|
|
|
|
|
if (!name || strlen(name) >= 255) {
|
|
return FALSE;
|
|
}
|
|
for (i = 0; i < strlen(name); i++) {
|
|
if (!isalnum(name[i]) && (name[i] != '_') && (name[i] != '-'))
|
|
return FALSE;
|
|
}
|
|
return TRUE;
|
|
}
|
|
|
|
static bool
|
|
glusterBlockIsVolListAcceptable(char *name)
|
|
{
|
|
char *tok, *tmp;
|
|
char delim[2] = {'\0', };
|
|
|
|
|
|
if (!name || GB_STRDUP(tmp, name) < 0) {
|
|
return FALSE;
|
|
}
|
|
|
|
delim[0] = GB_DELIMITER;
|
|
tok = strtok(tmp, delim);
|
|
while (tok != NULL) {
|
|
if (!glusterBlockIsNameAcceptable(tok)) {
|
|
GB_FREE(tmp);
|
|
return FALSE;
|
|
}
|
|
tok = strtok(NULL, delim);
|
|
}
|
|
|
|
GB_FREE(tmp);
|
|
return TRUE;
|
|
}
|
|
|
|
static bool
|
|
glusterBlockIsAddrAcceptable(char *addr)
|
|
{
|
|
int i = 0;
|
|
struct in_addr buf;
|
|
struct in6_addr buf6;
|
|
|
|
|
|
if (!addr || strlen(addr) == 0 || strlen(addr) > 255) {
|
|
return FALSE;
|
|
}
|
|
|
|
for (i = 0; i < strlen(addr); i++) {
|
|
if (!isdigit(addr[i]) && (addr[i] != '.'))
|
|
return FALSE;
|
|
}
|
|
|
|
if ((inet_pton(AF_INET, addr, &buf) != 1) &&
|
|
(inet_pton(AF_INET6, addr, &buf6) != 1)) {
|
|
return FALSE;
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
/* Checks if the block servers passed at commandline are ip's and match HA count
|
|
* ret > 0 -> ip's and HA requested is mismatching
|
|
* ret = 0 -> address list is acceptable
|
|
* ret < 0 -> hostname is passed or unknown delimers
|
|
*/
|
|
static int
|
|
glusterBlockIsAddrListAcceptable(size_t count, char *addr_list)
|
|
{
|
|
char *tok, *tmp;
|
|
char delim[2] = {'\0', };
|
|
unsigned int ncommas = 0;
|
|
|
|
|
|
if (!addr_list || strlen(addr_list) == 0 || GB_STRDUP(tmp, addr_list) < 0) {
|
|
return -1;
|
|
}
|
|
|
|
delim[0] = GB_DELIMITER;
|
|
tok = strtok(tmp, delim);
|
|
while (tok != NULL) {
|
|
if (!glusterBlockIsAddrAcceptable(tok)) {
|
|
GB_FREE(tmp);
|
|
return -1;
|
|
}
|
|
tok = strtok(NULL, delim);
|
|
ncommas++;
|
|
}
|
|
GB_FREE(tmp);
|
|
|
|
if (ncommas != count) {
|
|
return ncommas; /* number of ip's */
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int
|
|
glusterBlockParseVolumeBlock(char *volumeblock, char *volume, char *block,
|
|
size_t vol_len, size_t block_len,
|
|
char *helpstr, char *op)
|
|
{
|
|
int ret = -1;
|
|
char *sep = NULL;
|
|
char *tmp = NULL;
|
|
|
|
|
|
if (GB_STRDUP(tmp, volumeblock) < 0) {
|
|
goto out;
|
|
}
|
|
/* part before '/' is the volume name */
|
|
sep = strchr(tmp, '/');
|
|
if (!sep) {
|
|
MSG(stderr, "argument '<volname/blockname>'(%s) is incorrect",
|
|
volumeblock);
|
|
MSG(stderr, "%s", helpstr);
|
|
LOG("cli", GB_LOG_ERROR, "%s failed while parsing <volname/blockname>", op);
|
|
goto out;
|
|
}
|
|
*sep = '\0';
|
|
|
|
if (!glusterBlockIsNameAcceptable(tmp)) {
|
|
MSG(stderr, "volume name(%s) should contain only aplhanumeric,'-', '_' characters "
|
|
"and should be less than 255 characters long", volume);
|
|
goto out;
|
|
}
|
|
/* part after / is blockname */
|
|
if (!glusterBlockIsNameAcceptable(sep+1)) {
|
|
MSG(stderr, "block name(%s) should contain only aplhanumeric,'-', '_' characters "
|
|
"and should be less than 255 characters long", block);
|
|
goto out;
|
|
}
|
|
GB_STRCPY(volume, tmp, vol_len);
|
|
GB_STRCPY(block, sep+1, block_len);
|
|
ret = 0;
|
|
|
|
out:
|
|
GB_FREE(tmp);
|
|
return ret;
|
|
}
|
|
|
|
void
|
|
getCommandString(char **cmd, int argcount, char **options)
|
|
{
|
|
int total_length = 0;
|
|
int i;
|
|
|
|
for(i = 1; i < argcount; i++){
|
|
total_length = total_length + strlen(options[i])+1;
|
|
}
|
|
|
|
if (GB_ALLOC_N(*cmd, (total_length + 1))) {
|
|
LOG("cmdlog", GB_LOG_ERROR, "Could not allocate memory for command string");
|
|
return;
|
|
}
|
|
for (i = 1; i < argcount; i++) {
|
|
strcat(*cmd, options[i]);
|
|
strcat(*cmd, " ");
|
|
}
|
|
}
|
|
|
|
static int
|
|
glusterBlockModify(int argcount, char **options, int json)
|
|
{
|
|
size_t optind = 1;
|
|
blockModifyCli mobj = {{0}, };
|
|
blockModifySizeCli msobj = {{0}, };
|
|
char volume[255] = {0};
|
|
char block[255] = {0};
|
|
ssize_t sparse_ret;
|
|
int ret = -1;
|
|
|
|
|
|
if (argcount < 4 || argcount > 5) {
|
|
MSG(stderr, "Inadequate arguments for modify:\n%s", GB_MODIFY_HELP_STR);
|
|
return -1;
|
|
}
|
|
|
|
if (glusterBlockParseVolumeBlock(options[optind++], volume, block,
|
|
sizeof(volume), sizeof(block),
|
|
GB_MODIFY_HELP_STR, "modify")) {
|
|
goto out;
|
|
}
|
|
|
|
/* if auth given then collect status which is next by 'auth' arg */
|
|
if (!strcmp(options[optind], "auth")) {
|
|
optind++;
|
|
ret = convertStringToTrillianParse(options[optind++]);
|
|
if(ret >= 0) {
|
|
mobj.auth_mode = ret;
|
|
} else {
|
|
MSG(stderr, "'auth' option is incorrect");
|
|
MSG(stderr, GB_MODIFY_HELP_STR);
|
|
LOG("cli", GB_LOG_ERROR, "Modify failed while parsing argument "
|
|
"to auth for <%s/%s>", volume, block);
|
|
goto out;
|
|
}
|
|
|
|
if ((argcount - optind)) {
|
|
MSG(stderr, "unknown/unsupported option '%s' for modify auth:\n%s",
|
|
options[optind], GB_MODIFY_HELP_STR);
|
|
ret = -1;
|
|
goto out;
|
|
}
|
|
|
|
GB_STRCPYSTATIC(mobj.volume, volume);
|
|
GB_STRCPYSTATIC(mobj.block_name, block);
|
|
mobj.json_resp = json;
|
|
getCommandString(&mobj.cmd, argcount, options);
|
|
|
|
ret = glusterBlockCliRPC_1(&mobj, MODIFY_CLI);
|
|
if (ret) {
|
|
LOG("cli", GB_LOG_ERROR,
|
|
"failed modifying auth of block %s on volume %s", block, volume);
|
|
}
|
|
} else if (!strcmp(options[optind], "size")) {
|
|
optind++;
|
|
sparse_ret = glusterBlockParseSize("cli", options[optind++], 0);
|
|
if (sparse_ret < 0) {
|
|
MSG(stderr, "'<size>' is incorrect");
|
|
MSG(stderr, GB_MODIFY_HELP_STR);
|
|
LOG("cli", GB_LOG_ERROR, "Modify failed while parsing size for block <%s/%s>",
|
|
volume, block);
|
|
goto out;
|
|
}
|
|
|
|
if ((argcount - optind) && !strcmp(options[optind], "force")) {
|
|
optind++;
|
|
msobj.force = true;
|
|
}
|
|
|
|
if ((argcount - optind)) {
|
|
MSG(stderr, "unknown option '%s' for modify size:\n%s",
|
|
options[optind], GB_MODIFY_HELP_STR);
|
|
ret = -1;
|
|
goto out;
|
|
}
|
|
|
|
GB_STRCPYSTATIC(msobj.volume, volume);
|
|
GB_STRCPYSTATIC(msobj.block_name, block);
|
|
msobj.size = sparse_ret; /* size is unsigned long long */
|
|
msobj.json_resp = json;
|
|
getCommandString(&msobj.cmd, argcount, options);
|
|
|
|
ret = glusterBlockCliRPC_1(&msobj, MODIFY_SIZE_CLI);
|
|
if (ret) {
|
|
LOG("cli", GB_LOG_ERROR,
|
|
"failed modifying size of block %s on volume %s",
|
|
msobj.block_name, msobj.volume);
|
|
}
|
|
} else {
|
|
MSG(stderr, "unknown option '%s' for modify:\n%s",
|
|
options[optind], GB_MODIFY_HELP_STR);
|
|
ret = -1;
|
|
}
|
|
|
|
out:
|
|
GB_FREE(msobj.cmd);
|
|
GB_FREE(mobj.cmd);
|
|
|
|
return ret;
|
|
}
|
|
|
|
static int
|
|
glusterBlockCreate(int argcount, char **options, int json)
|
|
{
|
|
size_t optind = 1;
|
|
int ret = -1;
|
|
ssize_t sparse_ret;
|
|
blockCreateCli cobj = {{0}, };
|
|
bool TAKE_SIZE=true;
|
|
bool PREALLOC_OPT=false;
|
|
|
|
|
|
if (argcount <= optind) {
|
|
MSG(stderr, "Inadequate arguments for create:\n%s", GB_CREATE_HELP_STR);
|
|
return -1;
|
|
}
|
|
/* set defaults */
|
|
cobj.json_resp = json;
|
|
cobj.mpath = 1;
|
|
cobj.prealloc = 1;
|
|
|
|
if (glusterBlockParseVolumeBlock(options[optind++], cobj.volume, cobj.block_name,
|
|
sizeof(cobj.volume), sizeof(cobj.block_name),
|
|
GB_CREATE_HELP_STR, "create")) {
|
|
goto out;
|
|
}
|
|
|
|
while (argcount - optind > 2) {
|
|
switch (glusterBlockCLICreateOptEnumParse(options[optind++])) {
|
|
case GB_CLI_CREATE_HA:
|
|
if (isNumber(options[optind])) {
|
|
sscanf(options[optind++], "%u", &cobj.mpath);
|
|
if (!cobj.mpath) {
|
|
MSG(stderr, "'ha' cannot be zero.");
|
|
MSG(stderr, GB_CREATE_HELP_STR);
|
|
LOG("cli", GB_LOG_ERROR, "failed parsing ha as 0 for block <%s/%s>",
|
|
cobj.volume, cobj.block_name);
|
|
goto out;
|
|
}
|
|
} else {
|
|
MSG(stderr, "'ha' option is incorrect");
|
|
MSG(stderr, GB_CREATE_HELP_STR);
|
|
LOG("cli", GB_LOG_ERROR, "failed while parsing ha for block <%s/%s>",
|
|
cobj.volume, cobj.block_name);
|
|
goto out;
|
|
}
|
|
break;
|
|
case GB_CLI_CREATE_AUTH:
|
|
ret = convertStringToTrillianParse(options[optind++]);
|
|
if(ret >= 0) {
|
|
cobj.auth_mode = ret;
|
|
} else {
|
|
MSG(stderr, "'auth' option is incorrect");
|
|
MSG(stderr, GB_CREATE_HELP_STR);
|
|
LOG("cli", GB_LOG_ERROR, "Create failed while parsing argument "
|
|
"to auth for <%s/%s>",
|
|
cobj.volume, cobj.block_name);
|
|
goto out;
|
|
}
|
|
break;
|
|
case GB_CLI_CREATE_PREALLOC:
|
|
ret = convertStringToTrillianParse(options[optind++]);
|
|
if(ret >= 0) {
|
|
cobj.prealloc = ret;
|
|
PREALLOC_OPT=true;
|
|
} else {
|
|
MSG(stderr, "'prealloc' option is incorrect");
|
|
MSG(stderr, GB_CREATE_HELP_STR);
|
|
LOG("cli", GB_LOG_ERROR, "Create failed while parsing argument "
|
|
"to prealloc for <%s/%s>",
|
|
cobj.volume, cobj.block_name);
|
|
goto out;
|
|
}
|
|
break;
|
|
case GB_CLI_CREATE_STORAGE:
|
|
GB_STRCPYSTATIC(cobj.storage, options[optind++]);
|
|
TAKE_SIZE=false;
|
|
break;
|
|
case GB_CLI_CREATE_IO_TIMEOUT:
|
|
if (isNumber(options[optind])) {
|
|
sscanf(options[optind++], "%u", &cobj.io_timeout);
|
|
if (cobj.io_timeout < 1) {
|
|
MSG(stderr, "'io-timeout' should equal or larger than 1 second");
|
|
MSG(stderr, GB_CREATE_HELP_STR);
|
|
LOG("cli", GB_LOG_ERROR,
|
|
"failed while parsing io-timeout for block <%s/%s>",
|
|
cobj.volume, cobj.block_name);
|
|
goto out;
|
|
}
|
|
} else {
|
|
MSG(stderr, "'io-timeout' option is incorrect, hint: should be uint type");
|
|
MSG(stderr, GB_CREATE_HELP_STR);
|
|
LOG("cli", GB_LOG_ERROR, "failed while parsing io-timeout for block <%s/%s>",
|
|
cobj.volume, cobj.block_name);
|
|
goto out;
|
|
}
|
|
break;
|
|
case GB_CLI_CREATE_RBSIZE:
|
|
if (isNumber(options[optind])) {
|
|
sscanf(options[optind++], "%u", &cobj.rb_size);
|
|
if (cobj.rb_size < 1 || cobj.rb_size > 1024) {
|
|
MSG(stderr, "'ring-buffer' should be in range [1MB - 1024MB]");
|
|
MSG(stderr, GB_CREATE_HELP_STR);
|
|
LOG("cli", GB_LOG_ERROR,
|
|
"failed while parsing ring-buffer range [1MB - 1024MB] for block <%s/%s>",
|
|
cobj.volume, cobj.block_name);
|
|
goto out;
|
|
}
|
|
} else {
|
|
MSG(stderr, "'ring-buffer' option is incorrect, hint: should be uint type");
|
|
MSG(stderr, GB_CREATE_HELP_STR);
|
|
LOG("cli", GB_LOG_ERROR, "failed while parsing ring-buffer for block <%s/%s>",
|
|
cobj.volume, cobj.block_name);
|
|
goto out;
|
|
}
|
|
break;
|
|
case GB_CLI_CREATE_BLKSIZE:
|
|
if (isNumber(options[optind])) {
|
|
sscanf(options[optind++], "%u", &cobj.blk_size);
|
|
if (cobj.blk_size % 512) {
|
|
MSG(stderr, "'block-size' should be aligned to 512 bytes");
|
|
MSG(stderr, GB_CREATE_HELP_STR);
|
|
LOG("cli", GB_LOG_ERROR,
|
|
"failed while parsing block-size aligned to 512 bytes for block <%s/%s>",
|
|
cobj.volume, cobj.block_name);
|
|
goto out;
|
|
}
|
|
} else {
|
|
MSG(stderr, "'block-size' option is incorrect, hint: should be uint type");
|
|
MSG(stderr, GB_CREATE_HELP_STR);
|
|
LOG("cli", GB_LOG_ERROR, "failed while parsing block-size for block <%s/%s>",
|
|
cobj.volume, cobj.block_name);
|
|
goto out;
|
|
}
|
|
break;
|
|
case GB_CLI_CREATE_OPT_MAX:
|
|
default:
|
|
MSG(stderr, "unknown option '%s'", options[optind - 1]);
|
|
MSG(stderr, GB_CREATE_HELP_STR);
|
|
LOG("cli", GB_LOG_ERROR, "received an unknown option '%s' for block <%s/%s>",
|
|
options[optind - 1], cobj.volume, cobj.block_name);
|
|
goto out;
|
|
}
|
|
}
|
|
|
|
if (TAKE_SIZE) {
|
|
if (argcount - optind != 2) {
|
|
MSG(stderr, "Inadequate arguments for create:\n%s", GB_CREATE_HELP_STR);
|
|
LOG("cli", GB_LOG_ERROR,
|
|
"failed with Inadequate args for create block %s on volume %s with hosts %s",
|
|
cobj.block_name, cobj.volume, cobj.block_hosts);
|
|
goto out;
|
|
}
|
|
} else {
|
|
if (PREALLOC_OPT) {
|
|
MSG(stderr, "Inadequate arguments for create:\n%s", GB_CREATE_HELP_STR);
|
|
MSG(stderr, "Hint: do not use [prealloc <full|no>] in combination with [storage <filename>] option");
|
|
LOG("cli", GB_LOG_ERROR,
|
|
"failed with Inadequate args for create block %s on volume %s with hosts %s",
|
|
cobj.block_name, cobj.volume, cobj.block_hosts);
|
|
goto out;
|
|
}
|
|
|
|
if (argcount - optind != 1) {
|
|
MSG(stderr, "Inadequate arguments for create:\n%s", GB_CREATE_HELP_STR);
|
|
MSG(stderr, "Hint: do not use [size] in combination with [storage <filename>] option");
|
|
LOG("cli", GB_LOG_ERROR,
|
|
"failed with Inadequate args for create block %s on volume %s with hosts %s",
|
|
cobj.block_name, cobj.volume, cobj.block_hosts);
|
|
goto out;
|
|
}
|
|
}
|
|
|
|
if (GB_STRDUP(cobj.block_hosts, options[optind++]) < 0) {
|
|
LOG("cli", GB_LOG_ERROR, "failed while parsing servers for block <%s/%s>",
|
|
cobj.volume, cobj.block_name);
|
|
goto out;
|
|
}
|
|
|
|
/* defend on the use of hostnames */
|
|
ret = glusterBlockIsAddrListAcceptable(cobj.mpath, cobj.block_hosts);
|
|
if (ret < 0) {
|
|
MSG(stderr, "hostnames are not supported with gluster-block, use ips only");
|
|
MSG(stderr, "Hint: if you are already using ips, make sure there are no typos");
|
|
} else if (ret > 0) {
|
|
MSG(stderr, "number of ip's in the list passed are not matching HA count requested");
|
|
}
|
|
if (ret) {
|
|
LOG("cli", GB_LOG_ERROR,
|
|
"failed while parsing the host-list for create block %s on volume %s with hosts %s",
|
|
cobj.block_name, cobj.volume, cobj.block_hosts);
|
|
ret = -1;
|
|
goto out;
|
|
}
|
|
|
|
if (TAKE_SIZE) {
|
|
sparse_ret = glusterBlockParseSize("cli", options[optind], cobj.blk_size);
|
|
if (sparse_ret < 0) {
|
|
MSG(stderr, "'[size]' is incorrect");
|
|
MSG(stderr, GB_CREATE_HELP_STR);
|
|
LOG("cli", GB_LOG_ERROR, "failed while parsing size for block <%s/%s>",
|
|
cobj.volume, cobj.block_name);
|
|
goto out;
|
|
}
|
|
cobj.size = sparse_ret; /* size is unsigned long long */
|
|
}
|
|
|
|
getCommandString(&cobj.cmd, argcount, options);
|
|
ret = glusterBlockCliRPC_1(&cobj, CREATE_CLI);
|
|
if (ret) {
|
|
LOG("cli", GB_LOG_ERROR,
|
|
"failed creating block %s on volume %s with hosts %s",
|
|
cobj.block_name, cobj.volume, cobj.block_hosts);
|
|
}
|
|
|
|
out:
|
|
GB_FREE(cobj.block_hosts);
|
|
GB_FREE(cobj.cmd);
|
|
|
|
return ret;
|
|
}
|
|
|
|
|
|
static int
|
|
glusterBlockList(int argcount, char **options, int json)
|
|
{
|
|
blockListCli cobj = {{0},};
|
|
int ret = -1;
|
|
|
|
|
|
GB_ARGCHECK_OR_RETURN(argcount, 2, "list", GB_LIST_HELP_STR);
|
|
cobj.json_resp = json;
|
|
|
|
GB_STRCPYSTATIC(cobj.volume, options[1]);
|
|
|
|
ret = glusterBlockCliRPC_1(&cobj, LIST_CLI);
|
|
if (ret) {
|
|
LOG("cli", GB_LOG_ERROR, "failed listing blocks from volume %s",
|
|
cobj.volume);
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
|
|
|
|
static int
|
|
glusterBlockDelete(int argcount, char **options, int json)
|
|
{
|
|
blockDeleteCli dobj = {{0},};
|
|
size_t optind = 1;
|
|
int ret = -1;
|
|
|
|
|
|
if (argcount < 2 || argcount > 5) {
|
|
MSG(stderr, "Inadequate arguments for delete:\n%s", GB_DELETE_HELP_STR);
|
|
return -1;
|
|
}
|
|
|
|
dobj.json_resp = json;
|
|
|
|
/* default: delete storage */
|
|
dobj.unlink = 1;
|
|
|
|
if (glusterBlockParseVolumeBlock (options[optind++], dobj.volume,
|
|
dobj.block_name, sizeof(dobj.volume),
|
|
sizeof(dobj.block_name), GB_DELETE_HELP_STR,
|
|
"delete")) {
|
|
goto out;
|
|
}
|
|
|
|
if ((argcount - optind) && !strcmp(options[optind], "unlink-storage")) {
|
|
optind++;
|
|
ret = convertStringToTrillianParse(options[optind++]);
|
|
if(ret >= 0) {
|
|
dobj.unlink = ret;
|
|
} else {
|
|
MSG(stderr, "'unlink-storage' option is incorrect");
|
|
MSG(stderr, GB_DELETE_HELP_STR);
|
|
LOG("cli", GB_LOG_ERROR, "Delete failed while parsing argument "
|
|
"to unlink-storage for <%s/%s>",
|
|
dobj.volume, dobj.block_name);
|
|
goto out;
|
|
}
|
|
}
|
|
|
|
if ((argcount - optind) && !strcmp(options[optind], "force")) {
|
|
optind++;
|
|
dobj.force = true;
|
|
}
|
|
|
|
if (argcount - optind) {
|
|
MSG(stderr, "Unknown option: '%s'\n%s", options[optind], GB_DELETE_HELP_STR);
|
|
LOG("cli", GB_LOG_ERROR, "Delete failed parsing argument unknow option '%s'"
|
|
" for <%s/%s>", options[optind], dobj.volume, dobj.block_name);
|
|
goto out;
|
|
}
|
|
|
|
getCommandString(&dobj.cmd, argcount, options);
|
|
|
|
ret = glusterBlockCliRPC_1(&dobj, DELETE_CLI);
|
|
if (ret) {
|
|
LOG("cli", GB_LOG_ERROR, "failed deleting block %s on volume %s",
|
|
dobj.block_name, dobj.volume);
|
|
}
|
|
|
|
out:
|
|
GB_FREE(dobj.cmd);
|
|
|
|
return ret;
|
|
}
|
|
|
|
static int
|
|
glusterBlockReload(int argcount, char **options, int json)
|
|
{
|
|
blockReloadCli robj = {{0},};
|
|
int ret = -1;
|
|
|
|
|
|
if (argcount < 2 || argcount > 3) {
|
|
MSG(stderr, "Inadequate arguments for replace:\n%s", GB_RELOAD_HELP_STR);
|
|
return -1;
|
|
}
|
|
|
|
robj.json_resp = json;
|
|
|
|
if (glusterBlockParseVolumeBlock (options[1], robj.volume, robj.block_name,
|
|
sizeof(robj.volume), sizeof(robj.block_name),
|
|
GB_RELOAD_HELP_STR, "reload")) {
|
|
goto out;
|
|
}
|
|
|
|
if (argcount == 3) {
|
|
if (strcmp(options[2], "force")) {
|
|
MSG(stderr, "unknown option '%s' for reload:\n%s", options[2], GB_RELOAD_HELP_STR);
|
|
return -1;
|
|
} else {
|
|
robj.force = true;
|
|
}
|
|
}
|
|
|
|
getCommandString(&robj.cmd, argcount, options);
|
|
|
|
ret = glusterBlockCliRPC_1(&robj, RELOAD_CLI);
|
|
if (ret) {
|
|
LOG("cli", GB_LOG_ERROR,
|
|
"failed reload of block %s on volume %s",
|
|
robj.block_name, robj.volume);
|
|
}
|
|
|
|
out:
|
|
|
|
return ret;
|
|
}
|
|
|
|
static int
|
|
glusterBlockInfo(int argcount, char **options, int json)
|
|
{
|
|
blockInfoCli cobj = {{0},};
|
|
int ret = -1;
|
|
|
|
|
|
GB_ARGCHECK_OR_RETURN(argcount, 2, "info", GB_INFO_HELP_STR);
|
|
cobj.json_resp = json;
|
|
|
|
if (glusterBlockParseVolumeBlock (options[1], cobj.volume, cobj.block_name,
|
|
sizeof(cobj.volume), sizeof(cobj.block_name),
|
|
GB_INFO_HELP_STR, "info")) {
|
|
goto out;
|
|
}
|
|
|
|
ret = glusterBlockCliRPC_1(&cobj, INFO_CLI);
|
|
if (ret) {
|
|
LOG("cli", GB_LOG_ERROR,
|
|
"failed getting info of block %s on volume %s",
|
|
cobj.block_name, cobj.volume);
|
|
}
|
|
|
|
out:
|
|
|
|
return ret;
|
|
}
|
|
|
|
|
|
static int
|
|
glusterBlockReplace(int argcount, char **options, int json)
|
|
{
|
|
blockReplaceCli robj = {{0},};
|
|
int ret = -1;
|
|
int optind = 1;
|
|
|
|
|
|
if (argcount < 4 || argcount > 5) {
|
|
MSG(stderr, "Inadequate arguments for replace:\n%s", GB_REPLACE_HELP_STR);
|
|
return -1;
|
|
}
|
|
|
|
if (glusterBlockParseVolumeBlock(options[optind++], robj.volume, robj.block_name,
|
|
sizeof(robj.volume), sizeof(robj.block_name),
|
|
GB_REPLACE_HELP_STR, "replace")) {
|
|
goto out;
|
|
}
|
|
|
|
if (!glusterBlockIsAddrAcceptable(options[optind])) {
|
|
MSG(stderr, "host addr (%s) should be a valid ip address\n%s",
|
|
options[optind], GB_REPLACE_HELP_STR);
|
|
goto out;
|
|
}
|
|
GB_STRCPYSTATIC(robj.old_node, options[optind++]);
|
|
|
|
if (!glusterBlockIsAddrAcceptable(options[optind])) {
|
|
MSG(stderr, "host addr (%s) should be a valid ip address\n%s",
|
|
options[optind], GB_REPLACE_HELP_STR);
|
|
goto out;
|
|
}
|
|
GB_STRCPYSTATIC(robj.new_node, options[optind++]);
|
|
|
|
if (!strcmp(robj.old_node, robj.new_node)) {
|
|
MSG(stderr, "<old-node> (%s) and <new-node> (%s) cannot be same\n%s",
|
|
robj.old_node, robj.new_node, GB_REPLACE_HELP_STR);
|
|
goto out;
|
|
}
|
|
|
|
robj.json_resp = json;
|
|
|
|
if (argcount == 5) {
|
|
if (strcmp(options[optind], "force")) {
|
|
MSG(stderr, "unknown option '%s' for replace:\n%s", options[optind], GB_REPLACE_HELP_STR);
|
|
return -1;
|
|
} else {
|
|
robj.force = true;
|
|
}
|
|
}
|
|
|
|
getCommandString(&robj.cmd, argcount, options);
|
|
ret = glusterBlockCliRPC_1(&robj, REPLACE_CLI);
|
|
if (ret) {
|
|
LOG("cli", GB_LOG_ERROR, "failed replace on volume %s",
|
|
robj.volume);
|
|
}
|
|
|
|
out:
|
|
GB_FREE(robj.cmd);
|
|
|
|
return ret;
|
|
}
|
|
|
|
|
|
static int
|
|
glusterBlockGenConfig(int argcount, char **options, int json)
|
|
{
|
|
blockGenConfigCli robj = {0,};
|
|
int ret = -1;
|
|
int optind = 1;
|
|
|
|
|
|
GB_ARGCHECK_OR_RETURN(argcount, 4, "genconfig", GB_GENCONF_HELP_STR);
|
|
|
|
if (!glusterBlockIsVolListAcceptable(options[optind])) {
|
|
MSG(stderr, "volume list(%s) should be delimited by '%c' character only\n%s",
|
|
options[optind], GB_DELIMITER, GB_GENCONF_HELP_STR);
|
|
goto out;
|
|
}
|
|
|
|
GB_STRDUP(robj.volume, options[optind++]);
|
|
|
|
if (!strcmp(options[optind++], "enable-tpg")) {
|
|
if (!glusterBlockIsAddrAcceptable(options[optind])) {
|
|
MSG(stderr, "host addr (%s) should be a valid ip address\n%s",
|
|
options[optind -1], GB_REPLACE_HELP_STR);
|
|
goto out;
|
|
}
|
|
GB_STRCPYSTATIC(robj.addr, options[optind]);
|
|
} else {
|
|
MSG(stderr, "unknown option '%s' for genconfig:\n%s", options[optind -1], GB_GENCONF_HELP_STR);
|
|
goto out;
|
|
}
|
|
robj.json_resp = json;
|
|
|
|
ret = glusterBlockCliRPC_1(&robj, GENCONF_CLI);
|
|
if (ret) {
|
|
LOG("cli", GB_LOG_ERROR, "failed genconfig on volume %s", robj.volume);
|
|
}
|
|
|
|
out:
|
|
GB_FREE(robj.volume);
|
|
|
|
return ret;
|
|
}
|
|
|
|
|
|
static int
|
|
glusterBlockParseArgs(int count, char **options, size_t opt, int json)
|
|
{
|
|
int ret = 0;
|
|
|
|
|
|
while (1) {
|
|
switch (opt) {
|
|
case GB_CLI_CREATE:
|
|
ret = glusterBlockCreate(count, options, json);
|
|
if (ret && ret != EEXIST) {
|
|
LOG("cli", GB_LOG_ERROR, FAILED_CREATE);
|
|
}
|
|
goto out;
|
|
|
|
case GB_CLI_LIST:
|
|
ret = glusterBlockList(count, options, json);
|
|
if (ret) {
|
|
LOG("cli", GB_LOG_ERROR, FAILED_LIST);
|
|
}
|
|
goto out;
|
|
|
|
case GB_CLI_INFO:
|
|
ret = glusterBlockInfo(count, options, json);
|
|
if (ret) {
|
|
LOG("cli", GB_LOG_ERROR, FAILED_INFO);
|
|
}
|
|
goto out;
|
|
|
|
case GB_CLI_MODIFY:
|
|
ret = glusterBlockModify(count, options, json);
|
|
if (ret) {
|
|
LOG("cli", GB_LOG_ERROR, FAILED_MODIFY);
|
|
}
|
|
goto out;
|
|
|
|
case GB_CLI_REPLACE:
|
|
ret = glusterBlockReplace(count, options, json);
|
|
if (ret) {
|
|
LOG("cli", GB_LOG_ERROR, FAILED_REPLACE);
|
|
}
|
|
goto out;
|
|
|
|
case GB_CLI_GENCONFIG:
|
|
ret = glusterBlockGenConfig(count, options, json);
|
|
if (ret) {
|
|
LOG("cli", GB_LOG_ERROR, FAILED_GENCONFIG);
|
|
}
|
|
goto out;
|
|
|
|
case GB_CLI_DELETE:
|
|
ret = glusterBlockDelete(count, options, json);
|
|
if (ret) {
|
|
LOG("cli", GB_LOG_ERROR, FAILED_DELETE);
|
|
}
|
|
goto out;
|
|
|
|
case GB_CLI_RELOAD:
|
|
ret = glusterBlockReload(count, options, json);
|
|
if (ret) {
|
|
LOG("cli", GB_LOG_ERROR, FAILED_RELOAD);
|
|
}
|
|
goto out;
|
|
|
|
case GB_CLI_HELP:
|
|
case GB_CLI_HYPHEN_HELP:
|
|
case GB_CLI_USAGE:
|
|
case GB_CLI_HYPHEN_USAGE:
|
|
glusterBlockHelp();
|
|
goto out;
|
|
|
|
case GB_CLI_VERSION:
|
|
case GB_CLI_HYPHEN_VERSION:
|
|
MSG(stdout, "%s", argp_program_version);
|
|
goto out;
|
|
|
|
default:
|
|
ret = -1;
|
|
goto out;
|
|
}
|
|
}
|
|
|
|
out:
|
|
return ret;
|
|
}
|
|
|
|
|
|
int
|
|
main(int argc, char *argv[])
|
|
{
|
|
size_t opt = 0;
|
|
int count = 1;
|
|
int args = argc;
|
|
int json = GB_JSON_NONE;
|
|
int ret;
|
|
|
|
|
|
if (argc <= 1) {
|
|
glusterBlockHelp();
|
|
goto fail;
|
|
}
|
|
|
|
if (initGbConfig()) {
|
|
goto fail;
|
|
}
|
|
|
|
if(initLogging()) {
|
|
goto fail;
|
|
}
|
|
|
|
while (1) {
|
|
opt = glusterBlockCLIOptEnumParse(argv[count]);
|
|
if (opt < 1 || opt >= GB_CLI_OPT_MAX) {
|
|
MSG(stderr, "Unknown option: %s", argv[count]);
|
|
goto fail;
|
|
}
|
|
if (opt == GB_CLI_TIMEOUT) {
|
|
if (args <= 3) { /* some command is manditory */
|
|
glusterBlockHelp();
|
|
goto fail;
|
|
}
|
|
|
|
if (isNumber(argv[2])) {
|
|
sscanf(argv[2], "%ld", &cliOptTimeout);
|
|
} else {
|
|
MSG(stderr, "'timeout' option is incorrect, check usage.");
|
|
MSG(stderr, "hint: timeout argument accept only time in seconds.");
|
|
goto fail;
|
|
}
|
|
args = args - 2;
|
|
count = count + 2;
|
|
continue;
|
|
}
|
|
|
|
json = jsonResponseFormatParse(argv[argc-1]);
|
|
if (json == GB_JSON_MAX) {
|
|
MSG(stderr, "expecting '--json*', got '%s'",
|
|
argv[argc-1]);
|
|
return -1;
|
|
} else if (json != GB_JSON_NONE) {
|
|
args = args - 1; /*Commands don't need to handle json*/
|
|
}
|
|
break;
|
|
}
|
|
|
|
ret = glusterBlockParseArgs(args - 1, &argv[count], opt, json);
|
|
|
|
finiGbConfig();
|
|
|
|
return ret;
|
|
|
|
fail:
|
|
finiGbConfig();
|
|
exit(EXIT_FAILURE);
|
|
}
|