From 0143a2ef653d0f7a337c8220f127655dadbca942 Mon Sep 17 00:00:00 2001 From: Vijay Bellur Date: Thu, 18 Aug 2011 23:19:22 +0530 Subject: mgmt/glusterd, cli: Introduce gluster volume status Change-Id: Iea835b9e448e736016da2e44e3c9bfff93f2fa78 BUG: 3439 Reviewed-on: http://review.gluster.com/259 Tested-by: Gluster Build System Reviewed-by: Anand Avati --- xlators/mgmt/glusterd/src/glusterd-handler.c | 61 ++++++++++++++- xlators/mgmt/glusterd/src/glusterd-op-sm.c | 113 +++++++++++++++++++++++++++ xlators/mgmt/glusterd/src/glusterd-op-sm.h | 5 ++ xlators/mgmt/glusterd/src/glusterd-rpc-ops.c | 84 +++++++++++++++++++- xlators/mgmt/glusterd/src/glusterd-utils.c | 87 +++++++++++++++++++++ xlators/mgmt/glusterd/src/glusterd-utils.h | 4 + xlators/mgmt/glusterd/src/glusterd.h | 1 + 7 files changed, 353 insertions(+), 2 deletions(-) (limited to 'xlators') diff --git a/xlators/mgmt/glusterd/src/glusterd-handler.c b/xlators/mgmt/glusterd/src/glusterd-handler.c index 39f8976e8..09ed6ae2c 100644 --- a/xlators/mgmt/glusterd/src/glusterd-handler.c +++ b/xlators/mgmt/glusterd/src/glusterd-handler.c @@ -3874,6 +3874,63 @@ out: return ret; } +int +glusterd_handle_status_volume (rpcsvc_request_t *req) +{ + int32_t ret = -1; + gf1_cli_status_volume_req cli_req = {0,}; + dict_t *dict = NULL; + int lock_fail = 0; + glusterd_op_t cli_op = GD_OP_STATUS_VOLUME; + + GF_ASSERT (req); + + ret = glusterd_op_set_cli_op (cli_op); + if (ret) { + gf_log ("", GF_LOG_ERROR, "Unable to set cli op: %d", + ret); + lock_fail = 1; + goto out; + } + + ret = -1; + if (!gf_xdr_to_cli_status_volume_req (req->msg[0], &cli_req)) { + //failed to decode msg; + req->rpc_err = GARBAGE_ARGS; + goto out; + } + + gf_log ("glusterd", GF_LOG_INFO, "Received status volume req " + "for volume %s", cli_req.volname); + + dict = dict_new (); + if (!dict) + goto out; + + ret = dict_set_dynmstr (dict, "volname", cli_req.volname); + if (ret) + goto out; + + ret = glusterd_op_begin (req, GD_OP_STATUS_VOLUME, dict, _gf_true); + +out: + if (ret && dict) + dict_unref (dict); + + glusterd_friend_sm (); + glusterd_op_sm (); + + if (ret) { + ret = glusterd_op_send_cli_response (cli_op, ret, 0, req, + NULL, "operation failed"); + if (!lock_fail) + (void) glusterd_opinfo_unlock (); + + } + + return ret; +} + int glusterd_brick_rpc_notify (struct rpc_clnt *rpc, void *mydata, rpc_clnt_event_t event, @@ -4020,6 +4077,7 @@ rpcsvc_actor_t gd_svc_cli_actors[] = { [GLUSTER_CLI_QUOTA] = { "QUOTA", GLUSTER_CLI_QUOTA, glusterd_handle_quota, NULL, NULL}, [GLUSTER_CLI_LOG_LEVEL] = {"LOG_LEVEL", GLUSTER_CLI_LOG_LEVEL, glusterd_handle_log_level, NULL, NULL}, [GLUSTER_CLI_GETWD] = { "GETWD", GLUSTER_CLI_GETWD, glusterd_handle_getwd, NULL, NULL}, + [GLUSTER_CLI_STATUS_VOLUME] = {"STATUS_VOLUME", GLUSTER_CLI_STATUS_VOLUME, glusterd_handle_status_volume, NULL, NULL}, }; @@ -4064,7 +4122,8 @@ rpcsvc_actor_t glusterd1_mgmt_actors[] = { [GD_MGMT_CLI_FSM_LOG] = { "FSM_LOG", GD_MGMT_CLI_FSM_LOG, glusterd_handle_fsm_log, NULL, NULL}, [GD_MGMT_CLI_GSYNC_SET] = {"GSYNC_SET", GD_MGMT_CLI_GSYNC_SET, glusterd_handle_gsync_set, NULL, NULL}, [GD_MGMT_CLI_PROFILE_VOLUME] = { "STATS_VOLUME", GD_MGMT_CLI_PROFILE_VOLUME, glusterd_handle_cli_profile_volume, NULL, NULL}, - [GD_MGMT_CLI_LOG_LEVEL] = {"LOG_LEVEL", GD_MGMT_CLI_LOG_LEVEL, glusterd_handle_log_level, NULL, NULL} + [GD_MGMT_CLI_LOG_LEVEL] = {"LOG_LEVEL", GD_MGMT_CLI_LOG_LEVEL, glusterd_handle_log_level, NULL, NULL}, + [GD_MGMT_CLI_STATUS_VOLUME] = {"STATUS_VOLUME", GD_MGMT_CLI_STATUS_VOLUME, glusterd_handle_status_volume, NULL, NULL} }; struct rpcsvc_program glusterd1_mop_prog = { diff --git a/xlators/mgmt/glusterd/src/glusterd-op-sm.c b/xlators/mgmt/glusterd/src/glusterd-op-sm.c index 0875ec97a..a99c9fa13 100644 --- a/xlators/mgmt/glusterd/src/glusterd-op-sm.c +++ b/xlators/mgmt/glusterd/src/glusterd-op-sm.c @@ -1856,6 +1856,48 @@ out: return ret; } +static int +glusterd_op_stage_status_volume (dict_t *dict, char **op_errstr) +{ + int ret = -1; + gf_boolean_t exists = _gf_false; + char *volname = NULL; + glusterd_conf_t *priv = NULL; + xlator_t *this = NULL; + char msg[2048] = {0,}; + + GF_ASSERT (dict); + this = THIS; + GF_ASSERT (this); + priv = this->private; + GF_ASSERT(priv); + + + ret = dict_get_str (dict, "volname", &volname); + if (ret) { + gf_log ("glusterd", GF_LOG_ERROR, "Unable to get volume name"); + goto out; + } + + exists = glusterd_check_volume_exists (volname); + if (!exists) { + snprintf (msg, sizeof(msg), "Volume %s does not exist", volname); + gf_log ("glusterd", GF_LOG_ERROR, "%s", msg); + + *op_errstr = gf_strdup(msg); + ret = -1; + goto out; + } + + ret = 0; + + out: + if (ret && !(*op_errstr)) + *op_errstr = gf_strdup ("Validation Failed for Status"); + + gf_log ("glusterd", GF_LOG_DEBUG, "Returning: %d", ret); + return ret; +} int glusterd_query_extutil (char *resbuf, runner_t *runner) @@ -6439,6 +6481,67 @@ out: return ret; } +static int +glusterd_op_status_volume (dict_t *dict, char **op_errstr, + dict_t *rsp_dict) +{ + int ret = -1; + char *volname = NULL; + int count = 0; + int brick_count = 0; + glusterd_volinfo_t *volinfo = NULL; + glusterd_brickinfo_t *brickinfo = NULL; + glusterd_conf_t *priv = NULL; + xlator_t *this = NULL; + int32_t brick_index = 0; + + this = THIS; + GF_ASSERT (this); + priv = this->private; + + GF_ASSERT (priv); + + GF_ASSERT (dict); + + + ret = dict_get_str (dict, "volname", &volname); + if (!ret) { + ret = glusterd_volinfo_find (volname, &volinfo); + if (ret) { + gf_log ("", GF_LOG_ERROR, "Volume with name: %s " + "does not exist", volname); + goto out; + } + } + + if (!rsp_dict) { + //this should happen only on source + ret = 0; + rsp_dict = glusterd_op_get_ctx (GD_OP_STATUS_VOLUME); + } + + if (volname) { + list_for_each_entry (brickinfo, &volinfo->bricks, brick_list) { + if (!uuid_compare (brickinfo->uuid, priv->uuid)) { + ret = glusterd_add_brick_to_dict (volinfo, + brickinfo, + rsp_dict, + brick_index); + count++; + brick_count = count; + } + brick_index++; + } + } + + ret = dict_set_int32 (rsp_dict, "count", brick_count); + +out: + gf_log ("", GF_LOG_DEBUG, "Returning %d", ret); + + return ret; +} + static int glusterd_op_ac_none (glusterd_op_sm_event_t *event, void *ctx) { @@ -6664,6 +6767,7 @@ glusterd_op_build_payload (glusterd_op_t op, dict_t **req) case GD_OP_GSYNC_SET: case GD_OP_PROFILE_VOLUME: case GD_OP_LOG_LEVEL: + case GD_OP_STATUS_VOLUME: { dict_t *dict = ctx; dict_copy (dict, req_dict); @@ -7628,6 +7732,10 @@ glusterd_op_stage_validate (glusterd_op_t op, dict_t *dict, char **op_errstr, ret = glusterd_op_stage_log_level (dict, op_errstr); break; + case GD_OP_STATUS_VOLUME: + ret = glusterd_op_stage_status_volume (dict, op_errstr); + break; + default: gf_log ("", GF_LOG_ERROR, "Unknown op %d", op); @@ -7711,6 +7819,10 @@ glusterd_op_commit_perform (glusterd_op_t op, dict_t *dict, char **op_errstr, ret = glusterd_op_log_level (dict); break; + case GD_OP_STATUS_VOLUME: + ret = glusterd_op_status_volume (dict, op_errstr, rsp_dict); + break; + default: gf_log ("", GF_LOG_ERROR, "Unknown op %d", op); @@ -8733,6 +8845,7 @@ glusterd_op_free_ctx (glusterd_op_t op, void *ctx, gf_boolean_t ctx_free) case GD_OP_QUOTA: case GD_OP_PROFILE_VOLUME: case GD_OP_LOG_LEVEL: + case GD_OP_STATUS_VOLUME: dict_unref (ctx); break; case GD_OP_DELETE_VOLUME: diff --git a/xlators/mgmt/glusterd/src/glusterd-op-sm.h b/xlators/mgmt/glusterd/src/glusterd-op-sm.h index 5dc1a5637..b95d584ac 100644 --- a/xlators/mgmt/glusterd/src/glusterd-op-sm.h +++ b/xlators/mgmt/glusterd/src/glusterd-op-sm.h @@ -163,6 +163,11 @@ typedef struct glusterd_pr_brick_rsp_conv_t { dict_t *dict; } glusterd_pr_brick_rsp_conv_t; +typedef struct glusterd_status_rsp_conv_ { + int count; + dict_t *dict; +} glusterd_status_rsp_conv_t; + typedef struct glusterd_gsync_slaves { char *slave; char *host_uuid; diff --git a/xlators/mgmt/glusterd/src/glusterd-rpc-ops.c b/xlators/mgmt/glusterd/src/glusterd-rpc-ops.c index fa60430da..36868d3ce 100644 --- a/xlators/mgmt/glusterd/src/glusterd-rpc-ops.c +++ b/xlators/mgmt/glusterd/src/glusterd-rpc-ops.c @@ -57,7 +57,7 @@ glusterd_op_send_cli_response (glusterd_op_t op, int32_t op_ret, dict_t *ctx = NULL; char *free_ptr = NULL; glusterd_conf_t *conf = NULL; - xdrproc_t xdrproc; + xdrproc_t xdrproc = NULL; GF_ASSERT (THIS); @@ -407,6 +407,26 @@ glusterd_op_send_cli_response (glusterd_op_t op, int32_t op_ret, break; } + + case GD_OP_STATUS_VOLUME: + { + gf1_cli_status_volume_rsp rsp = {0,}; + rsp.op_ret = op_ret; + rsp.op_errno = op_errno; + if (op_errstr) + rsp.op_errstr = op_errstr; + else + rsp.op_errstr = ""; + ctx = op_ctx; + dict_allocate_and_serialize (ctx, + &rsp.dict.dict_val, + (size_t*)&rsp.dict.dict_len); + free_ptr = rsp.dict.dict_val; + cli_rsp = &rsp; + sfunc = gf_xdr_serialize_cli_status_volume_rsp; + xdrproc = (xdrproc_t) xdr_gf1_cli_status_volume_rsp; + break; + } case GD_OP_NONE: case GD_OP_MAX: { @@ -1219,6 +1239,62 @@ out: return ret; } +void +glusterd_volume_status_add_peer_rsp (dict_t *this, char *key, data_t *value, + void *data) +{ + glusterd_status_rsp_conv_t *rsp_ctx = NULL; + data_t *new_value = NULL; + int32_t ret = 0; + + if (strcmp (key, "count") == 0) + return; + + rsp_ctx = data; + new_value = data_copy (value); + GF_ASSERT (new_value); + + ret = dict_set (rsp_ctx->dict, key, new_value); + if (ret) + gf_log ("", GF_LOG_ERROR, "Unable to set key: %s in dict", + key); + + return; +} + +int +glusterd_volume_status_use_rsp_dict (dict_t *rsp_dict) +{ + int ret = 0; + glusterd_status_rsp_conv_t rsp_ctx = {0}; + int32_t brick_count = 0; + int32_t count = 0; + dict_t *ctx_dict = NULL; + glusterd_op_t op = GD_OP_NONE; + + GF_ASSERT (rsp_dict); + + ret = dict_get_int32 (rsp_dict, "count", &brick_count); + if (ret) { + ret = 0; //no bricks in the rsp + goto out; + } + + op = glusterd_op_get_op (); + GF_ASSERT (GD_OP_STATUS_VOLUME == op); + ctx_dict = glusterd_op_get_ctx (op); + + ret = dict_get_int32 (ctx_dict, "count", &count); + rsp_ctx.count = count; + rsp_ctx.dict = ctx_dict; + dict_foreach (rsp_dict, glusterd_volume_status_add_peer_rsp, &rsp_ctx); + dict_del (ctx_dict, "count"); + ret = dict_get_int32 (ctx_dict, "count", &brick_count); + ret = dict_set_int32 (ctx_dict, "count", count + brick_count); +out: + return ret; +} + int32_t glusterd3_1_commit_op_cbk (struct rpc_req *req, struct iovec *iov, int count, void *myframe) @@ -1330,6 +1406,12 @@ glusterd3_1_commit_op_cbk (struct rpc_req *req, struct iovec *iov, goto out; break; + case GD_OP_STATUS_VOLUME: + ret = glusterd_volume_status_use_rsp_dict (dict); + if (ret) + goto out; + break; + default: break; } diff --git a/xlators/mgmt/glusterd/src/glusterd-utils.c b/xlators/mgmt/glusterd/src/glusterd-utils.c index fb7f75c52..278b25c95 100644 --- a/xlators/mgmt/glusterd/src/glusterd-utils.c +++ b/xlators/mgmt/glusterd/src/glusterd-utils.c @@ -2538,6 +2538,93 @@ out: return -1; } +int32_t +glusterd_add_brick_to_dict (glusterd_volinfo_t *volinfo, + glusterd_brickinfo_t *brickinfo, + dict_t *dict, int32_t count) +{ + + int ret = -1; + char key[8192] = {0,}; + char base_key[8192] = {0}; + char pidfile[PATH_MAX] = {0}; + char path[PATH_MAX] = {0}; + FILE *file = NULL; + int32_t pid = -1; + xlator_t *this = NULL; + glusterd_conf_t *priv = NULL; + + GF_ASSERT (volinfo); + GF_ASSERT (brickinfo); + GF_ASSERT (dict); + + this = THIS; + GF_ASSERT (this); + + priv = this->private; + + snprintf (base_key, sizeof (base_key), "brick%d", count); + snprintf (key, sizeof (key), "%s.hostname", base_key); + ret = dict_set_str (dict, key, brickinfo->hostname); + if (ret) + goto out; + + memset (key, 0, sizeof (key)); + snprintf (key, sizeof (key), "%s.path", base_key); + ret = dict_set_str (dict, key, brickinfo->path); + if (ret) + goto out; + + memset (key, 0, sizeof (key)); + snprintf (key, sizeof (key), "%s.port", base_key); + ret = dict_set_int32 (dict, key, brickinfo->port); + if (ret) + goto out; + + + memset (key, 0, sizeof (key)); + snprintf (key, sizeof (key), "%s.status", base_key); + ret = dict_set_int32 (dict, key, brickinfo->signed_in); + if (ret) + goto out; + + if (!brickinfo->signed_in) + goto out; + + + GLUSTERD_GET_VOLUME_DIR (path, volinfo, priv); + GLUSTERD_GET_BRICK_PIDFILE (pidfile, path, brickinfo->hostname, + brickinfo->path); + + file = fopen (pidfile, "r+"); + if (!file) { + gf_log ("", GF_LOG_ERROR, "Unable to open pidfile: %s", + pidfile); + ret = -1; + goto out; + } + + ret = fscanf (file, "%d", &pid); + if (ret <= 0) { + gf_log ("", GF_LOG_ERROR, "Unable to read pidfile: %s", + pidfile); + ret = -1; + goto out; + } + + memset (key, 0, sizeof (key)); + snprintf (key, sizeof (key), "%s.pid", base_key); + ret = dict_set_int32 (dict, key, pid); + if (ret) + goto out; + +out: + if (ret) + gf_log ("", GF_LOG_DEBUG, "Returning %d", ret); + + return ret; +} + int glusterd_all_volume_cond_check (glusterd_condition_func func, int status, void *ctx) diff --git a/xlators/mgmt/glusterd/src/glusterd-utils.h b/xlators/mgmt/glusterd/src/glusterd-utils.h index 1f5223fef..93e2cb92d 100644 --- a/xlators/mgmt/glusterd/src/glusterd-utils.h +++ b/xlators/mgmt/glusterd/src/glusterd-utils.h @@ -282,4 +282,8 @@ glusterd_recreate_bricks (glusterd_conf_t *conf); int32_t glusterd_handle_upgrade_downgrade (dict_t *options, glusterd_conf_t *conf); +int32_t +glusterd_add_brick_to_dict (glusterd_volinfo_t *volinfo, + glusterd_brickinfo_t *brickinfo, + dict_t *dict, int32_t count); #endif diff --git a/xlators/mgmt/glusterd/src/glusterd.h b/xlators/mgmt/glusterd/src/glusterd.h index ab4049d0b..4362984fe 100644 --- a/xlators/mgmt/glusterd/src/glusterd.h +++ b/xlators/mgmt/glusterd/src/glusterd.h @@ -77,6 +77,7 @@ typedef enum glusterd_op_ { GD_OP_PROFILE_VOLUME, GD_OP_QUOTA, GD_OP_LOG_LEVEL, + GD_OP_STATUS_VOLUME, GD_OP_MAX, } glusterd_op_t; -- cgit