1
0
mirror of https://github.com/gluster/gluster-block.git synced 2026-02-05 12:45:33 +01:00

replace: add replace feature

1. create conf in new node
2. delete conf from old node
3. replace portals from nodes hosting other paths (HA)

$ gluster-block create sample/block ha 3 192.168.124.57,192.168.124.26,192.168.124.30 1GiB --json-pretty
{
  "IQN":"iqn.2016-12.org.gluster-block:d516bb5c-5f56-4d9c-96a7-385df19c2e2c",
  "PORTAL(S)":[
    "192.168.124.57:3260",
    "192.168.124.26:3260",
    "192.168.124.30:3260"
  ],
  "RESULT":"SUCCESS"
}

$ gluster-block help
gluster-block (0.3)
usage:
  gluster-block <command> <volname[/blockname]> [<args>] [--json*]

commands:
[...]
  replace <volname/blockname> <old-node> <new-node> [force]
        replace operations.
[...]

supported JSON formats:
  --json|--json-plain|--json-spaced|--json-pretty

$ gluster-block replace sample/block 192.168.124.26 192.168.124.56 --json-pretty
{
  "NAME":"block",
  "CREATE SUCCESS":"192.168.124.56",
  "DELETE SUCCESS":"192.168.124.26",
  "REPLACE PORTAL SUCCESS ON":[
    "192.168.124.57",
    "192.168.124.30"
  ],
  "RESULT":"SUCCESS"
}

Fixes: #4
Change-Id: I0411d15c407111db0d423052d9a6bc075174bf90
Signed-off-by: Prasanna Kumar Kalever <prasanna.kalever@redhat.com>
This commit is contained in:
Prasanna Kumar Kalever
2018-02-05 15:07:26 +05:30
parent f217c0bf9c
commit 540e81676b
10 changed files with 1452 additions and 277 deletions

View File

