From 1ed7bd14303fca5c3dd36a30a88d4d2d053f4334 Mon Sep 17 00:00:00 2001 From: Prasanna Kumar Kalever Date: Mon, 10 Apr 2017 12:32:47 +0530 Subject: modify: add support for one way authentication This patch introduce or rather implement modify command for enabling authentication for block devices. The schematics of authentication setting, looks like $ gluster-block modify block-test/sample-block auth enable --json-pretty { "SUCCESSFUL ON":[ "192.168.0.105" ], "IQN":"iqn.2016-12.org.gluster-block:8917def2-e90d-4406-8c9c-6d06b6851bbe", "USERNAME":"8917def2-e90d-4406-8c9c-6d06b6851bbe", "PASSWORD":"a3e75362-a446-45af-98d0-a1ed7e10d7f0", "RESULT":"SUCCESS" } As an effect it brings changes in 'info' command response, note PASSWORD $ gluster-block info block-test/sample-block --json-pretty { "NAME":"sample-block", "VOLUME":"block-test", "GBID":"8917def2-e90d-4406-8c9c-6d06b6851bbe", "SIZE":1073741824, "HA":1, "PASSWORD":"a3e75362-a446-45af-98d0-a1ed7e10d7f0", "BLOCK CONFIG NODE(S)":[ "192.168.0.105" ] } The schematics of auth disabling, looks like $ gluster-block modify block-test/sample-block auth disable --json-pretty { "SUCCESSFUL ON":[ "192.168.0.105" ], "IQN":"iqn.2016-12.org.gluster-block:add99c38-3c14-42d7-bf23-7d02f388e1e7", "RESULT":"SUCCESS" } Change-Id: I06d095b50401c131ac89cc142497f21d2205164a Fixes: #5 Signed-off-by: Prasanna Kumar Kalever --- cli/gluster-block.c | 204 ++++++++---- docs/gluster-block.8 | 5 + rpc/block_svc_routines.c | 805 ++++++++++++++++++++++++++++++++++++++++------- rpc/glfs-operations.c | 3 + rpc/glfs-operations.h | 1 + rpc/rpcl/block.x | 17 + tests/basic.t | 12 + utils/common.h | 2 + utils/utils.h | 47 ++- 9 files changed, 903 insertions(+), 193 deletions(-) diff --git a/cli/gluster-block.c b/cli/gluster-block.c index d5f9c02..3020587 100644 --- a/cli/gluster-block.c +++ b/cli/gluster-block.c @@ -12,6 +12,7 @@ # include "common.h" # include "block.h" # include "config.h" +# include @@ -19,7 +20,8 @@ typedef enum clioperations { CREATE_CLI = 1, LIST_CLI = 2, INFO_CLI = 3, - DELETE_CLI = 4 + DELETE_CLI = 4, + MODIFY_CLI = 5 } clioperations; const char *argp_program_version = "" \ @@ -36,6 +38,8 @@ const char *argp_program_version = "" \ "[ha ] [--json*]" #define GB_DELETE_HELP_STR "gluster-block delete [--json*]" +#define GB_MODIFY_HELP_STR "gluster-block modify "\ + " [--json*]" #define GB_INFO_HELP_STR "gluster-block info [--json*]" #define GB_LIST_HELP_STR "gluster-block list [--json*]" @@ -50,6 +54,7 @@ glusterBlockCliRPC_1(void *cobj, clioperations opt, char **out) blockDeleteCli *delete_obj; blockInfoCli *info_obj; blockListCli *list_obj; + blockModifyCli *modify_obj; blockResponse *reply = NULL; @@ -133,6 +138,15 @@ glusterBlockCliRPC_1(void *cobj, clioperations opt, char **out) goto out; } break; + case MODIFY_CLI: + modify_obj = cobj; + reply = block_modify_cli_1(modify_obj, clnt); + if (!reply) { + LOG("cli", GB_LOG_ERROR, "%sblock modify on volume %s failed", + clnt_sperror(clnt, "block_modify_cli_1"), modify_obj->volume); + goto out; + } + break; } if (reply) { @@ -180,6 +194,9 @@ glusterBlockHelp(void) " delete \n" " delete block device.\n" "\n" + " modify \n" + " modify block device.\n" + "\n" " help\n" " show this message and exit.\n" "\n" @@ -191,6 +208,116 @@ glusterBlockHelp(void) ); } +static bool +glusterBlockIsNameAcceptable (char *name) +{ + int i = 0; + if (!name || strlen(name) == 0) + return FALSE; + for (i = 0; i < strlen(name); i++) { + if (!isalnum (name[i]) && (name[i] != '_') && (name[i] != '-')) + return FALSE; + } + return TRUE; +} + +static int +glusterBlockParseVolumeBlock(char *volumeblock, char *volume, char *block, + char *helpstr, char *op) +{ + int ret = -1; + size_t len = 0; + char *sep = NULL; + + /* part before '/' is the volume name */ + sep = strchr(volumeblock, '/'); + if (!sep) { + MSG("argument ''(%s) doesn't seems to be right", + volumeblock); + MSG("%s\n", helpstr); + LOG("cli", GB_LOG_ERROR, "%s failed while parsing ", 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 ", op); + goto out; + } + strncpy(volume, volumeblock, len); + /* part after / is blockname */ + strncpy(block, sep+1, strlen(sep+1)); + if (!glusterBlockIsNameAcceptable (volume)) { + MSG("volume name(%s) should contain only aplhanumeric,'-' " + "and '_' characters", volume); + goto out; + } + if (!glusterBlockIsNameAcceptable (block)) { + MSG("block name(%s) should contain only aplhanumeric,'-' " + "and '_' characters", block); + goto out; + } + ret = 0; + out: + return ret; +} + +static int +glusterBlockModify(int argcount, char **options, int json) +{ + size_t optind = 2; + blockModifyCli mobj = {0, }; + int ret = -1; + char *out = NULL; + + mobj.json_resp = json; + if (argcount != 5) { + MSG("%s\n", "Insufficient arguments for modify:"); + MSG("%s\n", GB_MODIFY_HELP_STR); + return -1; + } + + if (glusterBlockParseVolumeBlock (options[optind++], mobj.volume, + mobj.block_name, 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++; + if(strcmp (options[optind], "enable") == 0) { + mobj.auth_mode = 1; + } else if (strcmp (options[optind], "disable") == 0) { + mobj.auth_mode = 0; + } else { + MSG("%s\n", "argument to 'auth' doesn't seems to be right"); + MSG("%s\n", GB_MODIFY_HELP_STR); + LOG("cli", GB_LOG_ERROR, "Modify failed while parsing argument " + "to auth for <%s/%s>", + mobj.volume, mobj.block_name); + goto out; + } + } + + ret = glusterBlockCliRPC_1(&mobj, MODIFY_CLI, &out); + if (ret) { + LOG("cli", GB_LOG_ERROR, + "failed getting info of block %s on volume %s", + mobj.block_name, mobj.volume); + } + + if (out) { + MSG("%s", out); + } + + out: + GB_FREE(out); + + return ret; +} static int glusterBlockCreate(int argcount, char **options, int json) @@ -200,8 +327,6 @@ glusterBlockCreate(int argcount, char **options, int json) ssize_t sparse_ret; char *out = NULL; blockCreateCli cobj = {0, }; - char *argcopy; - char *sep; cobj.json_resp = json; @@ -214,24 +339,11 @@ glusterBlockCreate(int argcount, char **options, int json) /* default mpath */ cobj.mpath = 1; - if (GB_STRDUP (argcopy, options[optind++]) < 0) { - goto out; - } - /* part before '/' is the volume name */ - sep = strchr(argcopy, '/'); - if (!sep) { - MSG("%s\n", - "first argument '' doesn't seems to be right"); - MSG("%s\n", GB_CREATE_HELP_STR); - LOG("cli", GB_LOG_ERROR, "%s", - "create failed while parsing "); + if (glusterBlockParseVolumeBlock (options[optind++], cobj.volume, + cobj.block_name, GB_CREATE_HELP_STR, + "create")) { goto out; } - *sep = '\0'; - strcpy(cobj.volume, argcopy); - - /* part after / is blockname */ - strcpy(cobj.block_name, sep + 1); if (argcount - optind >= 2) { /* atleast 2 needed */ /* if ha given then collect count which is next by 'ha' arg */ @@ -280,7 +392,6 @@ glusterBlockCreate(int argcount, char **options, int json) } out: - GB_FREE(argcopy); GB_FREE(cobj.block_hosts); GB_FREE(out); @@ -291,7 +402,7 @@ glusterBlockCreate(int argcount, char **options, int json) static int glusterBlockList(int argcount, char **options, int json) { - blockListCli cobj; + blockListCli cobj = {0}; char *out = NULL; int ret = -1; @@ -324,10 +435,8 @@ glusterBlockList(int argcount, char **options, int json) static int glusterBlockDelete(int argcount, char **options, int json) { - blockDeleteCli cobj; + blockDeleteCli cobj = {0}; char *out = NULL; - char *argcopy; - char *sep; int ret = -1; @@ -339,23 +448,11 @@ glusterBlockDelete(int argcount, char **options, int json) } - if (GB_STRDUP (argcopy, options[2]) < 0) { - goto out; - } - /* part before '/' is the volume name */ - sep = strchr(argcopy, '/'); - if (!sep) { - MSG("%s\n", "argument '' doesn't seems to be right"); - MSG("%s\n", GB_DELETE_HELP_STR); - LOG("cli", GB_LOG_ERROR, "%s", - "delete failed while parsing "); + if (glusterBlockParseVolumeBlock (options[2], cobj.volume, + cobj.block_name, GB_DELETE_HELP_STR, + "delete")) { goto out; } - *sep = '\0'; - strcpy(cobj.volume, argcopy); - - /* part after / is blockname */ - strcpy(cobj.block_name, sep + 1); ret = glusterBlockCliRPC_1(&cobj, DELETE_CLI, &out); if (ret) { @@ -368,7 +465,6 @@ glusterBlockDelete(int argcount, char **options, int json) } out: - GB_FREE(argcopy); GB_FREE(out); return ret; @@ -378,10 +474,8 @@ glusterBlockDelete(int argcount, char **options, int json) static int glusterBlockInfo(int argcount, char **options, int json) { - blockInfoCli cobj; + blockInfoCli cobj = {0}; char *out = NULL; - char *argcopy; - char *sep; int ret = -1; @@ -393,23 +487,11 @@ glusterBlockInfo(int argcount, char **options, int json) } - if (GB_STRDUP (argcopy, options[2]) < 0) { - goto out; - } - /* part before '/' is the volume name */ - sep = strchr(argcopy, '/'); - if (!sep) { - MSG("%s\n", "argument '' doesn't seems to be right"); - MSG("%s\n", GB_INFO_HELP_STR); - LOG("cli", GB_LOG_ERROR, "%s", - "info failed while parsing "); + if (glusterBlockParseVolumeBlock (options[2], cobj.volume, + cobj.block_name, GB_INFO_HELP_STR, + "info")) { goto out; } - *sep = '\0'; - strcpy(cobj.volume, argcopy); - - /* part after / is blockname */ - strcpy(cobj.block_name, sep + 1); ret = glusterBlockCliRPC_1(&cobj, INFO_CLI, &out); if (ret) { @@ -423,7 +505,6 @@ glusterBlockInfo(int argcount, char **options, int json) } out: - GB_FREE(argcopy); GB_FREE(out); return ret; @@ -479,7 +560,10 @@ glusterBlockParseArgs(int count, char **options) goto out; case GB_CLI_MODIFY: - MSG("option '%s' is not supported yet.\n", options[1]); + ret = glusterBlockModify(count, options, json); + if (ret) { + LOG("cli", GB_LOG_ERROR, "%s", FAILED_MODIFY); + } goto out; case GB_CLI_DELETE: diff --git a/docs/gluster-block.8 b/docs/gluster-block.8 index 66d29e7..1ae08af 100644 --- a/docs/gluster-block.8 +++ b/docs/gluster-block.8 @@ -53,6 +53,11 @@ details about block device. delete block device. .PP +.SS +\fBmodify\fR +modify block device. +.PP + .SS .BR help show this message and exit. diff --git a/rpc/block_svc_routines.c b/rpc/block_svc_routines.c index b966e05..8b3eaea 100644 --- a/rpc/block_svc_routines.c +++ b/rpc/block_svc_routines.c @@ -19,6 +19,7 @@ # define UUID_BUF_SIZE 38 +# define GB_DEFAULT_ERRCODE 255 # define GB_CREATE "create" # define GB_DELETE "delete" @@ -42,7 +43,8 @@ pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER; typedef enum operations { CREATE_SRV = 1, - DELETE_SRV = 2 + DELETE_SRV = 2, + MODIFY_SRV = 3 } operations; @@ -56,6 +58,14 @@ typedef struct blockRemoteObj { } blockRemoteObj; +typedef struct blockRemoteModifyResp { + char *attempt; + char *success; + char *rb_attempt; + char *rb_success; +} blockRemoteModifyResp; + + typedef struct blockRemoteDeleteResp { char *d_attempt; char *d_success; @@ -326,6 +336,14 @@ glusterBlockCallRPC_1(char *host, void *cobj, goto out; } break; + case MODIFY_SRV: + reply = block_modify_1((blockModify *)cobj, clnt); + if (!reply) { + LOG("mgmt", GB_LOG_ERROR, "%son host %s", + clnt_sperror(clnt, "block remote modify failed"), host); + goto out; + } + break; } if (reply) { @@ -466,7 +484,7 @@ glusterBlockCreateRemote(void *data) out: if (!args->reply) { - if (GB_ASPRINTF(&args->reply, "failed to config on %s %s\n", args->addr, + if (GB_ASPRINTF(&args->reply, "failed to configure on %s %s\n", args->addr, errMsg?errMsg:"") == -1) { ret = -1; } @@ -577,8 +595,8 @@ glusterBlockDeleteRemote(void *data) out: if (!args->reply) { - if (GB_ASPRINTF(&args->reply, "failed to delete config on %s", - args->addr) == -1) { + if (GB_ASPRINTF(&args->reply, "failed to delete config on %s %s", + args->addr, errMsg?errMsg:"") == -1) { ret = -1; } } @@ -589,6 +607,76 @@ glusterBlockDeleteRemote(void *data) } +static size_t +glusterBlockDeleteFillArgs(MetaInfo *info, bool deleteall, blockRemoteObj *args, + struct glfs *glfs, blockDelete *dobj) +{ + int i = 0; + size_t count = 0; + + for (i = 0, count = 0; i < info->nhosts; i++) { + switch (blockMetaStatusEnumParse(info->list[i]->status)) { + case GB_CONFIG_SUCCESS: + 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: + if (!deleteall) + break; + case GB_CLEANUP_INPROGRESS: + case GB_CLEANUP_FAIL: + case GB_CONFIG_FAIL: + if (args) { + args[count].glfs = glfs; + args[count].obj = (void *)dobj; + args[count].volume = info->volume; + args[count].addr = info->list[i]->addr; + } + count++; + break; + } + } + return count; +} + + +static int +glusterBlockCollectAttemptSuccess (blockRemoteObj *args, size_t count, + char **attempt, char **success) +{ + char *a_tmp = NULL; + char *s_tmp = NULL; + int i = 0; + + for (i = 0; i < count; i++) { + if (args[i].exit) { + if (GB_ASPRINTF(attempt, "%s %s", + (a_tmp==NULL?"":a_tmp), args[i].addr) == -1) { + goto fail; + } + GB_FREE(a_tmp); + a_tmp = *attempt; + } else { + if (GB_ASPRINTF(success, "%s %s", + (s_tmp==NULL?"":s_tmp), args[i].addr) == -1) { + goto fail; + } + GB_FREE(s_tmp); + s_tmp = *success; + } + } + return 0; + fail: + GB_FREE(a_tmp); + GB_FREE(s_tmp); + *attempt = NULL; + *success = NULL; + return -1; +} + + static int glusterBlockDeleteRemoteAsync(MetaInfo *info, struct glfs *glfs, @@ -599,7 +687,7 @@ glusterBlockDeleteRemoteAsync(MetaInfo *info, { pthread_t *tid = NULL; blockRemoteDeleteResp *local = *savereply; - static blockRemoteObj *args = NULL; + blockRemoteObj *args = NULL; char *d_attempt = NULL; char *d_success = NULL; char *a_tmp = NULL; @@ -616,27 +704,7 @@ glusterBlockDeleteRemoteAsync(MetaInfo *info, goto out; } - for (i = 0, count = 0; i < info->nhosts; i++) { - switch (blockMetaStatusEnumParse(info->list[i]->status)) { - case GB_CLEANUP_INPROGRESS: - case GB_CLEANUP_FAIL: - case GB_CONFIG_FAIL: - args[count].glfs = glfs; - args[count].obj = (void *)dobj; - args[count].volume = info->volume; - args[count].addr = info->list[i]->addr; - count++; - break; - } - if (deleteall && - blockMetaStatusEnumParse(info->list[i]->status) == GB_CONFIG_SUCCESS) { - args[count].glfs = glfs; - args[count].obj = (void *)dobj; - args[count].volume = info->volume; - args[count].addr = info->list[i]->addr; - count++; - } - } + count = glusterBlockDeleteFillArgs(info, deleteall, args, glfs, dobj); for (i = 0; i < count; i++) { pthread_create(&tid[i], NULL, glusterBlockDeleteRemote, &args[i]); @@ -646,23 +714,9 @@ glusterBlockDeleteRemoteAsync(MetaInfo *info, pthread_join(tid[i], NULL); } - /* collect return */ - for (i = 0; i < count; i++) { - if (args[i].exit) { - if (GB_ASPRINTF(&d_attempt, "%s %s", - (a_tmp==NULL?"":a_tmp), args[i].addr) == -1) { - goto out; - } - GB_FREE(a_tmp); - a_tmp = d_attempt; - } else { - if (GB_ASPRINTF(&d_success, "%s %s", - (s_tmp==NULL?"":s_tmp), args[i].addr) == -1) { - goto out; - } - GB_FREE(s_tmp); - s_tmp = d_success; - } + ret = glusterBlockCollectAttemptSuccess (args, count, &d_attempt, &d_success); + if (ret) { + goto out; } if (d_attempt) { @@ -707,6 +761,172 @@ glusterBlockDeleteRemoteAsync(MetaInfo *info, } +void * +glusterBlockModifyRemote(void *data) +{ + int ret; + blockRemoteObj *args = (blockRemoteObj *)data; + blockModify cobj = *(blockModify *)args->obj; + char *errMsg = NULL; + + GB_METAUPDATE_OR_GOTO(lock, args->glfs, cobj.block_name, cobj.volume, + ret, errMsg, out, "%s: AUTH%sENFORCEING\n", args->addr, + cobj.auth_mode?"":"CLEAR"); + + ret = glusterBlockCallRPC_1(args->addr, &cobj, MODIFY_SRV, &args->reply); + if (ret) { + if (errno == ENETUNREACH || errno == ECONNREFUSED || errno == ETIMEDOUT) { + LOG("mgmt", GB_LOG_ERROR, "%s hence %s for block %s on" + "host %s volume %s", strerror(errno), FAILED_REMOTE_MODIFY, + cobj.block_name, args->addr, args->volume); + goto out; + } + + if (ret == EKEYEXPIRED) { + LOG("mgmt", GB_LOG_ERROR, "%s [%s] hence modify block %s on" + "host %s volume %s failed", FAILED_DEPENDENCY, strerror(errno), + cobj.block_name, args->addr, args->volume); + goto out; + } + + GB_METAUPDATE_OR_GOTO(lock, args->glfs, cobj.block_name, cobj.volume, + ret, errMsg, out, "%s: AUTH%sENFORCEFAIL\n", + args->addr, cobj.auth_mode?"":"CLEAR"); + LOG("mgmt", GB_LOG_ERROR, "%s for block %s on host %s volume %s", + FAILED_REMOTE_MODIFY, cobj.block_name, args->addr, args->volume); + goto out; + } + + GB_METAUPDATE_OR_GOTO(lock, args->glfs, cobj.block_name, cobj.volume, + ret, errMsg, out, "%s: AUTH%sENFORCED\n", args->addr, + cobj.auth_mode?"":"CLEAR"); + + out: + if (!args->reply) { + if (GB_ASPRINTF(&args->reply, "failed to configure auth on %s %s", + args->addr, errMsg?errMsg:"") == -1) { + ret = -1; + } + } + GB_FREE(errMsg); + args->exit = ret; + + return NULL; +} + +static size_t +glusterBlockModifyArgsFill(blockModify *mobj, MetaInfo *info, + blockRemoteObj *args, struct glfs *glfs) +{ + int i = 0; + size_t count = 0; + bool fill = FALSE; + + for (i = 0, count = 0; i < info->nhosts; i++) { + switch (blockMetaStatusEnumParse(info->list[i]->status)) { + case GB_CONFIG_SUCCESS: + /* case GB_AUTH_ENFORCED: this is not required to be configured */ + case GB_AUTH_ENFORCE_FAIL: + case GB_AUTH_CLEAR_ENFORCED: + if (mobj->auth_mode) { + fill = TRUE; + } + break; + case GB_AUTH_ENFORCED: + if (!mobj->auth_mode) { + fill = TRUE; + } + break; + case GB_AUTH_ENFORCEING: + case GB_AUTH_CLEAR_ENFORCEING: + case GB_AUTH_CLEAR_ENFORCE_FAIL: + fill = TRUE; + break; + } + if (fill) { + if (args) { + args[count].glfs = glfs; + args[count].obj = (void *)mobj; + args[count].addr = info->list[i]->addr; + } + count++; + } + fill = FALSE; + } + return count; +} + + +static int +glusterBlockModifyRemoteAsync(MetaInfo *info, + struct glfs *glfs, + blockModify *mobj, + blockRemoteModifyResp **savereply, + bool rollback) +{ + pthread_t *tid = NULL; + blockRemoteModifyResp *local = *savereply; + blockRemoteObj *args = NULL; + int ret = -1; + size_t i; + size_t count = 0; + + + /* get all (configured - already auth enforced) node count */ + count = glusterBlockModifyArgsFill(mobj, info, NULL, glfs); + + if (GB_ALLOC_N(tid, count) < 0) { + goto out; + } + + if (GB_ALLOC_N(args, count) < 0) { + goto out; + } + + count = glusterBlockModifyArgsFill(mobj, info, args, glfs); + + for (i = 0; i < count; i++) { + pthread_create(&tid[i], NULL, glusterBlockModifyRemote, &args[i]); + } + + for (i = 0; i < count; i++) { + /* collect exit code */ + pthread_join(tid[i], NULL); + } + + if (!rollback) { + /* collect return */ + ret = glusterBlockCollectAttemptSuccess (args, count, &local->attempt, + &local->success); + if (ret) + goto out; + } else { + /* collect return */ + ret = glusterBlockCollectAttemptSuccess (args, count, + &local->rb_attempt, + &local->rb_success); + if (ret) + goto out; + } + for (i = 0; i < count; i++) { + if (args[i].exit == EKEYEXPIRED) { + ret = EKEYEXPIRED; + break; /* important to catch */ + } else if (args[i].exit) { + ret = -1; + } + } + + *savereply = local; + + out: + GB_FREE(args); + GB_FREE(tid); + + return ret; +} + + static int glusterBlockCleanUp(operations opt, struct glfs *glfs, char *blockname, bool deleteall, void *reply) @@ -747,20 +967,7 @@ glusterBlockCleanUp(operations opt, struct glfs *glfs, char *blockname, strcpy(dobj.block_name, blockname); strcpy(dobj.gbid, info->gbid); - for (i = 0; i < info->nhosts; i++) { - switch (blockMetaStatusEnumParse(info->list[i]->status)) { - case GB_CLEANUP_INPROGRESS: - case GB_CLEANUP_FAIL: - case GB_CONFIG_FAIL: - count++; - break; - } - if (deleteall && - blockMetaStatusEnumParse(info->list[i]->status) == GB_CONFIG_SUCCESS) { - count++; - } - } - + count = glusterBlockDeleteFillArgs(info, deleteall, NULL, NULL, NULL); asyncret = glusterBlockDeleteRemoteAsync(info, glfs, &dobj, count, deleteall, &drobj); if (asyncret) { @@ -873,7 +1080,7 @@ glusterBlockAuditRequest(struct glfs *glfs, morereq = blk->mpath - successcnt; /* needed nodes to complete req */ if (spare == 0) { LOG("mgmt", GB_LOG_WARNING, - "No Spare nodes to create (%s): rewinding creation of target" + "No Spare nodes to create (%s): rollingback creation of target" " on volume %s with given hosts %s", blk->block_name, blk->volume, blk->block_hosts); glusterBlockCleanUp(CREATE_SRV, glfs, @@ -883,7 +1090,7 @@ glusterBlockAuditRequest(struct glfs *glfs, goto out; } else if (spare < morereq) { LOG("mgmt", GB_LOG_WARNING, - "Not enough Spare nodes for (%s): rewinding creation of target" + "Not enough Spare nodes for (%s): rollingback creation of target" " on volume %s with given hosts %s", blk->block_name, blk->volume, blk->block_hosts); glusterBlockCleanUp(CREATE_SRV, glfs, @@ -927,8 +1134,8 @@ glusterBlockAuditRequest(struct glfs *glfs, } void -block_format_error_response (int json_resp, int errCode, char *errMsg, - struct blockResponse *reply) +blockFormatErrorResponse (int json_resp, int errCode, char *errMsg, + struct blockResponse *reply) { json_object *json_obj = NULL; reply->exit = errCode; @@ -946,10 +1153,277 @@ block_format_error_response (int json_resp, int errCode, char *errMsg, } } +static void +blockStr2arrayAddToJsonObj (json_object *json_obj, char *string, char *label, + json_object **json_array) +{ + char *tmp = NULL; + json_object *json_array1 = NULL; + + if (!string) + return; + + json_array1 = json_object_new_array(); + tmp = strtok (string, " "); + while (tmp != NULL) + { + json_object_array_add(json_array1, json_object_new_string(tmp)); + tmp = strtok (NULL, " "); + } + json_object_object_add(json_obj, label, json_array1); + *json_array = json_array1; +} + +static void +blockModifyCliFormatResponse (blockModifyCli *blk, struct blockModify *mobj, + int errCode, char *errMsg, + blockRemoteModifyResp *savereply, + MetaInfo *info, struct blockResponse *reply, + bool rollback) +{ + json_object *json_obj = NULL; + json_object *json_array[4] = {0}; + char *tmp2 = NULL; + char *tmp3 = NULL; + char *tmp = NULL; + int i = 0; + + if (!reply) { + return; + } + + if (errCode < 0) { + errCode = GB_DEFAULT_ERRCODE; + } + + if (errMsg) { + blockFormatErrorResponse(blk->json_resp, errCode, errMsg, reply); + return; + } + + if (blk->json_resp) { + json_obj = json_object_new_object(); + + blockStr2arrayAddToJsonObj (json_obj, savereply->attempt, "FAILED ON", + &json_array[0]); + + if (savereply->success) { + blockStr2arrayAddToJsonObj (json_obj, savereply->success, + "SUCCESSFUL ON", &json_array[1]); + tmp = NULL; + + GB_ASPRINTF(&tmp, "%s%s", GB_TGCLI_IQN_PREFIX, info->gbid); + json_object_object_add(json_obj, "IQN", + json_object_new_string(tmp?tmp:"")); + if (mobj->auth_mode) { + json_object_object_add(json_obj, "USERNAME", + json_object_new_string(info->gbid)); + json_object_object_add(json_obj, "PASSWORD", + json_object_new_string(mobj->passwd)); + } + } + + json_object_object_add(json_obj, "RESULT", + errCode?json_object_new_string("FAIL"):json_object_new_string("SUCCESS")); + + if (rollback) { + blockStr2arrayAddToJsonObj (json_obj, savereply->rb_attempt, + "ROLLBACK FAILED ON", &json_array[2]); + + blockStr2arrayAddToJsonObj (json_obj, savereply->rb_success, + "ROLLBACK SUCCESS ON", &json_array[3]); + } + + GB_ASPRINTF(&reply->out, "%s\n", json_object_to_json_string_ext(json_obj, + mapJsonFlagToJsonCstring(blk->json_resp))); + + for (i = 0; i < 4; i++) { + if (json_array[i]) { + json_object_put(json_array[i]); + } + } + json_object_put(json_obj); + } else { + /* save 'failed on'*/ + if (savereply->attempt) + GB_ASPRINTF(&tmp, "FAILED ON: %s\n", savereply->attempt); + + if (savereply->success) { + if (mobj->auth_mode) { + GB_ASPRINTF(&tmp2, "%s\nIQN: %s%s\nUSERNAME: %s\nPASSWORD: %s", + savereply->success, GB_TGCLI_IQN_PREFIX, info->gbid, + info->gbid, mobj->passwd); + } else { + GB_ASPRINTF(&tmp2, "%s\nIQN: %s%s", + savereply->success, GB_TGCLI_IQN_PREFIX, info->gbid); + } + } + + GB_ASPRINTF(&tmp3, "%sSUCCESSFUL ON: %s\n" "RESULT: %s\n", tmp?tmp:"", + savereply->success?tmp2:"None", errCode?"FAIL":"SUCCESS"); + + GB_FREE(tmp); + GB_FREE(tmp2); + + if (rollback) { + if (savereply->rb_attempt) { + GB_ASPRINTF(&tmp, "ROLLBACK FAILED ON: %s\n", savereply->rb_attempt); + } + if (savereply->rb_success) { + GB_ASPRINTF(&tmp2, "ROLLBACK SUCCESS ON: %s\n", savereply->rb_attempt); + } + } + + GB_ASPRINTF(&reply->out, "%s%s%s", tmp3, savereply->rb_attempt?tmp:"", + savereply->rb_success?tmp2:""); + GB_FREE(tmp2); + GB_FREE(tmp3); + } + GB_FREE(tmp); +} + +blockResponse * +block_modify_cli_1_svc(blockModifyCli *blk, struct svc_req *rqstp) +{ + int ret = -1; + static blockModify mobj; + static blockRemoteModifyResp *savereply = NULL; + static blockResponse *reply = NULL; + struct glfs *glfs; + struct glfs_fd *lkfd = NULL; + MetaInfo *info = NULL; + uuid_t uuid; + char passwd[UUID_BUF_SIZE]; + int asyncret; + bool rollback = false; + int errCode = 0; + char *errMsg = NULL; + + + if ((GB_ALLOC(reply) < 0) || (GB_ALLOC(savereply) < 0) || + (GB_ALLOC (info) < 0)) { + GB_FREE (reply); + GB_FREE (savereply); + GB_FREE (info); + return NULL; + } + + glfs = glusterBlockVolumeInit(blk->volume, &errCode, &errMsg); + if (!glfs) { + LOG("mgmt", GB_LOG_ERROR, + "glusterBlockVolumeInit(%s) for block %s failed [%s]", + blk->volume, blk->block_name, strerror(errno)); + goto initfail; + } + + lkfd = glusterBlockCreateMetaLockFile(glfs, blk->volume, &errCode, &errMsg); + if (!lkfd) { + LOG("mgmt", GB_LOG_ERROR, "%s %s for block %s", + FAILED_CREATING_META, blk->volume, blk->block_name); + goto nolock; + } + + GB_METALOCK_OR_GOTO(lkfd, blk->volume, ret, errMsg, nolock); + + if (glfs_access(glfs, blk->block_name, F_OK)) { + LOG("mgmt", GB_LOG_ERROR, + "block with name %s doesn't exist in the volume %s", + blk->block_name, blk->volume); + GB_ASPRINTF(&errMsg, "block %s/%s doesn't exist", blk->volume, + blk->block_name); + errCode = ENOENT; + goto out; + } + + ret = blockGetMetaInfo(glfs, blk->block_name, info, NULL); + if (ret) { + goto out; + } + + strcpy(mobj.block_name, blk->block_name); + strcpy(mobj.volume, blk->volume); + strcpy(mobj.gbid, info->gbid); + + if (blk->auth_mode) { + if(info->passwd[0] == '\0') { + uuid_generate(uuid); + uuid_unparse(uuid, passwd); + GB_METAUPDATE_OR_GOTO(lock, glfs, blk->block_name, blk->volume, + ret, errMsg, out, "PASSWORD: %s\n", passwd); + strcpy(mobj.passwd, passwd); + } else { + strcpy(mobj.passwd, info->passwd); + } + mobj.auth_mode = 1; + } else { + GB_METAUPDATE_OR_GOTO(lock, glfs, blk->block_name, blk->volume, + ret, errMsg, out, "PASSWORD: \n"); + mobj.auth_mode = 0; + } + + asyncret = glusterBlockModifyRemoteAsync(info, glfs, &mobj, + &savereply, rollback); + if (asyncret) { + LOG("mgmt", GB_LOG_WARNING, + "glusterBlockModifyRemoteAsync(auth=%d): return %d %s for block %s on volume %s", + blk->auth_mode, asyncret, FAILED_REMOTE_AYNC_MODIFY, blk->block_name, info->volume); + /* Unwind by removing authentication */ + if (blk->auth_mode) { + GB_METAUPDATE_OR_GOTO(lock, glfs, blk->block_name, blk->volume, + ret, errMsg, out, "PASSWORD: \n"); + } + + /* toggle */ + mobj.auth_mode = !mobj.auth_mode; + + rollback = true; + /* undo */ + asyncret = glusterBlockModifyRemoteAsync(info, glfs, &mobj, + &savereply, rollback); + if (asyncret) { + LOG("mgmt", GB_LOG_WARNING, + "glusterBlockModifyRemoteAsync(auth=%d): on rollback return %d %s " + "for block %s on volume %s", blk->auth_mode, asyncret, FAILED_REMOTE_AYNC_MODIFY, + blk->block_name, info->volume); + /* do nothing ? */ + } + } + + out: + if (ret == EKEYEXPIRED) { + GB_ASPRINTF(&errMsg, "Looks like targetcli and tcmu-runner are not " + "installed on " "few nodes.\n"); + } + + GB_METAUNLOCK(lkfd, blk->volume, ret, errMsg); + + nolock: + if (lkfd && glfs_close(lkfd) != 0) { + LOG("mgmt", GB_LOG_ERROR, + "glfs_close(%s): for block %s on volume %s failed[%s]", + GB_TXLOCKFILE, blk->block_name, blk->volume, strerror(errno)); + } + + initfail: + blockModifyCliFormatResponse (blk, &mobj, errCode, errMsg, savereply, info, + reply, rollback); + glfs_fini(glfs); + + if (savereply) { + GB_FREE(savereply->attempt); + GB_FREE(savereply->success); + GB_FREE(savereply->rb_attempt); + GB_FREE(savereply->rb_success); + GB_FREE(savereply); + } + + return reply; +} + void -block_create_cli_format_response(blockCreateCli *blk, int errCode, - char *errMsg, blockRemoteCreateResp *savereply, - struct blockResponse *reply) +blockCreateCliFormatResponse(blockCreateCli *blk, int errCode, + char *errMsg, blockRemoteCreateResp *savereply, + struct blockResponse *reply) { json_object *json_obj = NULL; json_object *json_array = NULL; @@ -962,11 +1436,11 @@ block_create_cli_format_response(blockCreateCli *blk, int errCode, } if (errCode < 0) { - errCode = 255; + errCode = GB_DEFAULT_ERRCODE; } if (errMsg) { - block_format_error_response(blk->json_resp, errCode, errMsg, reply); + blockFormatErrorResponse(blk->json_resp, errCode, errMsg, reply); return; } @@ -1006,7 +1480,7 @@ block_create_cli_format_response(blockCreateCli *blk, int errCode, } } tmp = NULL; - json_object_object_add(json_obj, "REWIND ON", json_array); + json_object_object_add(json_obj, "ROLLBACK ON", json_array); } json_object_object_add(json_obj, "RESULT", @@ -1030,7 +1504,7 @@ block_create_cli_format_response(blockCreateCli *blk, int errCode, /* save 'failed on'*/ tmp = NULL; if (savereply->obj->d_attempt || savereply->obj->d_success) { - if (GB_ASPRINTF(&tmp, "REWIND ON: %s %s\n", + if (GB_ASPRINTF(&tmp, "ROLLBACK ON: %s %s\n", savereply->obj->d_attempt?savereply->obj->d_attempt:"", savereply->obj->d_success?savereply->obj->d_success:"") == -1) { goto out; @@ -1062,7 +1536,7 @@ block_create_cli_1_svc(blockCreateCli *blk, struct svc_req *rqstp) if (GB_ALLOC(reply) < 0) { - goto out; + return NULL; } list = blockServerParse(blk->block_hosts); @@ -1141,7 +1615,7 @@ block_create_cli_1_svc(blockCreateCli *blk, struct svc_req *rqstp) if (errCode) { if (errCode == EKEYEXPIRED) { LOG("mgmt", GB_LOG_ERROR, "glusterBlockCreateRemoteAsync: return %d" - " rewinding the create request for block %s on volume %s with hosts %s", + " rollingback the create request for block %s on volume %s with hosts %s", errCode, blk->block_name, blk->volume, blk->block_hosts); glusterBlockCleanUp(CREATE_SRV, glfs, blk->block_name, TRUE, &savereply); @@ -1178,7 +1652,7 @@ block_create_cli_1_svc(blockCreateCli *blk, struct svc_req *rqstp) } optfail: - block_create_cli_format_response(blk, errCode, errMsg, savereply, reply); + blockCreateCliFormatResponse(blk, errCode, errMsg, savereply, reply); GB_FREE(errMsg); blockServerDefFree(list); glfs_fini(glfs); @@ -1289,9 +1763,9 @@ block_create_1_svc(blockCreate *blk, struct svc_req *rqstp) } void -block_delete_cli_format_response(blockDeleteCli *blk, int errCode, char *errMsg, - blockRemoteDeleteResp *savereply, - struct blockResponse *reply) +blockDeleteCliFormatResponse(blockDeleteCli *blk, int errCode, char *errMsg, + blockRemoteDeleteResp *savereply, + struct blockResponse *reply) { json_object *json_obj = NULL; json_object *json_array1 = NULL; @@ -1303,42 +1777,23 @@ block_delete_cli_format_response(blockDeleteCli *blk, int errCode, char *errMsg, } if (errCode < 0) { - errCode = 255; + errCode = GB_DEFAULT_ERRCODE; } reply->exit = errCode; if (errMsg) { - block_format_error_response(blk->json_resp, errCode, errMsg, reply); + blockFormatErrorResponse(blk->json_resp, errCode, errMsg, reply); return; } if (blk->json_resp) { json_obj = json_object_new_object(); - if (savereply->d_attempt) { - json_array1 = json_object_new_array(); - tmp = strtok (savereply->d_attempt, " "); - while (tmp!= NULL) - { - json_object_array_add(json_array1, json_object_new_string(tmp)); - tmp = strtok (NULL, " "); - } - tmp = NULL; - json_object_object_add(json_obj, "FAILED ON", json_array1); - } - - if (savereply->d_success) { - json_array2 = json_object_new_array(); - tmp = strtok (savereply->d_success, " "); - while (tmp!= NULL) - { - json_object_array_add(json_array2, json_object_new_string(tmp)); - tmp = strtok (NULL, " "); - } - tmp = NULL; - json_object_object_add(json_obj, "SUCCESSFUL ON", json_array2); - } + blockStr2arrayAddToJsonObj (json_obj, savereply->d_attempt, + "FAILED ON", &json_array1); + blockStr2arrayAddToJsonObj (json_obj, savereply->d_success, + "SUCCESSFUL ON", &json_array2); json_object_object_add(json_obj, "RESULT", errCode?json_object_new_string("FAIL"):json_object_new_string("SUCCESS")); @@ -1347,8 +1802,10 @@ block_delete_cli_format_response(blockDeleteCli *blk, int errCode, char *errMsg, json_object_to_json_string_ext(json_obj, mapJsonFlagToJsonCstring(blk->json_resp))); - json_object_put(json_array1); - json_object_put(json_array2); + if (json_array1) + json_object_put(json_array1); + if (json_array2) + json_object_put(json_array2); json_object_put(json_obj); } else { /* save 'failed on'*/ @@ -1438,7 +1895,7 @@ block_delete_cli_1_svc(blockDeleteCli *blk, struct svc_req *rqstp) } - block_delete_cli_format_response(blk, errCode, errMsg, savereply, reply); + blockDeleteCliFormatResponse(blk, errCode, errMsg, savereply, reply); glfs_fini(glfs); if (savereply) { @@ -1538,6 +1995,98 @@ block_delete_1_svc(blockDelete *blk, struct svc_req *rqstp) } +blockResponse * +block_modify_1_svc(blockModify *blk, struct svc_req *rqstp) +{ + int ret; + char *authattr = NULL; + char *authcred = NULL; + char *exec = NULL; + blockResponse *reply = NULL; + + + if (GB_ALLOC(reply) < 0) { + return NULL; + } + reply->exit = -1; + + /* Check if targetcli and tcmu-runner installed ? */ + ret = WEXITSTATUS(system(GB_TGCLI_GLFS_CHECK)); + if (ret == EKEYEXPIRED || ret == 1) { + reply->exit = EKEYEXPIRED; + if (GB_ASPRINTF(&reply->out, + "check if targetcli and tcmu-runner are installed.") == -1) { + goto out; + } + goto out; + } + + if (GB_ASPRINTF(&exec, GB_TGCLI_CHECK, blk->block_name) == -1) { + goto out; + } + + /* Check if block exist on this node ? */ + if (WEXITSTATUS(system(exec)) == 1) { + reply->exit = 0; + if (GB_ASPRINTF(&reply->out, "No %s.", blk->block_name) == -1) { + goto out; + } + goto out; + } + GB_FREE(exec); + + if (blk->auth_mode) { + if (GB_ASPRINTF(&authattr, "%s/%s%s/tpg1 set attribute authentication=1", + GB_TGCLI_ISCSI, GB_TGCLI_IQN_PREFIX, blk->gbid) == -1) { + goto out; + } + + if (GB_ASPRINTF(&authcred, "%s/%s%s/tpg1 set auth userid=%s password=%s", + GB_TGCLI_ISCSI, GB_TGCLI_IQN_PREFIX, blk->gbid, + blk->gbid, blk->passwd) == -1) { + goto out; + } + + if (GB_ASPRINTF(&exec, "%s && %s && %s", authattr, authcred, GB_TGCLI_SAVE) == -1) { + goto out; + } + } else { + if (GB_ASPRINTF(&exec, "%s/%s%s/tpg1 set attribute authentication=0 && %s", + GB_TGCLI_ISCSI, GB_TGCLI_IQN_PREFIX, blk->gbid, GB_TGCLI_SAVE) == -1) { + goto out; + } + } + + if (GB_ALLOC_N(reply->out, 4096) < 0) { + GB_FREE(reply); + goto out; + } + + ret = WEXITSTATUS(system(exec)); + if (ret) { + LOG("mgmt", GB_LOG_ERROR, + "system(): for block %s executing command %s failed(%s)", + blk->block_name, exec, strerror(errno)); + reply->exit = ret; + if (GB_ASPRINTF(&reply->out, + "cannot execute auth commands.") == -1) { + goto out; + } + goto out; + } + + /* command execution success */ + reply->exit = 0; + + out: + GB_FREE(exec); + GB_FREE(authattr); + GB_FREE(authcred); + + return reply; +} + + blockResponse * block_list_cli_1_svc(blockListCli *blk, struct svc_req *rqstp) { @@ -1624,7 +2173,7 @@ block_list_cli_1_svc(blockListCli *blk, struct svc_req *rqstp) } if (errCode < 0) { - errCode = 255; + errCode = GB_DEFAULT_ERRCODE; } reply->exit = errCode; @@ -1669,10 +2218,27 @@ block_list_cli_1_svc(blockListCli *blk, struct svc_req *rqstp) return reply; } +static bool +blockhostIsValid (char *status) +{ + switch (blockMetaStatusEnumParse(status)) { + case GB_CONFIG_SUCCESS: + 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: + return TRUE; + } + + return FALSE; +} + void -block_info_cli_format_response(blockInfoCli *blk, int errCode, - char *errMsg, MetaInfo *info, - struct blockResponse *reply) +blockInfoCliFormatResponse(blockInfoCli *blk, int errCode, + char *errMsg, MetaInfo *info, + struct blockResponse *reply) { json_object *json_obj = NULL; json_object *json_array = NULL; @@ -1685,10 +2251,10 @@ block_info_cli_format_response(blockInfoCli *blk, int errCode, } if (errCode < 0) { - errCode = 255; + errCode = GB_DEFAULT_ERRCODE; } if (errMsg) { - block_format_error_response(blk->json_resp, errCode, errMsg, reply); + blockFormatErrorResponse(blk->json_resp, errCode, errMsg, reply); return; } @@ -1699,11 +2265,12 @@ block_info_cli_format_response(blockInfoCli *blk, int errCode, json_object_object_add(json_obj, "GBID", json_object_new_string(info->gbid)); json_object_object_add(json_obj, "SIZE", json_object_new_int64(info->size)); json_object_object_add(json_obj, "HA", json_object_new_int(info->mpath)); + json_object_object_add(json_obj, "PASSWORD", json_object_new_string(info->passwd)); json_array = json_object_new_array(); for (i = 0; i < info->nhosts; i++) { - if (blockMetaStatusEnumParse(info->list[i]->status) == GB_CONFIG_SUCCESS) { + if (blockhostIsValid (info->list[i]->status)) { json_object_array_add(json_array, json_object_new_string(info->list[i]->addr)); } } @@ -1717,18 +2284,18 @@ block_info_cli_format_response(blockInfoCli *blk, int errCode, json_object_put(json_obj); } else { if (GB_ASPRINTF(&tmp, "NAME: %s\nVOLUME: %s\nGBID: %s\nSIZE: %zu\n" - "HA: %zu\nBLOCK CONFIG NODE(S):", - blk->block_name, info->volume, info->gbid, - info->size, info->mpath) == -1) { + "HA: %zu\nPASSWORD: %s\nBLOCK CONFIG NODE(S):", + blk->block_name, info->volume, info->gbid, info->size, info->mpath, + info->passwd) == -1) { goto out; } for (i = 0; i < info->nhosts; i++) { - if (blockMetaStatusEnumParse(info->list[i]->status) == GB_CONFIG_SUCCESS) { - if (GB_ASPRINTF(&out, "%s %s", tmp, info->list[i]->addr) == -1) { - GB_FREE (tmp); - goto out; - } - tmp = out; + if (blockhostIsValid (info->list[i]->status)) { + if (GB_ASPRINTF(&out, "%s %s", tmp, info->list[i]->addr) == -1) { + GB_FREE (tmp); + goto out; + } + tmp = out; } } if (GB_ASPRINTF(&reply->out, "%s\n", tmp) == -1) { @@ -1799,7 +2366,7 @@ block_info_cli_1_svc(blockInfoCli *blk, struct svc_req *rqstp) } - block_info_cli_format_response(blk, errCode, errMsg, info, reply); + blockInfoCliFormatResponse(blk, errCode, errMsg, info, reply); glfs_fini(glfs); GB_FREE(errMsg); blockFreeMetaInfo(info); diff --git a/rpc/glfs-operations.c b/rpc/glfs-operations.c index 98de51c..71dd0d2 100644 --- a/rpc/glfs-operations.c +++ b/rpc/glfs-operations.c @@ -291,6 +291,9 @@ blockStuffMetaInfo(MetaInfo *info, char *line) case GB_META_ENTRYCREATE: strcpy(info->entry, strchr(line, ' ')+1); break; + case GB_META_PASSWD: + strcpy(info->passwd, strchr(line, ' ')+1); + break; default: if(!info->list) { diff --git a/rpc/glfs-operations.h b/rpc/glfs-operations.h index 47aced2..f639d86 100644 --- a/rpc/glfs-operations.h +++ b/rpc/glfs-operations.h @@ -34,6 +34,7 @@ typedef struct MetaInfo { size_t size; size_t mpath; char entry[16]; + char passwd[38]; size_t nhosts; NodeInfo **list; diff --git a/rpc/rpcl/block.x b/rpc/rpcl/block.x index 5d9c2a5..df29542 100644 --- a/rpc/rpcl/block.x +++ b/rpc/rpcl/block.x @@ -22,6 +22,14 @@ struct blockCreate { char block_name[255]; }; +struct blockModify { + char volume[255]; + char block_name[255]; + char gbid[127]; + char passwd[127]; + bool auth_mode; +}; + struct blockCreateCli { char volume[255]; u_quad_t size; @@ -54,6 +62,13 @@ struct blockListCli { enum JsonResponseFormat json_resp; }; +struct blockModifyCli { + char block_name[255]; + char volume[255]; + bool auth_mode; + enum JsonResponseFormat json_resp; +}; + struct blockResponse { int exit; /* exit code of the command */ string out<>; /* output; TODO: return respective objects */ @@ -65,6 +80,7 @@ program GLUSTER_BLOCK { version GLUSTER_BLOCK_VERS { blockResponse BLOCK_CREATE(blockCreate) = 1; blockResponse BLOCK_DELETE(blockDelete) = 2; + blockResponse BLOCK_MODIFY(blockModify) = 3; } = 1; } = 21215311; /* B2 L12 O15 C3 K11 */ @@ -74,5 +90,6 @@ program GLUSTER_BLOCK_CLI { blockResponse BLOCK_LIST_CLI(blockListCli) = 2; blockResponse BLOCK_INFO_CLI(blockInfoCli) = 3; blockResponse BLOCK_DELETE_CLI(blockDeleteCli) = 4; + blockResponse BLOCK_MODIFY_CLI(blockModifyCli) = 5; } = 1; } = 212153113; /* B2 L12 O15 C3 K11 C3 */ diff --git a/tests/basic.t b/tests/basic.t index 8514cfb..6d8aa1a 100755 --- a/tests/basic.t +++ b/tests/basic.t @@ -79,12 +79,18 @@ sleep 1; # Block create TEST gluster-block create ${VOLNAME}/${BLKNAME} ha 1 ${HOST} 1GiB +# Modify Block with auth enable +TEST gluster-block modify ${VOLNAME}/${BLKNAME} auth enable + # Block list TEST gluster-block list ${VOLNAME} # Block info TEST gluster-block info ${VOLNAME}/${BLKNAME} +# Modify Block with auth disable +TEST gluster-block modify ${VOLNAME}/${BLKNAME} auth disable + # Block delete gluster-block delete ${VOLNAME}/${BLKNAME} @@ -93,10 +99,16 @@ echo -e "\n*** JSON responses ***\n" # Block create and expect json response TEST gluster-block create ${VOLNAME}/${BLKNAME} ha 1 ${HOST} 1GiB --json-pretty +# Modify Block with auth enable and expect json response +TEST gluster-block modify ${VOLNAME}/${BLKNAME} auth enable --json-pretty + # Block list and expect json response TEST gluster-block list ${VOLNAME} --json-pretty # Block info and expect json response TEST gluster-block info ${VOLNAME}/${BLKNAME} --json-pretty +# Modify Block with auth disable and expect json response +TEST gluster-block modify ${VOLNAME}/${BLKNAME} auth disable --json-pretty + cleanup; diff --git a/utils/common.h b/utils/common.h index b43220f..21bf855 100644 --- a/utils/common.h +++ b/utils/common.h @@ -52,6 +52,8 @@ static const char *const JsonResponseFormatLookup[] = { enum JsonResponseFormat jsonResponseFormatParse(const char *opt); +int convertStringToTrillianParse(const char *opt); + ssize_t glusterBlockCreateParseSize(const char *dom, char *value); # endif /* _COMMON_H */ diff --git a/utils/utils.h b/utils/utils.h index b0cf778..8cbf128 100644 --- a/utils/utils.h +++ b/utils/utils.h @@ -37,6 +37,11 @@ /* Target Info */ # define FAILED_INFO "failed in info" +/* Target Modify */ +# define FAILED_MODIFY "failed in modify" +# define FAILED_REMOTE_MODIFY "failed in remote modify" +# define FAILED_REMOTE_AYNC_MODIFY "failed in remote async modify" + /* Target Delete */ # define FAILED_DELETE "failed in delete" # define FAILED_REMOTE_DELETE "failed in remote delete" @@ -281,6 +286,7 @@ typedef enum Metakey { GB_META_HA = 3, GB_META_ENTRYCREATE = 4, GB_META_ENTRYDELETE = 5, + GB_META_PASSWD = 6, GB_METAKEY_MAX } Metakey; @@ -292,30 +298,43 @@ static const char *const MetakeyLookup[] = { [GB_META_HA] = "HA", [GB_META_ENTRYCREATE] = "ENTRYCREATE", [GB_META_ENTRYDELETE] = "ENTRYDELETE", + [GB_META_PASSWD] = "PASSWORD", [GB_METAKEY_MAX] = NULL }; typedef enum MetaStatus { - GB_CONFIG_SUCCESS = 0, - GB_CONFIG_FAIL = 1, - GB_CONFIG_INPROGRESS = 2, - GB_CLEANUP_SUCCESS = 3, - GB_CLEANUP_FAIL = 4, - GB_CLEANUP_INPROGRESS = 5, + GB_CONFIG_SUCCESS = 0, + GB_CONFIG_FAIL = 1, + GB_CONFIG_INPROGRESS = 2, + GB_AUTH_ENFORCEING = 3, + GB_AUTH_ENFORCED = 4, + GB_AUTH_ENFORCE_FAIL = 5, + GB_AUTH_CLEAR_ENFORCEING = 6, + GB_AUTH_CLEAR_ENFORCED = 7, + GB_AUTH_CLEAR_ENFORCE_FAIL = 8, + GB_CLEANUP_SUCCESS = 9, + GB_CLEANUP_FAIL = 10, + GB_CLEANUP_INPROGRESS = 11, GB_METASTATUS_MAX } MetaStatus; static const char *const MetaStatusLookup[] = { - [GB_CONFIG_SUCCESS] = "CONFIGSUCCESS", - [GB_CONFIG_FAIL] = "CONFIGFAIL", - [GB_CONFIG_INPROGRESS] = "CONFIGINPROGRESS", - [GB_CLEANUP_INPROGRESS] = "CLEANUPINPROGRESS", - [GB_CLEANUP_SUCCESS] = "CLEANUPSUCCESS", - [GB_CLEANUP_FAIL] = "CLEANUPFAIL", - - [GB_METASTATUS_MAX] = NULL, + [GB_CONFIG_SUCCESS] = "CONFIGSUCCESS", + [GB_CONFIG_FAIL] = "CONFIGFAIL", + [GB_CONFIG_INPROGRESS] = "CONFIGINPROGRESS", + [GB_AUTH_ENFORCEING] = "AUTHENFORCEING", + [GB_AUTH_ENFORCED] = "AUTHENFORCED", + [GB_AUTH_ENFORCE_FAIL] = "AUTHENFORCEFAIL", + [GB_AUTH_CLEAR_ENFORCEING] = "AUTHCLEARENFORCEING", + [GB_AUTH_CLEAR_ENFORCED] = "AUTHCLEARENFORCED", + [GB_AUTH_CLEAR_ENFORCE_FAIL] = "AUTHCLEARENFORCEFAIL", + [GB_CLEANUP_INPROGRESS] = "CLEANUPINPROGRESS", + [GB_CLEANUP_SUCCESS] = "CLEANUPSUCCESS", + [GB_CLEANUP_FAIL] = "CLEANUPFAIL", + + [GB_METASTATUS_MAX] = NULL, }; typedef enum RemoteCreateResp { -- cgit