/* Copyright (c) 2010-2011 Gluster, Inc. This file is part of GlusterFS. GlusterFS is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. GlusterFS is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . */ #include #include #include #include #include #ifndef _CONFIG_H #define _CONFIG_H #include "config.h" #endif #include "cli.h" #include "cli-cmd.h" #include "cli-mem-types.h" #include "cli1-xdr.h" #include "run.h" extern struct rpc_clnt *global_rpc; extern rpc_clnt_prog_t *cli_rpc_prog; int cli_cmd_volume_help_cbk (struct cli_state *state, struct cli_cmd_word *in_word, const char **words, int wordcount); int cli_cmd_volume_info_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; cli_cmd_volume_get_ctx_t ctx = {0,}; cli_local_t *local = NULL; int sent = 0; int parse_error = 0; proc = &cli_rpc_prog->proctable[GLUSTER_CLI_GET_VOLUME]; frame = create_frame (THIS, THIS->ctx->pool); if (!frame) goto out; if ((wordcount == 2) || (wordcount == 3 && !strcmp (words[2], "all"))) { ctx.flags = GF_CLI_GET_NEXT_VOLUME; proc = &cli_rpc_prog->proctable[GLUSTER_CLI_GET_NEXT_VOLUME]; } else if (wordcount == 3) { ctx.flags = GF_CLI_GET_VOLUME; ctx.volname = (char *)words[2]; if (strlen (ctx.volname) > 1024) { cli_out ("Invalid volume name"); goto out; } proc = &cli_rpc_prog->proctable[GLUSTER_CLI_GET_VOLUME]; } else { cli_usage_out (word->pattern); parse_error = 1; return -1; } local = cli_local_get (); if (!local) goto out; local->u.get_vol.flags = ctx.flags; if (ctx.volname) local->u.get_vol.volname = gf_strdup (ctx.volname); frame->local = local; if (proc->fn) { ret = proc->fn (frame, THIS, &ctx); } out: if (ret) { cli_cmd_sent_status_get (&sent); if ((sent == 0) && (parse_error == 0)) cli_out ("Getting Volume information failed!"); } return ret; } int cli_cmd_sync_volume_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; gf1_cli_sync_volume_req req = {0,}; int sent = 0; int parse_error = 0; if ((wordcount < 3) || (wordcount > 4)) { cli_usage_out (word->pattern); parse_error = 1; goto out; } if ((wordcount == 3) || !strcmp(words[3], "all")) { req.flags = GF_CLI_SYNC_ALL; req.volname = ""; } else { req.volname = (char *)words[3]; } req.hostname = (char *)words[2]; proc = &cli_rpc_prog->proctable[GLUSTER_CLI_SYNC_VOLUME]; frame = create_frame (THIS, THIS->ctx->pool); if (!frame) goto out; if (proc->fn) { ret = proc->fn (frame, THIS, &req); } out: if (ret) { cli_cmd_sent_status_get (&sent); if ((sent == 0) && (parse_error == 0)) cli_out ("Volume sync failed"); } return ret; } int cli_cmd_volume_create_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; dict_t *options = NULL; int sent = 0; int parse_error = 0; proc = &cli_rpc_prog->proctable[GLUSTER_CLI_CREATE_VOLUME]; frame = create_frame (THIS, THIS->ctx->pool); if (!frame) goto out; ret = cli_cmd_volume_create_parse (words, wordcount, &options); if (ret) { cli_usage_out (word->pattern); parse_error = 1; goto out; } 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 ("Volume create failed"); } return ret; } int cli_cmd_volume_delete_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; char *volname = NULL; gf_answer_t answer = GF_ANSWER_NO; const char *question = NULL; int sent = 0; int parse_error = 0; question = "Deleting volume will erase all information about the volume. " "Do you want to continue?"; proc = &cli_rpc_prog->proctable[GLUSTER_CLI_DELETE_VOLUME]; frame = create_frame (THIS, THIS->ctx->pool); if (!frame) goto out; if (wordcount != 3) { cli_usage_out (word->pattern); parse_error = 1; goto out; } answer = cli_cmd_get_confirmation (state, question); if (GF_ANSWER_NO == answer) { ret = 0; goto out; } volname = (char *)words[2]; if (proc->fn) { ret = proc->fn (frame, THIS, volname); } out: if (ret) { cli_cmd_sent_status_get (&sent); if ((sent == 0) && (parse_error == 0)) cli_out ("Volume delete failed"); } return ret; } int cli_cmd_volume_start_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; gf1_cli_start_vol_req req = {0,}; int sent = 0; int parse_error = 0; frame = create_frame (THIS, THIS->ctx->pool); if (!frame) goto out; if (wordcount < 3 || wordcount > 4) { cli_usage_out (word->pattern); parse_error = 1; goto out; } req.volname = (char *)words[2]; if (!req.volname) goto out; if (wordcount == 4) { if (!strcmp("force", words[3])) { req.flags |= GF_CLI_FLAG_OP_FORCE; } else { ret = -1; cli_usage_out (word->pattern); parse_error = 1; goto out; } } proc = &cli_rpc_prog->proctable[GLUSTER_CLI_START_VOLUME]; if (proc->fn) { ret = proc->fn (frame, THIS, &req); } out: if (ret) { cli_cmd_sent_status_get (&sent); if ((sent == 0) && (parse_error == 0)) cli_out ("Volume start failed"); } return ret; } gf_answer_t cli_cmd_get_confirmation (struct cli_state *state, const char *question) { char answer[5] = {'\0', }; char flush = '\0'; int len = 0; if (state->mode & GLUSTER_MODE_SCRIPT) return GF_ANSWER_YES; printf ("%s (y/n) ", question); if (fgets (answer, 4, stdin) == NULL) { cli_out("gluster cli read error"); goto out; } len = strlen (answer); if (answer [len - 1] == '\n'){ answer [--len] = '\0'; } else { do{ flush = getchar (); }while (flush != '\n'); } if (len > 3) goto out; if (!strcasecmp (answer, "y") || !strcasecmp (answer, "yes")) return GF_ANSWER_YES; else if (!strcasecmp (answer, "n") || !strcasecmp (answer, "no")) return GF_ANSWER_NO; out: cli_out ("Invalid input, please enter y/n"); return GF_ANSWER_NO; } int cli_cmd_volume_stop_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 flags = 0; gf1_cli_stop_vol_req req = {0,}; gf_answer_t answer = GF_ANSWER_NO; int sent = 0; int parse_error = 0; const char *question = "Stopping volume will make its data inaccessible. " "Do you want to continue?"; frame = create_frame (THIS, THIS->ctx->pool); if (!frame) goto out; if (wordcount < 3 || wordcount > 4) { cli_usage_out (word->pattern); parse_error = 1; goto out; } req.volname = (char *)words[2]; if (!req.volname) goto out; if (wordcount == 4) { if (!strcmp("force", words[3])) { flags |= GF_CLI_FLAG_OP_FORCE; } else { ret = -1; cli_usage_out (word->pattern); parse_error = 1; goto out; } } answer = cli_cmd_get_confirmation (state, question); if (GF_ANSWER_NO == answer) { ret = 0; goto out; } req.flags = flags; proc = &cli_rpc_prog->proctable[GLUSTER_CLI_STOP_VOLUME]; if (proc->fn) { ret = proc->fn (frame, THIS, &req); } out: if (ret) { cli_cmd_sent_status_get (&sent); if ((sent == 0) && (parse_error == 0)) cli_out ("Volume stop on '%s' failed", req.volname); } return ret; } int cli_cmd_volume_rename_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; dict_t *dict = NULL; int sent = 0; int parse_error = 0; frame = create_frame (THIS, THIS->ctx->pool); if (!frame) goto out; dict = dict_new (); if (!dict) goto out; if (wordcount != 4) { cli_usage_out (word->pattern); parse_error = 1; goto out; } ret = dict_set_str (dict, "old-volname", (char *)words[2]); if (ret) goto out; ret = dict_set_str (dict, "new-volname", (char *)words[3]); if (ret) goto out; proc = &cli_rpc_prog->proctable[GLUSTER_CLI_RENAME_VOLUME]; if (proc->fn) { ret = proc->fn (frame, THIS, dict); } out: if (dict) dict_destroy (dict); if (ret) { cli_cmd_sent_status_get (&sent); if ((sent == 0) && (parse_error == 0)) cli_out ("Volume rename on '%s' failed", (char *)words[2]); } return ret; } int cli_cmd_volume_defrag_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; dict_t *dict = NULL; int sent = 0; int parse_error = 0; int index = 0; #ifdef GF_SOLARIS_HOST_OS cli_out ("Command not supported on Solaris"); goto out; #endif frame = create_frame (THIS, THIS->ctx->pool); if (!frame) goto out; dict = dict_new (); if (!dict) goto out; if (!((wordcount == 4) || (wordcount == 5) || (wordcount == 6))) { cli_usage_out (word->pattern); parse_error = 1; goto out; } if (wordcount == 4) { index = 3; } else { if (strcmp (words[3], "fix-layout") && strcmp (words[3], "migrate-data")) { cli_usage_out (word->pattern); parse_error = 1; goto out; } index = 4; } if (strcmp (words[index], "start") && strcmp (words[index], "stop") && strcmp (words[index], "status")) { cli_usage_out (word->pattern); parse_error = 1; goto out; } ret = dict_set_str (dict, "volname", (char *)words[2]); if (ret) goto out; if (wordcount == 4) { ret = dict_set_str (dict, "command", (char *)words[3]); if (ret) goto out; } if (wordcount == 5) { ret = dict_set_str (dict, "start-type", (char *)words[3]); if (ret) goto out; ret = dict_set_str (dict, "command", (char *)words[4]); if (ret) goto out; } /* 'force' option is valid only for the 'migrate-data' key */ if (wordcount == 6) { if (strcmp (words[3], "migrate-data") || strcmp (words[4], "start") || strcmp (words[5], "force")) { cli_usage_out (word->pattern); parse_error = 1; goto out; } ret = dict_set_str (dict, "start-type", "migrate-data-force"); if (ret) goto out; ret = dict_set_str (dict, "command", (char *)words[4]); if (ret) goto out; } proc = &cli_rpc_prog->proctable[GLUSTER_CLI_DEFRAG_VOLUME]; if (proc->fn) { ret = proc->fn (frame, THIS, dict); } out: if (dict) dict_destroy (dict); if (ret) { cli_cmd_sent_status_get (&sent); if ((sent == 0) && (parse_error == 0)) cli_out ("Volume rebalance failed"); } return ret; } int cli_cmd_volume_reset_cbk (struct cli_state *state, struct cli_cmd_word *word, const char **words, int wordcount) { int sent = 0; int parse_error = 0; int ret = -1; rpc_clnt_procedure_t *proc = NULL; call_frame_t *frame = NULL; dict_t *options = NULL; proc = &cli_rpc_prog->proctable[GLUSTER_CLI_RESET_VOLUME]; frame = create_frame (THIS, THIS->ctx->pool); if (!frame) goto out; ret = cli_cmd_volume_reset_parse (words, wordcount, &options); if (ret) { cli_usage_out (word->pattern); parse_error = 1; goto out; } 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 ("Volume reset failed"); } return ret; } int cli_cmd_volume_profile_cbk (struct cli_state *state, struct cli_cmd_word *word, const char **words, int wordcount) { int sent = 0; int parse_error = 0; int ret = -1; rpc_clnt_procedure_t *proc = NULL; call_frame_t *frame = NULL; dict_t *options = NULL; ret = cli_cmd_volume_profile_parse (words, wordcount, &options); if (ret) { cli_usage_out (word->pattern); parse_error = 1; goto out; } proc = &cli_rpc_prog->proctable[GLUSTER_CLI_PROFILE_VOLUME]; frame = create_frame (THIS, THIS->ctx->pool); if (!frame) goto out; 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 ("Volume profile failed"); } return ret; } int cli_cmd_volume_set_cbk (struct cli_state *state, struct cli_cmd_word *word, const char **words, int wordcount) { int sent = 0; int parse_error = 0; int ret = -1; rpc_clnt_procedure_t *proc = NULL; call_frame_t *frame = NULL; dict_t *options = NULL; proc = &cli_rpc_prog->proctable[GLUSTER_CLI_SET_VOLUME]; frame = create_frame (THIS, THIS->ctx->pool); if (!frame) goto out; ret = cli_cmd_volume_set_parse (words, wordcount, &options); if (ret) { cli_usage_out (word->pattern); parse_error = 1; goto out; } 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 ("Volume set failed"); } return ret; } int cli_cmd_volume_add_brick_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; dict_t *options = NULL; int sent = 0; int parse_error = 0; frame = create_frame (THIS, THIS->ctx->pool); if (!frame) goto out; ret = cli_cmd_volume_add_brick_parse (words, wordcount, &options); if (ret) { cli_usage_out (word->pattern); parse_error = 1; goto out; } proc = &cli_rpc_prog->proctable[GLUSTER_CLI_ADD_BRICK]; 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 ("Volume add-brick failed"); } return ret; } int cli_cmd_quota_cbk (struct cli_state *state, struct cli_cmd_word *word, const char **words, int wordcount) { int ret = 0; int parse_err = 0; int32_t type = 0; rpc_clnt_procedure_t *proc = NULL; call_frame_t *frame = NULL; dict_t *options = NULL; gf_answer_t answer = GF_ANSWER_NO; const char *question = "Disabling quota will delete all the quota " "configuration. Do you want to continue?"; proc = &cli_rpc_prog->proctable[GLUSTER_CLI_QUOTA]; if (proc == NULL) { ret = -1; goto out; } frame = create_frame (THIS, THIS->ctx->pool); if (!frame) { ret = -1; goto out; } ret = cli_cmd_quota_parse (words, wordcount, &options); if (ret < 0) { cli_usage_out (word->pattern); parse_err = 1; goto out; } else if (dict_get_int32 (options, "type", &type) == 0 && type == GF_QUOTA_OPTION_TYPE_DISABLE) { answer = cli_cmd_get_confirmation (state, question); if (answer == GF_ANSWER_NO) goto out; } if (proc->fn) ret = proc->fn (frame, THIS, options); out: if (options) dict_unref (options); if (ret && parse_err == 0) cli_out ("Quota command failed"); return ret; } int cli_cmd_volume_remove_brick_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; dict_t *options = NULL; gf_answer_t answer = GF_ANSWER_NO; int sent = 0; int parse_error = 0; int need_question = 0; const char *question = "Removing brick(s) can result in data loss. " "Do you want to Continue?"; frame = create_frame (THIS, THIS->ctx->pool); if (!frame) goto out; ret = cli_cmd_volume_remove_brick_parse (words, wordcount, &options, &need_question); if (ret) { cli_usage_out (word->pattern); parse_error = 1; goto out; } if (!(state->mode & GLUSTER_MODE_SCRIPT) && need_question) { /* we need to ask question only in case of 'commit or force' */ answer = cli_cmd_get_confirmation (state, question); if (GF_ANSWER_NO == answer) { ret = 0; goto out; } } proc = &cli_rpc_prog->proctable[GLUSTER_CLI_REMOVE_BRICK]; if (proc->fn) { ret = proc->fn (frame, THIS, options); } out: if (ret) { cli_cmd_sent_status_get (&sent); if ((sent == 0) && (parse_error == 0)) cli_out ("Volume remove-brick failed"); } if (options) dict_unref (options); return ret; } int cli_cmd_volume_replace_brick_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; dict_t *options = NULL; int sent = 0; int parse_error = 0; #ifdef GF_SOLARIS_HOST_OS cli_out ("Command not supported on Solaris"); goto out; #endif proc = &cli_rpc_prog->proctable[GLUSTER_CLI_REPLACE_BRICK]; frame = create_frame (THIS, THIS->ctx->pool); if (!frame) goto out; ret = cli_cmd_volume_replace_brick_parse (words, wordcount, &options); if (ret) { cli_usage_out (word->pattern); parse_error = 1; goto out; } 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 ("Volume replace-brick failed"); } return ret; } int cli_cmd_volume_set_transport_cbk (struct cli_state *state, struct cli_cmd_word *word, const char **words, int wordcount) { cli_cmd_broadcast_response (0); return 0; } int cli_cmd_log_filename_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; dict_t *options = NULL; int sent = 0; int parse_error = 0; if (!((wordcount == 5) || (wordcount == 6))) { cli_usage_out (word->pattern); parse_error = 1; goto out; } proc = &cli_rpc_prog->proctable[GLUSTER_CLI_LOG_FILENAME]; frame = create_frame (THIS, THIS->ctx->pool); if (!frame) goto out; ret = cli_cmd_log_filename_parse (words, wordcount, &options); if (ret) goto out; if (proc->fn) { ret = proc->fn (frame, THIS, options); } out: if (options) dict_destroy (options); if (ret) { cli_cmd_sent_status_get (&sent); if ((sent == 0) && (parse_error == 0)) cli_out ("Volume log filename failed"); } return ret; } int cli_cmd_volume_top_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; dict_t *options = NULL; int sent = 0; int parse_error = 0; ret = cli_cmd_volume_top_parse (words, wordcount, &options); if (ret) { parse_error = 1; cli_usage_out (word->pattern); goto out; } proc = &cli_rpc_prog->proctable[GLUSTER_CLI_TOP_VOLUME]; frame = create_frame (THIS, THIS->ctx->pool); if (!frame) goto out; 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 ("Volume top failed"); } return ret; } int cli_cmd_log_locate_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; dict_t *options = NULL; int sent = 0; int parse_error = 0; if (!((wordcount == 4) || (wordcount == 5))) { cli_usage_out (word->pattern); parse_error = 1; goto out; } proc = &cli_rpc_prog->proctable[GLUSTER_CLI_LOG_LOCATE]; frame = create_frame (THIS, THIS->ctx->pool); if (!frame) goto out; ret = cli_cmd_log_locate_parse (words, wordcount, &options); if (ret) goto out; if (proc->fn) { ret = proc->fn (frame, THIS, options); } out: if (options) dict_destroy (options); if (ret) { cli_cmd_sent_status_get (&sent); if ((sent == 0) && (parse_error == 0)) cli_out ("getting log file location information failed"); } return ret; } int cli_cmd_log_rotate_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; dict_t *options = NULL; int sent = 0; int parse_error = 0; if (!((wordcount == 4) || (wordcount == 5))) { cli_usage_out (word->pattern); parse_error = 1; goto out; } proc = &cli_rpc_prog->proctable[GLUSTER_CLI_LOG_ROTATE]; frame = create_frame (THIS, THIS->ctx->pool); if (!frame) goto out; ret = cli_cmd_log_rotate_parse (words, wordcount, &options); if (ret) goto out; if (proc->fn) { ret = proc->fn (frame, THIS, options); } out: if (options) dict_destroy (options); if (ret) { cli_cmd_sent_status_get (&sent); if ((sent == 0) && (parse_error == 0)) cli_out ("Volume log rotate failed"); } return ret; } #if (SYNCDAEMON_COMPILE) static int cli_check_gsync_present () { char buff[PATH_MAX] = {0, }; runner_t runner = {0,}; char *ptr = NULL; int ret = 0; ret = setenv ("_GLUSTERD_CALLED_", "1", 1); if (-1 == ret) { gf_log ("", GF_LOG_WARNING, "setenv syscall failed, hence could" "not assert if geo-replication is installed"); goto out; } runinit (&runner); runner_add_args (&runner, GSYNCD_PREFIX"/gsyncd", "--version", NULL); runner_redir (&runner, STDOUT_FILENO, RUN_PIPE); ret = runner_start (&runner); if (ret == -1) { gf_log ("", GF_LOG_INFO, "geo-replication not installed"); goto out; } ptr = fgets(buff, sizeof(buff), runner_chio (&runner, STDOUT_FILENO)); if (ptr) { if (!strstr (buff, "gsyncd")) { ret = -1; goto out; } } else { ret = -1; goto out; } ret = runner_end (&runner); if (ret) gf_log ("", GF_LOG_ERROR, "geo-replication not installed"); out: gf_log ("cli", GF_LOG_DEBUG, "Returning %d", ret); return ret ? -1 : 0; } void cli_cmd_check_gsync_exists_cbk (struct cli_cmd *this) { int ret = 0; ret = cli_check_gsync_present (); if (ret) this->disable = _gf_true; } #endif int cli_cmd_volume_gsync_set_cbk (struct cli_state *state, struct cli_cmd_word *word, const char **words, int wordcount) { int ret = 0; int parse_err = 0; dict_t *options = NULL; rpc_clnt_procedure_t *proc = NULL; call_frame_t *frame = NULL; proc = &cli_rpc_prog->proctable [GLUSTER_CLI_GSYNC_SET]; if (proc == NULL) { ret = -1; goto out; } frame = create_frame (THIS, THIS->ctx->pool); if (frame == NULL) { ret = -1; goto out; } ret = cli_cmd_gsync_set_parse (words, wordcount, &options); if (ret) { cli_usage_out (word->pattern); parse_err = 1; goto out; } if (proc->fn) ret = proc->fn (frame, THIS, options); out: if (options) dict_unref (options); if (ret && parse_err == 0) cli_out (GEOREP" command failed"); return ret; } int cli_cmd_log_level_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; dict_t *dict = NULL; if (wordcount != 6) { cli_usage_out (word->pattern); goto out; } proc = &cli_rpc_prog->proctable[GLUSTER_CLI_LOG_LEVEL]; frame = create_frame (THIS, THIS->ctx->pool); if (!frame) goto out; ret = cli_cmd_log_level_parse (words, wordcount, &dict); if (ret) goto out; if (proc->fn) ret = proc->fn (frame, THIS, dict); out: return ret; } int cli_cmd_volume_status_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; dict_t *dict = NULL; if (wordcount != 3) { cli_usage_out (word->pattern); goto out; } proc = &cli_rpc_prog->proctable[GLUSTER_CLI_STATUS_VOLUME]; frame = create_frame (THIS, THIS->ctx->pool); if (!frame) goto out; ret = cli_cmd_volume_status_parse (words, wordcount, &dict); if (ret) goto out; if (proc->fn) ret = proc->fn (frame, THIS, dict); out: return ret; } int cli_print_brick_status (char *brick, int port, int online, int pid) { int fieldlen = CLI_VOL_STATUS_BRICK_LEN; char buf[80] = {0,}; int bricklen = 0; int i = 0; char *p = NULL; int num_tabs = 0; bricklen = strlen (brick); p = brick; while (bricklen > 0) { if (bricklen > fieldlen) { i++; strncpy (buf, p, fieldlen); buf[strlen(buf) + 1] = '\0'; cli_out ("%s", buf); p = brick + i * fieldlen; bricklen -= fieldlen; } else { num_tabs = (fieldlen - bricklen) / CLI_TAB_LENGTH + 1; printf ("%s", p); while (num_tabs-- != 0) printf ("\t"); cli_out ("%d\t%c\t%d", port, online?'Y':'N', pid); bricklen = 0; } } return 0; } struct cli_cmd volume_cmds[] = { { "volume info [all|]", cli_cmd_volume_info_cbk, "list information of all volumes"}, { "volume create [stripe ] [replica ] [transport ] ...", cli_cmd_volume_create_cbk, "create a new volume of specified type with mentioned bricks"}, { "volume delete ", cli_cmd_volume_delete_cbk, "delete volume specified by "}, { "volume start [force]", cli_cmd_volume_start_cbk, "start volume specified by "}, { "volume stop [force]", cli_cmd_volume_stop_cbk, "stop volume specified by "}, /*{ "volume rename ", cli_cmd_volume_rename_cbk, "rename volume to "},*/ { "volume add-brick ...", cli_cmd_volume_add_brick_cbk, "add brick to volume "}, { "volume remove-brick ... {start|pause|abort|status|commit|force}", cli_cmd_volume_remove_brick_cbk, "remove brick from volume "}, { "volume rebalance [fix-layout|migrate-data] {start|stop|status} [force]", cli_cmd_volume_defrag_cbk, "rebalance operations"}, { "volume replace-brick {start|pause|abort|status|commit}", cli_cmd_volume_replace_brick_cbk, "replace-brick operations"}, /*{ "volume set-transport [] ...", cli_cmd_volume_set_transport_cbk, "set transport type for volume "},*/ { "volume set ", cli_cmd_volume_set_cbk, "set options for volume "}, { "volume help", cli_cmd_volume_help_cbk, "display help for the volume command"}, { "volume log filename [BRICK] ", cli_cmd_log_filename_cbk, "set the log file for corresponding volume/brick"}, { "volume log locate [BRICK]", cli_cmd_log_locate_cbk, "locate the log file for corresponding volume/brick"}, { "volume log rotate [BRICK]", cli_cmd_log_rotate_cbk, "rotate the log file for corresponding volume/brick"}, { "volume sync [all|]", cli_cmd_sync_volume_cbk, "sync the volume information from a peer"}, { "volume reset [force]", cli_cmd_volume_reset_cbk, "reset all the reconfigured options"}, #if (SYNCDAEMON_COMPILE) {"volume "GEOREP" [] [] {start|stop|config|status} [options...]", cli_cmd_volume_gsync_set_cbk, "Geo-sync operations", cli_cmd_check_gsync_exists_cbk}, #endif { "volume profile {start|info|stop}", cli_cmd_volume_profile_cbk, "volume profile operations"}, { "volume quota [path] [value]", cli_cmd_quota_cbk, "quota translator specific operations"}, { "volume top {[open|read|write|opendir|readdir] " "|[read-perf|write-perf bs count ]} " " [brick ] [list-cnt ]", cli_cmd_volume_top_cbk, "volume top operations"}, {"volume log level ", cli_cmd_log_level_cbk, "log level for translator"}, { "volume status ", cli_cmd_volume_status_cbk, "display status of specified volume"}, { NULL, NULL, NULL } }; int cli_cmd_volume_help_cbk (struct cli_state *state, struct cli_cmd_word *in_word, const char **words, int wordcount) { struct cli_cmd *cmd = NULL; for (cmd = volume_cmds; cmd->pattern; cmd++) if (_gf_false == cmd->disable) cli_out ("%s - %s", cmd->pattern, cmd->desc); return 0; } int cli_cmd_volume_register (struct cli_state *state) { int ret = 0; struct cli_cmd *cmd = NULL; for (cmd = volume_cmds; cmd->pattern; cmd++) { ret = cli_cmd_register (&state->tree, cmd); if (ret) goto out; } out: return ret; }