From 2e81c881f036d90323fd07d7df07d881723d7a28 Mon Sep 17 00:00:00 2001 From: Mohammed Junaid Ahmed Date: Thu, 10 Feb 2011 05:29:34 +0000 Subject: gsync: cli support for gsyncd. Signed-off-by: Junaid Signed-off-by: Anand V. Avati BUG: 1570 (geosync related changes) URL: http://bugs.gluster.com/cgi-bin/bugzilla3/show_bug.cgi?id=1570 --- cli/src/cli-cmd-parser.c | 96 ++++ cli/src/cli-cmd-volume.c | 45 ++ cli/src/cli.h | 3 + cli/src/cli3_1-cops.c | 71 +++ rpc/rpc-lib/src/protocol-common.h | 2 + rpc/xdr/src/cli1-xdr.c | 28 ++ rpc/xdr/src/cli1-xdr.h | 34 +- rpc/xdr/src/cli1.c | 30 ++ rpc/xdr/src/cli1.h | 12 + rpc/xdr/src/cli1.x | 21 + xlators/mgmt/glusterd/src/glusterd-handler.c | 55 ++ xlators/mgmt/glusterd/src/glusterd-op-sm.c | 718 +++++++++++++++++++++++++++ xlators/mgmt/glusterd/src/glusterd.h | 7 + xlators/mgmt/glusterd/src/glusterd3_1-mops.c | 7 +- 14 files changed, 1127 insertions(+), 2 deletions(-) diff --git a/cli/src/cli-cmd-parser.c b/cli/src/cli-cmd-parser.c index 7c02e1f05..6fa1f80bd 100644 --- a/cli/src/cli-cmd-parser.c +++ b/cli/src/cli-cmd-parser.c @@ -1011,3 +1011,99 @@ out: return ret; } + +int32_t +cli_cmd_gsync_set_parse (const char **words, int wordcount, dict_t **options) +{ + int32_t ret = 0; + int32_t config_type = 0; + dict_t *dict = NULL; + gf1_cli_gsync_set type = GF_GSYNC_OPTION_TYPE_NONE; + + GF_ASSERT (words); + GF_ASSERT (options); + + GF_ASSERT ((strcmp (words[0], "volume")) == 0); + GF_ASSERT ((strcmp (words[1], "gsync")) == 0); + + dict = dict_new (); + if (!dict) + goto out; + + if (wordcount < 5) + goto out; + + ret = dict_set_str (dict, "master", (char *)words[3]); + if (ret < 0) + goto out; + + ret = dict_set_str (dict, "slave", (char *)words[4]); + if (ret < 0) + goto out; + + if ((strcmp (words[2], "start")) == 0) { + type = GF_GSYNC_OPTION_TYPE_START; + + goto set_type; + } + + if ((strcmp (words[2], "stop")) == 0) { + type = GF_GSYNC_OPTION_TYPE_STOP; + + goto set_type; + } + + if ((strcmp (words[2], "configure")) == 0) { + type = GF_GSYNC_OPTION_TYPE_CONFIGURE; + + if (strcmp (words [5], "config-set") == 0) { + config_type = GF_GSYNC_OPTION_TYPE_CONFIG_SET; + + ret = dict_set_str (dict, "op_name", (char *)words[6]); + if (ret < 0) + goto out; + + ret = dict_set_str (dict, "op_value", (char *)words[7]); + if (ret < 0) + goto out; + } + + if ((strcmp (words [5], "config-del")) == 0) { + config_type = GF_GSYNC_OPTION_TYPE_CONFIG_DEL; + + ret = dict_set_str (dict, "op_name", (char *)words[6]); + if (ret < 0) + goto out; + } + + if ((strcmp (words [5], "config-get")) == 0) { + config_type = GF_GSYNC_OPTION_TYPE_CONFIG_GET; + + ret = dict_set_str (dict, "op_name", (char *)words[6]); + if (ret < 0) + goto out; + } + + if ((strcmp (words [5], "config-get-all")) == 0) { + config_type = GF_GSYNC_OPTION_TYPE_CONFIG_GET_ALL; + } + + ret = dict_set_int32 (dict, "config_type", config_type); + if (ret < 0) + 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); + + return ret; +} + diff --git a/cli/src/cli-cmd-volume.c b/cli/src/cli-cmd-volume.c index fd2a7afe0..7ecfde2e0 100644 --- a/cli/src/cli-cmd-volume.c +++ b/cli/src/cli-cmd-volume.c @@ -879,6 +879,47 @@ out: return ret; } +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 [GF1_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 ("Gsync command failed"); + + return ret; +} struct cli_cmd volume_cmds[] = { { "volume info [all|]", @@ -953,6 +994,10 @@ struct cli_cmd volume_cmds[] = { cli_cmd_volume_reset_cbk, "reset all the reconfigured options"}, + {"volume gsync [options]", + cli_cmd_volume_gsync_set_cbk, + "Geo-sync operations"}, + { NULL, NULL, NULL } }; diff --git a/cli/src/cli.h b/cli/src/cli.h index c0fb5a7e5..77bc249d9 100644 --- a/cli/src/cli.h +++ b/cli/src/cli.h @@ -175,6 +175,9 @@ cli_cmd_volume_create_parse (const char **words, int wordcount, int32_t cli_cmd_volume_reset_parse (const char **words, int wordcount, dict_t **opt); +int32_t +cli_cmd_gsync_set_parse (const char **words, int wordcount, dict_t **opt); + int32_t cli_cmd_volume_set_parse (const char **words, int wordcount, dict_t **options); diff --git a/cli/src/cli3_1-cops.c b/cli/src/cli3_1-cops.c index a98815020..612b04724 100644 --- a/cli/src/cli3_1-cops.c +++ b/cli/src/cli3_1-cops.c @@ -2396,6 +2396,76 @@ out: return ret; } +int +gf_cli3_1_gsync_set_cbk (struct rpc_req *req, struct iovec *iov, + int count, void *myframe) +{ + int ret = 0; + gf1_cli_gsync_set_rsp rsp = {0, }; + + if (req->rpc_status == -1) { + ret = -1; + goto out; + } + + ret = gf_xdr_to_cli_gsync_set_rsp (*iov, &rsp); + if (ret < 0) { + gf_log ("", GF_LOG_ERROR, + "Unable to get response structure"); + goto out; + } + + if (rsp.op_errstr) + cli_out ("%s", rsp.op_errstr); + else if (rsp.op_ret) + cli_out ("command unsuccessful"); + else + cli_out ("command executed successfully"); + +out: + ret = rsp.op_ret; + + cli_cmd_broadcast_response (ret); + + return ret; +} + +int32_t +gf_cli3_1_gsync_set (call_frame_t *frame, xlator_t *this, + void *data) +{ + int ret = 0; + dict_t *dict = NULL; + gf1_cli_gsync_set_req req; + + if (!frame || !this || !data) { + ret = -1; + goto out; + } + + dict = data; + + ret = dict_allocate_and_serialize (dict, + &req.dict.dict_val, + (size_t *) &req.dict.dict_len); + if (ret < 0) { + gf_log (this->name, GF_LOG_ERROR, + "failed to serialize the data"); + + goto out; + } + + ret = cli_cmd_submit (&req, frame, cli_rpc_prog, + GD_MGMT_CLI_GSYNC_SET, NULL, + gf_xdr_from_cli_gsync_set_req, + this, gf_cli3_1_gsync_set_cbk); + +out: + return ret; +} + + + struct rpc_clnt_procedure gluster3_1_cli_actors[GF1_CLI_MAXVALUE] = { [GF1_CLI_NULL] = {"NULL", NULL }, [GF1_CLI_PROBE] = { "PROBE_QUERY", gf_cli3_1_probe}, @@ -2420,6 +2490,7 @@ struct rpc_clnt_procedure gluster3_1_cli_actors[GF1_CLI_MAXVALUE] = { [GF1_CLI_PMAP_PORTBYBRICK] = {"PMAP PORTBYBRICK", gf_cli3_1_pmap_b2p}, [GF1_CLI_SYNC_VOLUME] = {"SYNC_VOLUME", gf_cli3_1_sync_volume}, [GF1_CLI_RESET_VOLUME] = {"RESET_VOLUME", gf_cli3_1_reset_volume}, + [GF1_CLI_GSYNC_SET] = {"GSYNC_SET", gf_cli3_1_gsync_set}, [GF1_CLI_FSM_LOG] = {"FSM_LOG", gf_cli3_1_fsm_log} }; diff --git a/rpc/rpc-lib/src/protocol-common.h b/rpc/rpc-lib/src/protocol-common.h index 2fe70408e..7b31be2bd 100644 --- a/rpc/rpc-lib/src/protocol-common.h +++ b/rpc/rpc-lib/src/protocol-common.h @@ -105,6 +105,7 @@ enum gf_mgmt_procnum_ { GD_MGMT_CLI_SYNC_VOLUME, GD_MGMT_CLI_RESET_VOLUME, GD_MGMT_CLI_FSM_LOG, + GD_MGMT_CLI_GSYNC_SET, GD_MGMT_MAXVALUE, }; @@ -135,6 +136,7 @@ enum gf_cli_procnum { GF1_CLI_SYNC_VOLUME, GF1_CLI_RESET_VOLUME, GF1_CLI_FSM_LOG, + GF1_CLI_GSYNC_SET, GF1_CLI_MAXVALUE, }; diff --git a/rpc/xdr/src/cli1-xdr.c b/rpc/xdr/src/cli1-xdr.c index 084aa8b7b..9cb94eb8b 100644 --- a/rpc/xdr/src/cli1-xdr.c +++ b/rpc/xdr/src/cli1-xdr.c @@ -80,6 +80,14 @@ xdr_gf1_cli_op_flags (XDR *xdrs, gf1_cli_op_flags *objp) return TRUE; } +bool_t +xdr_gf1_cli_gsync_set (XDR *xdrs, gf1_cli_gsync_set *objp) +{ + if (!xdr_enum (xdrs, (enum_t *) objp)) + return FALSE; + return TRUE; +} + bool_t xdr_gf1_cli_probe_req (XDR *xdrs, gf1_cli_probe_req *objp) { @@ -641,3 +649,23 @@ xdr_gf1_cli_fsm_log_rsp (XDR *xdrs, gf1_cli_fsm_log_rsp *objp) return FALSE; return TRUE; } + +bool_t +xdr_gf1_cli_gsync_set_req (XDR *xdrs, gf1_cli_gsync_set_req *objp) +{ + if (!xdr_bytes (xdrs, (char **)&objp->dict.dict_val, (u_int *) &objp->dict. dict_len, ~0)) + return FALSE; + return TRUE; +} + +bool_t +xdr_gf1_cli_gsync_set_rsp (XDR *xdrs, gf1_cli_gsync_set_rsp *objp) +{ + if (!xdr_int (xdrs, &objp->op_ret)) + return FALSE; + if (!xdr_int (xdrs, &objp->op_errno)) + return FALSE; + if (!xdr_string (xdrs, &objp->op_errstr, ~0)) + return FALSE; + return TRUE; +} diff --git a/rpc/xdr/src/cli1-xdr.h b/rpc/xdr/src/cli1-xdr.h index c2ccb3237..3f77c9e9c 100644 --- a/rpc/xdr/src/cli1-xdr.h +++ b/rpc/xdr/src/cli1-xdr.h @@ -74,6 +74,18 @@ enum gf1_cli_op_flags { }; typedef enum gf1_cli_op_flags gf1_cli_op_flags; +enum gf1_cli_gsync_set { + GF_GSYNC_OPTION_TYPE_NONE = 0, + GF_GSYNC_OPTION_TYPE_START = 1, + GF_GSYNC_OPTION_TYPE_STOP = 2, + GF_GSYNC_OPTION_TYPE_CONFIGURE = 3, + GF_GSYNC_OPTION_TYPE_CONFIG_SET = 4, + GF_GSYNC_OPTION_TYPE_CONFIG_DEL = 5, + GF_GSYNC_OPTION_TYPE_CONFIG_GET = 6, + GF_GSYNC_OPTION_TYPE_CONFIG_GET_ALL = 7, +}; +typedef enum gf1_cli_gsync_set gf1_cli_gsync_set; + struct gf1_cli_probe_req { char *hostname; int port; @@ -391,11 +403,27 @@ struct gf1_cli_fsm_log_rsp { }; typedef struct gf1_cli_fsm_log_rsp gf1_cli_fsm_log_rsp; +struct gf1_cli_gsync_set_req { + struct { + u_int dict_len; + char *dict_val; + } dict; +}; +typedef struct gf1_cli_gsync_set_req gf1_cli_gsync_set_req; + +struct gf1_cli_gsync_set_rsp { + int op_ret; + int op_errno; + char *op_errstr; +}; +typedef struct gf1_cli_gsync_set_rsp gf1_cli_gsync_set_rsp; + /* the xdr functions */ #if defined(__STDC__) || defined(__cplusplus) extern bool_t xdr_gf1_cluster_type (XDR *, gf1_cluster_type*); extern bool_t xdr_gf1_cli_replace_op (XDR *, gf1_cli_replace_op*); +extern bool_t xdr_gf1_cli_gsync_set (XDR *, gf1_cli_gsync_set*); extern bool_t xdr_gf1_cli_friends_list (XDR *, gf1_cli_friends_list*); extern bool_t xdr_gf1_cli_get_volume (XDR *, gf1_cli_get_volume*); extern bool_t xdr_gf1_cli_sync_volume (XDR *, gf1_cli_sync_volume*); @@ -440,10 +468,13 @@ extern bool_t xdr_gf1_cli_log_rotate_rsp (XDR *, gf1_cli_log_rotate_rsp*); extern bool_t xdr_gf1_cli_sync_volume_rsp (XDR *, gf1_cli_sync_volume_rsp*); extern bool_t xdr_gf1_cli_fsm_log_req (XDR *, gf1_cli_fsm_log_req*); extern bool_t xdr_gf1_cli_fsm_log_rsp (XDR *, gf1_cli_fsm_log_rsp*); +extern bool_t xdr_gf1_cli_gsync_set_req (XDR *, gf1_cli_gsync_set_req*); +extern bool_t xdr_gf1_cli_gsync_set_rsp (XDR *, gf1_cli_gsync_set_rsp*); #else /* K&R C */ extern bool_t xdr_gf1_cluster_type (); extern bool_t xdr_gf1_cli_replace_op (); +extern bool_t xdr_gf1_cli_gsync_set (); extern bool_t xdr_gf1_cli_friends_list (); extern bool_t xdr_gf1_cli_get_volume (); extern bool_t xdr_gf1_cli_sync_volume (); @@ -488,7 +519,8 @@ extern bool_t xdr_gf1_cli_log_rotate_rsp (); extern bool_t xdr_gf1_cli_sync_volume_rsp (); extern bool_t xdr_gf1_cli_fsm_log_req (); extern bool_t xdr_gf1_cli_fsm_log_rsp (); - +extern bool_t xdr_gf1_cli_gsync_set_req (); +extern bool_t xdr_gf1_cli_gsync_set_rsp (); #endif /* K&R C */ #ifdef __cplusplus diff --git a/rpc/xdr/src/cli1.c b/rpc/xdr/src/cli1.c index 14f383941..7bdfd0332 100644 --- a/rpc/xdr/src/cli1.c +++ b/rpc/xdr/src/cli1.c @@ -437,6 +437,36 @@ gf_xdr_from_cli_reset_vol_req (struct iovec outmsg, void *req) (xdrproc_t)xdr_gf1_cli_reset_vol_req); } +ssize_t +gf_xdr_serialize_cli_gsync_set_rsp (struct iovec outmsg, void *rsp) +{ + return xdr_serialize_generic (outmsg, (void *)rsp, + (xdrproc_t)xdr_gf1_cli_gsync_set_rsp); + +} + +ssize_t +gf_xdr_to_cli_gsync_set_req (struct iovec inmsg, void *args) +{ + return xdr_to_generic (inmsg, (void *)args, + (xdrproc_t)xdr_gf1_cli_gsync_set_req); +} + +ssize_t +gf_xdr_to_cli_gsync_set_rsp (struct iovec inmsg, void *args) +{ + return xdr_to_generic (inmsg, (void *)args, + (xdrproc_t)xdr_gf1_cli_gsync_set_rsp); +} + + +ssize_t +gf_xdr_from_cli_gsync_set_req (struct iovec outmsg, void *req) +{ + return xdr_serialize_generic (outmsg, (void *)req, + (xdrproc_t)xdr_gf1_cli_gsync_set_req); +} + ssize_t gf_xdr_serialize_cli_set_vol_rsp (struct iovec outmsg, void *rsp) { diff --git a/rpc/xdr/src/cli1.h b/rpc/xdr/src/cli1.h index d0c43d802..7e80a18cb 100644 --- a/rpc/xdr/src/cli1.h +++ b/rpc/xdr/src/cli1.h @@ -185,6 +185,18 @@ gf_xdr_to_cli_reset_vol_rsp (struct iovec inmsg, void *args); ssize_t gf_xdr_from_cli_reset_vol_req (struct iovec outmsg, void *req); +ssize_t +gf_xdr_serialize_cli_gsync_set_rsp (struct iovec outmsg, void *rsp); + +ssize_t +gf_xdr_to_cli_gsync_set_req (struct iovec inmsg, void *args); + +ssize_t +gf_xdr_to_cli_gsync_set_rsp (struct iovec inmsg, void *args); + +ssize_t +gf_xdr_from_cli_gsync_set_req (struct iovec outmsg, void *req); + ssize_t gf_xdr_serialize_cli_set_vol_rsp (struct iovec outmsg, void *rsp); diff --git a/rpc/xdr/src/cli1.x b/rpc/xdr/src/cli1.x index 4a0bd7163..1bc07a14e 100644 --- a/rpc/xdr/src/cli1.x +++ b/rpc/xdr/src/cli1.x @@ -32,6 +32,17 @@ enum gf1_cli_op_flags { GF_CLI_FLAG_OP_FORCE = 1 }; +enum gf1_cli_gsync_set { + GF_GSYNC_OPTION_TYPE_NONE, + GF_GSYNC_OPTION_TYPE_START, + GF_GSYNC_OPTION_TYPE_STOP, + GF_GSYNC_OPTION_TYPE_CONFIGURE, + GF_GSYNC_OPTION_TYPE_CONFIG_SET, + GF_GSYNC_OPTION_TYPE_CONFIG_DEL, + GF_GSYNC_OPTION_TYPE_CONFIG_GET, + GF_GSYNC_OPTION_TYPE_CONFIG_GET_ALL +}; + struct gf1_cli_probe_req { string hostname<>; int port; @@ -280,3 +291,13 @@ struct gf1_cli_fsm_log_rsp { string op_errstr<>; opaque fsm_log<>; }; + +struct gf1_cli_gsync_set_req { + opaque dict<>; +}; + +struct gf1_cli_gsync_set_rsp { + int op_ret; + int op_errno; + string op_errstr<>; +}; diff --git a/xlators/mgmt/glusterd/src/glusterd-handler.c b/xlators/mgmt/glusterd/src/glusterd-handler.c index aafae5dad..b1a7ea810 100644 --- a/xlators/mgmt/glusterd/src/glusterd-handler.c +++ b/xlators/mgmt/glusterd/src/glusterd-handler.c @@ -1331,6 +1331,42 @@ out: return ret; } +int +glusterd_handle_gsync_set (rpcsvc_request_t *req) +{ + int32_t ret = 0; + dict_t *dict = NULL; + gf1_cli_gsync_set_req cli_req;// = {0, }; + + GF_ASSERT (req); + + if (!gf_xdr_to_cli_gsync_set_req (req->msg[0], &cli_req)) { + req->rpc_err = GARBAGE_ARGS; + ret = -1; + goto out; + } + + if (cli_req.dict.dict_len) { + dict = dict_new (); + + ret = dict_unserialize (cli_req.dict.dict_val, + cli_req.dict.dict_len, + &dict); + if (ret < 0) { + gf_log ("glusterd", GF_LOG_ERROR, "failed to " + "unserialize req-buffer to dictionary"); + goto out; + } else { + dict->extra_stdfree = cli_req.dict.dict_val; + } + } + + ret = glusterd_gsync_set (req, dict); + +out: + return ret; +} + int glusterd_handle_set_volume (rpcsvc_request_t *req) { @@ -3066,6 +3102,25 @@ glusterd_reset_volume (rpcsvc_request_t *req, dict_t *dict) return ret; } +int32_t +glusterd_gsync_set (rpcsvc_request_t *req, dict_t *dict) +{ + int ret = -1; + + glusterd_op_set_op (GD_OP_GSYNC_SET); + + glusterd_op_set_ctx (GD_OP_GSYNC_SET, dict); + + glusterd_op_set_ctx_free (GD_OP_GSYNC_SET, _gf_true); + + glusterd_op_set_cli_op (GD_MGMT_CLI_GSYNC_SET); + + glusterd_op_set_req (req); + + ret = glusterd_op_txn_begin (); + + return ret; +} int32_t diff --git a/xlators/mgmt/glusterd/src/glusterd-op-sm.c b/xlators/mgmt/glusterd/src/glusterd-op-sm.c index 699ebdb2b..fadafa6a5 100644 --- a/xlators/mgmt/glusterd/src/glusterd-op-sm.c +++ b/xlators/mgmt/glusterd/src/glusterd-op-sm.c @@ -86,6 +86,9 @@ static char *glusterd_op_sm_event_names[] = { "GD_OP_EVENT_INVALID" }; +static int +glusterd_restart_brick_servers (glusterd_volinfo_t *); + char* glusterd_op_sm_state_name_get (int state) { @@ -292,6 +295,7 @@ glusterd_op_build_payload (glusterd_op_t op, gd1_mgmt_stage_op_req **req) case GD_OP_LOG_FILENAME: case GD_OP_LOG_ROTATE: case GD_OP_SYNC_VOLUME: + case GD_OP_GSYNC_SET: { dict_t *dict = ctx; ret = dict_allocate_and_serialize (dict, @@ -1875,6 +1879,158 @@ out: return ret; } +char * +volname_from_master (char *master) +{ + if (master == NULL) + return NULL; + + return gf_strdup (master+1); +} + +/* status: return 0 when gsync is running + * return -1 when not running + */ +int +gsync_status (char *master, char *slave) +{ + int ret = 0; + char pidfile[1024] = {0,}; + FILE *file = NULL; + + ret = snprintf (pidfile, 1024, "/etc/glusterd/gsync/%s/%s.pid", + master, slave); + if (ret <= 0) { + ret = -1; + goto out; + } + + file = fopen (pidfile, "r+"); + if (file) { + ret = lockf (fileno (file), F_TLOCK, 0); + if (ret && ((EAGAIN == errno) || (EACCES == errno))) + ret = 0; + } +out: + return ret; +} + +static int +glusterd_op_stage_gsync_set (gd1_mgmt_stage_op_req *req, char **op_errstr) +{ + int ret = 0; + int type = 0; + dict_t *dict = NULL; + char *volname = NULL; + char *master = NULL; + char *slave = NULL; + gf_boolean_t exists = _gf_false; + glusterd_volinfo_t *volinfo = NULL; + + GF_ASSERT (req); + + dict = dict_new (); + if (!dict) { + ret = -1; + goto out; + } + + ret = dict_unserialize (req->buf.buf_val, req->buf.buf_len, &dict); + if (ret) { + gf_log ("", GF_LOG_WARNING, "Unable to unserialize dict"); + goto out; + } + + ret = dict_get_str (dict, "master", &master); + if (ret < 0) { + gf_log ("", GF_LOG_WARNING, "master not found"); + *op_errstr = gf_strdup ("master not found"); + ret = -1; + goto out; + } + + ret = dict_get_str (dict, "slave", &slave); + if (ret < 0) { + gf_log ("", GF_LOG_WARNING, "slave not found"); + *op_errstr = gf_strdup ("slave not found"); + ret = -1; + goto out; + } + + volname = volname_from_master (master); + if (volname == NULL) { + gf_log ("", GF_LOG_WARNING, "volname couldn't be found"); + *op_errstr = gf_strdup ("volname not found"); + ret = -1; + goto out; + } + + exists = glusterd_check_volume_exists (volname); + if (!exists) { + gf_log ("", GF_LOG_WARNING, "volname doesnot exist"); + *op_errstr = gf_strdup ("volname doesnot exist"); + ret = -1; + goto out; + } + + ret = dict_get_int32 (dict, "type", &type); + if (ret < 0) { + gf_log ("", GF_LOG_WARNING, "command type not found"); + *op_errstr = gf_strdup ("command unsuccessful"); + ret = -1; + goto out; + } + + if (type == GF_GSYNC_OPTION_TYPE_START) { + ret = glusterd_volinfo_find (volname, &volinfo); + if (ret) { + gf_log ("", GF_LOG_WARNING, "volinfo not found " + "for %s", volname); + *op_errstr = gf_strdup ("command unsuccessful"); + ret = -1; + goto out; + } + if (GLUSTERD_STATUS_STARTED != volinfo->status) { + gf_log ("", GF_LOG_WARNING, "%s volume not started", + volname); + *op_errstr = gf_strdup ("please start the volume"); + ret = -1; + goto out; + } + //check if the gsync is already started + ret = gsync_status (master, slave); + if (ret == 0) { + gf_log ("", GF_LOG_WARNING, "gsync already started"); + *op_errstr = gf_strdup ("gsync already started"); + ret = -1; + goto out; + } + ret = 0; + goto out; + } + + if (type == GF_GSYNC_OPTION_TYPE_STOP) { + ret = gsync_status (master, slave); + if (ret == -1) { + gf_log ("", GF_LOG_WARNING, "gsync not running"); + *op_errstr = gf_strdup ("gsync not running"); + ret = -1; + goto out; + } + ret = 0; + goto out; + } + + ret = 0; +out: + if (dict) + dict_unref (dict); + if (volname) + GF_FREE (volname); + + return ret; +} + static int glusterd_op_create_volume (gd1_mgmt_stage_op_req *req, char **op_errstr) { @@ -3420,6 +3576,541 @@ out: } +int +start_gsync (char *master, char *slave, char **op_errstr) +{ + int32_t ret = -1; + char cmd[1024] = {0,}; + char pidfile[1024] = {0,}; + + ret = snprintf (pidfile, 1024, "/etc/glusterd/gsync/%s/%s.pid", + master, slave); + + if (ret <= 0) { + ret = -1; + goto out; + } + + ret = gsync_status (master, slave); + if (ret == 0) { + gf_log ("", GF_LOG_WARNING, "gsync %s:%s" + "already started", master, slave); + + *op_errstr = gf_strdup ("gsync is running"); + ret = -1; + goto out; + } + + ret = snprintf (cmd, 1024, "mkdir -p /etc/glusterd/gsyncd/%s", + master); + if (ret <= 0) { + ret = -1; + gf_log ("", GF_LOG_WARNING, "failed to construct the " + "pid path"); + goto out; + } + ret = system (cmd); + if (ret == -1) { + gf_log ("", GF_LOG_WARNING, "failed to create the " + "pid path for %s %s", master, slave); + goto out; + } + + ret = snprintf (cmd, 1024, GFS_PREFIX + "/sbin/gsyncd/gsyncd.py %s %s --config-set " + "-p %s", master, slave, pidfile); + if (ret <= 0) { + ret = -1; + gf_log ("", GF_LOG_WARNING, "failed to construct the " + "config set command for %s %s", master, slave); + goto out; + } + + ret = system (cmd); + if (ret == -1) { + gf_log ("", GF_LOG_WARNING, "failed to set the pid " + "option for %s %s", master, slave); + goto out; + } + + ret = snprintf (cmd, 1024, GFS_PREFIX + "/sbin/gsyncd/gsyncd.py " + "%s %s", master, slave); + if (ret <= 0) { + ret = -1; + goto out; + } + + ret = system (cmd); + if (ret == -1) + goto out; + + ret = 0; + + *op_errstr = gf_strdup ("gsync started successfully"); + +out: + if (ret < 0 && *op_errstr == NULL) + *op_errstr = gf_strdup ("gsync start unsuccessful"); + + return ret; +} + +int +stop_gsync (char *master, char *slave, char **op_errstr) +{ + int32_t ret = -1; + pid_t pid = 0; + FILE *file = NULL; + char pidfile[1024] = {0,}; + char buf [256] = {0,}; + + ret = gsync_status (master, slave); + if (ret == -1) { + gf_log ("", GF_LOG_WARNING, "gsync is not running"); + *op_errstr = gf_strdup ("gsync is not running"); + goto out; + } + + ret = snprintf (pidfile, 1024, "/etc/glusterd/gsync/%s/%s.pid", + master, slave); + if (ret <= 0) { + ret = -1; + gf_log ("", GF_LOG_WARNING, "failed to create the pidfile"); + goto out; + } + + file = fopen (pidfile, "r+"); + if (!file) { + gf_log ("", GF_LOG_WARNING, "cannot open pid file"); + *op_errstr = gf_strdup ("stop unsuccessful"); + ret = -1; + goto out; + } + + ret = read (fileno(file), buf, 1024); + if (ret > 0) { + pid = strtol (buf, NULL, 10); + ret = kill (pid, SIGTERM); + if (ret) { + gf_log ("", GF_LOG_WARNING, + "failed to stop gsyncd"); + goto out; + } + } + ret = 0; + + *op_errstr = gf_strdup ("gsync stopped successfully"); + +out: + return ret; +} + +int +gsync_config_set (char *master, char *slave, + dict_t *dict, char **op_errstr) +{ + int32_t ret = -1; + char *op_name = NULL; + char *op_value = NULL; + char cmd[1024] = {0,}; + + ret = dict_get_str (dict, "op_name", &op_name); + if (ret < 0) { + gf_log ("", GF_LOG_WARNING, "failed to get the " + "option name for %s %s", master, slave); + + *op_errstr = gf_strdup ("configure command failed, " + "please check the log-file\n"); + goto out; + } + + ret = dict_get_str (dict, "op_value", &op_value); + if (ret < 0) { + gf_log ("", GF_LOG_WARNING, "failed to get " + "the option value for %s %s", + master, slave); + + *op_errstr = gf_strdup ("configure command " + "failed, please check " + "the log-file\n"); + goto out; + } + + ret = snprintf (cmd, 1024, GFS_PREFIX + "/sbin/gsyncd/gsyncd.py %s %s " + "--config-set %s %s", master, + slave, op_name, op_value); + if (ret <= 0) { + gf_log ("", GF_LOG_WARNING, "failed to " + "construct the gsyncd command"); + + *op_errstr = gf_strdup ("configure command failed, " + "please check the log-file\n"); + goto out; + } + + ret = system (cmd); + if (ret == -1) { + gf_log ("", GF_LOG_WARNING, "gsyncd failed to " + "set %s option for %s %s peer", + op_name, master, slave); + + *op_errstr = gf_strdup ("configure command " + "failed, please check " + "the log-file\n"); + goto out; + } + ret = 0; + *op_errstr = gf_strdup ("config-set successful"); + +out: + return ret; +} + +int +gsync_config_del (char *master, char *slave, + dict_t *dict, char **op_errstr) +{ + int32_t ret = -1; + char *op_name = NULL; + char cmd[1024] = {0,}; + + ret = dict_get_str (dict, "op_name", &op_name); + if (ret < 0) { + gf_log ("", GF_LOG_WARNING, "failed to get " + "the option for %s %s", master, slave); + + *op_errstr = gf_strdup ("configure command " + "failed, please check " + "the log-file\n"); + goto out; + } + + ret = snprintf (cmd, 4096, GFS_PREFIX + "/sbin/gsyncd/gsyncd.py %s %s " + "--config-del %s", master, + slave, op_name); + if (ret <= 0) { + gf_log ("", GF_LOG_WARNING, "failed to " + "construct the gsyncd command"); + *op_errstr = gf_strdup ("configure command " + "failed, please check " + "the log-file\n"); + goto out; + } + + ret = system (cmd); + if (ret == -1) { + gf_log ("", GF_LOG_WARNING, "failed to delete " + "%s option for %s %s peer", op_name, + master, slave); + *op_errstr = gf_strdup ("configure command " + "failed, please check " + "the log-file\n"); + goto out; + } + ret = 0; + *op_errstr = gf_strdup ("config-del successful"); +out: + return ret; +} + +int +gsync_config_get (char *master, char *slave, + dict_t *dict, char **op_errstr) +{ + int32_t ret = -1; + char *op_name = NULL; + char cmd[1024] = {0,}; + + ret = dict_get_str (dict, "op_name", &op_name); + if (ret < 0) { + gf_log ("", GF_LOG_WARNING, "failed to get " + "the option for %s %s", master, slave); + + *op_errstr = gf_strdup ("configure command " + "failed, please check " + "the log-file\n"); + goto out; + } + + ret = snprintf (cmd, 4096, GFS_PREFIX + "/sbin/gsyncd/gsyncd.py %s %s " + "--config-get %s", master, + slave, op_name); + if (ret <= 0) { + gf_log ("", GF_LOG_WARNING, "failed to " + "construct the gsyncd command"); + *op_errstr = gf_strdup ("configure command " + "failed, please check " + "the log-file\n"); + goto out; + } + + ret = system (cmd); + if (ret == -1) { + gf_log ("", GF_LOG_WARNING, "failed to get " + "%s option for %s %s peer", op_name, + master, slave); + *op_errstr = gf_strdup ("configure command " + "failed, please check " + "the log-file\n"); + goto out; + } + ret = 0; + *op_errstr = gf_strdup ("config-get successful"); +out: + return ret; +} + +int +gsync_config_get_all (char *master, char *slave, char **op_errstr) +{ + int32_t ret = -1; + char cmd[1024] = {0,}; + + ret = snprintf (cmd, 4096, GFS_PREFIX + "/sbin/gsyncd/gsyncd.py %s %s " + "--config-get-all", master, slave); + if (ret <= 0) { + gf_log ("", GF_LOG_WARNING, "failed to " + "construct the gsyncd command " + "for config-get-all"); + *op_errstr = gf_strdup ("configure command " + "failed, please check " + "the log-file\n"); + goto out; + } + + ret = system (cmd); + if (ret == -1) { + gf_log ("", GF_LOG_WARNING, "failed to get " + "all options for %s %s peer", master, + slave); + *op_errstr = gf_strdup ("configure command " + "failed, please check " + "the log-file\n"); + goto out; + } + ret = 0; + *op_errstr = gf_strdup ("config-get successful"); +out: + return ret; +} + +int +gsync_configure (char *master, char *slave, + dict_t *dict, char **op_errstr) +{ + int32_t ret = -1; + int32_t config_type = 0; + + ret = dict_get_int32 (dict, "config_type", &config_type); + if (ret < 0) { + gf_log ("", GF_LOG_WARNING, "couldn't get the " + "config-type for %s %s", master, slave); + *op_errstr = gf_strdup ("configure command failed, " + "please check the log-file\n"); + goto out; + } + + if (config_type == GF_GSYNC_OPTION_TYPE_CONFIG_SET) { + ret = gsync_config_set (master, slave, dict, op_errstr); + goto out; + } + + if (config_type == GF_GSYNC_OPTION_TYPE_CONFIG_DEL) { + ret = gsync_config_del (master, slave, dict, op_errstr); + goto out; + } + + if (config_type == GF_GSYNC_OPTION_TYPE_CONFIG_GET) { + ret = gsync_config_get (master, slave, dict, op_errstr); + goto out; + } + + if (config_type == GF_GSYNC_OPTION_TYPE_CONFIG_GET_ALL) { + ret = gsync_config_get_all (master, slave, op_errstr); + goto out; + } else { + gf_log ("", GF_LOG_WARNING, "Invalid config type"); + *op_errstr = gf_strdup ("Invalid config type"); + ret = -1; + } + +out: + return ret; +} + +int +gsync_command_exec (dict_t *dict, char **op_errstr) +{ + char *master = NULL; + char *slave = NULL; + int32_t ret = -1; + int32_t type = -1; + + GF_VALIDATE_OR_GOTO ("gsync", dict, out); + GF_VALIDATE_OR_GOTO ("gsync", op_errstr, out); + + ret = dict_get_int32 (dict, "type", &type); + if (ret < 0) + goto out; + + ret = dict_get_str (dict, "master", &master); + if (ret < 0) + goto out; + + ret = dict_get_str (dict, "slave", &slave); + if (ret < 0) + goto out; + + if (type == GF_GSYNC_OPTION_TYPE_START) { + ret = start_gsync (master, slave, op_errstr); + goto out; + } + + if (type == GF_GSYNC_OPTION_TYPE_STOP) { + ret = stop_gsync (master, slave, op_errstr); + goto out; + } + + if (type == GF_GSYNC_OPTION_TYPE_CONFIGURE) { + ret = gsync_configure (master, slave, dict, op_errstr); + goto out; + } else { + gf_log ("", GF_LOG_WARNING, "Invalid config type"); + *op_errstr = gf_strdup ("Invalid config type"); + ret = -1; + } +out: + return ret; +} + +int +glusterd_set_marker_gsync (char *master, char *value) +{ + char *volname = NULL; + glusterd_volinfo_t *volinfo = NULL; + int ret = -1; + + volname = volname_from_master (master); + + ret = glusterd_volinfo_find (volname, &volinfo); + if (ret) { + gf_log ("", GF_LOG_ERROR, "Volume not Found"); + ret = -1; + goto out; + } + + ret = dict_set_str (volinfo->dict, MARKER_VOL_KEY, value); + if (ret) { + gf_log ("", GF_LOG_ERROR, "Setting dict failed"); + goto out; + } + + ret = glusterd_create_volfiles (volinfo); + if (ret) { + gf_log ("", GF_LOG_ERROR, "Unable to create volfile" + " for setting of marker while 'gsync start'"); + ret = -1; + goto out; + } + + ret = glusterd_restart_brick_servers (volinfo); + if (ret) { + gf_log ("", GF_LOG_ERROR, "Unable to restart bricks" + " for setting of marker while 'gsync start'"); + ret = -1; + goto out; + } + + ret = glusterd_store_update_volume (volinfo); + if (ret) + goto out; + + ret = glusterd_volume_compute_cksum (volinfo); + if (ret) + goto out; + + if (GLUSTERD_STATUS_STARTED == volinfo->status) + ret = glusterd_check_generate_start_nfs (volinfo); + +out: + return ret; + +} + +int +glusterd_op_gsync_set (gd1_mgmt_stage_op_req *req) +{ + char *master = NULL; + int32_t ret = -1; + int32_t type = -1; + dict_t *dict = NULL; + dict_t *ctx = NULL; + char *op_errstr = NULL; + + GF_ASSERT (req); + + dict = dict_new (); + if (dict == NULL) + goto out; + + ret = dict_unserialize (req->buf.buf_val, req->buf.buf_len, &dict); + if (ret) { + gf_log ("", GF_LOG_WARNING, "Unable to unserialize dict"); + goto out; + } + + ret = dict_get_int32 (dict, "type", &type); + if (ret < 0) + goto out; + + ret = dict_get_str (dict, "master", &master); + if (ret < 0) + goto out; + + if (type == GF_GSYNC_OPTION_TYPE_START) { + ret = glusterd_set_marker_gsync (master, "on"); + if (ret != 0) { + gf_log ("", GF_LOG_WARNING, "marker start failed"); + op_errstr = gf_strdup ("gsync start failed"); + ret = -1; + goto out; + } + } + + if (type == GF_GSYNC_OPTION_TYPE_STOP) { + ret = glusterd_set_marker_gsync (master, "off"); + if (ret != 0) { + gf_log ("", GF_LOG_WARNING, "marker stop failed"); + op_errstr = gf_strdup ("gsync start failed"); + ret = -1; + goto out; + } + } +out: + ctx = glusterd_op_get_ctx (GD_OP_GSYNC_SET); + if (ctx) { + ret = gsync_command_exec (dict, &op_errstr); + if (op_errstr) { + ret = dict_set_str (ctx, "errstr", op_errstr); + if (ret) { + GF_FREE (op_errstr); + gf_log ("", GF_LOG_WARNING, "failed to set " + "error message in ctx"); + } + } + } + + if (dict) + dict_unref (dict); + + return ret; +} + static int glusterd_stop_bricks (glusterd_volinfo_t *volinfo) { @@ -4866,6 +5557,25 @@ glusterd_op_send_cli_response (int32_t op, int32_t op_ret, sfunc = gf_xdr_from_cli_sync_volume_rsp; break; } + case GD_MGMT_CLI_GSYNC_SET: + { + char *str = NULL; + gf1_cli_gsync_set_rsp rsp = {0,}; + ctx = op_ctx; + rsp.op_ret = op_ret; + rsp.op_errno = op_errno; + rsp.op_errstr = ""; + if (ctx) { + ret = dict_get_str (ctx, "errstr", + &str); + if (ret == 0) + rsp.op_errstr = gf_strdup (str); + } else if (op_errstr) + rsp.op_errstr = op_errstr; + cli_rsp = &rsp; + sfunc = gf_xdr_from_cli_sync_volume_rsp; + break; + } } ret = glusterd_submit_reply (req, cli_rsp, NULL, 0, NULL, @@ -5157,6 +5867,10 @@ glusterd_op_stage_validate (gd1_mgmt_stage_op_req *req, char **op_errstr, ret = glusterd_op_stage_sync_volume (req, op_errstr); break; + case GD_OP_GSYNC_SET: + ret = glusterd_op_stage_gsync_set (req, op_errstr); + break; + default: gf_log ("", GF_LOG_ERROR, "Unknown op %d", req->op); @@ -5225,6 +5939,10 @@ glusterd_op_commit_perform (gd1_mgmt_stage_op_req *req, char **op_errstr, ret = glusterd_op_sync_volume (req, op_errstr, rsp_dict); break; + case GD_OP_GSYNC_SET: + ret = glusterd_op_gsync_set (req); + break; + default: gf_log ("", GF_LOG_ERROR, "Unknown op %d", req->op); diff --git a/xlators/mgmt/glusterd/src/glusterd.h b/xlators/mgmt/glusterd/src/glusterd.h index 9914e7be7..1fb734c50 100644 --- a/xlators/mgmt/glusterd/src/glusterd.h +++ b/xlators/mgmt/glusterd/src/glusterd.h @@ -72,6 +72,7 @@ typedef enum glusterd_op_ { GD_OP_LOG_FILENAME, GD_OP_LOG_LOCATE, GD_OP_LOG_ROTATE, + GD_OP_GSYNC_SET, GD_OP_MAX, } glusterd_op_t; @@ -437,12 +438,18 @@ glusterd_set_volume (rpcsvc_request_t *req, dict_t *dict); int32_t glusterd_reset_volume (rpcsvc_request_t *req, dict_t *dict); +int32_t +glusterd_gsync_set (rpcsvc_request_t *req, dict_t *dict); + int glusterd_handle_set_volume (rpcsvc_request_t *req); int glusterd_handle_reset_volume (rpcsvc_request_t *req); +int +glusterd_handle_gsync_set (rpcsvc_request_t *req); + int glusterd_handle_fsm_log (rpcsvc_request_t *req); diff --git a/xlators/mgmt/glusterd/src/glusterd3_1-mops.c b/xlators/mgmt/glusterd/src/glusterd3_1-mops.c index 04ced866a..10e4daca0 100644 --- a/xlators/mgmt/glusterd/src/glusterd3_1-mops.c +++ b/xlators/mgmt/glusterd/src/glusterd3_1-mops.c @@ -1457,6 +1457,10 @@ glusterd_handle_rpc_msg (rpcsvc_request_t *req) ret = glusterd_handle_fsm_log (req); break; + case GD_MGMT_CLI_GSYNC_SET: + ret = glusterd_handle_gsync_set (req); + break; + default: gf_log("", GF_LOG_ERROR, "Recieved Invalid procnum:%d", req->procnum); @@ -1512,7 +1516,8 @@ rpcsvc_actor_t glusterd1_mgmt_actors[] = { [GD_MGMT_CLI_SET_VOLUME] = { "SET_VOLUME", GD_MGMT_CLI_SET_VOLUME, glusterd_handle_rpc_msg, NULL, NULL}, [GD_MGMT_CLI_SYNC_VOLUME] = { "SYNC_VOLUME", GD_MGMT_CLI_SYNC_VOLUME, glusterd_handle_rpc_msg, NULL, NULL}, [GD_MGMT_CLI_RESET_VOLUME] = { "RESET_VOLUME", GD_MGMT_CLI_RESET_VOLUME, glusterd_handle_rpc_msg, NULL, NULL}, - [GD_MGMT_CLI_FSM_LOG] = { "FSM_LOG", GD_MGMT_CLI_FSM_LOG, glusterd_handle_rpc_msg, NULL, NULL} + [GD_MGMT_CLI_FSM_LOG] = { "FSM_LOG", GD_MGMT_CLI_FSM_LOG, glusterd_handle_rpc_msg, NULL, NULL}, + [GD_MGMT_CLI_GSYNC_SET] = {"GSYNC_SET", GD_MGMT_CLI_GSYNC_SET, glusterd_handle_rpc_msg, NULL, NULL}, }; /*rpcsvc_actor_t glusterd1_mgmt_actors[] = { -- cgit