summaryrefslogtreecommitdiffstats
path: root/cli/src/cli.c
diff options
context:
space:
mode:
Diffstat (limited to 'cli/src/cli.c')
-rw-r--r--cli/src/cli.c456
1 files changed, 243 insertions, 213 deletions
diff --git a/cli/src/cli.c b/cli/src/cli.c
index a2e4d71bc..91b315ff1 100644
--- a/cli/src/cli.c
+++ b/cli/src/cli.c
@@ -1,22 +1,12 @@
/*
- 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>
@@ -74,104 +64,30 @@
#include "call-stub.h"
#include <fnmatch.h>
+#include "xdr-generic.h"
+
extern int connected;
/* using argp for command line parsing */
-static char gf_doc[] = "";
-
-static char argp_doc[] = "";
const char *argp_program_version = "" \
PACKAGE_NAME" "PACKAGE_VERSION" built on "__DATE__" "__TIME__ \
"\nRepository revision: " GLUSTERFS_REPOSITORY_REVISION "\n" \
- "Copyright (c) 2006-2010 Gluster Inc. " \
+ "Copyright (c) 2006-2011 Gluster Inc. " \
"<http://www.gluster.com>\n" \
"GlusterFS comes with ABSOLUTELY NO WARRANTY.\n" \
"You may redistribute copies of GlusterFS under the terms of "\
- "the GNU Affero General Public License.";
+ "the GNU General Public License.";
const char *argp_program_bug_address = "<" PACKAGE_BUGREPORT ">";
-static struct argp_option gf_options[] = {
- {0, 0, 0, 0, "Basic options:"},
- {0, }
-};
+
struct rpc_clnt *global_rpc;
rpc_clnt_prog_t *cli_rpc_prog;
-extern struct rpc_clnt_program cli3_1_prog;
-
-static error_t
-parse_opts (int key, char *arg, struct argp_state *argp_state)
-{
- struct cli_state *state = NULL;
- char **argv = NULL;
-
- state = argp_state->input;
-
- switch (key) {
- case ARGP_KEY_ARG:
- if (!state->argc) {
- argv = calloc (state->argc + 2,
- sizeof (*state->argv));
- } else {
- argv = realloc (state->argv, (state->argc + 2) *
- sizeof (*state->argv));
- }
- if (!argv)
- return -1;
-
- state->argv = argv;
-
- argv[state->argc] = strdup (arg);
- if (!argv[state->argc])
- return -1;
- state->argc++;
- argv[state->argc] = NULL;
-
- break;
- }
-
- return 0;
-}
-
-
-
-static char *
-generate_uuid ()
-{
- char tmp_str[1024] = {0,};
- char hostname[256] = {0,};
- struct timeval tv = {0,};
- struct tm now = {0, };
- char now_str[32];
-
- if (gettimeofday (&tv, NULL) == -1) {
- gf_log ("glusterfsd", GF_LOG_ERROR,
- "gettimeofday: failed %s",
- strerror (errno));
- }
-
- if (gethostname (hostname, 256) == -1) {
- gf_log ("glusterfsd", GF_LOG_ERROR,
- "gethostname: failed %s",
- strerror (errno));
- }
-
- localtime_r (&tv.tv_sec, &now);
- strftime (now_str, 32, "%Y/%m/%d-%H:%M:%S", &now);
- snprintf (tmp_str, 1024, "%s-%d-%s:%"
-#ifdef GF_DARWIN_HOST_OS
- PRId32,
-#else
- "ld",
-#endif
- hostname, getpid(), now_str, tv.tv_usec);
-
- return gf_strdup (tmp_str);
-}
+extern struct rpc_clnt_program cli_prog;
static int
glusterfs_ctx_defaults_init (glusterfs_ctx_t *ctx)
@@ -182,13 +98,13 @@ glusterfs_ctx_defaults_init (glusterfs_ctx_t *ctx)
xlator_mem_acct_init (THIS, cli_mt_end);
- ctx->process_uuid = generate_uuid ();
+ ctx->process_uuid = generate_glusterfs_ctx_id ();
if (!ctx->process_uuid)
return -1;
ctx->page_size = 128 * GF_UNIT_KB;
- ctx->iobuf_pool = iobuf_pool_new (8 * GF_UNIT_MB, ctx->page_size);
+ ctx->iobuf_pool = iobuf_pool_new ();
if (!ctx->iobuf_pool)
return -1;
@@ -201,22 +117,33 @@ glusterfs_ctx_defaults_init (glusterfs_ctx_t *ctx)
if (!pool)
return -1;
- /* frame_mem_pool size 112 * 16k */
- pool->frame_mem_pool = mem_pool_new (call_frame_t, 16384);
-
+ /* frame_mem_pool size 112 * 64 */
+ pool->frame_mem_pool = mem_pool_new (call_frame_t, 32);
if (!pool->frame_mem_pool)
return -1;
- /* stack_mem_pool size 256 * 8k */
- pool->stack_mem_pool = mem_pool_new (call_stack_t, 8192);
+ /* stack_mem_pool size 256 * 128 */
+ pool->stack_mem_pool = mem_pool_new (call_stack_t, 16);
if (!pool->stack_mem_pool)
return -1;
- ctx->stub_mem_pool = mem_pool_new (call_stub_t, 1024);
+ ctx->stub_mem_pool = mem_pool_new (call_stub_t, 16);
if (!ctx->stub_mem_pool)
return -1;
+ ctx->dict_pool = mem_pool_new (dict_t, 32);
+ if (!ctx->dict_pool)
+ return -1;
+
+ ctx->dict_pair_pool = mem_pool_new (data_pair_t, 512);
+ if (!ctx->dict_pair_pool)
+ return -1;
+
+ ctx->dict_data_pool = mem_pool_new (data_t, 512);
+ if (!ctx->dict_data_pool)
+ return -1;
+
INIT_LIST_HEAD (&pool->all_frames);
LOCK_INIT (&pool->lock);
ctx->pool = pool;
@@ -225,10 +152,6 @@ glusterfs_ctx_defaults_init (glusterfs_ctx_t *ctx)
cmd_args = &ctx->cmd_args;
- /* parsing command line arguments */
- cmd_args->log_file = "/dev/null";
- cmd_args->log_level = GF_LOG_NONE;
-
INIT_LIST_HEAD (&cmd_args->xlator_options);
lim.rlim_cur = RLIM_INFINITY;
@@ -240,20 +163,22 @@ glusterfs_ctx_defaults_init (glusterfs_ctx_t *ctx)
static int
-logging_init (glusterfs_ctx_t *ctx)
+logging_init (glusterfs_ctx_t *ctx, struct cli_state *state)
{
- cmd_args_t *cmd_args = NULL;
-
- cmd_args = &ctx->cmd_args;
+ char *log_file = state->log_file ? state->log_file :
+ DEFAULT_CLI_LOG_FILE_DIRECTORY "/cli.log";
- if (gf_log_init (cmd_args->log_file) == -1) {
- fprintf (stderr,
- "failed to open logfile %s. exiting\n",
- cmd_args->log_file);
+ /* passing ident as NULL means to use default ident for syslog */
+ if (gf_log_init (ctx, log_file, NULL) == -1) {
+ fprintf (stderr, "ERROR: failed to open logfile %s\n",
+ log_file);
return -1;
}
- gf_log_set_loglevel (cmd_args->log_level);
+ /* CLI should not have something to DEBUG after the release,
+ hence defaulting to INFO loglevel */
+ gf_log_set_loglevel ((state->log_level == -1) ? GF_LOG_INFO :
+ state->log_level);
return 0;
}
@@ -262,41 +187,41 @@ int
cli_submit_request (void *req, call_frame_t *frame,
rpc_clnt_prog_t *prog,
int procnum, struct iobref *iobref,
- cli_serialize_t sfunc, xlator_t *this,
- fop_cbk_fn_t cbkfn)
+ xlator_t *this, fop_cbk_fn_t cbkfn, xdrproc_t xdrproc)
{
int ret = -1;
int count = 0;
- char start_ping = 0;
struct iovec iov = {0, };
struct iobuf *iobuf = NULL;
char new_iobref = 0;
+ ssize_t xdr_size = 0;
GF_ASSERT (this);
- iobuf = iobuf_get (this->ctx->iobuf_pool);
- if (!iobuf) {
- goto out;
- };
+ if (req) {
+ xdr_size = xdr_sizeof (xdrproc, req);
+ iobuf = iobuf_get2 (this->ctx->iobuf_pool, xdr_size);
+ if (!iobuf) {
+ goto out;
+ };
- if (!iobref) {
- iobref = iobref_new ();
if (!iobref) {
- goto out;
- }
+ iobref = iobref_new ();
+ if (!iobref) {
+ goto out;
+ }
- new_iobref = 1;
- }
+ new_iobref = 1;
+ }
- iobref_add (iobref, iobuf);
+ iobref_add (iobref, iobuf);
- iov.iov_base = iobuf->ptr;
- iov.iov_len = 128 * GF_UNIT_KB;
+ iov.iov_base = iobuf->ptr;
+ iov.iov_len = iobuf_size (iobuf);
- /* Create the xdr payload */
- if (req && sfunc) {
- ret = sfunc (iov, req);
+ /* Create the xdr payload */
+ ret = xdr_serialize_generic (iov, req, xdrproc);
if (ret == -1) {
goto out;
}
@@ -308,22 +233,13 @@ cli_submit_request (void *req, call_frame_t *frame,
ret = rpc_clnt_submit (global_rpc, prog, procnum, cbkfn,
&iov, count,
NULL, 0, iobref, frame, NULL, 0, NULL, 0, NULL);
-
- if (ret == 0) {
- pthread_mutex_lock (&global_rpc->conn.lock);
- {
- if (!global_rpc->conn.ping_started) {
- start_ping = 1;
- }
- }
- pthread_mutex_unlock (&global_rpc->conn.lock);
- }
-
ret = 0;
out:
if (new_iobref)
iobref_unref (iobref);
+ if (iobuf)
+ iobuf_unref (iobuf);
return ret;
}
@@ -349,6 +265,12 @@ cli_rpc_notify (struct rpc_clnt *rpc, void *mydata, rpc_clnt_event_t event,
{
gf_log (this->name, GF_LOG_TRACE, "got RPC_CLNT_DISCONNECT");
connected = 0;
+ if (!global_state->prompt && global_state->await_connected) {
+ ret = 1;
+ cli_out ("Connection failed. Please check if gluster "
+ "daemon is operational.");
+ exit (ret);
+ }
break;
}
@@ -362,11 +284,44 @@ cli_rpc_notify (struct rpc_clnt *rpc, void *mydata, rpc_clnt_event_t event,
return ret;
}
+
+/*
+ * ret: 0: option successfully processed
+ * 1: signalling end of option list
+ * -1: unknown option or other issue
+ */
int
cli_opt_parse (char *opt, struct cli_state *state)
{
char *oarg;
+ if (strcmp (opt, "") == 0)
+ return 1;
+
+ if (strcmp (opt, "version") == 0) {
+ cli_out ("%s", argp_program_version);
+ exit (0);
+ }
+
+ if (strcmp (opt, "print-logdir") == 0) {
+ cli_out ("%s", DEFAULT_LOG_FILE_DIRECTORY);
+ exit (0);
+ }
+
+ if (strcmp (opt, "print-statedumpdir") == 0) {
+ cli_out ("%s", DEFAULT_VAR_RUN_DIRECTORY);
+ exit (0);
+ }
+
+ if (strcmp (opt, "xml") == 0) {
+#if (HAVE_LIB_XML)
+ state->mode |= GLUSTER_MODE_XML;
+#else
+ cli_err ("XML output not supported. Ignoring '--xml' option");
+#endif
+ return 0;
+ }
+
oarg = strtail (opt, "mode=");
if (oarg) {
if (strcmp (oarg, "script") == 0) {
@@ -384,6 +339,26 @@ cli_opt_parse (char *opt, struct cli_state *state)
return 0;
}
+ oarg = strtail (opt, "log-file=");
+ if (oarg) {
+ state->log_file = oarg;
+ return 0;
+ }
+
+ oarg = strtail (opt, "log-level=");
+ if (oarg) {
+ state->log_level = glusterd_check_log_level(oarg);
+ if (state->log_level == -1)
+ return -1;
+ return 0;
+ }
+
+ oarg = strtail (opt, "glusterd-sock=");
+ if (oarg) {
+ state->glusterd_sock = oarg;
+ return 0;
+ }
+
return -1;
}
@@ -394,28 +369,32 @@ parse_cmdline (int argc, char *argv[], struct cli_state *state)
int i = 0;
int j = 0;
char *opt = NULL;
- struct argp argp = { 0,};
- argp.options = gf_options;
- argp.parser = parse_opts;
- argp.args_doc = argp_doc;
- argp.doc = gf_doc;
+ state->argc=argc-1;
+ state->argv=&argv[1];
- for (i = 0; i < argc; i++) {
- opt = strtail (argv[i], "--");
+ for (i = 0; i < state->argc; i++) {
+ opt = strtail (state->argv[i], "--");
if (opt) {
ret = cli_opt_parse (opt, state);
if (ret == -1) {
+ cli_out ("unrecognized option --%s", opt);
+ return ret;
+ }
+ for (j = i; j < state->argc - 1; j++)
+ state->argv[j] = state->argv[j + 1];
+ state->argc--;
+ /* argv shifted, next check should be at i again */
+ i--;
+ if (ret == 1) {
+ /* end of cli options */
+ ret = 0;
break;
}
- for (j = i; j < argc - 1; j++)
- argv[j] = argv[j + 1];
- argc--;
}
}
- ret = argp_parse (&argp, argc, argv,
- ARGP_IN_ORDER, NULL, state);
+ state->argv[state->argc] = NULL;
return ret;
}
@@ -441,7 +420,7 @@ cli_state_init (struct cli_state *state)
int ret = 0;
- state->remote_host = "localhost";
+ state->log_level = -1;
tree = &state->tree;
tree->state = state;
@@ -460,12 +439,36 @@ cli_usage_out (const char *usage)
if (!usage || usage[0] == '\0')
return -1;
- cli_out ("Usage: %s", usage);
+ cli_err ("Usage: %s", usage);
return 0;
}
int
-cli_out (const char *fmt, ...)
+_cli_err (const char *fmt, ...)
+{
+ struct cli_state *state = NULL;
+ va_list ap;
+ int ret = 0;
+
+ state = global_state;
+
+ va_start (ap, fmt);
+
+#ifdef HAVE_READLINE
+ if (state->rl_enabled && !state->rl_processing)
+ return cli_rl_err(state, fmt, ap);
+#endif
+
+ ret = vfprintf (stderr, fmt, ap);
+ fprintf (stderr, "\n");
+ va_end (ap);
+
+ return ret;
+}
+
+
+int
+_cli_out (const char *fmt, ...)
{
struct cli_state *state = NULL;
va_list ap;
@@ -482,6 +485,7 @@ cli_out (const char *fmt, ...)
ret = vprintf (fmt, ap);
printf ("\n");
+ va_end (ap);
return ret;
}
@@ -490,7 +494,6 @@ struct rpc_clnt *
cli_rpc_init (struct cli_state *state)
{
struct rpc_clnt *rpc = NULL;
- struct rpc_clnt_config rpc_cfg = {0,};
dict_t *options = NULL;
int ret = -1;
int port = CLI_GLUSTERD_PORT;
@@ -498,35 +501,67 @@ cli_rpc_init (struct cli_state *state)
this = THIS;
- cli_rpc_prog = &cli3_1_prog;
+ cli_rpc_prog = &cli_prog;
options = dict_new ();
if (!options)
goto out;
- ret = dict_set_str (options, "remote-host", state->remote_host);
- if (ret)
- goto out;
+ /* Connect using to glusterd using the specified method, giving
+ * preference to unix socket connection. If nothing is specified connect
+ * to the default glusterd socket
+ */
+ if (state->glusterd_sock) {
+ gf_log ("cli", GF_LOG_INFO, "Connecting to glusterd using "
+ "sockfile %s", state->glusterd_sock);
+ ret = rpc_transport_unix_options_build (&options,
+ state->glusterd_sock,
+ 0);
+ if (ret)
+ goto out;
+ } else if (state->remote_host) {
+ gf_log ("cli", GF_LOG_INFO, "Connecting to remote glusterd at "
+ "%s", state->remote_host);
+ ret = dict_set_str (options, "remote-host", state->remote_host);
+ if (ret)
+ goto out;
- if (state->remote_port)
- port = state->remote_port;
+ if (state->remote_port)
+ port = state->remote_port;
- rpc_cfg.remote_host = state->remote_host;
- rpc_cfg.remote_port = port;
+ ret = dict_set_int32 (options, "remote-port", port);
+ if (ret)
+ goto out;
- ret = dict_set_int32 (options, "remote-port", port);
- if (ret)
- goto out;
+ ret = dict_set_str (options, "transport.address-family",
+ "inet");
+ if (ret)
+ goto out;
+ } else {
+ gf_log ("cli", GF_LOG_DEBUG, "Connecting to glusterd using "
+ "default socket");
+ ret = rpc_transport_unix_options_build
+ (&options, DEFAULT_GLUSTERD_SOCKFILE, 0);
+ if (ret)
+ goto out;
+ }
- ret = dict_set_str (options, "transport.address-family", "inet");
- if (ret)
+ rpc = rpc_clnt_new (options, this->ctx, this->name, 16);
+ if (!rpc)
goto out;
- rpc = rpc_clnt_init (&rpc_cfg, options, this->ctx, this->name);
-
- if (rpc) {
- ret = rpc_clnt_register_notify (rpc, cli_rpc_notify, this);
+ ret = rpc_clnt_register_notify (rpc, cli_rpc_notify, this);
+ if (ret) {
+ gf_log ("cli", GF_LOG_ERROR, "failed to register notify");
+ goto out;
}
+
+ ret = rpc_clnt_start (rpc);
out:
+ if (ret) {
+ if (rpc)
+ rpc_clnt_unref (rpc);
+ rpc = NULL;
+ }
return rpc;
}
@@ -544,32 +579,15 @@ void
cli_local_wipe (cli_local_t *local)
{
if (local) {
+ GF_FREE (local->get_vol.volname);
+ if (local->dict)
+ dict_unref (local->dict);
GF_FREE (local);
}
return;
}
-void
-cli_path_strip_trailing_slashes (char *path)
-{
- int i = 0;
- int len = 0;
-
- if (!path)
- return;
-
- len = strlen (path);
- for (i = len - 1; i > 0 ; i--) {
- if (path[i] != '/')
- break;
-
- }
-
- if (i < (len - 1))
- path[i + 1] = '\0';
-}
-
struct cli_state *global_state;
int
@@ -579,13 +597,19 @@ main (int argc, char *argv[])
int ret = -1;
glusterfs_ctx_t *ctx = NULL;
- ret = glusterfs_globals_init ();
+ ctx = glusterfs_ctx_new ();
+ if (!ctx)
+ return ENOMEM;
+
+#ifdef DEBUG
+ gf_mem_acct_enable_set (ctx);
+#endif
+
+ ret = glusterfs_globals_init (ctx);
if (ret)
return ret;
- ctx = glusterfs_ctx_get ();
- if (!ctx)
- return ENOMEM;
+ THIS->ctx = ctx;
ret = glusterfs_ctx_defaults_init (ctx);
if (ret)
@@ -602,19 +626,14 @@ main (int argc, char *argv[])
if (ret)
goto out;
- if (geteuid ()) {
- printf ("Only super user can run this command\n");
- return EPERM;
- }
+ ret = logging_init (ctx, &state);
+ if (ret)
+ goto out;
global_rpc = cli_rpc_init (&state);
if (!global_rpc)
goto out;
- ret = logging_init (ctx);
- if (ret)
- goto out;
-
ret = cli_cmds_register (&state);
if (ret)
goto out;
@@ -634,3 +653,14 @@ out:
return ret;
}
+
+void
+cli_print_line (int len)
+{
+ GF_ASSERT (len > 0);
+
+ while (len--)
+ printf ("-");
+
+ printf ("\n");
+}