summaryrefslogtreecommitdiffstats
path: root/cli/src/cli-cmd-volume.c
diff options
context:
space:
mode:
Diffstat (limited to 'cli/src/cli-cmd-volume.c')
-rw-r--r--cli/src/cli-cmd-volume.c1578
1 files changed, 1274 insertions, 304 deletions
diff --git a/cli/src/cli-cmd-volume.c b/cli/src/cli-cmd-volume.c
index 7a2109539..100be0b73 100644
--- a/cli/src/cli-cmd-volume.c
+++ b/cli/src/cli-cmd-volume.c
@@ -1,28 +1,23 @@
/*
- Copyright (c) 2010 Gluster, Inc. <http://www.gluster.com>
- This file is part of GlusterFS.
-
- GlusterFS is free software; you can redistribute it and/or modify
- it under the terms of the GNU Affero 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
- Affero General Public License for more details.
-
- You should have received a copy of the GNU Affero General Public License
- along with this program. If not, see
- <http://www.gnu.org/licenses/>.
-*/
+ Copyright (c) 2010-2012 Red Hat, Inc. <http://www.redhat.com>
+ This file is part of GlusterFS.
+ 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 <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <stdint.h>
#include <pthread.h>
+#include <sys/socket.h>
+#include <netdb.h>
+#include <sys/types.h>
+#include <netinet/in.h>
+
#ifndef _CONFIG_H
#define _CONFIG_H
#include "config.h"
@@ -32,6 +27,7 @@
#include "cli-cmd.h"
#include "cli-mem-types.h"
#include "cli1-xdr.h"
+#include "run.h"
extern struct rpc_clnt *global_rpc;
@@ -41,48 +37,6 @@ int
cli_cmd_volume_help_cbk (struct cli_state *state, struct cli_cmd_word *in_word,
const char **words, int wordcount);
-void
-cli_cmd_volume_start_usage ()
-{
- cli_out ("Usage: volume start <VOLNAME> [force]");
-}
-
-void
-cli_cmd_volume_stop_usage ()
-{
- cli_out ("Usage: volume stop <VOLNAME> [force]");
-}
-
-void
-cli_cmd_volume_rename_usage ()
-{
- cli_out ("Usage: volume rename <VOLNAME> <NEW-VOLNAME>");
-}
-
-void
-cli_cmd_volume_delete_usage ()
-{
- cli_out ("Usage: volume delete <VOLNAME>");
-}
-
-void
-cli_cmd_volume_info_usage ()
-{
- cli_out ("Usage: volume info [all|<VOLNAME>]");
-}
-
-void
-cli_cmd_volume_reset_usage ()
-{
- cli_out ("Usage: volume reset <VOLNAME> ");
-}
-
-void
-cli_cmd_volume_set_usage ()
-{
- cli_out ("Usage: volume set <VOLNAME> <KEY> <VALUE>");
-}
-
int
cli_cmd_volume_info_cbk (struct cli_state *state, struct cli_cmd_word *word,
const char **words, int wordcount)
@@ -92,8 +46,10 @@ cli_cmd_volume_info_cbk (struct cli_state *state, struct cli_cmd_word *word,
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[GF1_CLI_GET_VOLUME];
+ proc = &cli_rpc_prog->proctable[GLUSTER_CLI_GET_VOLUME];
frame = create_frame (THIS, THIS->ctx->pool);
if (!frame)
@@ -102,7 +58,7 @@ cli_cmd_volume_info_cbk (struct cli_state *state, struct cli_cmd_word *word,
if ((wordcount == 2) || (wordcount == 3 &&
!strcmp (words[2], "all"))) {
ctx.flags = GF_CLI_GET_NEXT_VOLUME;
- proc = &cli_rpc_prog->proctable[GF1_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];
@@ -110,9 +66,10 @@ cli_cmd_volume_info_cbk (struct cli_state *state, struct cli_cmd_word *word,
cli_out ("Invalid volume name");
goto out;
}
- proc = &cli_rpc_prog->proctable[GF1_CLI_GET_VOLUME];
+ proc = &cli_rpc_prog->proctable[GLUSTER_CLI_GET_VOLUME];
} else {
- cli_cmd_volume_info_usage ();
+ cli_usage_out (word->pattern);
+ parse_error = 1;
return -1;
}
@@ -121,9 +78,9 @@ cli_cmd_volume_info_cbk (struct cli_state *state, struct cli_cmd_word *word,
if (!local)
goto out;
- local->u.get_vol.flags = ctx.flags;
+ local->get_vol.flags = ctx.flags;
if (ctx.volname)
- local->u.get_vol.volname = gf_strdup (ctx.volname);
+ local->get_vol.volname = gf_strdup (ctx.volname);
frame->local = local;
@@ -132,17 +89,16 @@ cli_cmd_volume_info_cbk (struct cli_state *state, struct cli_cmd_word *word,
}
out:
- if (ret)
- cli_out ("Getting Volume information failed!");
- return ret;
+ if (ret) {
+ cli_cmd_sent_status_get (&sent);
+ if ((sent == 0) && (parse_error == 0))
+ cli_out ("Getting Volume information failed!");
+ }
-}
+ CLI_STACK_DESTROY (frame);
+ return ret;
-void
-cli_cmd_sync_volume_usage ()
-{
- cli_out ("Usage: volume sync <HOSTNAME> [all|<VOLNAME>]");
}
int
@@ -152,44 +108,227 @@ cli_cmd_sync_volume_cbk (struct cli_state *state, struct cli_cmd_word *word,
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;
+ dict_t *dict = NULL;
+ cli_local_t *local = NULL;
+ gf_answer_t answer = GF_ANSWER_NO;
+ const char *question = "Sync volume may make data "
+ "inaccessible while the sync "
+ "is in progress. Do you want "
+ "to continue?";
if ((wordcount < 3) || (wordcount > 4)) {
- cli_cmd_sync_volume_usage ();
- goto out;
+ cli_usage_out (word->pattern);
+ parse_error = 1;
+ goto out;
}
+ dict = dict_new ();
+ if (!dict)
+ goto out;
+
if ((wordcount == 3) || !strcmp(words[3], "all")) {
- req.flags = GF_CLI_SYNC_ALL;
- req.volname = "";
+ ret = dict_set_int32 (dict, "flags", (int32_t)
+ GF_CLI_SYNC_ALL);
+ if (ret) {
+ gf_log (THIS->name, GF_LOG_ERROR, "failed to set"
+ "flag");
+ goto out;
+ }
} else {
- req.volname = (char *)words[3];
+ ret = dict_set_str (dict, "volname", (char *) words[3]);
+ if (ret) {
+ gf_log (THIS->name, GF_LOG_ERROR, "failed to set "
+ "volume");
+ goto out;
+ }
+ }
+
+ ret = dict_set_str (dict, "hostname", (char *) words[2]);
+ if (ret) {
+ gf_log (THIS->name, GF_LOG_ERROR, "failed to set hostname");
+ goto out;
}
- req.hostname = (char *)words[2];
+ if (!(state->mode & GLUSTER_MODE_SCRIPT)) {
+ answer = cli_cmd_get_confirmation (state, question);
+ if (GF_ANSWER_NO == answer) {
+ ret = 0;
+ goto out;
+ }
+ }
- proc = &cli_rpc_prog->proctable[GF1_CLI_SYNC_VOLUME];
+ proc = &cli_rpc_prog->proctable[GLUSTER_CLI_SYNC_VOLUME];
frame = create_frame (THIS, THIS->ctx->pool);
if (!frame)
goto out;
+ CLI_LOCAL_INIT (local, words, frame, dict);
+
if (proc->fn) {
- ret = proc->fn (frame, THIS, &req);
+ ret = proc->fn (frame, THIS, dict);
}
out:
- if (ret)
- cli_out ("Volume sync failed");
+ if (ret) {
+ cli_cmd_sent_status_get (&sent);
+ if ((sent == 0) && (parse_error == 0))
+ cli_out ("Volume sync failed");
+ }
+
+ CLI_STACK_DESTROY (frame);
return ret;
}
-void
-cli_cmd_volume_create_usage ()
+
+gf_ai_compare_t
+cli_cmd_compare_addrinfo (struct addrinfo *first, struct addrinfo *next)
{
- cli_out ("Usage: volume create <NEW-VOLNAME> "
- "[stripe <COUNT>] [replica <COUNT>] [transport <tcp|rdma>] "
- "<NEW-BRICK> ...");
+ int ret = -1;
+ struct addrinfo *tmp1 = NULL;
+ struct addrinfo *tmp2 = NULL;
+ char firstip[NI_MAXHOST] = {0.};
+ char nextip[NI_MAXHOST] = {0,};
+
+ for (tmp1 = first; tmp1 != NULL; tmp1 = tmp1->ai_next) {
+ ret = getnameinfo (tmp1->ai_addr, tmp1->ai_addrlen, firstip,
+ NI_MAXHOST, NULL, 0, NI_NUMERICHOST);
+ if (ret)
+ return GF_AI_COMPARE_ERROR;
+ for (tmp2 = next; tmp2 != NULL; tmp2 = tmp2->ai_next) {
+ ret = getnameinfo (tmp2->ai_addr, tmp2->ai_addrlen, nextip,
+ NI_MAXHOST, NULL, 0, NI_NUMERICHOST);
+ if (ret)
+ return GF_AI_COMPARE_ERROR;
+ if (!strcmp (firstip, nextip)) {
+ return GF_AI_COMPARE_MATCH;
+ }
+ }
+ }
+ return GF_AI_COMPARE_NO_MATCH;
+}
+
+/* Check for non optimal brick order for replicate :
+ * Checks if bricks belonging to a replicate volume
+ * are present on the same server
+ */
+int32_t
+cli_cmd_check_brick_order (struct cli_state *state, const char *bricks,
+ int brick_count, int sub_count)
+{
+ int ret = -1;
+ int i = 0;
+ int j = 0;
+ int k = 0;
+ addrinfo_list_t *ai_list = NULL;
+ addrinfo_list_t *ai_list_tmp1 = NULL;
+ addrinfo_list_t *ai_list_tmp2 = NULL;
+ char *brick = NULL;
+ char *brick_list = NULL;
+ char *brick_list_dup = NULL;
+ char *tmpptr = NULL;
+ struct addrinfo *ai_info = NULL;
+ gf_answer_t answer = GF_ANSWER_NO;
+ const char *failed_question = NULL;
+ const char *found_question = NULL;
+ failed_question = "Failed to perform brick order check. "
+ "Do you want to continue creating the volume? ";
+ found_question = "Multiple bricks of a replicate volume are present"
+ " on the same server. This setup is not optimal.\n"
+ "Do you still want to continue creating the volume? ";
+
+ GF_ASSERT (bricks);
+ GF_ASSERT (brick_count > 0);
+ GF_ASSERT (sub_count > 0);
+
+ ai_list = malloc (sizeof (addrinfo_list_t));
+ ai_list->info = NULL;
+ INIT_LIST_HEAD (&ai_list->list);
+ brick_list = gf_strdup (bricks);
+ if (brick_list == NULL) {
+ gf_log ("cli", GF_LOG_DEBUG, "failed to allocate memory");
+ goto check_failed;
+ }
+ brick_list_dup = brick_list;
+ /* Resolve hostnames and get addrinfo */
+ while (i < brick_count) {
+ ++i;
+ brick = strtok_r (brick_list, " \n", &tmpptr);
+ brick_list = tmpptr;
+ if (brick == NULL)
+ goto check_failed;
+ brick = strtok_r (brick, ":", &tmpptr);
+ if (brick == NULL)
+ goto check_failed;
+ ret = getaddrinfo (brick, NULL, NULL, &ai_info);
+ if (ret)
+ goto check_failed;
+ ai_list_tmp1 = malloc (sizeof (addrinfo_list_t));
+ if (ai_list_tmp1 == NULL)
+ goto check_failed;
+ ai_list_tmp1->info = ai_info;
+ list_add_tail (&ai_list_tmp1->list, &ai_list->list);
+ ai_list_tmp1 = NULL;
+ }
+
+ i = 0;
+ ai_list_tmp1 = list_entry (ai_list->list.next, addrinfo_list_t, list);
+
+ /* Check for bad brick order */
+ while (i < brick_count) {
+ ++i;
+ ai_info = ai_list_tmp1->info;
+ ai_list_tmp1 = list_entry (ai_list_tmp1->list.next,
+ addrinfo_list_t, list);
+ if ( 0 == i % sub_count) {
+ j = 0;
+ continue;
+ }
+ ai_list_tmp2 = ai_list_tmp1;
+ k = j;
+ while (k < sub_count - 1) {
+ ++k;
+ ret = cli_cmd_compare_addrinfo (ai_info,
+ ai_list_tmp2->info);
+ if (GF_AI_COMPARE_ERROR == ret)
+ goto check_failed;
+ if (GF_AI_COMPARE_MATCH == ret)
+ goto found_bad_brick_order;
+ ai_list_tmp2 = list_entry (ai_list_tmp2->list.next,
+ addrinfo_list_t, list);
+ }
+ ++j;
+ }
+ gf_log ("cli", GF_LOG_INFO, "Brick order okay");
+ ret = 0;
+ goto out;
+
+check_failed:
+ gf_log ("cli", GF_LOG_INFO, "Failed bad brick order check");
+ answer = cli_cmd_get_confirmation(state, failed_question);
+ if (GF_ANSWER_YES == answer)
+ ret = 0;
+ goto out;
+
+found_bad_brick_order:
+ gf_log ("cli", GF_LOG_INFO, "Bad brick order found");
+ answer = cli_cmd_get_confirmation (state, found_question);
+ if (GF_ANSWER_YES == answer)
+ ret = 0;
+out:
+ ai_list_tmp2 = NULL;
+ i = 0;
+ GF_FREE (brick_list_dup);
+ list_for_each_entry (ai_list_tmp1, &ai_list->list, list) {
+ if (ai_list_tmp1->info)
+ freeaddrinfo (ai_list_tmp1->info);
+ free (ai_list_tmp2);
+ ai_list_tmp2 = ai_list_tmp1;
+ }
+ free (ai_list_tmp2);
+ return ret;
}
int
@@ -200,8 +339,15 @@ cli_cmd_volume_create_cbk (struct cli_state *state, struct cli_cmd_word *word,
rpc_clnt_procedure_t *proc = NULL;
call_frame_t *frame = NULL;
dict_t *options = NULL;
+ int sent = 0;
+ int parse_error = 0;
+ char *brick_list = NULL;
+ int32_t brick_count = 0;
+ int32_t sub_count = 0;
+ int32_t type = GF_CLUSTER_TYPE_NONE;
+ cli_local_t *local = NULL;
- proc = &cli_rpc_prog->proctable[GF1_CLI_CREATE_VOLUME];
+ proc = &cli_rpc_prog->proctable[GLUSTER_CLI_CREATE_VOLUME];
frame = create_frame (THIS, THIS->ctx->pool);
if (!frame)
@@ -210,17 +356,65 @@ cli_cmd_volume_create_cbk (struct cli_state *state, struct cli_cmd_word *word,
ret = cli_cmd_volume_create_parse (words, wordcount, &options);
if (ret) {
- cli_cmd_volume_create_usage ();
+ cli_usage_out (word->pattern);
+ parse_error = 1;
+ goto out;
+ }
+ /*Check brick order if type is replicate*/
+ ret = dict_get_int32 (options, "type", &type);
+ if (ret) {
+ gf_log ("cli", GF_LOG_ERROR, "Could not get brick type");
goto out;
}
+ if ((type == GF_CLUSTER_TYPE_REPLICATE) ||
+ (type == GF_CLUSTER_TYPE_STRIPE_REPLICATE)) {
+ if ((ret = dict_get_str (options, "bricks", &brick_list)) != 0) {
+ gf_log ("cli", GF_LOG_ERROR, "Replica bricks check : "
+ "Could not retrieve bricks list");
+ goto out;
+ }
+ if ((ret = dict_get_int32 (options, "count", &brick_count)) != 0) {
+ gf_log ("cli", GF_LOG_ERROR, "Replica bricks check : "
+ "Could not retrieve brick count");
+ goto out;
+ }
+ if ((ret = dict_get_int32 (options, "replica-count", &sub_count)) != 0) {
+ gf_log ("cli", GF_LOG_ERROR, "Replica bricks check : "
+ "Could not retrieve replica count");
+ goto out;
+ }
+ gf_log ("cli", GF_LOG_INFO, "Replicate cluster type found."
+ " Checking brick order.");
+ ret = cli_cmd_check_brick_order (state, brick_list, brick_count, sub_count);
+ if (ret) {
+ gf_log("cli", GF_LOG_INFO, "Not creating volume because of bad brick order");
+ goto out;
+ }
+ }
+
+ if (state->mode & GLUSTER_MODE_SCRIPT) {
+ ret = dict_set_int32 (options, "force", _gf_true);
+ if (ret) {
+ gf_log ("cli", GF_LOG_ERROR, "Failed to set force "
+ "option");
+ 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 ("Volume create failed");
+ }
+
+ CLI_STACK_DESTROY (frame);
return ret;
}
@@ -235,17 +429,27 @@ cli_cmd_volume_delete_cbk (struct cli_state *state, struct cli_cmd_word *word,
call_frame_t *frame = NULL;
char *volname = NULL;
gf_answer_t answer = GF_ANSWER_NO;
- const char *question = "Deleting volume will erase all information about the volume."
- "Do you want to continue?";
+ const char *question = NULL;
+ int sent = 0;
+ int parse_error = 0;
+ cli_local_t *local = NULL;
+ dict_t *dict = NULL;
- proc = &cli_rpc_prog->proctable[GF1_CLI_DELETE_VOLUME];
+ 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;
+ dict = dict_new ();
+ if (!dict)
+ goto out;
+
if (wordcount != 3) {
- cli_cmd_volume_delete_usage ();
+ cli_usage_out (word->pattern);
+ parse_error = 1;
goto out;
}
@@ -258,13 +462,27 @@ cli_cmd_volume_delete_cbk (struct cli_state *state, struct cli_cmd_word *word,
volname = (char *)words[2];
+ ret = dict_set_str (dict, "volname", volname);
+
+ if (ret) {
+ gf_log (THIS->name, GF_LOG_WARNING, "dict set failed");
+ goto out;
+ }
+
+ CLI_LOCAL_INIT (local, words, frame, dict);
+
if (proc->fn) {
- ret = proc->fn (frame, THIS, volname);
+ ret = proc->fn (frame, THIS, dict);
}
out:
- if (ret && volname)
- cli_out ("Deleting Volume %s failed", volname);
+ if (ret) {
+ cli_cmd_sent_status_get (&sent);
+ if ((sent == 0) && (parse_error == 0))
+ cli_out ("Volume delete failed");
+ }
+
+ CLI_STACK_DESTROY (frame);
return ret;
}
@@ -276,40 +494,75 @@ cli_cmd_volume_start_cbk (struct cli_state *state, struct cli_cmd_word *word,
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;
+ dict_t *dict = NULL;
+ int flags = 0;
+ cli_local_t *local = NULL;
frame = create_frame (THIS, THIS->ctx->pool);
if (!frame)
goto out;
if (wordcount < 3 || wordcount > 4) {
- cli_cmd_volume_start_usage ();
+ cli_usage_out (word->pattern);
+ parse_error = 1;
goto out;
}
- req.volname = (char *)words[2];
- if (!req.volname)
+ dict = dict_new ();
+ if (!dict) {
+ goto out;
+ }
+
+ if (!words[2])
+ goto out;
+
+ ret = dict_set_str (dict, "volname", (char *)words[2]);
+ if (ret) {
+ gf_log (THIS->name, GF_LOG_ERROR, "dict set failed");
goto out;
+ }
if (wordcount == 4) {
if (!strcmp("force", words[3])) {
- req.flags |= GF_CLI_FLAG_OP_FORCE;
+ flags |= GF_CLI_FLAG_OP_FORCE;
} else {
ret = -1;
- cli_cmd_volume_start_usage ();
+ cli_usage_out (word->pattern);
+ parse_error = 1;
goto out;
}
}
+ ret = dict_set_int32 (dict, "flags", flags);
+ if (ret) {
+ gf_log (THIS->name, GF_LOG_ERROR,
+ "dict set failed");
+ goto out;
+ }
+
+ if (ret < 0) {
+ gf_log (THIS->name, GF_LOG_ERROR,
+ "failed to serialize dict");
+ goto out;
+ }
+
+ proc = &cli_rpc_prog->proctable[GLUSTER_CLI_START_VOLUME];
- proc = &cli_rpc_prog->proctable[GF1_CLI_START_VOLUME];
+ CLI_LOCAL_INIT (local, words, frame, dict);
if (proc->fn) {
- ret = proc->fn (frame, THIS, &req);
+ ret = proc->fn (frame, THIS, dict);
}
out:
- if (!proc && ret && req.volname)
- cli_out ("Starting Volume %s failed", req.volname);
+ if (ret) {
+ cli_cmd_sent_status_get (&sent);
+ if ((sent == 0) && (parse_error == 0))
+ cli_out ("Volume start failed");
+ }
+
+ CLI_STACK_DESTROY (frame);
return ret;
}
@@ -319,18 +572,21 @@ cli_cmd_get_confirmation (struct cli_state *state, const char *question)
{
char answer[5] = {'\0', };
char flush = '\0';
- int len = 0;
+ size_t len;
if (state->mode & GLUSTER_MODE_SCRIPT)
return GF_ANSWER_YES;
printf ("%s (y/n) ", question);
- fgets (answer, 4, stdin);
+ if (fgets (answer, 4, stdin) == NULL) {
+ cli_out("gluster cli read error");
+ goto out;
+ }
len = strlen (answer);
- if (answer [len - 1] == '\n'){
+ if (len && answer [len - 1] == '\n'){
answer [--len] = '\0';
} else {
do{
@@ -361,34 +617,51 @@ cli_cmd_volume_stop_cbk (struct cli_state *state, struct cli_cmd_word *word,
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;
+ dict_t *dict = NULL;
+ char *volname = NULL;
+ cli_local_t *local = NULL;
const char *question = "Stopping volume will make its data inaccessible. "
- "Do you want to Continue?";
+ "Do you want to continue?";
frame = create_frame (THIS, THIS->ctx->pool);
if (!frame)
goto out;
if (wordcount < 3 || wordcount > 4) {
- cli_cmd_volume_stop_usage ();
- goto out;
+ cli_usage_out (word->pattern);
+ parse_error = 1;
+ goto out;
}
- req.volname = (char *)words[2];
- if (!req.volname)
+ volname = (char*) words[2];
+
+ dict = dict_new ();
+ ret = dict_set_str (dict, "volname", volname);
+ if (ret) {
+ gf_log (THIS->name, GF_LOG_ERROR, "dict set failed");
goto out;
+ }
if (wordcount == 4) {
if (!strcmp("force", words[3])) {
flags |= GF_CLI_FLAG_OP_FORCE;
} else {
ret = -1;
- cli_cmd_volume_stop_usage ();
+ cli_usage_out (word->pattern);
+ parse_error = 1;
goto out;
}
}
+ ret = dict_set_int32 (dict, "flags", flags);
+ if (ret) {
+ gf_log (THIS->name, GF_LOG_ERROR,
+ "dict set failed");
+ goto out;
+ }
answer = cli_cmd_get_confirmation (state, question);
@@ -397,16 +670,22 @@ cli_cmd_volume_stop_cbk (struct cli_state *state, struct cli_cmd_word *word,
goto out;
}
- req.flags = flags;
- proc = &cli_rpc_prog->proctable[GF1_CLI_STOP_VOLUME];
+ proc = &cli_rpc_prog->proctable[GLUSTER_CLI_STOP_VOLUME];
+
+ CLI_LOCAL_INIT (local, words, frame, dict);
if (proc->fn) {
- ret = proc->fn (frame, THIS, &req);
+ ret = proc->fn (frame, THIS, dict);
}
out:
- if (!proc && ret && req.volname)
- cli_out ("Stopping Volume %s failed", req.volname);
+ if (ret) {
+ cli_cmd_sent_status_get (&sent);
+ if ((sent == 0) && (parse_error == 0))
+ cli_out ("Volume stop on '%s' failed", volname);
+ }
+
+ CLI_STACK_DESTROY (frame);
return ret;
}
@@ -420,6 +699,8 @@ cli_cmd_volume_rename_cbk (struct cli_state *state, struct cli_cmd_word *word,
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);
@@ -431,7 +712,8 @@ cli_cmd_volume_rename_cbk (struct cli_state *state, struct cli_cmd_word *word,
goto out;
if (wordcount != 4) {
- cli_cmd_volume_rename_usage ();
+ cli_usage_out (word->pattern);
+ parse_error = 1;
goto out;
}
@@ -445,27 +727,25 @@ cli_cmd_volume_rename_cbk (struct cli_state *state, struct cli_cmd_word *word,
if (ret)
goto out;
- proc = &cli_rpc_prog->proctable[GF1_CLI_RENAME_VOLUME];
+ proc = &cli_rpc_prog->proctable[GLUSTER_CLI_RENAME_VOLUME];
if (proc->fn) {
ret = proc->fn (frame, THIS, dict);
}
out:
- if (!proc && ret) {
- if (dict)
- dict_destroy (dict);
- if (wordcount > 2)
- cli_out ("Renaming Volume %s failed", (char *)words[2]);
+ 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;
-}
+ CLI_STACK_DESTROY (frame);
-void
-cli_cmd_volume_defrag_usage ()
-{
- cli_out ("Usage: volume rebalance <VOLNAME> <start|stop|status>");
+ return ret;
}
int
@@ -476,123 +756,184 @@ cli_cmd_volume_defrag_cbk (struct cli_state *state, struct cli_cmd_word *word,
rpc_clnt_procedure_t *proc = NULL;
call_frame_t *frame = NULL;
dict_t *dict = NULL;
+ int sent = 0;
+ int parse_error = 0;
+ cli_local_t *local = NULL;
+#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;
+ ret = cli_cmd_volume_defrag_parse (words, wordcount, &dict);
- if (wordcount != 4) {
- cli_cmd_volume_defrag_usage();
- goto out;
+ if (ret) {
+ cli_usage_out (word->pattern);
+ parse_error = 1;
}
- ret = dict_set_str (dict, "volname", (char *)words[2]);
- if (ret)
- goto out;
+ proc = &cli_rpc_prog->proctable[GLUSTER_CLI_DEFRAG_VOLUME];
- ret = dict_set_str (dict, "command", (char *)words[3]);
- if (ret)
- goto out;
-
- proc = &cli_rpc_prog->proctable[GF1_CLI_DEFRAG_VOLUME];
+ CLI_LOCAL_INIT (local, words, frame, dict);
if (proc->fn) {
ret = proc->fn (frame, THIS, dict);
}
out:
- if (!proc && ret) {
- if (dict)
- dict_destroy (dict);
-
- if (wordcount > 2)
- cli_out ("Rebalance of Volume %s failed",
- (char *)words[2]);
+ if (ret) {
+ cli_cmd_sent_status_get (&sent);
+ if ((sent == 0) && (parse_error == 0))
+ cli_out ("Volume rebalance failed");
}
- return 0;
+ CLI_STACK_DESTROY (frame);
+
+ return ret;
}
int
-cli_cmd_volume_reset_cbk (struct cli_state *state, struct cli_cmd_word *word,
+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;
+ cli_local_t *local = NULL;
- proc = &cli_rpc_prog->proctable[GF1_CLI_RESET_VOLUME];
+ 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_cmd_volume_reset_usage ();
+ 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 ("Volume reset failed");
+ }
+
+ CLI_STACK_DESTROY (frame);
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;
+ cli_local_t *local = 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;
+
+ CLI_LOCAL_INIT (local, words, frame, options);
+
+ 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 profile failed");
+ }
+
+ CLI_STACK_DESTROY (frame);
+
+ 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;
+ cli_local_t *local = NULL;
+ char *op_errstr = NULL;
- proc = &cli_rpc_prog->proctable[GF1_CLI_SET_VOLUME];
+ 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);
-
+ ret = cli_cmd_volume_set_parse (words, wordcount, &options, &op_errstr);
if (ret) {
- cli_cmd_volume_set_usage ();
+ if (op_errstr) {
+ cli_err ("%s", op_errstr);
+ GF_FREE (op_errstr);
+ } else
+ 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 ("Volume set failed");
+ }
- return ret;
+ CLI_STACK_DESTROY (frame);
-}
+ return ret;
-void
-cli_cmd_volume_add_brick_usage ()
-{
- cli_out ("Usage: volume add-brick <VOLNAME> "
- "<NEW-BRICK> ...");
}
int
@@ -604,42 +945,122 @@ cli_cmd_volume_add_brick_cbk (struct cli_state *state,
rpc_clnt_procedure_t *proc = NULL;
call_frame_t *frame = NULL;
dict_t *options = NULL;
+ int sent = 0;
+ int parse_error = 0;
+ gf_answer_t answer = GF_ANSWER_NO;
+ cli_local_t *local = NULL;
+
+ const char *question = "Changing the 'stripe count' of the volume is "
+ "not a supported feature. In some cases it may result in data "
+ "loss on the volume. Also there may be issues with regular "
+ "filesystem operations on the volume after the change. Do you "
+ "really want to continue with 'stripe' count option ? ";
frame = create_frame (THIS, THIS->ctx->pool);
if (!frame)
goto out;
ret = cli_cmd_volume_add_brick_parse (words, wordcount, &options);
-
if (ret) {
- cli_cmd_volume_add_brick_usage ();
+ cli_usage_out (word->pattern);
+ parse_error = 1;
goto out;
}
- proc = &cli_rpc_prog->proctable[GF1_CLI_ADD_BRICK];
+ /* TODO: there are challenges in supporting changing of
+ stripe-count, untill it is properly supported give warning to user */
+ if (dict_get (options, "stripe-count")) {
+ answer = cli_cmd_get_confirmation (state, question);
+
+ if (GF_ANSWER_NO == answer) {
+ ret = 0;
+ goto out;
+ }
+ }
+
+ if (state->mode & GLUSTER_MODE_SCRIPT) {
+ ret = dict_set_int32 (options, "force", _gf_true);
+ if (ret) {
+ gf_log ("cli", GF_LOG_ERROR, "Failed to set force "
+ "option");
+ goto out;
+ }
+ }
+
+ proc = &cli_rpc_prog->proctable[GLUSTER_CLI_ADD_BRICK];
+
+ CLI_LOCAL_INIT (local, words, frame, options);
if (proc->fn) {
ret = proc->fn (frame, THIS, options);
}
out:
- if (!proc && ret) {
- if (wordcount > 2) {
- char *volname = (char *) words[2];
- cli_out ("Adding brick to Volume %s failed",volname );
- }
+ if (ret) {
+ cli_cmd_sent_status_get (&sent);
+ if ((sent == 0) && (parse_error == 0))
+ cli_out ("Volume add-brick failed");
}
- if (options)
- dict_unref (options);
+
+ CLI_STACK_DESTROY (frame);
+
return ret;
}
-
-void
-cli_cmd_volume_remove_brick_usage ()
+int
+cli_cmd_quota_cbk (struct cli_state *state, struct cli_cmd_word *word,
+ const char **words, int wordcount)
{
- cli_out ("Usage: volume remove-brick <VOLNAME> "
- "<BRICK> ...");
+
+ 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;
+ cli_local_t *local = NULL;
+ 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;
+ }
+
+ CLI_LOCAL_INIT (local, words, frame, options);
+
+ if (proc->fn)
+ ret = proc->fn (frame, THIS, options);
+
+out:
+ if (ret && parse_err == 0)
+ cli_out ("Quota command failed");
+
+ CLI_STACK_DESTROY (frame);
+
+ return ret;
+
}
int
@@ -652,6 +1073,10 @@ cli_cmd_volume_remove_brick_cbk (struct cli_state *state,
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;
+ cli_local_t *local = NULL;
const char *question = "Removing brick(s) can result in data loss. "
"Do you want to Continue?";
@@ -660,46 +1085,43 @@ cli_cmd_volume_remove_brick_cbk (struct cli_state *state,
if (!frame)
goto out;
- ret = cli_cmd_volume_remove_brick_parse (words, wordcount, &options);
-
+ ret = cli_cmd_volume_remove_brick_parse (words, wordcount, &options,
+ &need_question);
if (ret) {
- cli_cmd_volume_remove_brick_usage ();
+ 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;
+ 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[GF1_CLI_REMOVE_BRICK];
+ proc = &cli_rpc_prog->proctable[GLUSTER_CLI_REMOVE_BRICK];
+
+ CLI_LOCAL_INIT (local, words, frame, options);
if (proc->fn) {
ret = proc->fn (frame, THIS, options);
}
out:
- if (!proc && ret) {
- if (wordcount > 2) {
- char *volname = (char *) words[2];
- cli_out ("Removing brick from Volume %s failed",volname );
- }
+ 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;
-}
+ CLI_STACK_DESTROY (frame);
-void
-cli_cmd_volume_replace_brick_usage ()
-{
- cli_out("Usage: volume replace-brick <VOLNAME> "
- "<BRICK> <NEW-BRICK> start|pause|abort|commit|status");
-}
+ return ret;
+}
int
cli_cmd_volume_replace_brick_cbk (struct cli_state *state,
@@ -711,8 +1133,15 @@ cli_cmd_volume_replace_brick_cbk (struct cli_state *state,
rpc_clnt_procedure_t *proc = NULL;
call_frame_t *frame = NULL;
dict_t *options = NULL;
+ int sent = 0;
+ int parse_error = 0;
+ cli_local_t *local = NULL;
- proc = &cli_rpc_prog->proctable[GF1_CLI_REPLACE_BRICK];
+#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)
@@ -721,23 +1150,36 @@ cli_cmd_volume_replace_brick_cbk (struct cli_state *state,
ret = cli_cmd_volume_replace_brick_parse (words, wordcount, &options);
if (ret) {
- cli_cmd_volume_replace_brick_usage ();
+ cli_usage_out (word->pattern);
+ parse_error = 1;
goto out;
}
+ if (state->mode & GLUSTER_MODE_SCRIPT) {
+ ret = dict_set_int32 (options, "force", _gf_true);
+ if (ret) {
+ gf_log ("cli", GF_LOG_ERROR, "Failed to set force"
+ "option");
+ goto out;
+ }
+ }
+
+ CLI_LOCAL_INIT (local, words, frame, options);
+
if (proc->fn) {
ret = proc->fn (frame, THIS, options);
}
out:
if (ret) {
- if (wordcount > 2) {
- char *volname = (char *) words[2];
- cli_out ("Replacing brick from Volume %s failed",volname );
- }
+ cli_cmd_sent_status_get (&sent);
+ if ((sent == 0) && (parse_error == 0))
+ cli_out ("Volume replace-brick failed");
}
- return ret;
+ CLI_STACK_DESTROY (frame);
+
+ return ret;
}
@@ -750,147 +1192,649 @@ cli_cmd_volume_set_transport_cbk (struct cli_state *state,
return 0;
}
-void
-cli_cmd_log_filename_usage ()
+int
+cli_cmd_volume_top_cbk (struct cli_state *state, struct cli_cmd_word *word,
+ const char **words, int wordcount)
{
- cli_out ("Usage: volume log filename <VOLNAME> [BRICK] <PATH>");
+
+ 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;
+ cli_local_t *local = NULL;
+
+ 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;
+
+ CLI_LOCAL_INIT (local, words, frame, options);
+
+ 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 top failed");
+ }
+
+ CLI_STACK_DESTROY (frame);
+
+ return ret;
+
}
+
int
-cli_cmd_log_filename_cbk (struct cli_state *state, struct cli_cmd_word *word,
- const char **words, int wordcount)
+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;
+ cli_local_t *local = NULL;
- if (!((wordcount == 5) || (wordcount == 6))) {
- cli_cmd_log_filename_usage ();
- goto out;
+ if (!((wordcount == 4) || (wordcount == 5))) {
+ cli_usage_out (word->pattern);
+ parse_error = 1;
+ goto out;
}
- proc = &cli_rpc_prog->proctable[GF1_CLI_LOG_FILENAME];
+ proc = &cli_rpc_prog->proctable[GLUSTER_CLI_LOG_ROTATE];
frame = create_frame (THIS, THIS->ctx->pool);
if (!frame)
goto out;
- ret = cli_cmd_log_filename_parse (words, wordcount, &options);
+ ret = cli_cmd_log_rotate_parse (words, wordcount, &options);
if (ret)
goto out;
+ CLI_LOCAL_INIT (local, words, frame, options);
+
if (proc->fn) {
ret = proc->fn (frame, THIS, options);
}
out:
- if (ret)
- cli_out ("setting log filename failed");
-
- 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");
+ }
+ CLI_STACK_DESTROY (frame);
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_log_locate_usage ()
+cli_cmd_check_gsync_exists_cbk (struct cli_cmd *this)
{
- cli_out ("Usage: volume log locate <VOLNAME> [BRICK]");
+
+ int ret = 0;
+
+ ret = cli_check_gsync_present ();
+ if (ret)
+ this->disable = _gf_true;
+
}
+#endif
int
-cli_cmd_log_locate_cbk (struct cli_state *state, struct cli_cmd_word *word,
- const char **words, int wordcount)
+cli_cmd_volume_gsync_set_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 ret = 0;
+ int parse_err = 0;
dict_t *options = NULL;
+ rpc_clnt_procedure_t *proc = NULL;
+ call_frame_t *frame = NULL;
+ cli_local_t *local = NULL;
- if (!((wordcount == 4) || (wordcount == 5))) {
- cli_cmd_log_locate_usage ();
- goto out;
+ proc = &cli_rpc_prog->proctable [GLUSTER_CLI_GSYNC_SET];
+ if (proc == NULL) {
+ ret = -1;
+ goto out;
}
- proc = &cli_rpc_prog->proctable[GF1_CLI_LOG_LOCATE];
-
frame = create_frame (THIS, THIS->ctx->pool);
- if (!frame)
+ if (frame == NULL) {
+ ret = -1;
goto out;
+ }
- ret = cli_cmd_log_locate_parse (words, wordcount, &options);
- if (ret)
+ ret = cli_cmd_gsync_set_parse (words, wordcount, &options);
+ if (ret) {
+ cli_usage_out (word->pattern);
+ parse_err = 1;
goto out;
+ }
- if (proc->fn) {
+ CLI_LOCAL_INIT (local, words, frame, options);
+
+ if (proc->fn)
ret = proc->fn (frame, THIS, options);
+
+out:
+ if (ret && parse_err == 0)
+ cli_out (GEOREP" command failed");
+
+ CLI_STACK_DESTROY (frame);
+
+ 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;
+ uint32_t cmd = 0;
+ cli_local_t *local = NULL;
+
+ ret = cli_cmd_volume_status_parse (words, wordcount, &dict);
+
+ if (ret) {
+ cli_usage_out (word->pattern);
+ goto out;
}
+ ret = dict_get_uint32 (dict, "cmd", &cmd);
+ if (ret)
+ goto out;
+
+ if (!(cmd & GF_CLI_STATUS_ALL)) {
+ /* for one volume or brick */
+ proc = &cli_rpc_prog->proctable[GLUSTER_CLI_STATUS_VOLUME];
+ } else {
+ /* volume status all or all detail */
+ proc = &cli_rpc_prog->proctable[GLUSTER_CLI_STATUS_ALL];
+ }
+
+ if (!proc->fn)
+ goto out;
+
+ frame = create_frame (THIS, THIS->ctx->pool);
+ if (!frame)
+ goto out;
+
+ CLI_LOCAL_INIT (local, words, frame, dict);
+
+ ret = proc->fn (frame, THIS, dict);
+
out:
+ CLI_STACK_DESTROY (frame);
+
+ return ret;
+}
+
+
+int
+cli_get_detail_status (dict_t *dict, int i, cli_volume_status_t *status)
+{
+ uint64_t free = 0;
+ uint64_t total = 0;
+ char key[1024] = {0};
+ int ret = 0;
+
+ memset (key, 0, sizeof (key));
+ snprintf (key, sizeof (key), "brick%d.free", i);
+ ret = dict_get_uint64 (dict, key, &free);
+
+ status->free = gf_uint64_2human_readable (free);
+ if (!status->free)
+ goto out;
+
+ memset (key, 0, sizeof (key));
+ snprintf (key, sizeof (key), "brick%d.total", i);
+ ret = dict_get_uint64 (dict, key, &total);
+
+ status->total = gf_uint64_2human_readable (total);
+ if (!status->total)
+ goto out;
+
+#ifdef GF_LINUX_HOST_OS
+ memset (key, 0, sizeof (key));
+ snprintf (key, sizeof (key), "brick%d.device", i);
+ ret = dict_get_str (dict, key, &(status->device));
+ if (ret)
+ status->device = NULL;
+#endif
+
+ memset (key, 0, sizeof (key));
+ snprintf (key, sizeof (key), "brick%d.block_size", i);
+ ret = dict_get_uint64 (dict, key, &(status->block_size));
+ if (ret) {
+ ret = 0;
+ status->block_size = 0;
+ }
+
+#ifdef GF_LINUX_HOST_OS
+ memset (key, 0, sizeof (key));
+ snprintf (key, sizeof (key), "brick%d.mnt_options", i);
+ ret = dict_get_str (dict, key, &(status->mount_options));
+ if (ret)
+ status->mount_options = NULL;
+
+ memset (key, 0, sizeof (key));
+ snprintf (key, sizeof (key), "brick%d.fs_name", i);
+ ret = dict_get_str (dict, key, &(status->fs_name));
+ if (ret) {
+ ret = 0;
+ status->fs_name = NULL;
+ }
+
+ memset (key, 0, sizeof (key));
+ snprintf (key, sizeof (key), "brick%d.inode_size", i);
+ ret = dict_get_str (dict, key, &(status->inode_size));
+ if (ret)
+ status->inode_size = NULL;
+#endif /* GF_LINUX_HOST_OS */
+
+ memset (key, 0, sizeof (key));
+ snprintf (key, sizeof (key), "brick%d.total_inodes", i);
+ ret = dict_get_uint64 (dict, key,
+ &(status->total_inodes));
if (ret)
- cli_out ("getting log file location information failed");
+ status->total_inodes = 0;
- if (options)
- dict_destroy (options);
+ memset (key, 0, sizeof (key));
+ snprintf (key, sizeof (key), "brick%d.free_inodes", i);
+ ret = dict_get_uint64 (dict, key, &(status->free_inodes));
+ if (ret) {
+ ret = 0;
+ status->free_inodes = 0;
+ }
+ out:
return ret;
}
void
-cli_cmd_log_rotate_usage ()
+cli_print_detailed_status (cli_volume_status_t *status)
{
- cli_out ("Usage: volume log rotate <VOLNAME> [BRICK]");
+ cli_out ("%-20s : %-20s", "Brick", status->brick);
+ if (status->online)
+ cli_out ("%-20s : %-20d", "Port", status->port);
+ else
+ cli_out ("%-20s : %-20s", "Port", "N/A");
+ cli_out ("%-20s : %-20c", "Online", (status->online) ? 'Y' : 'N');
+ cli_out ("%-20s : %-20s", "Pid", status->pid_str);
+
+#ifdef GF_LINUX_HOST_OS
+ if (status->fs_name)
+ cli_out ("%-20s : %-20s", "File System", status->fs_name);
+ else
+ cli_out ("%-20s : %-20s", "File System", "N/A");
+
+ if (status->device)
+ cli_out ("%-20s : %-20s", "Device", status->device);
+ else
+ cli_out ("%-20s : %-20s", "Device", "N/A");
+
+ if (status->mount_options) {
+ cli_out ("%-20s : %-20s", "Mount Options",
+ status->mount_options);
+ } else {
+ cli_out ("%-20s : %-20s", "Mount Options", "N/A");
+ }
+
+ if (status->inode_size) {
+ cli_out ("%-20s : %-20s", "Inode Size",
+ status->inode_size);
+ } else {
+ cli_out ("%-20s : %-20s", "Inode Size", "N/A");
+ }
+#endif
+ if (status->free)
+ cli_out ("%-20s : %-20s", "Disk Space Free", status->free);
+ else
+ cli_out ("%-20s : %-20s", "Disk Space Free", "N/A");
+
+ if (status->total)
+ cli_out ("%-20s : %-20s", "Total Disk Space", status->total);
+ else
+ cli_out ("%-20s : %-20s", "Total Disk Space", "N/A");
+
+
+ if (status->total_inodes) {
+ cli_out ("%-20s : %-20ld", "Inode Count",
+ status->total_inodes);
+ } else {
+ cli_out ("%-20s : %-20s", "Inode Count", "N/A");
+ }
+
+ if (status->free_inodes) {
+ cli_out ("%-20s : %-20ld", "Free Inodes",
+ status->free_inodes);
+ } else {
+ cli_out ("%-20s : %-20s", "Free Inodes", "N/A");
+ }
}
int
-cli_cmd_log_rotate_cbk (struct cli_state *state, struct cli_cmd_word *word,
- const char **words, int wordcount)
+cli_print_brick_status (cli_volume_status_t *status)
+{
+ int fieldlen = CLI_VOL_STATUS_BRICK_LEN;
+ int bricklen = 0;
+ char *p = NULL;
+ int num_tabs = 0;
+
+ p = status->brick;
+ bricklen = strlen (p);
+ while (bricklen > 0) {
+ if (bricklen > fieldlen) {
+ cli_out ("%.*s", fieldlen, p);
+ p += fieldlen;
+ bricklen -= fieldlen;
+ } else {
+ num_tabs = (fieldlen - bricklen) / CLI_TAB_LENGTH + 1;
+ printf ("%s", p);
+ while (num_tabs-- != 0)
+ printf ("\t");
+ if (status->port) {
+ if (status->online)
+ cli_out ("%d\t%c\t%s",
+ status->port,
+ status->online?'Y':'N',
+ status->pid_str);
+ else
+ cli_out ("%s\t%c\t%s",
+ "N/A",
+ status->online?'Y':'N',
+ status->pid_str);
+ }
+ else
+ cli_out ("%s\t%c\t%s",
+ "N/A", status->online?'Y':'N',
+ status->pid_str);
+ bricklen = 0;
+ }
+ }
+
+ return 0;
+}
+
+int
+cli_cmd_volume_heal_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;
+ xlator_t *this = NULL;
+ cli_local_t *local = NULL;
- if (!((wordcount == 4) || (wordcount == 5))) {
- cli_cmd_log_rotate_usage ();
+ this = THIS;
+ frame = create_frame (this, this->ctx->pool);
+ if (!frame)
+ goto out;
+
+ if (wordcount < 3) {
+ cli_usage_out (word->pattern);
+ parse_error = 1;
goto out;
}
- proc = &cli_rpc_prog->proctable[GF1_CLI_LOG_ROTATE];
+ ret = cli_cmd_volume_heal_options_parse (words, wordcount, &options);
+ if (ret) {
+ cli_usage_out (word->pattern);
+ parse_error = 1;
+ goto out;
+ }
+
+ proc = &cli_rpc_prog->proctable[GLUSTER_CLI_HEAL_VOLUME];
+
+ CLI_LOCAL_INIT (local, words, frame, options);
+
+ 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 heal failed");
+ }
+
+ CLI_STACK_DESTROY (frame);
+
+ return ret;
+}
+
+int
+cli_cmd_volume_statedump_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;
+ cli_local_t *local = NULL;
frame = create_frame (THIS, THIS->ctx->pool);
if (!frame)
goto out;
- ret = cli_cmd_log_rotate_parse (words, wordcount, &options);
+ if (wordcount < 3) {
+ cli_usage_out (word->pattern);
+ parse_error = 1;
+ goto out;
+ }
+
+ if (wordcount >= 3) {
+ ret = cli_cmd_volume_statedump_options_parse (words, wordcount,
+ &options);
+ if (ret) {
+ parse_error = 1;
+ gf_log ("cli", GF_LOG_ERROR, "Error parsing "
+ "statedump options");
+ cli_out ("Error parsing options");
+ cli_usage_out (word->pattern);
+ }
+ }
+
+ ret = dict_set_str (options, "volname", (char *)words[2]);
if (ret)
goto out;
+ proc = &cli_rpc_prog->proctable[GLUSTER_CLI_STATEDUMP_VOLUME];
+
+ CLI_LOCAL_INIT (local, words, frame, options);
+
if (proc->fn) {
ret = proc->fn (frame, THIS, options);
}
out:
- if (ret)
- cli_out ("log rotate failed");
+ if (ret) {
+ cli_cmd_sent_status_get (&sent);
+ if ((sent == 0) && (parse_error = 0))
+ cli_out ("Volume statedump failed");
+ }
- if (options)
- dict_destroy (options);
+ CLI_STACK_DESTROY (frame);
return ret;
}
+int
+cli_cmd_volume_list_cbk (struct cli_state *state, struct cli_cmd_word *word,
+ const char **words, int wordcount)
+{
+ int ret = -1;
+ call_frame_t *frame = NULL;
+ rpc_clnt_procedure_t *proc = NULL;
+ int sent = 0;
+
+ frame = create_frame (THIS, THIS->ctx->pool);
+ if (!frame)
+ goto out;
+
+ proc = &cli_rpc_prog->proctable[GLUSTER_CLI_LIST_VOLUME];
+ if (proc->fn) {
+ ret = proc->fn (frame, THIS, NULL);
+ }
+
+out:
+ if (ret) {
+ cli_cmd_sent_status_get (&sent);
+ if (sent == 0)
+ cli_out ("Volume list failed");
+ }
+
+ CLI_STACK_DESTROY (frame);
+
+ return ret;
+}
+
+int
+cli_cmd_volume_clearlocks_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;
+ cli_local_t *local = NULL;
+
+ frame = create_frame (THIS, THIS->ctx->pool);
+ if (!frame)
+ goto out;
+
+ if (wordcount < 7 || wordcount > 8) {
+ cli_usage_out (word->pattern);
+ parse_error = 1;
+ goto out;
+ }
+
+ ret = cli_cmd_volume_clrlks_opts_parse (words, wordcount, &options);
+ if (ret) {
+ parse_error = 1;
+ gf_log ("cli", GF_LOG_ERROR, "Error parsing "
+ "clear-locks options");
+ cli_out ("Error parsing options");
+ cli_usage_out (word->pattern);
+ }
+
+ ret = dict_set_str (options, "volname", (char *)words[2]);
+ if (ret)
+ goto out;
+
+ ret = dict_set_str (options, "path", (char *)words[3]);
+ if (ret)
+ goto out;
+
+ proc = &cli_rpc_prog->proctable[GLUSTER_CLI_CLRLOCKS_VOLUME];
+
+ CLI_LOCAL_INIT (local, words, frame, options);
+
+ 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 clear-locks failed");
+ }
+
+ CLI_STACK_DESTROY (frame);
+
+ return ret;
+}
struct cli_cmd volume_cmds[] = {
{ "volume info [all|<VOLNAME>]",
cli_cmd_volume_info_cbk,
"list information of all volumes"},
- { "volume create <NEW-VOLNAME> [stripe <COUNT>] [replica <COUNT>] [transport <tcp|rdma>] <NEW-BRICK> ...",
+ { "volume create <NEW-VOLNAME> [stripe <COUNT>] [replica <COUNT>] "
+ "[transport <tcp|rdma|tcp,rdma>] <NEW-BRICK>"
+#ifdef HAVE_BD_XLATOR
+ "?<vg_name>"
+#endif
+ "... [force]",
+
cli_cmd_volume_create_cbk,
"create a new volume of specified type with mentioned bricks"},
@@ -910,27 +1854,19 @@ struct cli_cmd volume_cmds[] = {
cli_cmd_volume_rename_cbk,
"rename volume <VOLNAME> to <NEW-VOLNAME>"},*/
- { "volume add-brick <VOLNAME> <NEW-BRICK> ...",
+ { "volume add-brick <VOLNAME> [<stripe|replica> <COUNT>] <NEW-BRICK> ... [force]",
cli_cmd_volume_add_brick_cbk,
"add brick to volume <VOLNAME>"},
- { "volume remove-brick <VOLNAME> <BRICK> ...",
+ { "volume remove-brick <VOLNAME> [replica <COUNT>] <BRICK> ... [start|stop|status|commit|force]",
cli_cmd_volume_remove_brick_cbk,
"remove brick from volume <VOLNAME>"},
- { "volume rebalance <VOLNAME> start",
- cli_cmd_volume_defrag_cbk,
- "start rebalance of volume <VOLNAME>"},
-
- { "volume rebalance <VOLNAME> stop",
- cli_cmd_volume_defrag_cbk,
- "stop rebalance of volume <VOLNAME>"},
-
- { "volume rebalance <VOLNAME> status",
+ { "volume rebalance <VOLNAME> [fix-layout] {start|stop|status} [force]",
cli_cmd_volume_defrag_cbk,
- "rebalance status of volume <VOLNAME>"},
+ "rebalance operations"},
- { "volume replace-brick <VOLNAME> (<BRICK> <NEW-BRICK>) start|pause|abort|status",
+ { "volume replace-brick <VOLNAME> <BRICK> <NEW-BRICK> {start [force]|pause|abort|status|commit [force]}",
cli_cmd_volume_replace_brick_cbk,
"replace-brick operations"},
@@ -946,14 +1882,6 @@ struct cli_cmd volume_cmds[] = {
cli_cmd_volume_help_cbk,
"display help for the volume command"},
- { "volume log filename <VOLNAME> [BRICK] <PATH>",
- cli_cmd_log_filename_cbk,
- "set the log file for corresponding volume/brick"},
-
- { "volume log locate <VOLNAME> [BRICK]",
- cli_cmd_log_locate_cbk,
- "locate the log file for corresponding volume/brick"},
-
{ "volume log rotate <VOLNAME> [BRICK]",
cli_cmd_log_rotate_cbk,
"rotate the log file for corresponding volume/brick"},
@@ -961,10 +1889,55 @@ struct cli_cmd volume_cmds[] = {
{ "volume sync <HOSTNAME> [all|<VOLNAME>]",
cli_cmd_sync_volume_cbk,
"sync the volume information from a peer"},
-
- { "volume reset <VOLNAME> ",
+
+ { "volume reset <VOLNAME> [option] [force]",
cli_cmd_volume_reset_cbk,
- "reset all the reconfigured options"},
+ "reset all the reconfigured options"},
+
+#if (SYNCDAEMON_COMPILE)
+ {"volume "GEOREP" [<VOLNAME>] [<SLAVE-URL>] {create [push-pem] [force]"
+ "|start [force]|stop [force]|config|status [detail]|delete} [options...]",
+ cli_cmd_volume_gsync_set_cbk,
+ "Geo-sync operations",
+ cli_cmd_check_gsync_exists_cbk},
+#endif
+
+ { "volume profile <VOLNAME> {start|stop|info [nfs]}",
+ cli_cmd_volume_profile_cbk,
+ "volume profile operations"},
+
+ { "volume quota <VOLNAME> <enable|disable|limit-usage|list|remove> [path] [value]",
+ cli_cmd_quota_cbk,
+ "quota translator specific operations"},
+
+ { "volume top <VOLNAME> {open|read|write|opendir|readdir|clear} [nfs|brick <brick>] [list-cnt <value>] |\n"
+ "volume top <VOLNAME> {read-perf|write-perf} [bs <size> count <count>] [brick <brick>] [list-cnt <value>]",
+ cli_cmd_volume_top_cbk,
+ "volume top operations"},
+
+ { "volume status [all | <VOLNAME> [nfs|shd|<BRICK>]]"
+ " [detail|clients|mem|inode|fd|callpool|tasks]",
+ cli_cmd_volume_status_cbk,
+ "display status of all or specified volume(s)/brick"},
+
+ { "volume heal <VOLNAME> [{full | statistics {heal-count {replica <hostname:brickname>}} |info {healed | heal-failed | split-brain}}]",
+ cli_cmd_volume_heal_cbk,
+ "self-heal commands on volume specified by <VOLNAME>"},
+
+ {"volume statedump <VOLNAME> [nfs] [all|mem|iobuf|callpool|priv|fd|"
+ "inode|history]...",
+ cli_cmd_volume_statedump_cbk,
+ "perform statedump on bricks"},
+
+ {"volume list",
+ cli_cmd_volume_list_cbk,
+ "list all volumes in cluster"},
+
+ {"volume clear-locks <VOLNAME> <path> kind {blocked|granted|all}"
+ "{inode [range]|entry [basename]|posix [range]}",
+ cli_cmd_volume_clearlocks_cbk,
+ "Clear locks held on path"
+ },
{ NULL, NULL, NULL }
};
@@ -976,11 +1949,8 @@ cli_cmd_volume_help_cbk (struct cli_state *state, struct cli_cmd_word *in_word,
struct cli_cmd *cmd = NULL;
for (cmd = volume_cmds; cmd->pattern; cmd++)
- cli_out ("%s - %s", cmd->pattern, cmd->desc);
-
-
- if (!state->rl_enabled)
- exit (0);
+ if (_gf_false == cmd->disable)
+ cli_out ("%s - %s", cmd->pattern, cmd->desc);
return 0;
}
@@ -992,8 +1962,8 @@ cli_cmd_volume_register (struct cli_state *state)
struct cli_cmd *cmd = NULL;
for (cmd = volume_cmds; cmd->pattern; cmd++) {
- ret = cli_cmd_register (&state->tree, cmd->pattern, cmd->cbk,
- cmd->desc);
+
+ ret = cli_cmd_register (&state->tree, cmd);
if (ret)
goto out;
}