From 096b23f187d0b3ccbed25d8bd02723a61cc4da2d Mon Sep 17 00:00:00 2001 From: shishir gowda Date: Thu, 24 Oct 2013 15:47:14 +0530 Subject: mgmt/glusterd: snapshot config changes Also refactored code in glusterd for create command Additionally, removed brick-op func from mgmt_iniate_all_phases Change-Id: Iddcc332009c5716adee7f2b04c93b352fb983446 Signed-off-by: shishir gowda --- cli/src/cli-cmd-parser.c | 104 ++++- cli/src/cli-cmd-snapshot.c | 6 +- cli/src/cli-rpc-ops.c | 49 +++ rpc/xdr/src/cli1-xdr.c | 11 + rpc/xdr/src/cli1-xdr.h | 11 + rpc/xdr/src/cli1-xdr.x | 10 +- xlators/mgmt/glusterd/src/glusterd-mgmt.c | 8 - xlators/mgmt/glusterd/src/glusterd-snapshot.c | 609 ++++++++++++++++++++------ xlators/mgmt/glusterd/src/glusterd-utils.c | 11 + xlators/mgmt/glusterd/src/glusterd.c | 3 + xlators/mgmt/glusterd/src/glusterd.h | 3 + 11 files changed, 656 insertions(+), 169 deletions(-) diff --git a/cli/src/cli-cmd-parser.c b/cli/src/cli-cmd-parser.c index cf790918c..b7078ff28 100644 --- a/cli/src/cli-cmd-parser.c +++ b/cli/src/cli-cmd-parser.c @@ -3163,6 +3163,82 @@ out: return ret; } +int32_t +cli_snap_config_parse (const char **words, int wordcount, dict_t *options) +{ + dict_t *dict = NULL; + char *volname = NULL; + int ret = -1; + char *key = NULL; + char *value = NULL; + uint64_t limit = 0; + gf1_cli_snapshot type = GF_SNAP_OPTION_TYPE_NONE; + + GF_ASSERT (words); + GF_ASSERT (options); + + if ((wordcount != 3) && (wordcount != 5)) + goto out; + + volname = (char *)words[2]; + + GF_ASSERT (volname); + + type = GF_SNAP_OPTION_TYPE_CONFIG; + ret = dict_set_int32 (options, "type", type); + if (ret) { + gf_log ("", GF_LOG_ERROR, + "Failed to set type."); + goto out; + } + + ret = dict_set_str (options, "volname", volname); + if (ret) { + gf_log ("", GF_LOG_ERROR, + "Failed to set volname."); + goto out; + } + + /* snapshot config [snap_max_limit ] */ + + if (wordcount == 3) { + ret = dict_set_int32 (options, "config-command", + GF_SNAP_CONFIG_DISPLAY); + goto out; + } + + key = (char *) words[3]; + value = (char *) words[4]; + if ( !key || !value) { + ret = -1; + goto out; + } + if (strncmp (key, "snap-max-limit", 14)) { + gf_log ("", GF_LOG_ERROR, "Invalid key"); + goto out; + } + if (!strncmp (volname, "all", 3)) { + ret = dict_set_int32 (options, "config-command", + GF_SNAP_CONFIG_SYS_MAX); + } else { + ret = dict_set_int32 (options, "config-command", + GF_SNAP_CONFIG_VOL_MAX); + } + + limit = (uint64_t) atoll (value); + ret = dict_set_uint64 (options, "limit", limit); + if (ret) { + gf_log ("", GF_LOG_ERROR, + "Failed to set limit."); + goto out; + } + if (ret) + goto out; + +out: + return ret; +} + int32_t cli_cmd_snapshot_parse (const char **words, int wordcount, dict_t **options) @@ -3171,7 +3247,7 @@ cli_cmd_snapshot_parse (const char **words, int wordcount, dict_t **options) dict_t *dict = NULL; gf1_cli_snapshot type = GF_SNAP_OPTION_TYPE_NONE; int32_t cmdi = 0; - char *opwords[] = {"create", "list", NULL}; + char *opwords[] = {"create", "list", "config", NULL}; char *w = NULL; int i = 0; @@ -3211,12 +3287,6 @@ cli_cmd_snapshot_parse (const char **words, int wordcount, dict_t **options) goto out; type = GF_SNAP_OPTION_TYPE_CREATE; cmdi = 1; - ret = dict_set_int32 (dict, "type", type); - if (ret) { - gf_log ("", GF_LOG_ERROR, - "Failed to set type."); - goto out; - } ret = cli_snap_create_parse (dict, words, wordcount, cmdi); @@ -3239,14 +3309,8 @@ cli_cmd_snapshot_parse (const char **words, int wordcount, dict_t **options) goto out; } } - type = GF_SNAP_OPTION_TYPE_LIST; - ret = dict_set_int32 (dict, "type" , type); - if (ret) { - gf_log ("" , GF_LOG_ERROR, - "Failed to set type."); - goto out; - } + type = GF_SNAP_OPTION_TYPE_LIST; ret = cli_snap_list_parse (dict, words, wordcount, cmdi); @@ -3256,11 +3320,23 @@ cli_cmd_snapshot_parse (const char **words, int wordcount, dict_t **options) "list command parsing failed."); goto out; } + } else if (strcmp (w, "config") == 0){ + /* snapshot config [snap_max_limit ] */ + + type = GF_SNAP_OPTION_TYPE_CONFIG; + + ret = cli_snap_config_parse (words, wordcount, dict); } else { gf_log ("", GF_LOG_ERROR, "Opword Mismatch"); goto out; } + ret = dict_set_int32 (dict, "type", type); + if (ret) { + gf_log ("", GF_LOG_ERROR, + "Failed to set type."); + goto out; + } /* If you got so far, input is valid */ ret = 0; out: diff --git a/cli/src/cli-cmd-snapshot.c b/cli/src/cli-cmd-snapshot.c index afe8bf901..6c2b3d5e5 100644 --- a/cli/src/cli-cmd-snapshot.c +++ b/cli/src/cli-cmd-snapshot.c @@ -77,7 +77,7 @@ struct cli_cmd snapshot_cmds[] = { cli_cmd_snapshot_help_cbk, "display help for snapshot commands" }, - {"snapshot create [-n ] [-d ]", + {"snapshot create [-n ] [-d ]", cli_cmd_snapshot_cbk, "Snapshot Create." }, @@ -86,6 +86,10 @@ struct cli_cmd snapshot_cmds[] = { cli_cmd_snapshot_cbk, "Snapshot List." }, + {"snapshot config < volname | all > [ snap-max-limit ]", + cli_cmd_snapshot_cbk, + "Snapshot Config." + }, { NULL, NULL, NULL } }; diff --git a/cli/src/cli-rpc-ops.c b/cli/src/cli-rpc-ops.c index 20cad3bb3..e881e18fc 100644 --- a/cli/src/cli-rpc-ops.c +++ b/cli/src/cli-rpc-ops.c @@ -7806,6 +7806,9 @@ gf_cli_snapshot_cbk (struct rpc_req *req, struct iovec *iov, int32_t type = 0; int64_t volcount = -1; call_frame_t *frame = NULL; + uint64_t limit = 0; + int32_t config_command = 0; + char *volname = NULL; if (req->rpc_status == -1) { ret = -1; @@ -7903,6 +7906,52 @@ gf_cli_snapshot_cbk (struct rpc_req *req, struct iovec *iov, } break; + case GF_SNAP_OPTION_TYPE_CONFIG: + if (rsp.op_ret) { + cli_err ("Snapshot Config : failed: %s", + rsp.op_errstr ? rsp.op_errstr : + "Please check log file for details"); + ret = rsp.op_ret; + goto out; + } + + ret = dict_get_int32 (dict, "config-command", &config_command); + + if (ret) { + gf_log("", GF_LOG_DEBUG, "Could not fetch config type"); + ret = -1; + goto out; + } + + ret = dict_get_str (dict, "volname", &volname); + if (ret) { + gf_log("", GF_LOG_DEBUG, "Could not fetch " + "volname"); + ret = -1; + goto out; + } + + if (!strcmp (volname, "all")) { + volname = "System"; + } + + if (config_command == GF_SNAP_CONFIG_DISPLAY) { + + ret = dict_get_uint64 (dict, "limit", &limit); + if (ret) { + gf_log("", GF_LOG_DEBUG, "Could not fetch " + "limit for %s", volname); + ret = -1; + goto out; + } + cli_out ("Max snapshot count set for %s is %"PRIu64, + volname, limit); + } else { + cli_out ("Snapshot config max set for %s successfull", + volname); + } + break; + default: cli_err ("Unknown command executed"); ret = -1; diff --git a/rpc/xdr/src/cli1-xdr.c b/rpc/xdr/src/cli1-xdr.c index f0f08d334..97b210e14 100644 --- a/rpc/xdr/src/cli1-xdr.c +++ b/rpc/xdr/src/cli1-xdr.c @@ -189,6 +189,17 @@ xdr_gf1_cli_snapshot (XDR *xdrs, gf1_cli_snapshot *objp) return TRUE; } +bool_t +xdr_gf1_cli_snapshot_config (XDR *xdrs, gf1_cli_snapshot_config *objp) +{ + register int32_t *buf; + buf = NULL; + + if (!xdr_enum (xdrs, (enum_t *) objp)) + return FALSE; + return TRUE; +} + bool_t xdr_gf_cli_req (XDR *xdrs, gf_cli_req *objp) { diff --git a/rpc/xdr/src/cli1-xdr.h b/rpc/xdr/src/cli1-xdr.h index 0987d6d41..4c4cb0f18 100644 --- a/rpc/xdr/src/cli1-xdr.h +++ b/rpc/xdr/src/cli1-xdr.h @@ -182,6 +182,15 @@ enum gf1_cli_snapshot { }; typedef enum gf1_cli_snapshot gf1_cli_snapshot; +enum gf1_cli_snapshot_config { + GF_SNAP_CONFIG_TYPE_NONE = 0, + GF_SNAP_CONFIG_SYS_MAX = 0 + 1, + GF_SNAP_CONFIG_VOL_MAX = 0 + 2, + GF_SNAP_CONFIG_DISPLAY = 0 + 3, + GF_SNAP_CONFIG_CG_MAX = 0 + 4, +}; +typedef enum gf1_cli_snapshot_config gf1_cli_snapshot_config; + struct gf_cli_req { struct { u_int dict_len; @@ -294,6 +303,7 @@ extern bool_t xdr_gf1_cli_stats_op (XDR *, gf1_cli_stats_op*); extern bool_t xdr_gf1_cli_top_op (XDR *, gf1_cli_top_op*); extern bool_t xdr_gf_cli_status_type (XDR *, gf_cli_status_type*); extern bool_t xdr_gf1_cli_snapshot (XDR *, gf1_cli_snapshot*); +extern bool_t xdr_gf1_cli_snapshot_config (XDR *, gf1_cli_snapshot_config*); extern bool_t xdr_gf_cli_req (XDR *, gf_cli_req*); extern bool_t xdr_gf_cli_rsp (XDR *, gf_cli_rsp*); extern bool_t xdr_gf1_cli_peer_list_req (XDR *, gf1_cli_peer_list_req*); @@ -323,6 +333,7 @@ extern bool_t xdr_gf1_cli_stats_op (); extern bool_t xdr_gf1_cli_top_op (); extern bool_t xdr_gf_cli_status_type (); extern bool_t xdr_gf1_cli_snapshot (); +extern bool_t xdr_gf1_cli_snapshot_config (); extern bool_t xdr_gf_cli_req (); extern bool_t xdr_gf_cli_rsp (); extern bool_t xdr_gf1_cli_peer_list_req (); diff --git a/rpc/xdr/src/cli1-xdr.x b/rpc/xdr/src/cli1-xdr.x index 3a28d5256..8167abbf9 100644 --- a/rpc/xdr/src/cli1-xdr.x +++ b/rpc/xdr/src/cli1-xdr.x @@ -124,7 +124,7 @@ enum gf_cli_status_type { /* Identifiers for snapshot clis */ enum gf1_cli_snapshot { - GF_SNAP_OPTION_TYPE_NONE, + GF_SNAP_OPTION_TYPE_NONE = 0, GF_SNAP_OPTION_TYPE_CREATE, GF_SNAP_OPTION_TYPE_DELETE, GF_SNAP_OPTION_TYPE_RESTORE, @@ -135,6 +135,14 @@ enum gf1_cli_snapshot { GF_SNAP_OPTION_TYPE_CONFIG }; +enum gf1_cli_snapshot_config { + GF_SNAP_CONFIG_TYPE_NONE = 0, + GF_SNAP_CONFIG_SYS_MAX, + GF_SNAP_CONFIG_VOL_MAX, + GF_SNAP_CONFIG_DISPLAY, + GF_SNAP_CONFIG_CG_MAX +}; + struct gf_cli_req { opaque dict<>; } ; diff --git a/xlators/mgmt/glusterd/src/glusterd-mgmt.c b/xlators/mgmt/glusterd/src/glusterd-mgmt.c index defd8f477..e6f341ada 100644 --- a/xlators/mgmt/glusterd/src/glusterd-mgmt.c +++ b/xlators/mgmt/glusterd/src/glusterd-mgmt.c @@ -1316,14 +1316,6 @@ glusterd_mgmt_v3_initiate_all_phases (rpcsvc_request_t *req, glusterd_op_t op, goto out; } - /* BRICK OP PHASE */ - ret = glusterd_mgmt_v3_brick_op (conf, op, req_dict, - &op_errstr, npeers); - if (ret) { - gf_log ("", GF_LOG_ERROR, "Brick Ops Failed"); - goto out; - } - /* COMMIT OP PHASE */ ret = glusterd_mgmt_v3_commit (conf, op, req_dict, &op_errstr, npeers); diff --git a/xlators/mgmt/glusterd/src/glusterd-snapshot.c b/xlators/mgmt/glusterd/src/glusterd-snapshot.c index c946e4dbd..87ed711dc 100644 --- a/xlators/mgmt/glusterd/src/glusterd-snapshot.c +++ b/xlators/mgmt/glusterd/src/glusterd-snapshot.c @@ -44,7 +44,155 @@ #endif int -glusterd_snapshot_prevalidate (dict_t *dict, char **op_errstr, +glusterd_snapshot_config_limit_prevalidate (dict_t *dict, char **op_errstr, + int config_command) +{ + char *volname = NULL; + glusterd_volinfo_t *volinfo = NULL; + uint64_t limit = 0; + xlator_t *this = NULL; + int ret = -1; + char err_str[PATH_MAX] = {0,}; + glusterd_conf_t *conf = NULL; + + this = THIS; + + GF_ASSERT (this); + GF_ASSERT (dict); + GF_ASSERT (*op_errstr); + + conf = this->private; + + GF_ASSERT (conf); + + switch (config_command) { + + case GF_SNAP_CONFIG_SYS_MAX: + ret = dict_get_uint64 (dict, "limit", &limit); + if (ret) { + snprintf (err_str, PATH_MAX,"Failed to get the" + " snapshot limit"); + *op_errstr = gf_strdup (err_str); + gf_log (this->name, GF_LOG_ERROR, "%s", err_str); + goto out; + } + if (limit < 0 || limit > GLUSTERD_SNAPS_MAX_LIMIT) { + ret = -1; + snprintf (err_str, PATH_MAX,"Invalid max snap limit " + "%"PRIu64 ". Expected range 0 - %"PRIu64, + limit, conf->snap_max_limit); + *op_errstr = gf_strdup (err_str); + gf_log (this->name, GF_LOG_ERROR, "%s", err_str); + goto out; + } + break; + + case GF_SNAP_CONFIG_VOL_MAX: + // volume wide limit + ret = dict_get_str (dict, "volname", &volname); + if (ret) { + snprintf (err_str, PATH_MAX,"Failed to get the" + " volume name"); + *op_errstr = gf_strdup (err_str); + gf_log (this->name, GF_LOG_ERROR, "%s", err_str); + goto out; + } + ret = glusterd_volinfo_find (volname, &volinfo); + if (ret) { + snprintf (err_str, PATH_MAX,"Failed to get the" + " volinfo for volume %s", volname); + *op_errstr = gf_strdup (err_str); + gf_log (this->name, GF_LOG_ERROR, "%s", err_str); + goto out; + } + ret = dict_get_uint64 (dict, "limit", &limit); + if (ret) { + snprintf (err_str, PATH_MAX,"Failed to get the" + " snapshot limit volinfo for volume %s", + volname); + *op_errstr = gf_strdup (err_str); + gf_log (this->name, GF_LOG_ERROR, "%s", err_str); + goto out; + } + if (limit < 0 || limit > conf->snap_max_limit) { + ret = -1; + snprintf (err_str, PATH_MAX,"Invalid max snap limit " + "%"PRIu64 " for volume %s. Expected range" + " 0 - %"PRIu64, limit, volname, + conf->snap_max_limit); + *op_errstr = gf_strdup (err_str); + gf_log (this->name, GF_LOG_ERROR, "%s", err_str); + goto out; + } + break; + + case GF_SNAP_CONFIG_CG_MAX: + break; + + case GF_SNAP_CONFIG_DISPLAY: + ret = dict_get_str (dict, "volname", &volname); + if (ret) { + snprintf (err_str, PATH_MAX,"Failed to get the" + " volume name"); + *op_errstr = gf_strdup (err_str); + gf_log (this->name, GF_LOG_ERROR, "%s", err_str); + goto out; + } + if (!strncmp (volname, "all", 3)) { + ret = 0; + goto out; + } + ret = glusterd_volinfo_find (volname, &volinfo); + if (ret) { + snprintf (err_str, PATH_MAX,"Failed to get the" + " volinfo for volume %s", volname); + *op_errstr = gf_strdup (err_str); + gf_log (this->name, GF_LOG_ERROR, "%s", err_str); + goto out; + } + break; + default: + break; + } +out: + return ret; +} + +int +glusterd_snapshot_config_prevalidate (dict_t *dict, char **op_errstr) +{ + int config_command = 0; + xlator_t *this = NULL; + int ret = -1; + + this = THIS; + ret = dict_get_int32 (dict, "config-command", &config_command); + if (ret) { + gf_log (this->name, GF_LOG_ERROR, + "failed to get config-command type"); + goto out; + } + + switch (config_command) { + case GF_SNAP_CONFIG_SYS_MAX: + case GF_SNAP_CONFIG_VOL_MAX: + case GF_SNAP_CONFIG_CG_MAX: + case GF_SNAP_CONFIG_DISPLAY: + ret = glusterd_snapshot_config_limit_prevalidate (dict, + op_errstr, + config_command); + break; + default: + ret = -1; + gf_log (this->name, GF_LOG_ERROR, "Incorrect config op"); + break; + } +out: + return ret; +} + +int +glusterd_snapshot_create_prevalidate (dict_t *dict, char **op_errstr, dict_t *rsp_dict) { char *volname = NULL; @@ -52,6 +200,49 @@ glusterd_snapshot_prevalidate (dict_t *dict, char **op_errstr, int64_t volume_count = 0; char volname_buf[PATH_MAX] = {0, }; int64_t i = 0; + xlator_t *this = NULL; + int ret = -1; + + ret = dict_get_int64 (dict, "volcount", &volume_count); + if (ret) { + gf_log (this->name, GF_LOG_ERROR, "failed to " + "get the volume count"); + goto out; + } + for (i = 0; i < volume_count; i++) { + snprintf (volname_buf, sizeof (volname_buf), + "volname%ld", i+1); + ret = dict_get_str (dict, volname_buf, + &volname); + if (ret) { + gf_log (this->name, GF_LOG_ERROR, + "failed to get volume name"); + goto out; + } + ret = glusterd_volinfo_find (volname, &volinfo); + if (ret) { + gf_log (this->name, GF_LOG_ERROR, + "failed to get the volinfo for " + "the volume %s", volname); + goto out; + } + if (glusterd_is_defrag_on (volinfo)) { + ret = -1; + gf_log (this->name, GF_LOG_WARNING, + "rebalance process is running " + "for the volume %s", volname); + goto out; + } + //Also check whether geo replication is running + } +out: + return ret; +} + +int +glusterd_snapshot_prevalidate (dict_t *dict, char **op_errstr, + dict_t *rsp_dict) +{ int snap_command = 0; xlator_t *this = NULL; int ret = -1; @@ -61,6 +252,7 @@ glusterd_snapshot_prevalidate (dict_t *dict, char **op_errstr, GF_ASSERT (this); GF_ASSERT (dict); GF_ASSERT (rsp_dict); //not sure if this is needed, verify. + ret = dict_get_int32 (dict, "type", &snap_command); if (ret) { gf_log (this->name, GF_LOG_ERROR, "unable to get the type of " @@ -69,49 +261,20 @@ glusterd_snapshot_prevalidate (dict_t *dict, char **op_errstr, } switch (snap_command) { - case (GF_SNAP_OPTION_TYPE_CREATE): - { - ret = dict_get_int64 (dict, "volcount", &volume_count); - if (ret) { - gf_log (this->name, GF_LOG_ERROR, "failed to " - "get the volume count"); - goto out; - } - for (i = 0; i < volume_count; i++) { - snprintf (volname_buf, sizeof (volname_buf), - "volname%ld", i+1); - ret = dict_get_str (dict, volname_buf, - &volname); - if (ret) { - gf_log (this->name, GF_LOG_ERROR, - "failed to get volume name"); - goto out; - } - ret = glusterd_volinfo_find (volname, &volinfo); - if (ret) { - gf_log (this->name, GF_LOG_ERROR, - "failed to get the volinfo for " - "the volume %s", volname); - goto out; - } - if (glusterd_is_defrag_on (volinfo)) { - gf_log (this->name, GF_LOG_WARNING, - "rebalance process is running " - "for the volume %s", volname); - goto out; - } - //Also check whether geo replication is running - } - break; - } + case (GF_SNAP_OPTION_TYPE_CREATE): + ret = glusterd_snapshot_create_prevalidate (dict, op_errstr, + rsp_dict); + break; + + case (GF_SNAP_OPTION_TYPE_CONFIG): + ret = glusterd_snapshot_config_prevalidate (dict, op_errstr); + break; + default: gf_log (this->name, GF_LOG_WARNING, "invalid snap command"); goto out; break; } - - ret = 0; - out: return ret; } @@ -2088,123 +2251,96 @@ out: */ int32_t -glusterd_snapshot (dict_t *dict, char **op_errstr, dict_t *rsp_dict) +glusterd_snapshot_create_commit (dict_t *dict, char **op_errstr, + dict_t *rsp_dict) { - int ret = -1; - int i = 0; - int snap_command = 0; - int64_t volume_count = 0; - gf_boolean_t is_cg = _gf_false; - char *name = NULL; - char *volname = NULL; - char *tmp = NULL; - char volname_buf[PATH_MAX] = {0, }; - xlator_t *this = NULL; - glusterd_volinfo_t *volinfo = NULL; - glusterd_snap_cg_t *cg = NULL; - glusterd_conf_t *priv = NULL; - uuid_t cg_id; - - this = THIS; + char *name = NULL; + char *volname = NULL; + glusterd_volinfo_t *volinfo = NULL; + int64_t volume_count = 0; + char volname_buf[PATH_MAX] = {0, }; + int i = 0; + xlator_t *this = NULL; + int ret = -1; + glusterd_snap_cg_t *cg = NULL; + gf_boolean_t is_cg = _gf_false; + uuid_t cg_id; + glusterd_conf_t *priv = NULL; + char *tmp = NULL; + + ret = dict_get_int64 (dict, "volcount", &volume_count); + if (ret) { + gf_log (this->name, GF_LOG_ERROR, "failed to " + "get the volume count"); + goto out; + } - GF_ASSERT (this); - GF_ASSERT (dict); - GF_ASSERT (rsp_dict); //not sure if this is needed, verify. + //snap-name should not be set if volume_count > 1 + ret = dict_get_str (dict, "snap-name", &name); + if (volume_count > 1 && !ret) + GF_ASSERT (0); - priv = this->private; - GF_ASSERT (priv); + if (volume_count > 1) { + is_cg = _gf_true; + ret = dict_get_str (dict, "cg-name", &name); + uuid_generate (cg_id); + } else if (volume_count == 1) { + ret = dict_get_str (dict, "snap-name", &name); + } - ret = dict_get_int32 (dict, "type", &snap_command); - if (ret) { - gf_log (this->name, GF_LOG_ERROR, "unable to get the type of " - "the snapshot command"); - goto out; + if (!name) { + name = generate_snapname (volname, NULL, is_cg); + if (!name) { + gf_log (this->name, GF_LOG_ERROR, + "strdup of internal snapname" + " ((%s) failed for the " + "volume %s", name, + volname); + goto out; + } } - switch (snap_command) { - case (GF_SNAP_OPTION_TYPE_CREATE): - { - ret = dict_get_int64 (dict, "volcount", &volume_count); - if (ret) { - gf_log (this->name, GF_LOG_ERROR, "failed to " - "get the volume count"); - goto out; - } + for (i = 1; i < volume_count + 1; i++) { + snprintf (volname_buf, sizeof (volname_buf), + "volname%d", i); + ret = dict_get_str (dict, volname_buf, + &volname); + if (ret) { + gf_log (this->name, GF_LOG_ERROR, + "failed to get volume name"); + goto out; + } - //snap-name should not be set if volume_count > 1 - ret = dict_get_str (dict, "snap-name", &name); - if (volume_count > 1 && !ret) - GF_ASSERT (0); - - if (volume_count > 1) { - is_cg = _gf_true; - ret = dict_get_str (dict, "cg-name", &name); - uuid_generate (cg_id); - } else if (volume_count == 1) { - ret = dict_get_str (dict, "snap-name", &name); - } + ret = glusterd_volinfo_find (volname, &volinfo); + if (ret) { + gf_log (this->name, GF_LOG_ERROR, + "failed to get the volinfo for " + "the volume %s", volname); + goto out; + } - if (!name) { - name = generate_snapname (volname, NULL, is_cg); - if (!name) { - gf_log (this->name, GF_LOG_ERROR, - "strdup of internal snapname" - " ((%s) failed for the " - "volume %s", name, - volname); - goto out; - } - } + tmp = generate_snapname (volname, name, is_cg); + if (!tmp) { + gf_log (this->name, + GF_LOG_ERROR, "strdup " + "failed (%s)", name); + goto out; + } - for (i = 1; i < volume_count + 1; i++) { - snprintf (volname_buf, sizeof (volname_buf), - "volname%d", i); - ret = dict_get_str (dict, volname_buf, - &volname); - if (ret) { - gf_log (this->name, GF_LOG_ERROR, - "failed to get volume name"); - goto out; - } - - ret = glusterd_volinfo_find (volname, &volinfo); - if (ret) { - gf_log (this->name, GF_LOG_ERROR, - "failed to get the volinfo for " - "the volume %s", volname); - goto out; - } - - tmp = generate_snapname (volname, name, is_cg); - if (!tmp) { - gf_log (this->name, - GF_LOG_ERROR, "strdup " - "failed (%s)", name); - goto out; - } - - /* TODO: Create a stub where the bricks are - added parallely by worker threads so that - the snap creating happens parallely. - */ - ret = glusterd_do_snap (volinfo, tmp, dict, - is_cg, cg_id); - if (ret) { - gf_log (this->name, GF_LOG_WARNING, "taking the " - "snapshot of the volume %s failed", - volname); - goto out; - } - } - break; + /* TODO: Create a stub where the bricks are + added parallely by worker threads so that + the snap creating happens parallely. + */ + ret = glusterd_do_snap (volinfo, tmp, dict, + is_cg, cg_id); + if (ret) { + gf_log (this->name, GF_LOG_WARNING, "taking the " + "snapshot of the volume %s failed", + volname); + goto out; } - default: - gf_log (this->name, GF_LOG_WARNING, "invalid snap command"); - goto out; - break; } - if (volume_count > 1) { cg = glusterd_new_snap_cg_object (volume_count); if (!cg) { @@ -2227,6 +2363,187 @@ glusterd_snapshot (dict_t *dict, char **op_errstr, dict_t *rsp_dict) goto out; } } +out: + return ret; +} + +int +glusterd_snapshot_config_commit (dict_t *dict, char **op_errstr, + dict_t *rsp_dict) +{ + char *volname = NULL; + glusterd_volinfo_t *volinfo = NULL; + uint64_t limit = 0; + xlator_t *this = NULL; + int ret = -1; + char err_str[PATH_MAX] = {0,}; + glusterd_conf_t *conf = NULL; + int config_command = 0; + + this = THIS; + + GF_ASSERT (this); + GF_ASSERT (dict); + GF_ASSERT (*op_errstr); + GF_ASSERT (rsp_dict); + + conf = this->private; + + GF_ASSERT (conf); + + ret = dict_get_int32 (dict, "config-command", &config_command); + if (ret) { + gf_log (this->name, GF_LOG_ERROR, + "failed to get config-command type"); + goto out; + } + + switch (config_command) { + + case GF_SNAP_CONFIG_SYS_MAX: + ret = dict_get_uint64 (dict, "limit", &limit); + if (ret) { + snprintf (err_str, PATH_MAX,"Failed to get the" + " snapshot limit"); + *op_errstr = gf_strdup (err_str); + gf_log (this->name, GF_LOG_ERROR, "%s", err_str); + goto out; + } + conf->snap_max_limit = limit; + // TODO: do store + + break; + + case GF_SNAP_CONFIG_VOL_MAX: + // volume wide limit + ret = dict_get_str (dict, "volname", &volname); + if (ret) { + snprintf (err_str, PATH_MAX,"Failed to get the" + " volume name"); + *op_errstr = gf_strdup (err_str); + gf_log (this->name, GF_LOG_ERROR, "%s", err_str); + goto out; + } + ret = glusterd_volinfo_find (volname, &volinfo); + if (ret) { + snprintf (err_str, PATH_MAX,"Failed to get the" + " volinfo for volume %s", volname); + *op_errstr = gf_strdup (err_str); + gf_log (this->name, GF_LOG_ERROR, "%s", err_str); + goto out; + } + ret = dict_get_uint64 (dict, "limit", &limit); + if (ret) { + snprintf (err_str, PATH_MAX,"Failed to get the" + " snapshot limit volinfo for volume %s", + volname); + *op_errstr = gf_strdup (err_str); + gf_log (this->name, GF_LOG_ERROR, "%s", err_str); + goto out; + } + volinfo->snap_max_limit = limit; + //TODO: do store + break; + + case GF_SNAP_CONFIG_CG_MAX: + break; + case GF_SNAP_CONFIG_DISPLAY: + ret = dict_get_str (dict, "volname", &volname); + if (ret) { + snprintf (err_str, PATH_MAX,"Failed to get the" + " volume name"); + *op_errstr = gf_strdup (err_str); + gf_log (this->name, GF_LOG_ERROR, "%s", err_str); + goto out; + } + if (!strncmp (volname, "all", 3)) { + limit = conf->snap_max_limit; + } else { + ret = glusterd_volinfo_find (volname, &volinfo); + if (ret) { + snprintf (err_str, PATH_MAX,"Failed to get the" + " volinfo for volume %s", volname); + *op_errstr = gf_strdup (err_str); + gf_log (this->name, GF_LOG_ERROR, "%s", + err_str); + goto out; + } + limit = volinfo->snap_max_limit; + } + + ret = dict_set_uint64 (rsp_dict, "limit", limit); + if (ret) { + snprintf (err_str, PATH_MAX,"Failed to get the" + " set limit for volume %s", + volname); + *op_errstr = gf_strdup (err_str); + gf_log (this->name, GF_LOG_ERROR, "%s", err_str); + goto out; + } + break; + + default: + break; + } + + ret = dict_set_str (rsp_dict, "volname", volname); + if (ret) { + gf_log (this->name, GF_LOG_ERROR, "Failed to set the" + " volume name"); + goto out; + } + ret = dict_set_int32 (dict, "config-command", config_command); + if (ret) { + gf_log (this->name, GF_LOG_ERROR, + "failed to set config-command type"); + goto out; + } +out: + return ret; +} +int32_t +glusterd_snapshot (dict_t *dict, char **op_errstr, dict_t *rsp_dict) +{ + + xlator_t *this = NULL; + glusterd_conf_t *priv = NULL; + int32_t snap_command = 0; + int ret = -1; + + this = THIS; + + GF_ASSERT (this); + GF_ASSERT (dict); + GF_ASSERT (rsp_dict); //not sure if this is needed, verify. + + priv = this->private; + GF_ASSERT (priv); + + ret = dict_get_int32 (dict, "type", &snap_command); + if (ret) { + gf_log (this->name, GF_LOG_ERROR, "unable to get the type of " + "the snapshot command"); + goto out; + } + + switch (snap_command) { + case (GF_SNAP_OPTION_TYPE_CREATE): + ret = glusterd_snapshot_create_commit (dict, op_errstr, + rsp_dict); + break; + + case GF_SNAP_OPTION_TYPE_CONFIG: + ret = glusterd_snapshot_config_commit (dict, op_errstr, + rsp_dict); + break; + + default: + gf_log (this->name, GF_LOG_WARNING, "invalid snap command"); + goto out; + break; + } + + ret = 0; @@ -2313,12 +2630,14 @@ glusterd_handle_snapshot_fn (rpcsvc_request_t *req) case GF_SNAP_OPTION_TYPE_LIST: ret = glusterd_handle_snapshot_list (req, cli_op, dict); break; + case GF_SNAP_OPTION_TYPE_CONFIG: + ret = glusterd_mgmt_v3_initiate_all_phases (req, cli_op, dict); + break; case GF_SNAP_OPTION_TYPE_RESTORE: case GF_SNAP_OPTION_TYPE_DELETE: case GF_SNAP_OPTION_TYPE_START: case GF_SNAP_OPTION_TYPE_STOP: case GF_SNAP_OPTION_TYPE_STATUS: - case GF_SNAP_OPTION_TYPE_CONFIG: gf_log (this->name, GF_LOG_ERROR, "Operation (%d) not " "supported ", type); diff --git a/xlators/mgmt/glusterd/src/glusterd-utils.c b/xlators/mgmt/glusterd/src/glusterd-utils.c index 771b0af5a..1f5cc741b 100644 --- a/xlators/mgmt/glusterd/src/glusterd-utils.c +++ b/xlators/mgmt/glusterd/src/glusterd-utils.c @@ -427,6 +427,12 @@ glusterd_volinfo_new (glusterd_volinfo_t **volinfo) { glusterd_volinfo_t *new_volinfo = NULL; int32_t ret = -1; + xlator_t *this = NULL; + glusterd_conf_t *conf = NULL; + + this = THIS; + + conf = this->private; GF_ASSERT (volinfo); @@ -455,6 +461,11 @@ glusterd_volinfo_new (glusterd_volinfo_t **volinfo) goto out; } + if (conf) + new_volinfo->snap_max_limit = conf->snap_max_limit; + else + new_volinfo->snap_max_limit = GLUSTERD_SNAPS_MAX_LIMIT; + new_volinfo->xl = THIS; *volinfo = new_volinfo; diff --git a/xlators/mgmt/glusterd/src/glusterd.c b/xlators/mgmt/glusterd/src/glusterd.c index c0531d375..60f671902 100644 --- a/xlators/mgmt/glusterd/src/glusterd.c +++ b/xlators/mgmt/glusterd/src/glusterd.c @@ -1321,6 +1321,9 @@ init (xlator_t *this) conf->gfs_mgmt = &gd_brick_prog; strncpy (conf->workdir, workdir, PATH_MAX); + conf->snap_max_limit = GLUSTERD_SNAPS_MAX_LIMIT; + //TODO: read from saved value and update + synclock_init (&conf->big_lock); pthread_mutex_init (&conf->xprt_lock, NULL); INIT_LIST_HEAD (&conf->xprt_list); diff --git a/xlators/mgmt/glusterd/src/glusterd.h b/xlators/mgmt/glusterd/src/glusterd.h index 10b338dda..1d5aa515b 100644 --- a/xlators/mgmt/glusterd/src/glusterd.h +++ b/xlators/mgmt/glusterd/src/glusterd.h @@ -52,6 +52,7 @@ "S56glusterd-geo-rep-create-post.sh" +#define GLUSTERD_SNAPS_MAX_LIMIT 256 #define GLUSTERD_SERVER_QUORUM "server" #define FMTSTR_CHECK_VOL_EXISTS "Volume %s does not exist" @@ -157,6 +158,7 @@ typedef struct { rpcsvc_t *uds_rpc; /* RPCSVC for the unix domain socket */ uint32_t base_port; struct list_head snap_cg; + uint64_t snap_max_limit; char *snap_bricks_directory; } glusterd_conf_t; @@ -276,6 +278,7 @@ struct glusterd_volinfo_ { int type; int brick_count; uint64_t snap_count; + uint64_t snap_max_limit; struct list_head vol_list; struct list_head bricks; struct list_head snaps; -- cgit