@@ -14,14 +14,16 @@
# include "config.h"
# define GB_CREATE_HELP_STR "gluster-block create <volname/blockname> "\
"[ha <count>] [auth <enable|disable>] "\
"[prealloc <full|no>] <HOST1[,HOST2,...]> "\
# define GB_CREATE_HELP_STR "gluster-block create <volname/blockname> " \
"[ha <count>] [auth <enable|disable>] " \
"[prealloc <full|no>] <HOST1[,HOST2,...]> " \
"<size> [--json*]"
# define GB_DELETE_HELP_STR "gluster-block delete <volname/blockname> [force] [--json*]"
# define GB_MODIFY_HELP_STR "gluster-block modify <volname/blockname> "\
# define GB_MODIFY_HELP_STR "gluster-block modify <volname/blockname> " \
"<auth enable|disable> [--json*]"
# define GB_REPLACE_HELP_STR "gluster-block replace <volname/blockname> " \
"<old-node> <new-node> [force] [--json*]"
# define GB_INFO_HELP_STR "gluster-block info <volname/blockname> [--json*]"
# define GB_LIST_HELP_STR "gluster-block list <volname> [--json*]"
@@ -43,7 +45,8 @@ typedef enum clioperations {
LIST_CLI = 2,
INFO_CLI = 3,
DELETE_CLI = 4,
MODIFY_CLI = 5
MODIFY_CLI = 5,
REPLACE_CLI = 6
} clioperations;
@@ -59,6 +62,7 @@ glusterBlockCliRPC_1(void *cobj, clioperations opt)
blockInfoCli *info_obj;
blockListCli *list_obj;
blockModifyCli *modify_obj;
blockReplaceCli *replace_obj;
blockResponse reply = {0,};
char errMsg[2048] = {0};
@@ -145,6 +149,15 @@ glusterBlockCliRPC_1(void *cobj, clioperations opt)
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, "%sblock %s replace on volume %s failed",
clnt_sperror(clnt, "block_replace_cli_1"), replace_obj->block_name,
replace_obj->volume);
goto out;
}
break;
}
out:
@@ -204,6 +217,9 @@ glusterBlockHelp(void)
" modify <volname/blockname> <auth enable|disable>\n"
" modify block device.\n"
"\n"
" replace <volname/blockname> <old-node> <new-node> [force]\n"
" replace operations.\n"
"\n"
" help\n"
" show this message and exit.\n"
"\n"
@@ -216,13 +232,26 @@ glusterBlockHelp(void)
}
static bool
glusterBlockIsNameAcceptable (char *name)
glusterBlockIsNameAcceptable(char *name)
{
int i = 0;
if (!name || strlen(name) == 0)
if (!name || strlen(name) == 0 || strlen(name) > 255)
return FALSE;
for (i = 0; i < strlen(name); i++) {
if (!isalnum (name[i]) && (name[i] != '_') && (name[i] != '-'))
if (!isalnum(name[i]) && (name[i] != '_') && (name[i] != '-'))
return FALSE;
}
return TRUE;
}
static bool
glusterBlockIsAddrAcceptable(char *addr)
{
int i = 0;
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;
}
return TRUE;
@@ -235,9 +264,14 @@ glusterBlockParseVolumeBlock(char *volumeblock, char *volume, char *block,
int ret = -1;
size_t len = 0;
char *sep = NULL;
char *tmp = NULL;
if (GB_STRDUP(tmp, volumeblock) < 0) {
goto out;
}
/* part before '/' is the volume name */
sep = strchr(volumeblock, '/');
sep = strchr(tmp, '/');
if (!sep) {
MSG("argument '<volname/blockname>'(%s) is incorrect\n",
volumeblock);
@@ -245,29 +279,25 @@ glusterBlockParseVolumeBlock(char *volumeblock, char *volume, char *block,
LOG("cli", GB_LOG_ERROR, "%s failed while parsing <volname/blockname>", op);
goto out;
}
len = sep - volumeblock;
if (len >= 255 || strlen(sep+1) >= 255) {
MSG("%s\n", "Both volname and blockname should be less than 255 "
"characters long");
MSG("%s\n", helpstr);
LOG("cli", GB_LOG_ERROR, "%s failed while parsing <volname/blockname>", op);
*sep = '\0';
if (!glusterBlockIsNameAcceptable(tmp)) {
MSG("volume name(%s) should contain only aplhanumeric,'-', '_' characters "
"and should be less than 255 characters long\n", volume);
goto out;
}
strncpy(volume, volumeblock, len);
/* part after / is blockname */
if (!glusterBlockIsNameAcceptable(sep+1)) {
MSG("block name(%s) should contain only aplhanumeric,'-', '_' characters "
"and should be less than 255 characters long\n", block);
goto out;
}
strncpy(volume, tmp, strlen(tmp));
strncpy(block, sep+1, strlen(sep+1));
if (!glusterBlockIsNameAcceptable (volume)) {
MSG("volume name(%s) should contain only aplhanumeric,'-' "
"and '_' characters\n", volume);
goto out;
}
if (!glusterBlockIsNameAcceptable (block)) {
MSG("block name(%s) should contain only aplhanumeric,'-' "
"and '_' characters\n", block);
goto out;
}
ret = 0;
out:
GB_FREE(tmp);
return ret;
}
@@ -522,6 +552,68 @@ glusterBlockInfo(int argcount, char **options, int json)
}
static int
glusterBlockReplace(int argcount, char **options, int json)
{
blockReplaceCli robj = {0};
int ret = -1;
bool singleBlock = false;
char helpMsg[256] = {0, };
if (argcount < 5 || argcount > 6) {
MSG("Inadequate arguments for replace:\n%s\n", GB_REPLACE_HELP_STR);
return -1;
}
if (glusterBlockParseVolumeBlock(options[2], robj.volume, robj.block_name,
helpMsg, "replace")) {
goto out;
}
if (!glusterBlockIsAddrAcceptable(options[3])) {
MSG("host addr (%s) should be a valid ip address\n%s\n",
options[3], GB_REPLACE_HELP_STR);
goto out;
}
strcpy(robj.old_node, options[3]);
if (!glusterBlockIsAddrAcceptable(options[4])) {
MSG("host addr (%s) should be a valid ip address\n%s\n",
options[4], GB_REPLACE_HELP_STR);
goto out;
}
strcpy(robj.new_node, options[4]);
if (!strncmp(robj.old_node, robj.new_node, 255)) {
MSG("<old-node> (%s) and <new-node> (%s) cannot be same\n%s\n",
robj.old_node, robj.new_node, GB_REPLACE_HELP_STR);
goto out;
}
robj.json_resp = json;
if (argcount == 6) {
if (strcmp(options[5], "force")) {
MSG("unknown option '%s' for replace:\n%s\n", options[5], GB_REPLACE_HELP_STR);
return -1;
} else {
robj.force = true;
}
}
ret = glusterBlockCliRPC_1(&robj, REPLACE_CLI);
if (ret) {
LOG("cli", GB_LOG_ERROR, "failed replace on volume %s",
robj.volume);
}
out:
return ret;
}
static int
glusterBlockParseArgs(int count, char **options)
{
@@ -577,6 +669,13 @@ glusterBlockParseArgs(int count, char **options)
}
goto out;
case GB_CLI_REPLACE:
ret = glusterBlockReplace(count, options, json);
if (ret) {
LOG("cli", GB_LOG_ERROR, "%s", FAILED_REPLACE);
}
goto out;
case GB_CLI_DELETE:
ret = glusterBlockDelete(count, options, json);
if (ret) {

File diff suppressed because it is too large Load Diff

View File

@@ -358,6 +358,115 @@ blockStuffMetaInfo(MetaInfo *info, char *line)
}
int
blockParseValidServers(struct glfs* glfs, char *metafile,
int *errCode, blockServerDefPtr *savelist, char *skiphost)
{
blockServerDefPtr list = *savelist;
char fpath[PATH_MAX] = {0};
struct glfs_fd *tgmfd = NULL;
char line[1024];
int ret = -1;
char *h, *s, *sep;
size_t i, count = 0;
bool match;
snprintf(fpath, sizeof fpath, "%s/%s", GB_METADIR, metafile);
tgmfd = glfs_open(glfs, fpath, O_RDONLY);
if (!tgmfd) {
if (errCode) {
*errCode = errno;
}
LOG("gfapi", GB_LOG_ERROR, "glfs_open(%s) failed[%s]", metafile,
strerror(errno));
goto out;
}
while ((ret = glfs_read (tgmfd, line, sizeof(line), 0)) > 0) {
/* clip till current line */
h = line;
sep = strchr(h, '\n');
*sep = '\0';
count += strlen(h) + 1;
/* Part before ':' */
sep = strchr(h, ':');
*sep = '\0';
switch (blockMetaKeyEnumParse(h)) {
case GB_META_VOLUME:
case GB_META_GBID:
case GB_META_SIZE:
case GB_META_HA:
case GB_META_ENTRYCREATE:
case GB_META_PASSWD:
break;
default:
if (skiphost && !strcmp(h, skiphost)) {
break; /* switch case */
}
/* Part after ':' and before '\n' */
s = sep + 1;
while(*s == ' ') {
s++;
}
if (!list) {
if (blockhostIsValid(s)) {
if (GB_ALLOC(list) < 0)
goto out;
if (GB_ALLOC(list->hosts) < 0)
goto out;
if (GB_STRDUP(list->hosts[0], h) < 0)
goto out;
list->nhosts = 1;
}
} else {
match = false;
for (i = 0; i < list->nhosts; i++) {
if (!strcmp(list->hosts[i], h)) {
match = true;
break; /* for loop */
}
}
if (!match && blockhostIsValid(s)){
if(GB_REALLOC_N(list->hosts, list->nhosts+1) < 0)
goto out;
if (GB_STRDUP(list->hosts[list->nhosts], h) < 0)
goto out;
list->nhosts++;
}
}
break; /* switch case */
}
glfs_lseek(tgmfd, count, SEEK_SET);
}
if (ret < 0 && errCode) { /*Failure from glfs_read*/
*errCode = errno;
goto out;
}
*savelist = list;
list = NULL;
ret = 0;
out:
if (tgmfd && glfs_close(tgmfd) != 0) {
LOG("gfapi", GB_LOG_ERROR, "glfs_close(%s): failed[%s]",
metafile, strerror(errno));
}
blockServerDefFree(list);
return ret;
}
int
blockGetMetaInfo(struct glfs* glfs, char* metafile, MetaInfo *info,
int *errCode)

View File

@@ -64,4 +64,8 @@ blockGetMetaInfo(struct glfs* glfs, char* metafile, MetaInfo *info,
void
blockFreeMetaInfo(MetaInfo *info);
int
blockParseValidServers(struct glfs* glfs, char *metafile, int *errCode,
blockServerDefPtr *savelist, char *skiphost);
#endif /* _GLFS_OPERATIONS_H */

View File

@@ -33,6 +33,14 @@ struct blockModify {
bool auth_mode;
};
struct blockReplace {
char volume[255];
char block_name[255];
char gbid[127];
char ipaddr[255];
char ripaddr[255];
};
struct blockCreateCli {
char volume[255];
u_quad_t size;
@@ -75,6 +83,15 @@ struct blockModifyCli {
enum JsonResponseFormat json_resp;
};
struct blockReplaceCli {
char volume[255];
char block_name[255];
char old_node[255];
char new_node[255];
bool force;
enum JsonResponseFormat json_resp;
};
struct blockResponse {
int exit; /* exit code of the command */
string out<>; /* output; TODO: return respective objects */
@@ -88,6 +105,7 @@ program GLUSTER_BLOCK {
blockResponse BLOCK_DELETE(blockDelete) = 2;
blockResponse BLOCK_MODIFY(blockModify) = 3;
blockResponse BLOCK_VERSION() = 4;
blockResponse BLOCK_REPLACE(blockReplace) = 5;
} = 1;
} = 21215311; /* B2 L12 O15 C3 K11 */
@@ -98,5 +116,6 @@ program GLUSTER_BLOCK_CLI {
blockResponse BLOCK_INFO_CLI(blockInfoCli) = 3;
blockResponse BLOCK_DELETE_CLI(blockDeleteCli) = 4;
blockResponse BLOCK_MODIFY_CLI(blockModifyCli) = 5;
blockResponse BLOCK_REPLACE_CLI(blockReplaceCli) = 6;
} = 1;
} = 212153113; /* B2 L12 O15 C3 K11 C3 */

View File

@@ -37,6 +37,8 @@ enum gbCapabilities {
GB_MODIFY_CAP,
GB_MODIFY_AUTH_CAP,
GB_REPLACE_CAP,
GB_JSON_CAP,
GB_CAP_MAX
@@ -55,6 +57,8 @@ static const char *const gbCapabilitiesLookup[] = {
[GB_MODIFY_CAP] = "modify",
[GB_MODIFY_AUTH_CAP] = "modify_auth",
[GB_REPLACE_CAP] = "replace",
[GB_JSON_CAP] = "json",
[GB_CAP_MAX] = NULL

View File

@@ -157,3 +157,43 @@ convertStringToTrillianParse(const char *opt)
return -1;
}
void
blockServerDefFree(blockServerDefPtr blkServers)
{
size_t i;
if (!blkServers) {
return;
}
for (i = 0; i < blkServers->nhosts; i++) {
GB_FREE(blkServers->hosts[i]);
}
GB_FREE(blkServers->hosts);
GB_FREE(blkServers);
}
bool
blockhostIsValid(char *status)
{
switch (blockMetaStatusEnumParse(status)) {
case GB_CONFIG_SUCCESS:
case GB_CLEANUP_INPROGRESS:
case GB_AUTH_ENFORCEING:
case GB_AUTH_ENFORCED:
case GB_AUTH_ENFORCE_FAIL:
case GB_AUTH_CLEAR_ENFORCED:
case GB_AUTH_CLEAR_ENFORCEING:
case GB_AUTH_CLEAR_ENFORCE_FAIL:
case GB_RP_SUCCESS:
case GB_RP_FAIL:
case GB_RP_INPROGRESS:
return TRUE;
}
return FALSE;
}

View File

@@ -16,6 +16,13 @@
# include "block.h"
typedef struct blockServerDef {
size_t nhosts;
char **hosts;
} blockServerDef;
typedef blockServerDef *blockServerDefPtr;
static const char *const JsonResponseFormatLookup[] = {
[GB_JSON_NONE] = "",
@@ -82,4 +89,8 @@ char* glusterBlockFormatSize(const char *dom, size_t bytes);
int convertStringToTrillianParse(const char *opt);
void blockServerDefFree(blockServerDefPtr blkServers);
bool blockhostIsValid(char *status);
# endif /* _COMMON_H */

View File

@@ -96,3 +96,15 @@ modify_auth: true
# Since: 0.2
##
json: true
##
# Nature: cli command
#
# Label: 'replace'
#
# Description: capability to replace node for a given block
#
# Since: 0.4
##
replace: true

View File

@@ -85,6 +85,10 @@
# define FAILED_DELETING_FILE "failed while deleting block file from gluster volume"
# define FAILED_DELETING_META "failed while deleting block meta file from volume"
/* Target Replace */
# define FAILED_REPLACE "failed in replace"
# define FAILED_REMOTE_REPLACE "failed in remote replace portal"
# define FAILED_DEPENDENCY "failed dependency, check if you have targetcli and tcmu-runner installed"
# define FMT_WARN(fmt...) do { if (0) printf (fmt); } while (0)
@@ -328,18 +332,19 @@ extern struct gbConf gbConf;
typedef enum gbCliCmdlineOption {
GB_CLI_UNKNOWN = 0,
GB_CLI_CREATE = 1,
GB_CLI_LIST = 2,
GB_CLI_INFO = 3,
GB_CLI_DELETE = 4,
GB_CLI_MODIFY = 5,
GB_CLI_HELP = 6,
GB_CLI_HYPHEN_HELP = 7,
GB_CLI_VERSION = 8,
GB_CLI_HYPHEN_VERSION = 9,
GB_CLI_USAGE = 10,
GB_CLI_HYPHEN_USAGE = 11,
GB_CLI_UNKNOWN = 0,
GB_CLI_CREATE,
GB_CLI_LIST,
GB_CLI_INFO,
GB_CLI_DELETE,
GB_CLI_MODIFY,
GB_CLI_REPLACE,
GB_CLI_HELP,
GB_CLI_HYPHEN_HELP,
GB_CLI_VERSION,
GB_CLI_HYPHEN_VERSION,
GB_CLI_USAGE,
GB_CLI_HYPHEN_USAGE,
GB_CLI_OPT_MAX
} gbCliCmdlineOption;
@@ -351,6 +356,7 @@ static const char *const gbCliCmdlineOptLookup[] = {
[GB_CLI_INFO] = "info",
[GB_CLI_DELETE] = "delete",
[GB_CLI_MODIFY] = "modify",
[GB_CLI_REPLACE] = "replace",
[GB_CLI_HELP] = "help",
[GB_CLI_HYPHEN_HELP] = "--help",
[GB_CLI_VERSION] = "version",
@@ -442,6 +448,9 @@ typedef enum MetaStatus {
GB_CLEANUP_SUCCESS = 9,
GB_CLEANUP_FAIL = 10,
GB_CLEANUP_INPROGRESS = 11,
GB_RP_SUCCESS = 12,
GB_RP_INPROGRESS = 13,
GB_RP_FAIL = 14,
GB_METASTATUS_MAX
} MetaStatus;
@@ -459,6 +468,9 @@ static const char *const MetaStatusLookup[] = {
[GB_CLEANUP_INPROGRESS] = "CLEANUPINPROGRESS",
[GB_CLEANUP_SUCCESS] = "CLEANUPSUCCESS",
[GB_CLEANUP_FAIL] = "CLEANUPFAIL",
[GB_RP_SUCCESS] = "RPSUCCESS",
[GB_RP_INPROGRESS] = "RPINPROGRESS",
[GB_RP_FAIL] = "RPFAIL",
[GB_METASTATUS_MAX] = NULL,
};