From 3c72850e8d00f0cf35ae054136be076a394e08e9 Mon Sep 17 00:00:00 2001 From: "M. Mohan Kumar" Date: Thu, 29 Nov 2012 21:46:07 +0530 Subject: BD Backend: CLI commands to create/delete image Cli commands added to create/delete a LV device. The following command creates lv in a given vg. $ gluster bd create :/ The following command deletes lv in a given vg. $ gluster bd delete :/ BUG: 805138 Change-Id: Ie4e100eca14e2ee32cf2bb4dd064b17230d673bf Signed-off-by: M. Mohan Kumar Reviewed-on: http://review.gluster.org/3718 Tested-by: Gluster Build System Reviewed-by: Vijay Bellur --- cli/src/Makefile.am | 3 + cli/src/cli-cmd-misc.c | 7 +- cli/src/cli-cmd-volume-bdevice.c | 225 +++++++++++++++++++++++++++++++++++++++ cli/src/cli-cmd.c | 5 + cli/src/cli-cmd.h | 4 + cli/src/cli-rpc-ops.c | 131 +++++++++++++++++++++++ cli/src/cli.h | 13 +++ 7 files changed, 387 insertions(+), 1 deletion(-) create mode 100644 cli/src/cli-cmd-volume-bdevice.c (limited to 'cli') diff --git a/cli/src/Makefile.am b/cli/src/Makefile.am index 393077688..7054f1120 100644 --- a/cli/src/Makefile.am +++ b/cli/src/Makefile.am @@ -3,6 +3,9 @@ sbin_PROGRAMS = gluster gluster_SOURCES = cli.c registry.c input.c cli-cmd.c cli-rl.c \ cli-cmd-volume.c cli-cmd-peer.c cli-rpc-ops.c cli-cmd-parser.c\ cli-cmd-system.c cli-cmd-misc.c cli-xml-output.c +if ENABLE_BD_XLATOR +gluster_SOURCES += cli-cmd-volume-bdevice.c +endif gluster_LDADD = $(top_builddir)/libglusterfs/src/libglusterfs.la $(GF_LDADD)\ $(RLLIBS) $(top_builddir)/rpc/xdr/src/libgfxdr.la \ diff --git a/cli/src/cli-cmd-misc.c b/cli/src/cli-cmd-misc.c index f3ef12147..5f3a77ca6 100644 --- a/cli/src/cli-cmd-misc.c +++ b/cli/src/cli-cmd-misc.c @@ -31,6 +31,7 @@ extern struct cli_cmd volume_cmds[]; extern struct cli_cmd cli_probe_cmds[]; extern struct cli_cmd cli_log_cmds[]; extern struct cli_cmd cli_system_cmds[]; +extern struct cli_cmd cli_bd_cmds[]; struct cli_cmd cli_misc_cmds[]; int @@ -45,7 +46,11 @@ cli_cmd_display_help (struct cli_state *state, struct cli_cmd_word *in_word, const char **words, int wordcount) { struct cli_cmd *cmd[] = {volume_cmds, cli_probe_cmds, - cli_misc_cmds, NULL}; + cli_misc_cmds, +#ifdef HAVE_BD_XLATOR + cli_bd_cmds, +#endif + NULL}; struct cli_cmd *cmd_ind = NULL; int i = 0; diff --git a/cli/src/cli-cmd-volume-bdevice.c b/cli/src/cli-cmd-volume-bdevice.c new file mode 100644 index 000000000..ea7edab65 --- /dev/null +++ b/cli/src/cli-cmd-volume-bdevice.c @@ -0,0 +1,225 @@ +/* + CLI for BD translator + + Copyright IBM, Corp. 2012 + + This file is part of GlusterFS. + + Author: + M. Mohan Kumar + + 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. +*/ + +#ifndef _CONFIG_H +#define _CONFIG_H +#include "config.h" +#endif + +#include "cli.h" +#include "cli-cmd.h" +#include + +extern rpc_clnt_prog_t *cli_rpc_prog; + +int +cli_cmd_bd_help_cbk (struct cli_state *state, struct cli_cmd_word *in_word, + const char **words, int wordcount); + +int32_t +cli_cmd_bd_parse (dict_t *dict, const char **words) +{ + char *volname = NULL; + char *buff = NULL; + char *buffp = NULL; + int ret = -1; + char *save = NULL; + char *path = NULL; + char *size = NULL; + char *eptr = NULL; + gf_xl_bd_op_t bd_op = GF_BD_OP_INVALID; + + /* volname:/path */ + if (!strchr (words[2], ':') || !strchr (words[2], '/')) { + cli_out ("invalid parameter %s, needs ", + words[2]); + return -1; + } + buff = buffp = gf_strdup (words[2]); + volname = strtok_r (buff, ":", &save); + path = strtok_r (NULL, ":", &save); + + ret = dict_set_dynstr (dict, "volname", gf_strdup (volname)); + if (ret) + goto out; + + ret = dict_set_dynstr (dict, "path", gf_strdup (path)); + if (ret) + goto out; + + if (!strcasecmp (words[1], "create")) + bd_op = GF_BD_OP_NEW_BD; + else if (!strcasecmp (words[1], "delete")) + bd_op = GF_BD_OP_DELETE_BD; + else + return -1; + + ret = dict_set_int32 (dict, "bd-op", bd_op); + if (ret) + goto out; + + if (bd_op == GF_BD_OP_NEW_BD) { + /* If no suffix given we will treat it as MB */ + strtoull (words[3], &eptr, 0); + /* no suffix */ + if (!eptr[0]) + gf_asprintf (&size, "%sMB", words[3]); + else + size = gf_strdup (words[3]); + + ret = dict_set_dynstr (dict, "size", size); + if (ret) + goto out; + } + + ret = 0; +out: + GF_FREE (buffp); + return ret; +} + +/* + * bd create :/path + * bd delete :/path + */ +int32_t +cli_cmd_bd_validate (const char **words, int wordcount, dict_t **options) +{ + dict_t *dict = NULL; + int ret = -1; + char *op[] = { "create", "delete", NULL }; + int index = 0; + + for (index = 0; op[index]; index++) + if (!strcasecmp (words[1], op[index])) + break; + + if (!op[index]) + return -1; + + dict = dict_new (); + if (!dict) + goto out; + + if (!strcasecmp (words[1], "create")) { + if (wordcount != 4) + goto out; + } else if (!strcasecmp (words[1], "delete")) { + if (wordcount != 3) + goto out; + } else { + ret = -1; + goto out; + } + + ret = cli_cmd_bd_parse (dict, words); + if (ret < 0) + goto out; + + *options = dict; + ret = 0; +out: + if (ret) + dict_unref (dict); + return ret; +} + +int +cli_cmd_bd_cbk (struct cli_state *state, struct cli_cmd_word *word, + const char **words, int wordcount) +{ + int ret = -1; + rpc_clnt_procedure_t *proc = NULL; + call_frame_t *frame = NULL; + int sent = 0; + int parse_error = 0; + dict_t *options = NULL; + cli_local_t *local = NULL; + + proc = &cli_rpc_prog->proctable[GLUSTER_CLI_BD_OP]; + + frame = create_frame (THIS, THIS->ctx->pool); + if (!frame) + goto out; + + ret = cli_cmd_bd_validate (words, wordcount, &options); + if (ret) { + cli_usage_out (word->pattern); + parse_error = 1; + goto out; + } + + CLI_LOCAL_INIT (local, words, frame, options); + if (proc->fn) { + ret = proc->fn (frame, THIS, options); + } + +out: + if (options) + dict_unref (options); + + if (ret) { + cli_cmd_sent_status_get (&sent); + if ((sent == 0) && (parse_error == 0)) + cli_out ("BD op failed!"); + } + + CLI_STACK_DESTROY (frame); + + return ret; +} + +struct cli_cmd cli_bd_cmds[] = { + { "bd help", + cli_cmd_bd_help_cbk, + "display help for bd command"}, + { "bd create : ", + cli_cmd_bd_cbk, + "\n\tcreate a block device where size can be " + "suffixed with KB, MB etc. Default size is in MB"}, + { "bd delete :", + cli_cmd_bd_cbk, + "Delete a block device"}, + { NULL, NULL, NULL } +}; + +int +cli_cmd_bd_help_cbk (struct cli_state *state, struct cli_cmd_word *in_word, + const char **words, int wordcount) +{ + struct cli_cmd *cmd = NULL; + + for (cmd = cli_bd_cmds; cmd->pattern; cmd++) + if (_gf_false == cmd->disable) + cli_out ("%s - %s", cmd->pattern, cmd->desc); + + return 0; +} + +int +cli_cmd_bd_register (struct cli_state *state) +{ + int ret = 0; + struct cli_cmd *cmd = NULL; + + for (cmd = cli_bd_cmds; cmd->pattern; cmd++) { + ret = cli_cmd_register (&state->tree, cmd); + if (ret) + goto out; + } +out: + return ret; +} diff --git a/cli/src/cli-cmd.c b/cli/src/cli-cmd.c index 64aba5d9f..7a697603e 100644 --- a/cli/src/cli-cmd.c +++ b/cli/src/cli-cmd.c @@ -231,6 +231,11 @@ cli_cmds_register (struct cli_state *state) if (ret) goto out; +#ifdef HAVE_BD_XLATOR + ret = cli_cmd_bd_register (state); + if (ret) + goto out; +#endif out: return ret; } diff --git a/cli/src/cli-cmd.h b/cli/src/cli-cmd.h index a30a6cfe4..0ad37d498 100644 --- a/cli/src/cli-cmd.h +++ b/cli/src/cli-cmd.h @@ -118,4 +118,8 @@ cli_cmd_submit (void *req, call_frame_t *frame, gf_answer_t cli_cmd_get_confirmation (struct cli_state *state, const char *question); int cli_cmd_sent_status_get (int *status); + +#ifdef HAVE_BD_XLATOR +int cli_cmd_bd_register (struct cli_state *state); +#endif #endif /* __CLI_CMD_H__ */ diff --git a/cli/src/cli-rpc-ops.c b/cli/src/cli-rpc-ops.c index 77e15ee29..9e4e03d07 100644 --- a/cli/src/cli-rpc-ops.c +++ b/cli/src/cli-rpc-ops.c @@ -2601,6 +2601,134 @@ out: return ret; } +#ifdef HAVE_BD_XLATOR +int +gf_cli_bd_op_cbk (struct rpc_req *req, struct iovec *iov, + int count, void *myframe) +{ + gf_cli_rsp rsp = {0,}; + int ret = -1; + cli_local_t *local = NULL; + dict_t *dict = NULL; + dict_t *input_dict = NULL; + gf_xl_bd_op_t bd_op = GF_BD_OP_INVALID; + char *operation = NULL; + call_frame_t *frame = NULL; + + if (-1 == req->rpc_status) + goto out; + + ret = xdr_to_generic (*iov, &rsp, (xdrproc_t)xdr_gf_cli_rsp); + if (ret < 0) { + gf_log ("", GF_LOG_ERROR, "error"); + goto out; + } + + dict = dict_new (); + if (!dict) { + ret = -1; + goto out; + } + + frame = myframe; + if (frame) + local = frame->local; + + if (local) { + input_dict = local->dict; + ret = dict_get_int32 (input_dict, "bd-op", + (int32_t *)&bd_op); + } + + switch (bd_op) { + case GF_BD_OP_NEW_BD: + operation = gf_strdup ("create"); + break; + case GF_BD_OP_DELETE_BD: + operation = gf_strdup ("delete"); + break; + default: + break; + } + + ret = dict_unserialize (rsp.dict.dict_val, rsp.dict.dict_len, &dict); + if (ret) + goto out; + + gf_log ("cli", GF_LOG_INFO, "Received resp to %s bd op", operation); + + if (global_state->mode & GLUSTER_MODE_XML) { + ret = cli_xml_output_dict ("BdOp", dict, rsp.op_ret, + rsp.op_errno, rsp.op_errstr); + if (ret) + gf_log ("cli", GF_LOG_ERROR, + "Error outputting to xml"); + goto out; + } + + if (rsp.op_ret && strcmp (rsp.op_errstr, "")) + cli_err ("%s", rsp.op_errstr); + else + cli_out ("BD %s has been %s", operation, + (rsp.op_ret) ? "unsuccessful": + "successful."); + ret = rsp.op_ret; + +out: + cli_cmd_broadcast_response (ret); + + if (dict) + dict_unref (dict); + + if (operation) + GF_FREE (operation); + + if (rsp.dict.dict_val) + free (rsp.dict.dict_val); + if (rsp.op_errstr) + free (rsp.op_errstr); + return ret; +} + +int32_t +gf_cli_bd_op (call_frame_t *frame, xlator_t *this, + void *data) +{ + gf_cli_req req = { {0,} }; + int ret = 0; + dict_t *dict = NULL; + + if (!frame || !this || !data) { + ret = -1; + goto out; + } + + dict = dict_ref ((dict_t *)data); + if (!dict) + goto out; + + ret = dict_allocate_and_serialize (dict, + &req.dict.dict_val, + &req.dict.dict_len); + + + ret = cli_cmd_submit (&req, frame, cli_rpc_prog, + GLUSTER_CLI_BD_OP, NULL, + this, gf_cli_bd_op_cbk, + (xdrproc_t) xdr_gf_cli_req); + +out: + if (dict) + dict_unref (dict); + + if (req.dict.dict_val) + GF_FREE (req.dict.dict_val); + + gf_log ("cli", GF_LOG_DEBUG, "Returning %d", ret); + return ret; +} +#endif + int32_t gf_cli_create_volume (call_frame_t *frame, xlator_t *this, void *data) @@ -6227,6 +6355,9 @@ struct rpc_clnt_procedure gluster_cli_actors[GLUSTER_CLI_MAXVALUE] = { [GLUSTER_CLI_STATEDUMP_VOLUME] = {"STATEDUMP_VOLUME", gf_cli_statedump_volume}, [GLUSTER_CLI_LIST_VOLUME] = {"LIST_VOLUME", gf_cli_list_volume}, [GLUSTER_CLI_CLRLOCKS_VOLUME] = {"CLEARLOCKS_VOLUME", gf_cli_clearlocks_volume}, +#ifdef HAVE_BD_XLATOR + [GLUSTER_CLI_BD_OP] = {"BD_OP", gf_cli_bd_op}, +#endif }; struct rpc_clnt_program cli_prog = { diff --git a/cli/src/cli.h b/cli/src/cli.h index a5f85ec88..6e05e0996 100644 --- a/cli/src/cli.h +++ b/cli/src/cli.h @@ -37,6 +37,19 @@ #define CLI_TAB_LENGTH 8 #define CLI_BRICK_STATUS_LINE_LEN 78 +#define CLI_LOCAL_INIT(local, words, frame, dictionary) \ + do { \ + local = cli_local_get (); \ + \ + if (local) { \ + local->words = words; \ + if (dictionary) \ + local->dict = dictionary; \ + if (frame) \ + frame->local = local; \ + } \ + } while (0) + enum argp_option_keys { ARGP_DEBUG_KEY = 133, ARGP_PORT_KEY = 'p', -- cgit