From 14b9fab371eb7a160fbf15ea4b979d0d98a0e5e0 Mon Sep 17 00:00:00 2001 From: Csaba Henk Date: Tue, 19 Apr 2011 08:59:26 +0000 Subject: cli: change geo-replication syntax to support slave-only invocation (for sake of slave side configurability). Also pulled out sub-op, now we have volume geo-replication [] [] {start|stop|config|status} [options...] -- more convenient to use when working on a given session (ie. we just change the geo-rep subcommands), and aligns better with other volume commands, cf. eg. volume replace-brick {start|pause|abort|status|commit} Signed-off-by: Csaba Henk Signed-off-by: Anand Avati BUG: 2785 (gsyncd logs on slave side go to /dev/null) URL: http://bugs.gluster.com/cgi-bin/bugzilla3/show_bug.cgi?id=2785 --- cli/src/cli-cmd-parser.c | 155 ++++++++++++++++++++++++++--------------------- cli/src/cli-cmd-volume.c | 2 +- 2 files changed, 86 insertions(+), 71 deletions(-) (limited to 'cli') diff --git a/cli/src/cli-cmd-parser.c b/cli/src/cli-cmd-parser.c index 4a395c849a9..2954609b76a 100644 --- a/cli/src/cli-cmd-parser.c +++ b/cli/src/cli-cmd-parser.c @@ -1117,6 +1117,12 @@ out: return ret; } +static gf_boolean_t +gsyncd_url_check (const char *w) +{ + return !!strpbrk (w, ":/"); +} + int32_t cli_cmd_gsync_set_parse (const char **words, int wordcount, dict_t **options) { @@ -1126,7 +1132,10 @@ cli_cmd_gsync_set_parse (const char **words, int wordcount, dict_t **options) char *append_str = NULL; size_t append_len = 0; char *subop = NULL; - int i = 0; + int i = 0; + unsigned masteri = 0; + unsigned slavei = 0; + unsigned cmdi = 0; GF_ASSERT (words); GF_ASSERT (options); @@ -1138,94 +1147,112 @@ cli_cmd_gsync_set_parse (const char **words, int wordcount, dict_t **options) if (!dict) goto out; + /* new syntax: + * + * volume geo-replication [$m [$s]] status + * volume geo-replication [$m] $s config [[!]$opt [$val]] + * volume geo-replication $m $s start|stop + */ + if (wordcount < 3) goto out; - if ((strcmp (words[2], "status")) == 0) { - type = GF_GSYNC_OPTION_TYPE_STATUS; - - if (wordcount > 5) - goto out; - - if (wordcount < 4) - goto set_type; - ret = dict_set_str (dict, "master", (char *)words[3]); - if (ret < 0) - goto out; - - if (wordcount < 5) - goto set_type; - ret = dict_set_str (dict, "slave", (char *)words[4]); - if (ret < 0) - goto out; + for (i = 2; i <= 3 && i < wordcount - 1; i++) { + if (gsyncd_url_check (words[i])) { + slavei = i; + break; + } + } - goto set_type; + if (slavei) { + cmdi = slavei + 1; + if (slavei == 3) + masteri = 2; + } else if (i == 2) { + /* no $s, can only be status cmd + * (with either a single $m before it or nothing; + * i remaining 2 is a good check for this condition) + */ + cmdi = wordcount - 1; + if (i < cmdi) + masteri = i; } - if (wordcount < 5) - goto out; + /* now check if input really complies syntax + * (in a somewhat redundant way, in favor + * transparent soundness) + */ - ret = dict_set_str (dict, "master", (char *)words[3]); - if (ret < 0) + if (masteri && gsyncd_url_check (words[masteri])) goto out; - - ret = dict_set_str (dict, "slave", (char *)words[4]); - if (ret < 0) + if (slavei && !gsyncd_url_check (words[slavei])) goto out; - if ((strcmp (words[2], "start")) == 0) { - if (wordcount != 5) + if (strcmp (words[cmdi], "status") == 0) { + type = GF_GSYNC_OPTION_TYPE_STATUS; + + if (slavei && !masteri) goto out; + } else if (strcmp (words[cmdi], "config") == 0) { + type = GF_GSYNC_OPTION_TYPE_CONFIG; + if (!slavei) + goto out; + } else if (strcmp (words[cmdi], "start") == 0) { type = GF_GSYNC_OPTION_TYPE_START; - goto set_type; - } + if (!masteri || !slavei) + goto out; + } else if (strcmp (words[cmdi], "stop") == 0) { + type = GF_GSYNC_OPTION_TYPE_STOP; - if ((strcmp (words[2], "stop")) == 0) { - if (wordcount != 5) + if (!masteri || !slavei) goto out; + } else + goto out; - type = GF_GSYNC_OPTION_TYPE_STOP; + if (type != GF_GSYNC_OPTION_TYPE_CONFIG && cmdi < wordcount - 1) + goto out; - goto set_type; - } + /* If got so far, input is valid, assemble the message */ - if ((strcmp (words[2], "config")) == 0) { - type = GF_GSYNC_OPTION_TYPE_CONFIG; + ret = 0; - switch (wordcount) { - case 5: + if (masteri) + ret = dict_set_str (dict, "master", (char *)words[masteri]); + if (!ret && slavei) + ret = dict_set_str (dict, "slave", (char *)words[slavei]); + if (!ret) + ret = dict_set_int32 (dict, "type", type); + if (!ret && type == GF_GSYNC_OPTION_TYPE_CONFIG) { + switch ((wordcount - 1) - cmdi) { + case 0: subop = gf_strdup ("get-all"); break; - case 6: - if (words[5][0] == '!') { - (words[5])++; + case 1: + if (words[cmdi + 1][0] == '!') { + (words[cmdi + 1])++; subop = gf_strdup ("del"); } else subop = gf_strdup ("get"); - ret = dict_set_str (dict, "op_name", ((char *)words[5])); + ret = dict_set_str (dict, "op_name", ((char *)words[cmdi + 1])); if (ret < 0) goto out; break; default: - if (wordcount < 7) { - ret = -1; - - goto out; - } - subop = gf_strdup ("set"); - ret = dict_set_str (dict, "op_name", (char *)words[5]); + ret = dict_set_str (dict, "op_name", ((char *)words[cmdi + 1])); if (ret < 0) goto out; - /*XXX hack to get around the fact, where parsing of - * args is done based on spaces */ - for (i = 6; i < wordcount; i++) + + /* join the varargs by spaces to get the op_value */ + + for (i = cmdi + 2; i < wordcount; i++) append_len += (strlen (words[i]) + 1); - append_len++; /* trailing strcat will add two bytes, make space for that */ + /* trailing strcat will add two bytes, make space for that */ + append_len++; append_str = GF_CALLOC (1, append_len, cli_mt_append_str); if (!append_str) { @@ -1233,39 +1260,27 @@ cli_cmd_gsync_set_parse (const char **words, int wordcount, dict_t **options) goto out; } - for (i = 6; i< wordcount; i++) { + for (i = cmdi + 2; i < wordcount; i++) { strcat (append_str, words[i]); strcat (append_str, " "); } append_str[append_len - 2] = '\0'; ret = dict_set_dynstr (dict, "op_value", append_str); - if (ret < 0) - goto out; } - if (!subop || dict_set_dynstr (dict, "subop", subop) != 0) { + if (!subop || dict_set_dynstr (dict, "subop", subop) != 0) ret = -1; - goto out; - } - } else { - ret = -1; - goto out; } -set_type: - ret = dict_set_int32 (dict, "type", type); - if (ret < 0) - goto out; - - *options = dict; out: if (ret) { if (dict) dict_destroy (dict); if (append_str) GF_FREE (append_str); - } + } else + *options = dict; return ret; } diff --git a/cli/src/cli-cmd-volume.c b/cli/src/cli-cmd-volume.c index f6caddbc334..3d4a26544b6 100644 --- a/cli/src/cli-cmd-volume.c +++ b/cli/src/cli-cmd-volume.c @@ -1165,7 +1165,7 @@ struct cli_cmd volume_cmds[] = { "reset all the reconfigured options"}, #if (SYNCDAEMON_COMPILE) - {"volume "GEOREP" [[] ] [options]", + {"volume "GEOREP" [] [] {start|stop|config|status} [options...]", cli_cmd_volume_gsync_set_cbk, "Geo-sync operations"}, #endif -- cgit