From 46f460fa669ce9f7b9f2de9e54cefc3726dcd029 Mon Sep 17 00:00:00 2001 From: Prasanna Kumar Kalever Date: Wed, 10 Jan 2018 23:48:38 +0530 Subject: versioning: add capabilities support Change-Id: Ic63f7c9fa169ee37b796093554c59016fbbfaa46 Signed-off-by: Prasanna Kumar Kalever --- rpc/block_svc_routines.c | 472 +++++++++++++++++++++++++++++++++++++++--- rpc/rpcl/block.x | 1 + utils/Makefile.am | 17 +- utils/capabilities.c | 109 ++++++++++ utils/capabilities.h | 65 ++++++ utils/gluster-block-caps.info | 98 +++++++++ utils/utils.h | 8 + 7 files changed, 741 insertions(+), 29 deletions(-) create mode 100644 utils/capabilities.c create mode 100644 utils/capabilities.h create mode 100644 utils/gluster-block-caps.info diff --git a/rpc/block_svc_routines.c b/rpc/block_svc_routines.c index c0c437f..433b185 100644 --- a/rpc/block_svc_routines.c +++ b/rpc/block_svc_routines.c @@ -10,6 +10,7 @@ # include "common.h" +# include "capabilities.h" # include "glfs-operations.h" # include @@ -18,8 +19,8 @@ # include -# define UUID_BUF_SIZE 38 -# define GB_DEFAULT_ERRCODE 255 +# define UUID_BUF_SIZE 38 +# define GB_DEFAULT_ERRCODE 255 # define GB_CREATE "create" # define GB_DELETE "delete" @@ -37,6 +38,8 @@ # define GB_DEFAULT_ERRMSG "Operation failed, please check the log "\ "file to find the reason." +# define GB_OLD_CAP_MAX 9 + pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER; typedef enum operations { @@ -45,7 +48,8 @@ typedef enum operations { MODIFY_SRV, MODIFY_TPGC_SRV, LIST_SRV, - INFO_SRV + INFO_SRV, + VERSION_SRV } operations; @@ -170,6 +174,25 @@ mapJsonFlagToJsonCstring(int jsonflag) } +static 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: + return TRUE; + } + + return FALSE; +} + + static void blockCreateParsedRespFree(blockRemoteCreateResp *savereply) { @@ -299,6 +322,7 @@ blockRemoteCreateRespParse(char *output, blockRemoteCreateResp **savereply) return -1; } + struct addrinfo * glusterBlockGetSockaddr(char *host) { @@ -373,7 +397,6 @@ out: } - int glusterBlockCallRPC_1(char *host, void *cobj, operations opt, bool *rpc_sent, char **out) @@ -382,8 +405,10 @@ glusterBlockCallRPC_1(char *host, void *cobj, int ret = -1; int sockfd = -1; int errsv = 0; + size_t i; blockResponse reply = {0,}; struct addrinfo *res = NULL; + gbCapResp *obj = NULL; *rpc_sent = FALSE; @@ -410,6 +435,15 @@ glusterBlockCallRPC_1(char *host, void *cobj, goto out; } break; + case VERSION_SRV: + *rpc_sent = TRUE; + ret = block_version_1((void*)cobj, &reply, clnt); + if (ret != RPC_SUCCESS) { + LOG("mgmt", GB_LOG_ERROR, "%son host %s", + clnt_sperror(clnt, "block remote version failed"), host); + goto out; + } + break; case DELETE_SRV: *rpc_sent = TRUE; if (block_delete_1((blockDelete *)cobj, &reply, clnt) != RPC_SUCCESS) { @@ -432,10 +466,26 @@ glusterBlockCallRPC_1(char *host, void *cobj, goto out; } - if (GB_STRDUP(*out, reply.out) < 0) { - goto out; - } ret = reply.exit; + if (opt != VERSION_SRV) { + if (GB_STRDUP(*out, reply.out) < 0) { + goto out; + } + } else { + if (GB_ALLOC(obj) < 0) { + return -1; + } + obj->capMax = reply.xdata.xdata_len/sizeof(gbCapObj); + gbCapObj *caps = (gbCapObj *)reply.xdata.xdata_val; + if (GB_ALLOC_N(obj->response, obj->capMax) < 0) { + return -1; + } + for (i = 0; i < obj->capMax; i++) { + strncpy(obj->response[i].cap, caps[i].cap, 256); + obj->response[i].status = caps[i].status; + } + *out = (char *) obj; + } out: if (clnt) { @@ -534,6 +584,187 @@ blockServerParse(char *blkServers) } +void * +glusterBlockCapabilitiesRemote(void *data) +{ + int ret; + blockRemoteObj *args = (blockRemoteObj *)data; + bool rpc_sent = FALSE; + + + /* Get peers capabilities */ + ret = glusterBlockCallRPC_1(args->addr, NULL, VERSION_SRV, &rpc_sent, + &args->reply); + if (ret && ret != RPC_PROCUNAVAIL) { + if (!rpc_sent) { + LOG("mgmt", GB_LOG_ERROR, "%s hence %s on host %s", + strerror(errno), FAILED_REMOTE_CAPS, args->addr); + ret = -ENOTCONN; + } else { + LOG("mgmt", GB_LOG_ERROR, "%s for on host %s", + FAILED_REMOTE_CAPS, args->addr); + ret = -1; + } + } + + args->exit = ret; + + return NULL; +} + + +/* function to imitate caps of older gluster-block versions */ +gbCapResp * +glusterBlockMimicOldCaps(void) +{ + size_t i; + gbCapResp *caps = NULL; + + + if (GB_ALLOC(caps) < 0) { + return NULL; + } + + caps->capMax = GB_OLD_CAP_MAX; + if (GB_ALLOC_N(caps->response, GB_OLD_CAP_MAX) < 0) { + GB_FREE(caps); + return NULL; + } + + strncpy(caps->response[0].cap, "create", 256); + strncpy(caps->response[1].cap, "create_ha", 256); + strncpy(caps->response[2].cap, "create_prealloc", 256); + strncpy(caps->response[3].cap, "create_auth", 256); + + strncpy(caps->response[4].cap, "delete", 256); + strncpy(caps->response[5].cap, "delete_force", 256); + + strncpy(caps->response[6].cap, "modify", 256); + strncpy(caps->response[7].cap, "modify_auth", 256); + + strncpy(caps->response[8].cap, "json", 256); + + for (i = 0; i < GB_OLD_CAP_MAX; i++) { + caps->response[i].status = true; + } + + return caps; +} + + +static int +blockRemoteCapabilitiesRespParse(size_t count, blockRemoteObj *args, + bool *minCaps, char **errMsg) +{ + size_t i, j, k; + int ret = -1; + gbCapResp **caps = NULL; + bool CAP_MATCH; + + + if (GB_ALLOC_N(caps, count) < 0) { + return -1; + } + for (i = 0; i < count; i++) { + caps[i] = (gbCapResp *) args[i].reply; + } + + for (i = 0; i < count; i++) { + if (args[i].exit == RPC_PROCUNAVAIL) { + caps[i] = glusterBlockMimicOldCaps(); + } else if (args[i].exit) { + ret = args[i].exit; + GB_ASPRINTF(errMsg, "host %s returned %d", args[i].addr, ret); + goto out; + } + } + + for (i = 0; i < GB_CAP_MAX; i++) { + if (minCaps[i] == false) { + continue; + } + /* Check if all remotes contain this cap */ + for (j = 0; j < count; j++) { + CAP_MATCH=false; + if (!caps[j]) { + GB_ASPRINTF(errMsg, "capability empty on %s", args[j].addr); + goto out; + } + for (k = 0; k < caps[j]->capMax; k++) { + if (!strncmp(gbCapabilitiesLookup[i], caps[j]->response[k].cap, 256) && + caps[j]->response[k].status) { + CAP_MATCH=true; + break; + } + } + if (!CAP_MATCH) { + GB_ASPRINTF(errMsg, "capability '%s' doesn't exit on %s", + gbCapabilitiesLookup[i], args[j].addr); + goto out; + } + } + } + + ret = 0; + out: + for (i = 0; i < count; i++) { + if (caps[i]) { + GB_FREE(caps[i]->response); + GB_FREE(caps[i]); + } + } + GB_FREE(caps); + return ret; +} + + +static int +glusterBlockCapabilityRemoteAsync(blockServerDef *servers, bool *minCaps, + char **errMsg) +{ + static blockRemoteObj *args = NULL; + pthread_t *tid = NULL; + int ret = -1; + size_t i; + + + /* skip if nhosts = 1 */ + if (!servers || (servers->nhosts <= 1)) { + return 0; + } + + if (GB_ALLOC_N(tid, servers->nhosts) < 0) { + goto out; + } + + if (GB_ALLOC_N(args, servers->nhosts) < 0) { + goto out; + } + + for (i = 0; i < servers->nhosts; i++) { + args[i].addr = servers->hosts[i]; + } + + for (i = 0; i < servers->nhosts; i++) { + pthread_create(&tid[i], NULL, glusterBlockCapabilitiesRemote, &args[i]); + } + + for (i = 0; i < servers->nhosts; i++) { + /* collect exit code */ + pthread_join(tid[i], NULL); + } + + /* Verify the capabilities */ + ret = blockRemoteCapabilitiesRespParse(servers->nhosts, args, minCaps, errMsg); + + out: + GB_FREE(args); + GB_FREE(tid); + + return ret; +} + + void * glusterBlockCreateRemote(void *data) { @@ -1360,6 +1591,65 @@ blockStr2arrayAddToJsonObj (json_object *json_obj, char *string, char *label, } +bool * +glusterBlockBuildMinCaps(void *data, operations opt) +{ + blockCreateCli *cblk = NULL; + blockDeleteCli *dblk = NULL; + blockModifyCli *mblk = NULL; + bool *minCaps = NULL; + + + if (GB_ALLOC_N(minCaps, GB_CAP_MAX) < 0) { + return NULL; + } + + switch (opt) { + case CREATE_SRV: + cblk = (blockCreateCli *)data; + + minCaps[GB_CREATE_CAP] = true; + if (cblk->mpath > 1) { + minCaps[GB_CREATE_HA_CAP] = true; + } + if (cblk->prealloc) { + minCaps[GB_CREATE_PREALLOC_CAP] = true; + } + if (cblk->auth_mode) { + minCaps[GB_CREATE_AUTH_CAP] = true; + } + if (cblk->json_resp) { + minCaps[GB_JSON_CAP] = true; + } + break; + case DELETE_SRV: + dblk = (blockDeleteCli *)data; + + minCaps[GB_DELETE_CAP] = true; + if (dblk->force) { + minCaps[GB_DELETE_FORCE_CAP] = true; + } + if (dblk->json_resp) { + minCaps[GB_JSON_CAP] = true; + } + break; + case MODIFY_SRV: + mblk = (blockModifyCli *)data; + + minCaps[GB_MODIFY_CAP] = true; + if (mblk->auth_mode) { + minCaps[GB_MODIFY_AUTH_CAP] = true; + } + if (mblk->json_resp) { + minCaps[GB_JSON_CAP] = true; + } + break; + } + + return minCaps; +} + + static void blockModifyCliFormatResponse (blockModifyCli *blk, struct blockModify *mobj, int errCode, char *errMsg, @@ -1482,6 +1772,85 @@ blockModifyCliFormatResponse (blockModifyCli *blk, struct blockModify *mobj, } + +static int +glusterBlockCheckCapabilities(void* blk, operations opt, blockServerDefPtr list, + char **errMsg) +{ + int errCode = 0; + bool *minCaps = NULL; + char *localErrMsg = NULL; + + + /* skip if nhosts = 1 */ + if (!list || (list->nhosts <= 1)) { + return 0; + } + + minCaps = glusterBlockBuildMinCaps(blk, opt); + if (!minCaps) { + errCode = ENOMEM; + goto out; + } + + errCode = glusterBlockCapabilityRemoteAsync(list, minCaps, &localErrMsg); + if (errCode) { + LOG("mgmt", GB_LOG_ERROR, "glusterBlockCapabilityRemoteAsync() failed (%s)", + localErrMsg); + if (errCode == -ENOTCONN) { + if (GB_ASPRINTF(errMsg, "Version check failed [%s] (Hint: See if all " + "servers are up and running gluster-blockd daemon)", + localErrMsg) == -1) { + errCode = ENOMEM; + } + } else { + if (GB_ASPRINTF(errMsg, "Version check failed between block servers. (%s)", + localErrMsg) == -1) { + errCode = ENOMEM; + } + } + goto out; + } + + out: + GB_FREE(minCaps); + GB_FREE(localErrMsg); + return errCode; +} + + +blockServerDefPtr +glusterBlockGetListFromInfo(MetaInfo *info) +{ + size_t i; + blockServerDefPtr list = NULL; + + + if (!info || GB_ALLOC(list) < 0) { + return NULL; + } + + if (GB_ALLOC_N(list->hosts, info->mpath) < 0) { + goto out; + } + + for (i = 0; i < info->nhosts; i++) { + if (blockhostIsValid (info->list[i]->status)) { + if (GB_STRDUP(list->hosts[i], info->list[i]->addr) < 0) { + goto out; + } + list->nhosts++; + } + } + + return list; + + out: + blockServerDefFree(list); + return NULL; +} + + blockResponse * block_modify_cli_1_svc_st(blockModifyCli *blk, struct svc_req *rqstp) { @@ -1498,6 +1867,8 @@ block_modify_cli_1_svc_st(blockModifyCli *blk, struct svc_req *rqstp) bool rollback = false; int errCode = 0; char *errMsg = NULL; + blockServerDefPtr list = NULL; + size_t i; LOG("mgmt", GB_LOG_DEBUG, @@ -1544,6 +1915,20 @@ block_modify_cli_1_svc_st(blockModifyCli *blk, struct svc_req *rqstp) goto out; } + list = glusterBlockGetListFromInfo(info); + if (!list) { + errCode = ENOMEM; + goto out; + } + + errCode = glusterBlockCheckCapabilities((void *)blk, MODIFY_SRV, list, &errMsg); + if (errCode) { + LOG("mgmt", GB_LOG_ERROR, + "glusterBlockCheckCapabilities() for block %s on volume %s failed", + blk->block_name, blk->volume); + goto out; + } + strcpy(mobj.block_name, blk->block_name); strcpy(mobj.volume, blk->volume); strcpy(mobj.gbid, info->gbid); @@ -1610,6 +1995,7 @@ block_modify_cli_1_svc_st(blockModifyCli *blk, struct svc_req *rqstp) out: GB_METAUNLOCK(lkfd, blk->volume, ret, errMsg); + blockServerDefFree(list); nolock: if (lkfd && glfs_close(lkfd) != 0) { @@ -1796,6 +2182,7 @@ blockCreateCliFormatResponse(struct glfs *glfs, blockCreateCli *blk, return; } + blockResponse * block_create_cli_1_svc_st(blockCreateCli *blk, struct svc_req *rqstp) { @@ -1837,6 +2224,14 @@ block_create_cli_1_svc_st(blockCreateCli *blk, struct svc_req *rqstp) goto optfail; } + errCode = glusterBlockCheckCapabilities((void *)blk, CREATE_SRV, list, &errMsg); + if (errCode) { + LOG("mgmt", GB_LOG_ERROR, + "glusterBlockCheckCapabilities() for block %s on volume %s failed", + blk->block_name, blk->volume); + goto optfail; + } + glfs = glusterBlockVolumeInit(blk->volume, &errCode, &errMsg); if (!glfs) { LOG("mgmt", GB_LOG_ERROR, @@ -2302,6 +2697,8 @@ block_delete_cli_1_svc_st(blockDeleteCli *blk, struct svc_req *rqstp) char *errMsg = NULL; int errCode = 0; int ret; + blockServerDefPtr list = NULL; + size_t i; LOG("mgmt", GB_LOG_INFO, "delete cli request, volume=%s blockname=%s", @@ -2361,6 +2758,20 @@ block_delete_cli_1_svc_st(blockDeleteCli *blk, struct svc_req *rqstp) } } + list = glusterBlockGetListFromInfo(info); + if (!list) { + errCode = ENOMEM; + goto out; + } + + errCode = glusterBlockCheckCapabilities((void *)blk, DELETE_SRV, list, &errMsg); + if (errCode) { + LOG("mgmt", GB_LOG_ERROR, + "glusterBlockCheckCapabilities() for block %s on volume %s failed", + blk->block_name, blk->volume); + goto out; + } + errCode = glusterBlockCleanUp(glfs, blk->block_name, TRUE, TRUE, savereply); if (errCode) { LOG("mgmt", GB_LOG_WARNING, "glusterBlockCleanUp: return %d " @@ -2368,9 +2779,9 @@ block_delete_cli_1_svc_st(blockDeleteCli *blk, struct svc_req *rqstp) } out: - GB_FREE(info); - GB_METAUNLOCK(lkfd, blk->volume, errCode, errMsg); + blockServerDefFree(list); + GB_FREE(info); optfail: if (lkfd && glfs_close(lkfd) != 0) { @@ -2462,6 +2873,22 @@ block_delete_1_svc_st(blockDelete *blk, struct svc_req *rqstp) return reply; } +blockResponse * +block_version_1_svc_st(void *data, struct svc_req *rqstp) +{ + int ret = -1; + blockResponse *reply = NULL; + + if (GB_ALLOC(reply) < 0) { + return NULL; + } + + reply->exit = gbSetCapabilties(&reply); + + GB_ASPRINTF(&reply->out, "In version"); + return reply; + +} blockResponse * block_modify_1_svc_st(blockModify *blk, struct svc_req *rqstp) @@ -2725,23 +3152,6 @@ block_list_cli_1_svc_st(blockListCli *blk, struct svc_req *rqstp) return reply; } -static 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: - return TRUE; - } - - return FALSE; -} void blockInfoCliFormatResponse(blockInfoCli *blk, int errCode, @@ -2938,6 +3348,16 @@ block_modify_1_svc(blockModify *blk, blockResponse *reply, struct svc_req *rqstp } +bool_t +block_version_1_svc(void *data, blockResponse *reply, struct svc_req *rqstp) +{ + int ret; + + GB_RPC_CALL(version, data, reply, rqstp, ret); + return ret; +} + + bool_t block_create_cli_1_svc(blockCreateCli *blk, blockResponse *reply, struct svc_req *rqstp) diff --git a/rpc/rpcl/block.x b/rpc/rpcl/block.x index 66d1e32..6eeb321 100644 --- a/rpc/rpcl/block.x +++ b/rpc/rpcl/block.x @@ -87,6 +87,7 @@ program GLUSTER_BLOCK { blockResponse BLOCK_CREATE(blockCreate) = 1; blockResponse BLOCK_DELETE(blockDelete) = 2; blockResponse BLOCK_MODIFY(blockModify) = 3; + blockResponse BLOCK_VERSION() = 4; } = 1; } = 21215311; /* B2 L12 O15 C3 K11 */ diff --git a/utils/Makefile.am b/utils/Makefile.am index bdebb52..6eadf79 100644 --- a/utils/Makefile.am +++ b/utils/Makefile.am @@ -1,16 +1,27 @@ noinst_LTLIBRARIES = libgb.la -libgb_la_SOURCES = common.c utils.c lru.c +libgb_la_SOURCES = common.c utils.c lru.c capabilities.c -noinst_HEADERS = common.h utils.h lru.h list.h +noinst_HEADERS = common.h utils.h lru.h list.h capabilities.h -libgb_la_CFLAGS = $(GFAPI_CFLAGS) -DDATADIR=\"$(localstatedir)\" \ +libgb_la_CFLAGS = $(GFAPI_CFLAGS) \ + -DDATADIR=\"$(localstatedir)\" -DCONFDIR=\"$(sysconfigdir)\" \ -I$(top_builddir)/ -I$(top_builddir)/rpc/rpcl libgb_la_LIBADD = $(GFAPI_LIBS) libgb_ladir = $(includedir)/gluster-block/utils +EXTRA_DIST = gluster-block-caps.info + DISTCLEANFILES = Makefile.in CLEANFILES = *~ + +install-data-local: + $(MKDIR_P) $(DESTDIR)${sysconfigdir}; \ + $(INSTALL_DATA) gluster-block-caps.info \ + $(DESTDIR)${sysconfigdir}/gluster-block-caps.info; + +uninstall-local: + rm -f $(DESTDIR)${sysconfigdir}/gluster-block-caps.info diff --git a/utils/capabilities.c b/utils/capabilities.c new file mode 100644 index 0000000..d44dc8f --- /dev/null +++ b/utils/capabilities.c @@ -0,0 +1,109 @@ +/* + Copyright (c) 2018 Red Hat, Inc. + 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 "capabilities.h" + + +int +gbCapabilitiesEnumParse(const char *cap) +{ + int i; + + + if (!cap) { + return GB_CAP_MAX; + } + + for (i = 0; i < GB_CAP_MAX; i++) { + if (!strcmp(cap, gbCapabilitiesLookup[i])) { + return i; + } + } + + return i; +} + + +int +gbSetCapabilties(blockResponse **c) +{ + FILE * fp; + char *line = NULL; + size_t len = 0; + int count = 0; + int ret = 0; + blockResponse *reply = *c; + gbCapObj *caps = NULL; + char *p, *sep; + + + fp = fopen(GB_CAPS_FILE, "r"); + if (fp == NULL) { + return -1; + } + + if (GB_ALLOC_N(caps, GB_CAP_MAX) < 0) { + fclose(fp); + return -1; + } + + while ((getline(&line, &len, fp)) != -1) { + if (!line) { + continue; + } + if ((line[0] == '\n') || (line[0] == '#')) { + GB_FREE(line); + continue; + } + + /* Part before ':' */ + p = line; + sep = strchr(p, ':'); + *sep = '\0'; + + ret = gbCapabilitiesEnumParse(p); + if (ret != GB_CAP_MAX) { + strncpy(caps[count].cap, gbCapabilitiesLookup[ret], 256); + + /* Part after ':' and before '\n' */ + p = sep + 1; + sep = strchr(p, '\n'); + *sep = '\0'; + + while(isspace((unsigned char)*p)) p++; + ret = convertStringToTrillianParse(p); + if (ret >= 0) { + caps[count].status = ret; + } else { + ret = -1; + goto out; + } + count++; + } + + GB_FREE(line); + } + + if (GB_CAP_MAX != count) { + ret = -1; + goto out; + } + + reply->xdata.xdata_len = GB_CAP_MAX * sizeof(gbCapObj); + reply->xdata.xdata_val = (char *) caps; + + ret = 0; + out: + GB_FREE(line); + fclose(fp); + + return ret; +} diff --git a/utils/capabilities.h b/utils/capabilities.h new file mode 100644 index 0000000..b157d80 --- /dev/null +++ b/utils/capabilities.h @@ -0,0 +1,65 @@ +/* + Copyright (c) 2018 Red Hat, Inc. + 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 "block.h" +# include "common.h" + + +typedef struct gbCapObj { + char cap[256]; + bool status; +} gbCapObj; + + +typedef struct gbCapResp { + int capMax; + gbCapObj *response; +} gbCapResp; + + +enum gbCapabilities { + GB_CREATE_CAP, + GB_CREATE_HA_CAP, + GB_CREATE_PREALLOC_CAP, + GB_CREATE_AUTH_CAP, + + GB_DELETE_CAP, + GB_DELETE_FORCE_CAP, + + GB_MODIFY_CAP, + GB_MODIFY_AUTH_CAP, + + GB_JSON_CAP, + + GB_CAP_MAX +}; + + +static const char *const gbCapabilitiesLookup[] = { + [GB_CREATE_CAP] = "create", + [GB_CREATE_HA_CAP] = "create_ha", + [GB_CREATE_PREALLOC_CAP] = "create_prealloc", + [GB_CREATE_AUTH_CAP] = "create_auth", + + [GB_DELETE_CAP] = "delete", + [GB_DELETE_FORCE_CAP] = "delete_force", + + [GB_MODIFY_CAP] = "modify", + [GB_MODIFY_AUTH_CAP] = "modify_auth", + + [GB_JSON_CAP] = "json", + + [GB_CAP_MAX] = NULL +}; + + +int gbCapabilitiesEnumParse(const char *cap); +int gbSetCapabilties (blockResponse **c); diff --git a/utils/gluster-block-caps.info b/utils/gluster-block-caps.info new file mode 100644 index 0000000..2dcdbd4 --- /dev/null +++ b/utils/gluster-block-caps.info @@ -0,0 +1,98 @@ +## +# Nature: cli command +# +# Label: 'create' +# +# Description: capability to create block storage in local node +# +# Since: 0.1 +## +create: true + +## +# Nature: cli sub-command +# +# Label: 'ha' +# +# Description: capability to replicate configuration of block for high availability +# +# Since: 0.1 +## +create_ha: true + +## +# Nature: cli sub-command +# +# Label: 'prealloc' +# +# Description: capability to preallocate underline storage +# +# Since: 0.3 +## +create_prealloc: true + +## +# Nature: cli sub-command +# +# Label: 'auth' +# +# Description: capability to set CHAP authentication for block +# +# Since: 0.2 +## +create_auth: true + +## +# Nature: cli command +# +# Label: 'delete' +# +# Description: capability to delete a block storage +# +# Since: 0.1 +## +delete: true + +## +# Nature: cli command +# +# Label: 'force' +# +# Description: capability to delete a block storage forcefully +# +# Since: 0.1 +## +delete_force: true + +## +# Nature: cli command +# +# Label: 'modify' +# +# Description: capability to modify already existing block +# +# Since: 0.2 +## +modify: true + +## +# Nature: cli sub-command +# +# Label: 'auth' +# +# Description: capability to modify CHAP authentication caps for existing block +# +# Since: 0.2 +## +modify_auth: true + +## +# Nature: cli sub-command +# +# Label: '--json' +# +# Description: capability to furnish results of any command in json formated way +# +# Since: 0.2 +## +json: true diff --git a/utils/utils.h b/utils/utils.h index 8a30d25..7141a3f 100644 --- a/utils/utils.h +++ b/utils/utils.h @@ -31,6 +31,9 @@ # define GB_LOCK_FILE GB_INFODIR "/gluster-blockd.lock" # define GB_UNIX_ADDRESS GB_INFODIR "/gluster-blockd.socket" + +# define GB_CAPS_FILE CONFDIR "/gluster-block-caps.info" + # define GB_TCP_PORT 24010 # define GB_TCP_PORT_STR "24010" @@ -59,6 +62,11 @@ # define FAILED_CREATING_FILE "failed while creating block file in gluster volume" # define FAILED_CREATING_META "failed while creating block meta file from volume" +/* Target Capabilities */ +# define FAILED_CAPS "failed in capabilities check" +# define FAILED_REMOTE_CAPS "failed in remote capabilities check" +# define FAILED_REMOTE_AYNC_CAPS "failed in remote async capabilities check" + /* Target List */ # define FAILED_LIST "failed in list" -- cgit