From ad234382336a6f2dafb4cb698dfabbf7957b498b Mon Sep 17 00:00:00 2001 From: Pranith Kumar K Date: Mon, 20 Sep 2010 09:54:12 +0000 Subject: cli, mgmt/glusterd: volume sync command Signed-off-by: Pranith Kumar K Signed-off-by: Vijay Bellur BUG: 1310 () URL: http://bugs.gluster.com/cgi-bin/bugzilla3/show_bug.cgi?id=1310 --- xlators/mgmt/glusterd/src/glusterd-handler.c | 142 ++++++++- xlators/mgmt/glusterd/src/glusterd-op-sm.c | 430 +++++++++++++++++---------- xlators/mgmt/glusterd/src/glusterd-op-sm.h | 3 +- xlators/mgmt/glusterd/src/glusterd-sm.c | 77 +++-- xlators/mgmt/glusterd/src/glusterd-utils.c | 71 +++-- xlators/mgmt/glusterd/src/glusterd-utils.h | 15 +- xlators/mgmt/glusterd/src/glusterd.h | 12 +- xlators/mgmt/glusterd/src/glusterd3_1-mops.c | 49 ++- 8 files changed, 583 insertions(+), 216 deletions(-) (limited to 'xlators/mgmt/glusterd/src') diff --git a/xlators/mgmt/glusterd/src/glusterd-handler.c b/xlators/mgmt/glusterd/src/glusterd-handler.c index bc015293f4a..da9eca02174 100644 --- a/xlators/mgmt/glusterd/src/glusterd-handler.c +++ b/xlators/mgmt/glusterd/src/glusterd-handler.c @@ -297,7 +297,7 @@ out: return ret; } -static int +int glusterd_add_volume_detail_to_dict (glusterd_volinfo_t *volinfo, dict_t *volumes, int count) { @@ -2013,6 +2013,108 @@ out: return ret; } +int +glusterd_handle_sync_volume (rpcsvc_request_t *req) +{ + int32_t ret = -1; + gf1_cli_sync_volume_req cli_req = {0,}; + dict_t *dict = NULL; + gf1_cli_sync_volume_rsp cli_rsp = {0.}; + char msg[2048] = {0,}; + gf_boolean_t free_hostname = _gf_true; + gf_boolean_t free_volname = _gf_true; + glusterd_volinfo_t *volinfo = NULL; + + GF_ASSERT (req); + + if (!gf_xdr_to_cli_sync_volume_req (req->msg[0], &cli_req)) { + //failed to decode msg; + req->rpc_err = GARBAGE_ARGS; + goto out; + } + gf_log ("glusterd", GF_LOG_NORMAL, "Received volume sync req " + "for volume %s", + (cli_req.flags & GF_CLI_SYNC_ALL) ? "all" : cli_req.volname); + + dict = dict_new (); + if (!dict) { + gf_log ("", GF_LOG_ERROR, "Can't allocate sync vol dict"); + goto out; + } + + if (!glusterd_is_local_addr (cli_req.hostname)) { + ret = -1; + snprintf (msg, sizeof (msg), "sync from localhost" + " not allowed"); + goto out; + } + + ret = dict_set_dynmstr (dict, "hostname", cli_req.hostname); + if (ret) { + gf_log ("", GF_LOG_ERROR, "hostname set failed"); + snprintf (msg, sizeof (msg), "hostname set failed"); + goto out; + } else { + free_hostname = _gf_false; + } + + ret = dict_set_int32 (dict, "flags", cli_req.flags); + if (ret) { + gf_log ("", GF_LOG_ERROR, "volume flags set failed"); + snprintf (msg, sizeof (msg), "volume flags set failed"); + goto out; + } + + if (!cli_req.flags) { + ret = glusterd_volinfo_find (cli_req.volname, &volinfo); + if (!ret) { + snprintf (msg, sizeof (msg), "please delete the " + "volume: %s before sync", cli_req.volname); + ret = -1; + goto out; + } + + ret = dict_set_dynmstr (dict, "volname", cli_req.volname); + if (ret) { + gf_log ("", GF_LOG_ERROR, "volume name set failed"); + snprintf (msg, sizeof (msg), "volume name set failed"); + goto out; + } else { + free_volname = _gf_false; + } + } else { + free_volname = _gf_false; + if (glusterd_volume_count_get ()) { + snprintf (msg, sizeof (msg), "please delete all the " + "volumes before full sync"); + ret = -1; + goto out; + } + } + + ret = glusterd_sync_volume (req, dict); + +out: + if (ret) { + cli_rsp.op_ret = -1; + cli_rsp.op_errstr = msg; + glusterd_submit_reply(req, &cli_rsp, NULL, 0, NULL, + gf_xdr_from_cli_sync_volume_rsp); + if (free_hostname && cli_req.hostname) + free (cli_req.hostname); + if (free_volname && cli_req.volname) + free (cli_req.volname); + if (dict) + dict_unref (dict); + if (!glusterd_opinfo_unlock()) + gf_log ("glusterd", GF_LOG_ERROR, "Unlock on " + "opinfo failed"); + + ret = 0; //sent error to cli, prevent second reply + } + + return ret; +} int glusterd_op_lock_send_resp (rpcsvc_request_t *req, int32_t status) @@ -2156,9 +2258,9 @@ out: int glusterd_op_commit_send_resp (rpcsvc_request_t *req, - int32_t op, int32_t status, char *op_errstr) + int32_t op, int32_t status, char *op_errstr, + dict_t *rsp_dict) { - dict_t *rsp_dict = NULL; gd1_mgmt_commit_op_rsp rsp = {{0}, }; int ret = -1; @@ -2172,18 +2274,14 @@ glusterd_op_commit_send_resp (rpcsvc_request_t *req, else rsp.op_errstr = ""; - rsp_dict = dict_new (); - if (!rsp_dict) { - gf_log ("", GF_LOG_DEBUG, - "Out of memory"); - ret = -1; - goto out; - } - - if (op == GD_OP_REPLACE_BRICK) { + switch (op) { + case GD_OP_REPLACE_BRICK: ret = glusterd_fill_rb_commit_rsp (rsp_dict); if (ret) goto out; + break; + default: + break; } ret = dict_allocate_and_serialize (rsp_dict, @@ -2203,8 +2301,6 @@ glusterd_op_commit_send_resp (rpcsvc_request_t *req, "Responded to commit, ret: %d", ret); out: - if (rsp_dict) - dict_unref (rsp_dict); if (rsp.dict.dict_val) GF_FREE (rsp.dict.dict_val); return ret; @@ -3084,6 +3180,24 @@ glusterd_log_rotate (rpcsvc_request_t *req, dict_t *dict) return ret; } +int32_t +glusterd_sync_volume (rpcsvc_request_t *req, dict_t *ctx) +{ + int32_t ret = -1; + + GF_ASSERT (req); + GF_ASSERT (ctx); + + glusterd_op_set_op (GD_OP_SYNC_VOLUME); + glusterd_op_set_ctx (GD_OP_SYNC_VOLUME, ctx); + glusterd_op_set_ctx_free (GD_OP_SYNC_VOLUME, _gf_true); + glusterd_op_set_req (req); + + ret = glusterd_op_txn_begin (); + + return ret; +} + int32_t glusterd_list_friends (rpcsvc_request_t *req, dict_t *dict, int32_t flags) diff --git a/xlators/mgmt/glusterd/src/glusterd-op-sm.c b/xlators/mgmt/glusterd/src/glusterd-op-sm.c index 651cb22e036..a6c1c779a7f 100644 --- a/xlators/mgmt/glusterd/src/glusterd-op-sm.c +++ b/xlators/mgmt/glusterd/src/glusterd-op-sm.c @@ -84,7 +84,7 @@ glusterd_destroy_commit_ctx (glusterd_op_commit_ctx_t *ctx) GF_FREE (ctx); } -static void +void glusterd_set_volume_status (glusterd_volinfo_t *volinfo, glusterd_volume_status status) { @@ -99,6 +99,27 @@ glusterd_is_volume_started (glusterd_volinfo_t *volinfo) return (!(volinfo->status == GLUSTERD_STATUS_STARTED)); } +gf_boolean_t +glusterd_are_all_volumes_stopped () +{ + glusterd_conf_t *priv = NULL; + xlator_t *this = NULL; + glusterd_volinfo_t *voliter = NULL; + + this = THIS; + GF_ASSERT (this); + priv = this->private; + GF_ASSERT (priv); + + list_for_each_entry (voliter, &priv->volumes, vol_list) { + if (voliter->status == GLUSTERD_STATUS_STARTED) + return _gf_false; + } + + return _gf_true; + +} + static int glusterd_op_get_len (glusterd_op_t op) { @@ -158,6 +179,7 @@ glusterd_op_build_payload (glusterd_op_t op, gd1_mgmt_stage_op_req **req) int len = 0; int ret = -1; gd1_mgmt_stage_op_req *stage_req = NULL; + void *ctx = NULL; GF_ASSERT (op < GD_OP_MAX); GF_ASSERT (op > GD_OP_NONE); @@ -178,12 +200,18 @@ glusterd_op_build_payload (glusterd_op_t op, gd1_mgmt_stage_op_req **req) stage_req->op = op; //stage_req->buf.buf_len = len; + ctx = (void*)glusterd_op_get_ctx (op); + if (!ctx) { + gf_log ("", GF_LOG_ERROR, "Null Context for " + "op %d", op); + ret = -1; + goto out; + } + switch (op) { case GD_OP_CREATE_VOLUME: { - dict_t *dict = NULL; - dict = glusterd_op_get_ctx (op); - GF_ASSERT (dict); + dict_t *dict = ctx; ++glusterfs_port; ret = dict_set_int32 (dict, "port", glusterfs_port); ret = dict_allocate_and_serialize (dict, @@ -197,124 +225,36 @@ glusterd_op_build_payload (glusterd_op_t op, gd1_mgmt_stage_op_req **req) case GD_OP_START_VOLUME: { - glusterd_op_start_volume_ctx_t *ctx = NULL; - ctx = glusterd_op_get_ctx (op); - GF_ASSERT (ctx); + glusterd_op_start_volume_ctx_t *ctx1 = ctx; stage_req->buf.buf_len = - strlen (ctx->volume_name); + strlen (ctx1->volume_name); stage_req->buf.buf_val = - gf_strdup (ctx->volume_name); - } - break; - - case GD_OP_STOP_VOLUME: - { - dict_t *dict = NULL; - dict = glusterd_op_get_ctx (op); - if (!dict) { - gf_log ("", GF_LOG_ERROR, "Null Context for " - "stop volume"); - ret = -1; - goto out; - } - ret = dict_allocate_and_serialize (dict, - &stage_req->buf.buf_val, - (size_t *)&stage_req->buf.buf_len); - if (ret) { - goto out; - } + gf_strdup (ctx1->volume_name); } break; case GD_OP_DELETE_VOLUME: { - glusterd_op_delete_volume_ctx_t *ctx = NULL; - ctx = glusterd_op_get_ctx (op); - GF_ASSERT (ctx); + glusterd_op_delete_volume_ctx_t *ctx1 = ctx; stage_req->buf.buf_len = - strlen (ctx->volume_name); + strlen (ctx1->volume_name); stage_req->buf.buf_val = - gf_strdup (ctx->volume_name); + gf_strdup (ctx1->volume_name); } break; + case GD_OP_STOP_VOLUME: case GD_OP_ADD_BRICK: - { - dict_t *dict = NULL; - dict = glusterd_op_get_ctx (op); - GF_ASSERT (dict); - ret = dict_allocate_and_serialize (dict, - &stage_req->buf.buf_val, - (size_t *)&stage_req->buf.buf_len); - if (ret) { - goto out; - } - } - break; - case GD_OP_REPLACE_BRICK: - { - dict_t *dict = NULL; - dict = glusterd_op_get_ctx (op); - GF_ASSERT (dict); - ret = dict_allocate_and_serialize (dict, - &stage_req->buf.buf_val, - (size_t *)&stage_req->buf.buf_len); - if (ret) { - goto out; - } - } - break; - case GD_OP_SET_VOLUME: - { - dict_t *dict = NULL; - dict = glusterd_op_get_ctx (op); - GF_ASSERT (dict); - ret = dict_allocate_and_serialize (dict, - &stage_req->buf.buf_val, - (size_t *)&stage_req->buf.buf_len); - if (ret) { - goto out; - } - } - break; - case GD_OP_REMOVE_BRICK: - { - dict_t *dict = NULL; - dict = glusterd_op_get_ctx (op); - GF_ASSERT (dict); - ret = dict_allocate_and_serialize (dict, - &stage_req->buf.buf_val, - (size_t *)&stage_req->buf.buf_len); - if (ret) { - goto out; - } - } - break; - case GD_OP_LOG_FILENAME: - { - dict_t *dict = NULL; - dict = glusterd_op_get_ctx (op); - GF_ASSERT (dict); - ret = dict_allocate_and_serialize (dict, - &stage_req->buf.buf_val, - (size_t *)&stage_req->buf.buf_len); - if (ret) { - goto out; - } - } - break; - case GD_OP_LOG_ROTATE: + case GD_OP_SYNC_VOLUME: { - dict_t *dict = NULL; - dict = glusterd_op_get_ctx (op); - GF_ASSERT (dict); + dict_t *dict = ctx; ret = dict_allocate_and_serialize (dict, - &stage_req->buf.buf_val, + &stage_req->buf.buf_val, (size_t *)&stage_req->buf.buf_len); if (ret) { goto out; @@ -333,31 +273,6 @@ out: return ret; } -static int -glusterd_check_generate_start_nfs (glusterd_volinfo_t *volinfo) -{ - int ret = -1; - - if (!volinfo) { - gf_log ("", GF_LOG_ERROR, "Invalid Arguments"); - goto out; - } - - ret = volgen_generate_nfs_volfile (volinfo); - if (ret) - goto out; - - if (glusterd_is_nfs_started ()) { - ret = glusterd_nfs_server_stop (); - if (ret) - goto out; - } - - ret = glusterd_nfs_server_start (); -out: - return ret; -} - static int glusterd_op_stage_create_volume (gd1_mgmt_stage_op_req *req, char **op_errstr) { @@ -455,8 +370,9 @@ glusterd_op_stage_create_volume (gd1_mgmt_stage_op_req *req, char **op_errstr) snprintf (cmd_str, 1024, "%s", brick_info->path); ret = glusterd_resolve_brick (brick_info); if (ret) { - gf_log ("glusterd", GF_LOG_ERROR, - "cannot resolve brick"); + gf_log ("glusterd", GF_LOG_ERROR, "cannot resolve " + "brick: %s:%s", brick_info->hostname, + brick_info->path); goto out; } @@ -466,7 +382,7 @@ glusterd_op_stage_create_volume (gd1_mgmt_stage_op_req *req, char **op_errstr) snprintf (msg, 2048,"Volume name %s, brick" ": %s:%s, path %s not present", volname, brick_info->hostname, brick_info->path, brick_info->path); - gf_log ("glusterd",GF_LOG_ERROR, "%s", msg); + gf_log ("glusterd",GF_LOG_ERROR, "%s", msg); *op_errstr = gf_strdup (msg); goto out; } @@ -722,7 +638,7 @@ glusterd_op_stage_add_brick (gd1_mgmt_stage_op_req *req, char **op_errstr) struct stat st_buf = {0,}; char cmd_str[1024]; glusterd_conf_t *priv = NULL; - char msg[2048]; + char msg[2048] = {0,}; GF_ASSERT (req); @@ -928,7 +844,7 @@ out: static int glusterd_op_stage_log_filename (gd1_mgmt_stage_op_req *req) { - int ret = 0; + int ret = -1; dict_t *dict = NULL; char *volname = NULL; gf_boolean_t exists = _gf_false; @@ -970,7 +886,7 @@ out: static int glusterd_op_stage_log_rotate (gd1_mgmt_stage_op_req *req) { - int ret = 0; + int ret = -1; dict_t *dict = NULL; char *volname = NULL; gf_boolean_t exists = _gf_false; @@ -1134,7 +1050,7 @@ glusterd_check_option_exists(char *optstring) static int glusterd_op_stage_remove_brick (gd1_mgmt_stage_op_req *req) { - int ret = 0; + int ret = -1; dict_t *dict = NULL; char *volname = NULL; glusterd_volinfo_t *volinfo = NULL; @@ -1202,6 +1118,80 @@ out: return ret; } +static int +glusterd_op_stage_sync_volume (gd1_mgmt_stage_op_req *req, char **op_errstr) +{ + int ret = -1; + dict_t *dict = NULL; + char *volname = NULL; + char *hostname = NULL; + gf_boolean_t exists = _gf_false; + glusterd_peerinfo_t *peerinfo = NULL; + char msg[2048] = {0,}; + + GF_ASSERT (req); + + dict = dict_new (); + if (!dict) + goto out; + + ret = dict_unserialize (req->buf.buf_val, req->buf.buf_len, &dict); + if (ret) { + gf_log ("", GF_LOG_ERROR, "Unable to unserialize dict"); + goto out; + } + + ret = dict_get_str (dict, "hostname", &hostname); + if (ret) { + snprintf (msg, sizeof (msg), "hostname couldn't be " + "retrieved from msg"); + *op_errstr = gf_strdup (msg); + goto out; + } + + ret = glusterd_is_local_addr (hostname); + if (ret) { + ret = glusterd_friend_find (NULL, hostname, &peerinfo); + if (ret) { + snprintf (msg, sizeof (msg), "%s, is not a friend", + hostname); + *op_errstr = gf_strdup (msg); + goto out; + } + + if (!peerinfo->connected) { + snprintf (msg, sizeof (msg), "%s, is not connected at " + "the moment", hostname); + *op_errstr = gf_strdup (msg); + ret = -1; + goto out; + } + } else { + + //volname is not present in case of sync all + ret = dict_get_str (dict, "volname", &volname); + if (!ret) { + exists = glusterd_check_volume_exists (volname); + if (!exists) { + snprintf (msg, sizeof (msg), "volume: %s, " + "doesn't exist", volname); + *op_errstr = gf_strdup (msg); + ret = -1; + goto out; + } + } else { + ret = 0; + } + } + +out: + if (dict) + dict_unref (dict); + gf_log ("", GF_LOG_DEBUG, "Returning %d", ret); + + return ret; +} + static int glusterd_op_create_volume (gd1_mgmt_stage_op_req *req, char **op_errstr) { @@ -2390,7 +2380,7 @@ glusterd_op_set_volume (gd1_mgmt_stage_op_req *req) dict = dict_new (); if (!dict) goto out; - + ret = dict_unserialize (req->buf.buf_val, req->buf.buf_len, &dict); if (ret) { @@ -2454,9 +2444,9 @@ glusterd_op_set_volume (gd1_mgmt_stage_op_req *req) ret = -1; goto out; } - - + + gf_log ("", GF_LOG_DEBUG, "Received set volume command"); @@ -2469,7 +2459,7 @@ out: static int glusterd_op_remove_brick (gd1_mgmt_stage_op_req *req) { - int ret = 0; + int ret = -1; dict_t *dict = NULL; char *volname = NULL; glusterd_conf_t *priv = NULL; @@ -2642,18 +2632,17 @@ glusterd_op_start_volume (gd1_mgmt_stage_op_req *req, char **op_errstr) { int ret = 0; char volname[1024] = {0,}; - glusterd_conf_t *priv = NULL; glusterd_volinfo_t *volinfo = NULL; + glusterd_conf_t *priv = NULL; glusterd_brickinfo_t *brickinfo = NULL; xlator_t *this = NULL; int32_t mybrick = 0; - GF_ASSERT (req); - this = THIS; GF_ASSERT (this); priv = this->private; GF_ASSERT (priv); + GF_ASSERT (req); strncpy (volname, req->buf.buf_val, req->buf.buf_len); @@ -2661,8 +2650,18 @@ glusterd_op_start_volume (gd1_mgmt_stage_op_req *req, char **op_errstr) if (ret) goto out; - list_for_each_entry (brickinfo, &volinfo->bricks, brick_list) { + if (uuid_is_null (brickinfo->uuid)) { + ret = glusterd_resolve_brick (brickinfo); + if (ret) { + gf_log ("glusterd", GF_LOG_ERROR, + "cannot resolve brick: %s:%s", + brickinfo->hostname, brickinfo->path); + goto out; + } + + } + if (!uuid_compare (brickinfo->uuid, priv->uuid)) { gf_log ("", GF_LOG_NORMAL, "About to start glusterfs" " for brick %s:%s", brickinfo->hostname, @@ -2697,7 +2696,7 @@ out: static int glusterd_op_log_filename (gd1_mgmt_stage_op_req *req) { - int ret = 0; + int ret = -1; dict_t *dict = NULL; glusterd_conf_t *priv = NULL; glusterd_volinfo_t *volinfo = NULL; @@ -2785,7 +2784,7 @@ out: static int glusterd_op_log_rotate (gd1_mgmt_stage_op_req *req) { - int ret = 0; + int ret = -1; dict_t *dict = NULL; glusterd_conf_t *priv = NULL; glusterd_volinfo_t *volinfo = NULL; @@ -2901,10 +2900,10 @@ glusterd_op_stop_volume (gd1_mgmt_stage_op_req *req) char *volname = NULL; glusterd_conf_t *priv = NULL; glusterd_volinfo_t *volinfo = NULL; - glusterd_brickinfo_t *brickinfo = NULL; xlator_t *this = NULL; - int32_t mybrick = 0; dict_t *dict = NULL; + glusterd_brickinfo_t *brickinfo = NULL; + int32_t mybrick = 0; this = THIS; GF_ASSERT (this); @@ -2925,6 +2924,16 @@ glusterd_op_stop_volume (gd1_mgmt_stage_op_req *req) goto out; list_for_each_entry (brickinfo, &volinfo->bricks, brick_list) { + if (uuid_is_null (brickinfo->uuid)) { + ret = glusterd_resolve_brick (brickinfo); + if (ret) { + gf_log ("glusterd", GF_LOG_ERROR, + "cannot resolve brick: %s:%s", + brickinfo->hostname, brickinfo->path); + goto out; + } + + } if (!uuid_compare (brickinfo->uuid, priv->uuid)) { gf_log ("", GF_LOG_NORMAL, "About to stop glusterfs" " for brick %s:%s", brickinfo->hostname, @@ -2957,7 +2966,6 @@ glusterd_op_stop_volume (gd1_mgmt_stage_op_req *req) } else { ret = glusterd_check_generate_start_nfs (volinfo); } - out: if (flags & GF_CLI_FLAG_OP_FORCE) ret = 0; @@ -2966,6 +2974,91 @@ out: return ret; } +static int +glusterd_op_sync_volume (gd1_mgmt_stage_op_req *req, char **op_errstr, + dict_t *rsp_dict) +{ + int ret = -1; + dict_t *dict = NULL; + char *volname = NULL; + char *hostname = NULL; + char msg[2048] = {0,}; + int count = 1; + int vol_count = 0; + glusterd_conf_t *priv = NULL; + glusterd_volinfo_t *volinfo = NULL; + xlator_t *this = NULL; + + GF_ASSERT (req); + this = THIS; + GF_ASSERT (this); + priv = this->private; + GF_ASSERT (priv); + + + dict = dict_new (); + if (!dict) + goto out; + + ret = dict_unserialize (req->buf.buf_val, req->buf.buf_len, &dict); + if (ret) { + gf_log ("", GF_LOG_ERROR, "Unable to unserialize dict"); + goto out; + } + + ret = dict_get_str (dict, "hostname", &hostname); + if (ret) { + snprintf (msg, sizeof (msg), "hostname couldn't be " + "retrieved from msg"); + *op_errstr = gf_strdup (msg); + goto out; + } + + if (glusterd_is_local_addr (hostname)) { + ret = 0; + goto out; + } + + //volname is not present in case of sync all + 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 " + "not exists", volname); + goto out; + } + } + + if (!rsp_dict) { + //this should happen only on source + ret = 0; + goto out; + } + + if (volname) { + ret = glusterd_add_volume_to_dict (volinfo, rsp_dict, + 1); + vol_count = 1; + } else { + list_for_each_entry (volinfo, &priv->volumes, vol_list) { + ret = glusterd_add_volume_to_dict (volinfo, + rsp_dict, count); + if (ret) + goto out; + + vol_count = count++; + } + } + ret = dict_set_int32 (rsp_dict, "count", vol_count); +out: + if (dict) + dict_unref (dict); + gf_log ("", GF_LOG_DEBUG, "Returning %d", ret); + + return ret; +} + static int glusterd_op_ac_none (glusterd_op_sm_event_t *event, void *ctx) { @@ -3475,6 +3568,19 @@ glusterd_op_send_cli_response (int32_t op, int32_t op_ret, sfunc = gf_xdr_serialize_cli_log_rotate_rsp; break; } + case GD_MGMT_CLI_SYNC_VOLUME: + { + gf1_cli_sync_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 = ""; + cli_rsp = &rsp; + sfunc = gf_xdr_from_cli_sync_volume_rsp; + break; + } } ret = glusterd_submit_reply (req, cli_rsp, NULL, 0, NULL, @@ -3635,6 +3741,7 @@ glusterd_op_ac_commit_op (glusterd_op_sm_event_t *event, void *ctx) glusterd_op_commit_ctx_t *commit_ctx = NULL; int32_t status = 0; char *op_errstr = NULL; + dict_t *rsp_dict = NULL; GF_ASSERT (ctx); @@ -3642,14 +3749,27 @@ glusterd_op_ac_commit_op (glusterd_op_sm_event_t *event, void *ctx) req = &commit_ctx->stage_req; - status = glusterd_op_commit_perform (req, &op_errstr); + rsp_dict = dict_new (); + if (!rsp_dict) { + gf_log ("", GF_LOG_DEBUG, + "Out of memory"); + ret = -1; + goto out; + } + + + status = glusterd_op_commit_perform (req, &op_errstr, rsp_dict); if (status) { gf_log ("", GF_LOG_ERROR, "Commit failed: %d", status); } - ret = glusterd_op_commit_send_resp (commit_ctx->req, req->op, status, op_errstr); + ret = glusterd_op_commit_send_resp (commit_ctx->req, req->op, status, + op_errstr, rsp_dict); +out: + if (rsp_dict) + dict_unref (rsp_dict); if (op_errstr && (strcmp (op_errstr, ""))) GF_FREE (op_errstr); @@ -3723,6 +3843,10 @@ glusterd_op_stage_validate (gd1_mgmt_stage_op_req *req, char **op_errstr) ret = glusterd_op_stage_log_rotate (req); break; + case GD_OP_SYNC_VOLUME: + ret = glusterd_op_stage_sync_volume (req, op_errstr); + break; + default: gf_log ("", GF_LOG_ERROR, "Unknown op %d", req->op); @@ -3735,7 +3859,8 @@ glusterd_op_stage_validate (gd1_mgmt_stage_op_req *req, char **op_errstr) int32_t -glusterd_op_commit_perform (gd1_mgmt_stage_op_req *req, char **op_errstr) +glusterd_op_commit_perform (gd1_mgmt_stage_op_req *req, char **op_errstr, + dict_t *rsp_dict) { int ret = -1; @@ -3782,6 +3907,10 @@ glusterd_op_commit_perform (gd1_mgmt_stage_op_req *req, char **op_errstr) ret = glusterd_op_log_rotate (req); break; + case GD_OP_SYNC_VOLUME: + ret = glusterd_op_sync_volume (req, op_errstr, rsp_dict); + break; + default: gf_log ("", GF_LOG_ERROR, "Unknown op %d", req->op); @@ -4191,6 +4320,7 @@ glusterd_op_free_ctx (glusterd_op_t op, void *ctx, gf_boolean_t ctx_free) case GD_OP_REPLACE_BRICK: case GD_OP_LOG_FILENAME: case GD_OP_LOG_ROTATE: + case GD_OP_SYNC_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 e14f007591e..2f39d24f709 100644 --- a/xlators/mgmt/glusterd/src/glusterd-op-sm.h +++ b/xlators/mgmt/glusterd/src/glusterd-op-sm.h @@ -196,7 +196,8 @@ int32_t glusterd_op_stage_validate (gd1_mgmt_stage_op_req *req, char **op_errstr); int32_t -glusterd_op_commit_perform (gd1_mgmt_stage_op_req *req, char **op_errstr); +glusterd_op_commit_perform (gd1_mgmt_stage_op_req *req, char **op_errstr, + dict_t* dict); void * glusterd_op_get_ctx (glusterd_op_t op); diff --git a/xlators/mgmt/glusterd/src/glusterd-sm.c b/xlators/mgmt/glusterd/src/glusterd-sm.c index 602494b1412..025fee7755a 100644 --- a/xlators/mgmt/glusterd/src/glusterd-sm.c +++ b/xlators/mgmt/glusterd/src/glusterd-sm.c @@ -619,6 +619,60 @@ glusterd_destroy_friend_event_context (glusterd_friend_sm_event_t *event) } } +int +glusterd_check_and_add_friend (glusterd_friend_sm_event_t *event) +{ + rpcsvc_request_t *req = NULL; + glusterd_peerinfo_t *peerinfo = NULL; + glusterd_friend_sm_event_type_t event_type = 0; + glusterd_friend_req_ctx_t *fr_ctx = NULL; + glusterd_probe_ctx_t *pb_ctx = NULL; + gf_boolean_t add_friend = _gf_false; + char rhost[UNIX_PATH_MAX + 1] = {0}; + char *host_str = NULL; + int port = 6969; //TODO, use standard + int ret = 0; + + peerinfo = event->peerinfo; + event_type = event->event; + + if (!peerinfo && + (GD_FRIEND_EVENT_PROBE == event_type)) { + add_friend = _gf_true; + pb_ctx = event->ctx; + req = pb_ctx->req; + } + if (!peerinfo && + (GD_FRIEND_EVENT_RCVD_FRIEND_REQ == event_type)) { + add_friend = _gf_true; + fr_ctx = event->ctx; + req = fr_ctx->req; + } + if (add_friend) { + if (req) { + ret = glusterd_remote_hostname_get (req, rhost, + sizeof (rhost)); + if (!ret) + host_str = rhost; + } + ret = glusterd_friend_add ((const char*)host_str, port, + GD_FRIEND_STATE_DEFAULT, + NULL, NULL, &peerinfo, 0); + if (ret) { + gf_log ("glusterd", GF_LOG_ERROR, "Unable to add peer, " + "ret = %d", ret); + ret = 1; + goto out; + } + GF_ASSERT (peerinfo); + event->peerinfo = peerinfo; + } + ret = 0; + +out: + return ret; +} + int glusterd_friend_sm () { @@ -629,32 +683,21 @@ glusterd_friend_sm () glusterd_sm_t *state = NULL; glusterd_peerinfo_t *peerinfo = NULL; glusterd_friend_sm_event_type_t event_type = 0; - int port = 6969; //TODO, use standard gf_boolean_t is_await_conn = _gf_false; + int loop = 0; while (!list_empty (&gd_friend_sm_queue)) { list_for_each_entry_safe (event, tmp, &gd_friend_sm_queue, list) { list_del_init (&event->list); - peerinfo = event->peerinfo; event_type = event->event; - if (!peerinfo && - (GD_FRIEND_EVENT_PROBE == event_type || - GD_FRIEND_EVENT_RCVD_FRIEND_REQ == event_type)) { - ret = glusterd_friend_add (NULL, port, - GD_FRIEND_STATE_DEFAULT, - NULL, NULL, &peerinfo, 0); - - if (ret) { - gf_log ("glusterd", GF_LOG_ERROR, "Unable to add peer, " - "ret = %d", ret); - continue; - } - GF_ASSERT (peerinfo); - event->peerinfo = peerinfo; - } + loop = glusterd_check_and_add_friend (event); + if (loop) + continue; + + peerinfo = event->peerinfo; if (!peerinfo) goto out; diff --git a/xlators/mgmt/glusterd/src/glusterd-utils.c b/xlators/mgmt/glusterd/src/glusterd-utils.c index 017ab687327..358d6ffe46f 100644 --- a/xlators/mgmt/glusterd/src/glusterd-utils.c +++ b/xlators/mgmt/glusterd/src/glusterd-utils.c @@ -1000,6 +1000,7 @@ glusterd_is_cli_op_req (int32_t op) case GD_MGMT_CLI_LOG_FILENAME: case GD_MGMT_CLI_LOG_LOCATE: case GD_MGMT_CLI_LOG_ROTATE: + case GD_MGMT_CLI_SYNC_VOLUME: return _gf_true; break; } @@ -1452,7 +1453,6 @@ out: return ret; } - int32_t glusterd_import_friend_volumes (dict_t *vols) { @@ -1470,7 +1470,6 @@ glusterd_import_friend_volumes (dict_t *vols) ret = glusterd_import_friend_volume (vols, i); if (ret) goto out; - i++; } @@ -1645,27 +1644,6 @@ glusterd_nfs_server_stop () return glusterd_service_stop ("nfsd", pidfile, SIGTERM, _gf_false); } -gf_boolean_t -glusterd_are_all_volumes_stopped () -{ - glusterd_conf_t *priv = NULL; - xlator_t *this = NULL; - glusterd_volinfo_t *voliter = NULL; - - this = THIS; - GF_ASSERT (this); - priv = this->private; - GF_ASSERT (priv); - - list_for_each_entry (voliter, &priv->volumes, vol_list) { - if (voliter->status == GLUSTERD_STATUS_STARTED) - return _gf_false; - } - - return _gf_true; - -} - int glusterd_remote_hostname_get (rpcsvc_request_t *req, char *remote_host, int len) { @@ -1691,3 +1669,50 @@ glusterd_remote_hostname_get (rpcsvc_request_t *req, char *remote_host, int len) return 0; } +int +glusterd_check_generate_start_nfs (glusterd_volinfo_t *volinfo) +{ + int ret = -1; + + if (!volinfo) { + gf_log ("", GF_LOG_ERROR, "Invalid Arguments"); + goto out; + } + + ret = volgen_generate_nfs_volfile (volinfo); + if (ret) + goto out; + + if (glusterd_is_nfs_started ()) { + ret = glusterd_nfs_server_stop (); + if (ret) + goto out; + } + + ret = glusterd_nfs_server_start (); +out: + return ret; +} + +int +glusterd_volume_count_get (void) +{ + glusterd_volinfo_t *tmp_volinfo = NULL; + int32_t ret = 0; + xlator_t *this = NULL; + glusterd_conf_t *priv = NULL; + + this = THIS; + GF_ASSERT (this); + + priv = this->private; + + list_for_each_entry (tmp_volinfo, &priv->volumes, vol_list) { + ret++; + } + + + gf_log ("", GF_LOG_DEBUG, "Returning %d", ret); + return ret; + +} diff --git a/xlators/mgmt/glusterd/src/glusterd-utils.h b/xlators/mgmt/glusterd/src/glusterd-utils.h index a74fa871faf..e03968dfeeb 100644 --- a/xlators/mgmt/glusterd/src/glusterd-utils.h +++ b/xlators/mgmt/glusterd/src/glusterd-utils.h @@ -143,10 +143,19 @@ glusterd_nfs_server_stop (); int glusterd_file_copy (int out, int in); -gf_boolean_t -glusterd_are_all_volumes_stopped (); - int glusterd_remote_hostname_get (rpcsvc_request_t *req, char *remote_host, int len); +int32_t +glusterd_import_friend_volumes (dict_t *vols); +void +glusterd_set_volume_status (glusterd_volinfo_t *volinfo, + glusterd_volume_status status); +int +glusterd_check_generate_start_nfs (glusterd_volinfo_t *volinfo); +int32_t +glusterd_volume_count_get (void); +int32_t +glusterd_add_volume_to_dict (glusterd_volinfo_t *volinfo, + dict_t *dict, int32_t count); #endif diff --git a/xlators/mgmt/glusterd/src/glusterd.h b/xlators/mgmt/glusterd/src/glusterd.h index cfa22930136..48d78bc339a 100644 --- a/xlators/mgmt/glusterd/src/glusterd.h +++ b/xlators/mgmt/glusterd/src/glusterd.h @@ -296,7 +296,8 @@ glusterd_xfer_cli_probe_resp (rpcsvc_request_t *req, int32_t op_ret, int glusterd_op_commit_send_resp (rpcsvc_request_t *req, - int32_t op, int32_t status, char *op_errstr); + int32_t op, int32_t status, char *op_errstr, + dict_t *rsp_dict); int glusterd_xfer_friend_remove_resp (rpcsvc_request_t *req, char *hostname, int port); @@ -365,8 +366,12 @@ glusterd_handle_log_locate (rpcsvc_request_t *req); int glusterd_handle_log_rotate (rpcsvc_request_t *req); +int +glusterd_handle_sync_volume (rpcsvc_request_t *req); + int32_t glusterd_log_filename (rpcsvc_request_t *req, dict_t *dict); + int32_t glusterd_log_rotate (rpcsvc_request_t *req, dict_t *dict); @@ -386,4 +391,9 @@ glusterd_xfer_cli_deprobe_resp (rpcsvc_request_t *req, int32_t op_ret, int glusterd_fetchspec_notify (xlator_t *this); +int32_t +glusterd_sync_volume (rpcsvc_request_t *req, dict_t *ctx); +int +glusterd_add_volume_detail_to_dict (glusterd_volinfo_t *volinfo, + dict_t *volumes, int count); #endif diff --git a/xlators/mgmt/glusterd/src/glusterd3_1-mops.c b/xlators/mgmt/glusterd/src/glusterd3_1-mops.c index 244b71009e7..99b5f7b4e5d 100644 --- a/xlators/mgmt/glusterd/src/glusterd3_1-mops.c +++ b/xlators/mgmt/glusterd/src/glusterd3_1-mops.c @@ -552,6 +552,23 @@ out: return ret; } +static int32_t +glusterd_sync_use_rsp_dict (dict_t *rsp_dict) +{ + int ret = 0; + + GF_ASSERT (rsp_dict); + + if (!rsp_dict) { + goto out; + } + + ret = glusterd_import_friend_volumes (rsp_dict); +out: + return ret; + +} + static int32_t glusterd_rb_use_rsp_dict (dict_t *rsp_dict) { @@ -663,10 +680,19 @@ glusterd3_1_commit_op_cbk (struct rpc_req *req, struct iovec *iov, goto out; } } else { - if (rsp.op == GD_OP_REPLACE_BRICK) { + switch (rsp.op) { + case GD_OP_REPLACE_BRICK: ret = glusterd_rb_use_rsp_dict (dict); if (ret) goto out; + break; + case GD_OP_SYNC_VOLUME: + ret = glusterd_sync_use_rsp_dict (dict); + if (ret) + goto out; + break; + default: + break; } event_type = GD_OP_EVENT_RCVD_ACC; } @@ -956,7 +982,8 @@ glusterd3_1_cluster_lock (call_frame_t *frame, xlator_t *this, list_for_each_entry (peerinfo, &priv->peers, uuid_list) { GF_ASSERT (peerinfo); - if (peerinfo->state.state != GD_FRIEND_STATE_BEFRIENDED) + if ((peerinfo->state.state != GD_FRIEND_STATE_BEFRIENDED) && + (glusterd_op_get_op() != GD_OP_SYNC_VOLUME)) continue; dummy_frame = create_frame (this, this->ctx->pool); @@ -1007,7 +1034,8 @@ glusterd3_1_cluster_unlock (call_frame_t *frame, xlator_t *this, list_for_each_entry (peerinfo, &priv->peers, uuid_list) { GF_ASSERT (peerinfo); - if (peerinfo->state.state != GD_FRIEND_STATE_BEFRIENDED) + if ((peerinfo->state.state != GD_FRIEND_STATE_BEFRIENDED) && + (glusterd_op_get_op() != GD_OP_SYNC_VOLUME)) continue; dummy_frame = create_frame (this, this->ctx->pool); @@ -1091,7 +1119,8 @@ glusterd3_1_stage_op (call_frame_t *frame, xlator_t *this, list_for_each_entry (peerinfo, &priv->peers, uuid_list) { GF_ASSERT (peerinfo); - if (peerinfo->state.state != GD_FRIEND_STATE_BEFRIENDED) + if ((peerinfo->state.state != GD_FRIEND_STATE_BEFRIENDED) && + (glusterd_op_get_op() != GD_OP_SYNC_VOLUME)) continue; dummy_frame = create_frame (this, this->ctx->pool); @@ -1171,7 +1200,8 @@ glusterd3_1_commit_op (call_frame_t *frame, xlator_t *this, if (ret) goto out; - ret = glusterd_op_commit_perform ((gd1_mgmt_stage_op_req *)req, &op_errstr); + ret = glusterd_op_commit_perform ((gd1_mgmt_stage_op_req *)req, &op_errstr, + NULL);//rsp_dict invalid for source if (ret) { gf_log ("", GF_LOG_ERROR, "Commit failed"); @@ -1182,7 +1212,8 @@ glusterd3_1_commit_op (call_frame_t *frame, xlator_t *this, list_for_each_entry (peerinfo, &priv->peers, uuid_list) { GF_ASSERT (peerinfo); - if (peerinfo->state.state != GD_FRIEND_STATE_BEFRIENDED) + if ((peerinfo->state.state != GD_FRIEND_STATE_BEFRIENDED) && + (glusterd_op_get_op() != GD_OP_SYNC_VOLUME)) continue; dummy_frame = create_frame (this, this->ctx->pool); @@ -1339,6 +1370,10 @@ glusterd_handle_rpc_msg (rpcsvc_request_t *req) ret = glusterd_handle_set_volume (req); break; + case GD_MGMT_CLI_SYNC_VOLUME: + ret = glusterd_handle_sync_volume (req); + break; + default: gf_log("", GF_LOG_ERROR, "Recieved Invalid procnum:%d", req->procnum); @@ -1393,7 +1428,7 @@ rpcsvc_actor_t glusterd1_mgmt_actors[] = { [GD_MGMT_CLI_LOG_LOCATE] = { "LOG LOCATE", GD_MGMT_CLI_LOG_LOCATE, glusterd_handle_log_locate, NULL, NULL}, [GD_MGMT_CLI_LOG_ROTATE] = { "LOG FILENAME", GD_MGMT_CLI_LOG_ROTATE, glusterd_handle_rpc_msg, NULL, NULL}, [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}, }; /*rpcsvc_actor_t glusterd1_mgmt_actors[] = { -- cgit