diff options
-rw-r--r-- | cli/src/cli-cmd-parser.c | 156 | ||||
-rw-r--r-- | cli/src/cli-cmd-snapshot.c | 8 | ||||
-rw-r--r-- | cli/src/cli-rpc-ops.c | 48 | ||||
-rw-r--r-- | rpc/xdr/src/cli1-xdr.x | 14 | ||||
-rwxr-xr-x | tests/basic/volume-snapshot.t | 34 | ||||
-rwxr-xr-x | tests/snapshot.rc | 13 | ||||
-rw-r--r-- | xlators/mgmt/glusterd/src/glusterd-snapshot.c | 333 | ||||
-rw-r--r-- | xlators/mgmt/glusterd/src/glusterd-volume-ops.c | 61 | ||||
-rw-r--r-- | xlators/mgmt/glusterd/src/glusterd.h | 1 |
9 files changed, 601 insertions, 67 deletions
diff --git a/cli/src/cli-cmd-parser.c b/cli/src/cli-cmd-parser.c index de0654a744b..e7f41fa7203 100644 --- a/cli/src/cli-cmd-parser.c +++ b/cli/src/cli-cmd-parser.c @@ -3297,6 +3297,102 @@ out: return ret; } +/* snapshot activate <snapname> [force] + * @arg-0, dict : Request Dictionary to be sent to server side. + * @arg-1, words : Contains individual words of CLI command. + * @arg-2, wordcount: Contains number of words present in the CLI command. + * + * return value : -1 on failure + * 0 on success + */ +int +cli_snap_activate_parse (dict_t *dict, const char **words, int wordcount) +{ + + int ret = -1; + int flags = 0; + + GF_ASSERT (words); + GF_ASSERT (dict); + + if ((wordcount < 3) || (wordcount > 4)) { + gf_log ("cli", GF_LOG_ERROR, "Invalid Syntax"); + goto out; + } + + ret = dict_set_str (dict, "snapname", (char *)words[2]); + if (ret) { + gf_log ("cli", GF_LOG_ERROR, "Unable to save snap-name %s", + words[2]); + goto out; + } + + if (wordcount == 4) { + if (!strcmp("force", (char *)words[3])) { + flags = GF_CLI_FLAG_OP_FORCE; + } else { + gf_log ("cli", GF_LOG_ERROR, "Invalid option"); + ret = -1; + goto out; + } + } + ret = dict_set_int32 (dict, "flags", flags); + if (ret) { + gf_log ("cli", GF_LOG_ERROR, "Unable to save force option"); + goto out; + } +out: + return ret; +} + +/* snapshot deactivate <snapname> + * @arg-0, dict : Request Dictionary to be sent to server side. + * @arg-1, words : Contains individual words of CLI command. + * @arg-2, wordcount: Contains number of words present in the CLI command. + * + * return value : -1 on failure + * 0 on success + * 1 if user cancelled the request + */ +int +cli_snap_deactivate_parse (dict_t *dict, const char **words, int wordcount, + struct cli_state *state) +{ + + int ret = -1; + gf_answer_t answer = GF_ANSWER_NO; + const char *question = "Deactivating snap will make its " + "data inaccessible. Do you want to " + "continue?"; + + + GF_ASSERT (words); + GF_ASSERT (dict); + + if ((wordcount != 3)) { + gf_log ("cli", GF_LOG_ERROR, "Invalid Syntax"); + goto out; + } + + ret = dict_set_str (dict, "snapname", (char *)words[2]); + if (ret) { + gf_log ("cli", GF_LOG_ERROR, "Unable to save snap-name %s", + words[2]); + goto out; + } + + answer = cli_cmd_get_confirmation (state, question); + if (GF_ANSWER_NO == answer) { + ret = 1; + gf_log ("cli", GF_LOG_DEBUG, "User cancelled " + "snapshot deactivate operation"); + goto out; + } + +out: + return ret; +} + /* snapshot delete <snapname> * @arg-0, dict : Request Dictionary to be sent to server side. * @arg-1, words : Contains individual words of CLI command. @@ -3648,9 +3744,9 @@ 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; char *w = NULL; - char *opwords[] = {"create", "delete", "restore", "start", - "stop", "list", "status", "config", - "info", NULL}; + char *opwords[] = {"create", "delete", "restore", + "activate", "deactivate", "list", + "status", "config", "info", NULL}; char *invalid_snapnames[] = {"description", "force", "volume", NULL}; @@ -3690,8 +3786,11 @@ cli_cmd_snapshot_parse (const char **words, int wordcount, dict_t **options, type = GF_SNAP_OPTION_TYPE_RESTORE; } else if (!strcmp (w, "status")) { type = GF_SNAP_OPTION_TYPE_STATUS; + } else if (!strcmp (w, "activate")) { + type = GF_SNAP_OPTION_TYPE_ACTIVATE; + } else if (!strcmp (w, "deactivate")) { + type = GF_SNAP_OPTION_TYPE_DEACTIVATE; } - if (type != GF_SNAP_OPTION_TYPE_CONFIG) { ret = dict_set_int32 (dict, "hold_snap_locks", _gf_true); if (ret) { @@ -3702,6 +3801,18 @@ cli_cmd_snapshot_parse (const char **words, int wordcount, dict_t **options, } } + /* Following commands does not require volume locks */ + if (type == GF_SNAP_OPTION_TYPE_STATUS || + type == GF_SNAP_OPTION_TYPE_ACTIVATE || + type == GF_SNAP_OPTION_TYPE_DEACTIVATE) { + ret = dict_set_int32 (dict, "hold_vol_locks", _gf_false); + if (ret) { + gf_log ("cli", GF_LOG_ERROR, "Setting volume lock " + "flag failed"); + goto out; + } + } + /* Check which op is intended */ switch (type) { case GF_SNAP_OPTION_TYPE_CREATE: @@ -3764,8 +3875,12 @@ cli_cmd_snapshot_parse (const char **words, int wordcount, dict_t **options, */ ret = cli_snap_delete_parse (dict, words, wordcount, state); if (ret) { - gf_log ("cli", GF_LOG_ERROR, "Failed to parse " - "snapshot delete command"); + /* A positive ret value means user cancelled + * the command */ + if (ret < 0) { + gf_log ("cli", GF_LOG_ERROR, "Failed to parse " + "snapshot delete command"); + } goto out; } break; @@ -3816,7 +3931,34 @@ cli_cmd_snapshot_parse (const char **words, int wordcount, dict_t **options, goto out; } break; - + case GF_SNAP_OPTION_TYPE_ACTIVATE: + /* Syntax: + * snapshot activate <snapname> [force] + */ + ret = cli_snap_activate_parse (dict, words, wordcount); + if (ret) { + gf_log ("cli", GF_LOG_ERROR, "Failed to parse " + "start command"); + goto out; + } + break; + case GF_SNAP_OPTION_TYPE_DEACTIVATE: + /* Syntax: + * snapshot deactivate <snapname> + */ + ret = cli_snap_deactivate_parse (dict, words, wordcount, + state); + if (ret) { + /* A positive ret value means user cancelled + * the command */ + if (ret < 0) { + gf_log ("cli", GF_LOG_ERROR, + "Failed to parse deactivate " + "command"); + } + goto out; + } + break; default: gf_log ("", GF_LOG_ERROR, "Opword Mismatch"); goto out; diff --git a/cli/src/cli-cmd-snapshot.c b/cli/src/cli-cmd-snapshot.c index 941dcbdd2a3..45fa5673f7a 100644 --- a/cli/src/cli-cmd-snapshot.c +++ b/cli/src/cli-cmd-snapshot.c @@ -110,6 +110,14 @@ struct cli_cmd snapshot_cmds[] = { cli_cmd_snapshot_cbk, "Snapshot Delete." }, + {"snapshot activate <snapname> [force]", + cli_cmd_snapshot_cbk, + "Activate snapshot volume." + }, + {"snapshot deactivate <snapname>", + cli_cmd_snapshot_cbk, + "Deactivate snapshot volume." + }, { NULL, NULL, NULL } }; diff --git a/cli/src/cli-rpc-ops.c b/cli/src/cli-rpc-ops.c index 47614323e3e..f174e27e46d 100644 --- a/cli/src/cli-rpc-ops.c +++ b/cli/src/cli-rpc-ops.c @@ -8544,7 +8544,55 @@ gf_cli_snapshot_cbk (struct rpc_req *req, struct iovec *iov, ret = 0; break; + case GF_SNAP_OPTION_TYPE_ACTIVATE: + /* TODO: Check if rsp.op_ret needs to be checked here. Or is + * it ok to check this in the start of the function where we + * get rsp.*/ + if (rsp.op_ret) { + cli_err("snapshot activate: failed: %s", + rsp.op_errstr ? rsp.op_errstr : + "Please check log file for details"); + ret = rsp.op_ret; + goto out; + } + + ret = dict_get_str (dict, "snapname", &snap_name); + if (ret) { + gf_log ("cli", GF_LOG_ERROR, + "Failed to get snap name"); + goto out; + } + + cli_out ("Snapshot activate: %s: Snap activated " + "successfully", snap_name); + + ret = 0; + break; + case GF_SNAP_OPTION_TYPE_DEACTIVATE: + /* TODO: Check if rsp.op_ret needs to be checked here. Or is + * it ok to check this in the start of the function where we + * get rsp.*/ + if (rsp.op_ret) { + cli_err("snapshot deactivate: failed: %s", + rsp.op_errstr ? rsp.op_errstr : + "Please check log file for details"); + ret = rsp.op_ret; + goto out; + } + + ret = dict_get_str (dict, "snapname", &snap_name); + if (ret) { + gf_log ("cli", GF_LOG_ERROR, + "Failed to get snap name"); + goto out; + } + + cli_out ("Snapshot deactivate: %s: Snap deactivated " + "successfully", snap_name); + + ret = 0; + break; case GF_SNAP_OPTION_TYPE_INFO: if (rsp.op_ret) { cli_err ("Snapshot info : failed: %s", diff --git a/rpc/xdr/src/cli1-xdr.x b/rpc/xdr/src/cli1-xdr.x index 0e4e0376e88..2b68cc26068 100644 --- a/rpc/xdr/src/cli1-xdr.x +++ b/rpc/xdr/src/cli1-xdr.x @@ -142,8 +142,8 @@ enum gf1_cli_snapshot { GF_SNAP_OPTION_TYPE_CREATE, GF_SNAP_OPTION_TYPE_DELETE, GF_SNAP_OPTION_TYPE_RESTORE, - GF_SNAP_OPTION_TYPE_START, - GF_SNAP_OPTION_TYPE_STOP, + GF_SNAP_OPTION_TYPE_ACTIVATE, + GF_SNAP_OPTION_TYPE_DEACTIVATE, GF_SNAP_OPTION_TYPE_LIST, GF_SNAP_OPTION_TYPE_STATUS, GF_SNAP_OPTION_TYPE_CONFIG, @@ -152,8 +152,8 @@ enum gf1_cli_snapshot { enum gf1_cli_snapshot_info { GF_SNAP_INFO_TYPE_ALL = 0, - GF_SNAP_INFO_TYPE_SNAP = 1, - GF_SNAP_INFO_TYPE_VOL = 2 + GF_SNAP_INFO_TYPE_SNAP, + GF_SNAP_INFO_TYPE_VOL }; enum gf1_cli_snapshot_config { @@ -163,9 +163,9 @@ enum gf1_cli_snapshot_config { }; enum gf1_cli_snapshot_status { - GF_SNAP_STATUS_TYPE_ALL = 0, - GF_SNAP_STATUS_TYPE_SNAP = 1, - GF_SNAP_STATUS_TYPE_VOL = 2 + GF_SNAP_STATUS_TYPE_ALL = 0, + GF_SNAP_STATUS_TYPE_SNAP, + GF_SNAP_STATUS_TYPE_VOL }; struct gf_cli_req { diff --git a/tests/basic/volume-snapshot.t b/tests/basic/volume-snapshot.t index e6c47f0d527..30dfbbca195 100755 --- a/tests/basic/volume-snapshot.t +++ b/tests/basic/volume-snapshot.t @@ -28,6 +28,26 @@ function create_snapshots() { wait $PID_1 $PID_2 } +function activate_snapshots() { + $CLI_1 snapshot activate ${V0}_snap & + PID_1=$! + + $CLI_1 snapshot activate ${V1}_snap & + PID_2=$! + + wait $PID_1 $PID_2 +} + +function deactivate_snapshots() { + $CLI_1 snapshot deactivate ${V0}_snap & + PID_1=$! + + $CLI_1 snapshot deactivate ${V1}_snap & + PID_2=$! + + wait $PID_1 $PID_2 +} + function delete_snapshots() { $CLI_1 snapshot delete ${V0}_snap & PID_1=$! @@ -68,6 +88,20 @@ EXPECT 'Started' volinfo_field $V1 'Status'; #Snapshot Operations create_snapshots + +EXPECT 'Started' snapshot_status ${V0}_snap; +EXPECT 'Started' snapshot_status ${V1}_snap; + +deactivate_snapshots + +EXPECT 'Stopped' snapshot_status ${V0}_snap; +EXPECT 'Stopped' snapshot_status ${V1}_snap; + +activate_snapshots + +EXPECT 'Started' snapshot_status ${V0}_snap; +EXPECT 'Started' snapshot_status ${V1}_snap; + TEST snapshot_exists 1 ${V0}_snap TEST snapshot_exists 1 ${V1}_snap TEST $CLI_1 snapshot config $V0 snap-max-hard-limit 100 diff --git a/tests/snapshot.rc b/tests/snapshot.rc index 37c250344f1..a208fa3d410 100755 --- a/tests/snapshot.rc +++ b/tests/snapshot.rc @@ -286,6 +286,19 @@ function snapshot_n_exists() { return $ret } +#Check for the status of snapshot for a volume +#Arg1 : <Snap Name> +function snapshot_status() +{ + local snap=$1; + + #TODO: Right now just fetches the status of the single snap volume. + #When snapshot will have multiple snap volumes, should have a + #cummulative logic for status + $CLI_1 snapshot info $snap | grep "Status" | sed 's/.*: //'; +} + + # TODO: Cleanup code duplication function volinfo_field() { diff --git a/xlators/mgmt/glusterd/src/glusterd-snapshot.c b/xlators/mgmt/glusterd/src/glusterd-snapshot.c index 9c64fe2d61a..73723422bc7 100644 --- a/xlators/mgmt/glusterd/src/glusterd-snapshot.c +++ b/xlators/mgmt/glusterd/src/glusterd-snapshot.c @@ -2854,16 +2854,6 @@ glusterd_handle_snapshot_status (rpcsvc_request_t *req, glusterd_op_t op, } } - /* Volume lock is not necessary for snapshot status, hence - * turning it off - */ - ret = dict_set_int8 (dict, "hold_vol_locks", 0); - if (ret) { - gf_log (this->name, GF_LOG_ERROR, "Setting volume lock " - "flag failed"); - goto out; - } - ret = glusterd_mgmt_v3_initiate_snap_phases (req, op, dict); if (ret) { gf_log (this->name, GF_LOG_ERROR, "Failed to initiate " @@ -3751,35 +3741,13 @@ glusterd_do_snap_vol (glusterd_volinfo_t *origin_vol, glusterd_snap_t *snap, goto out; } - list_for_each_entry (brickinfo, &snap_vol->bricks, brick_list) { - if (uuid_compare (brickinfo->uuid, MY_UUID)) - continue; + /*Starting the snap volume without GF_CLI_FLAG_OP_FORCE option*/ + ret = glusterd_start_volume (snap_vol, 0); - if (brickinfo->snap_status == -1) { - gf_log (this->name, GF_LOG_INFO, - "not starting snap brick %s:%s for " - "for the snap %s (volume: %s)", - brickinfo->hostname, brickinfo->path, - snap->snapname, origin_vol->volname); - continue; - } - - ret = glusterd_brick_start (snap_vol, brickinfo, _gf_true); - if (ret) { - gf_log (this->name, GF_LOG_WARNING, "starting the " - "brick %s:%s for the snap %s (volume: %s) " - "failed", brickinfo->hostname, brickinfo->path, - snap->snapname, origin_vol->volname); - goto out; - } - } - - snap_vol->status = GLUSTERD_STATUS_STARTED; - ret = glusterd_store_volinfo (snap_vol, - GLUSTERD_VOLINFO_VER_AC_INCREMENT); if (ret) { gf_log (this->name, GF_LOG_ERROR, - "Failed to store snap volinfo"); + "Failed to activate snap volume %s of the snap %s", + snap_vol->volname, snap->snapname); goto out; } @@ -3794,6 +3762,105 @@ out: return snap_vol; } +/*This is the prevalidate function for both activate and deactive of snap + * For Activate operation pass is_op_activate as _gf_true + * For Deactivate operation pass is_op_activate as _gf_false + * */ +int +glusterd_snapshot_activate_deactivate_prevalidate (dict_t *dict, + char **op_errstr, dict_t *rsp_dict, gf_boolean_t is_op_activate) +{ + int32_t ret = -1; + char *snapname = NULL; + xlator_t *this = NULL; + glusterd_snap_t *snap = NULL; + glusterd_volinfo_t *snap_volinfo = NULL; + char err_str[PATH_MAX] = ""; + gf_loglevel_t loglevel = GF_LOG_ERROR; + glusterd_volume_status volume_status = GLUSTERD_STATUS_STOPPED; + int flags = 0; + + this = THIS; + + if (!dict || !op_errstr) { + gf_log (this->name, GF_LOG_ERROR, "input parameters NULL"); + goto out; + } + + ret = dict_get_str (dict, "snapname", &snapname); + if (ret) { + gf_log (this->name, GF_LOG_ERROR, "Getting the snap name " + "failed"); + goto out; + } + + snap = glusterd_find_snap_by_name (snapname); + if (!snap) { + snprintf (err_str, sizeof (err_str), "Snap %s does not exist.", + snapname); + ret = -1; + goto out; + } + + /*If its activation of snap then fetch the flags*/ + if (is_op_activate) { + ret = dict_get_int32 (dict, "flags", &flags); + if (ret) { + gf_log (this->name, GF_LOG_ERROR, + "Unable to get flags"); + goto out; + } + } + + /* TODO : As of now there is only volume in snapshot. + * Change this when multiple volume snapshot is introduced + */ + snap_volinfo = list_entry (snap->volumes.next, glusterd_volinfo_t, + vol_list); + if (!snap_volinfo) { + gf_log (this->name, GF_LOG_ERROR, + "Unable to fetch snap_volinfo"); + ret = -1; + goto out; + } + + /*TODO: When multiple snapvolume are involved a cummulative + * logic is required to tell whether is snapshot is + * started/partially started/stopped*/ + if (is_op_activate) { + volume_status = GLUSTERD_STATUS_STARTED; + } + + if (snap_volinfo->status == volume_status) { + if (is_op_activate) { + /* if flag is to GF_CLI_FLAG_OP_FORCE + * try to start the snap volume, even + * if the volume_status is GLUSTERD_STATUS_STARTED. + * By doing so we try to bring + * back the brick processes that are down*/ + if (!(flags & GF_CLI_FLAG_OP_FORCE)) { + snprintf (err_str, sizeof (err_str), + "Snap %s is already activated.", snapname); + ret = -1; + } + } else { + snprintf (err_str, sizeof (err_str), + "Snap %s is already deactivated.", snapname); + ret = -1; + } + goto out; + } + ret = 0; +out: + + if (ret && err_str[0] != '\0') { + gf_log (this->name, loglevel, "%s", err_str); + *op_errstr = gf_strdup (err_str); + } + + return ret; +} + /* This is a snapshot remove handler function. This function will be * executed in the originator node. This function is responsible for * calling mgmt v3 framework to do the actual remove on all the bricks @@ -4009,6 +4076,134 @@ out: } int32_t +glusterd_snapshot_activate_commit (dict_t *dict, char **op_errstr, + dict_t *rsp_dict) +{ + int32_t ret = -1; + char *snapname = NULL; + glusterd_snap_t *snap = NULL; + glusterd_volinfo_t *snap_volinfo = NULL; + xlator_t *this = NULL; + int flags = 0; + + this = THIS; + GF_ASSERT (this); + GF_ASSERT (dict); + GF_ASSERT (rsp_dict); + GF_ASSERT (op_errstr); + + if (!dict || !op_errstr) { + gf_log (this->name, GF_LOG_ERROR, "input parameters NULL"); + goto out; + } + + ret = dict_get_str (dict, "snapname", &snapname); + if (ret) { + gf_log (this->name, GF_LOG_ERROR, "Getting the snap name " + "failed"); + goto out; + } + + ret = dict_get_int32 (dict, "flags", &flags); + if (ret) { + gf_log (this->name, GF_LOG_ERROR, "Unable to get flags"); + goto out; + } + + snap = glusterd_find_snap_by_name (snapname); + if (!snap) { + gf_log (this->name, GF_LOG_ERROR, "Snap %s does not exist", + snapname); + ret = -1; + goto out; + } + + /* TODO : As of now there is only volume in snapshot. + * Change this when multiple volume snapshot is introduced + */ + snap_volinfo = list_entry (snap->volumes.next, glusterd_volinfo_t, + vol_list); + if (!snap_volinfo) { + gf_log (this->name, GF_LOG_ERROR, + "Unable to fetch snap_volinfo"); + ret = -1; + goto out; + } + + ret = glusterd_start_volume (snap_volinfo, flags); + + if (ret) { + gf_log (this->name, GF_LOG_ERROR, + "Failed to activate snap volume %s of the snap %s", + snap_volinfo->volname, snap->snapname); + goto out; + } + ret = 0; +out: + return ret; +} + +int32_t +glusterd_snapshot_deactivate_commit (dict_t *dict, char **op_errstr, + dict_t *rsp_dict) +{ + int32_t ret = -1; + char *snapname = NULL; + glusterd_snap_t *snap = NULL; + glusterd_volinfo_t *snap_volinfo = NULL; + xlator_t *this = NULL; + + this = THIS; + GF_ASSERT (this); + GF_ASSERT (dict); + GF_ASSERT (rsp_dict); + GF_ASSERT (op_errstr); + + if (!dict || !op_errstr) { + gf_log (this->name, GF_LOG_ERROR, "input parameters NULL"); + goto out; + } + + ret = dict_get_str (dict, "snapname", &snapname); + if (ret) { + gf_log (this->name, GF_LOG_ERROR, "Getting the snap name " + "failed"); + goto out; + } + + snap = glusterd_find_snap_by_name (snapname); + if (!snap) { + gf_log (this->name, GF_LOG_ERROR, "Snap %s does not exist", + snapname); + ret = -1; + goto out; + } + + /* TODO : As of now there is only volume in snapshot. + * Change this when multiple volume snapshot is introduced + */ + snap_volinfo = list_entry (snap->volumes.next, glusterd_volinfo_t, + vol_list); + if (!snap_volinfo) { + gf_log (this->name, GF_LOG_ERROR, + "Unable to fetch snap_volinfo"); + ret = -1; + goto out; + } + + ret = glusterd_stop_volume (snap_volinfo); + if (ret) { + gf_log (this->name, GF_LOG_ERROR, "Failed to deactivate" + "snap %s", snapname); + goto out; + } + + ret = 0; +out: + return ret; +} + +int32_t glusterd_snapshot_remove_commit (dict_t *dict, char **op_errstr, dict_t *rsp_dict) { @@ -5220,6 +5415,27 @@ glusterd_snapshot (dict_t *dict, char **op_errstr, dict_t *rsp_dict) } break; + case GF_SNAP_OPTION_TYPE_ACTIVATE: + ret = glusterd_snapshot_activate_commit (dict, op_errstr, + rsp_dict); + if (ret) { + gf_log (this->name, GF_LOG_WARNING, "Failed to " + "activate snapshot"); + goto out; + } + + break; + + case GF_SNAP_OPTION_TYPE_DEACTIVATE: + ret = glusterd_snapshot_deactivate_commit (dict, op_errstr, + rsp_dict); + if (ret) { + gf_log (this->name, GF_LOG_WARNING, "Failed to " + "deactivate snapshot"); + goto out; + } + + break; case GF_SNAP_OPTION_TYPE_STATUS: ret = glusterd_snapshot_status_commit (dict, op_errstr, @@ -5395,6 +5611,25 @@ glusterd_snapshot_prevalidate (dict_t *dict, char **op_errstr, goto out; } break; + + case GF_SNAP_OPTION_TYPE_ACTIVATE: + ret = glusterd_snapshot_activate_deactivate_prevalidate (dict, + op_errstr, rsp_dict, _gf_true); + if (ret) { + gf_log (this->name, GF_LOG_WARNING, "Snapshot activate " + "validation failed"); + goto out; + } + break; + case GF_SNAP_OPTION_TYPE_DEACTIVATE: + ret = glusterd_snapshot_activate_deactivate_prevalidate (dict, + op_errstr, rsp_dict, _gf_false); + if (ret) { + gf_log (this->name, GF_LOG_WARNING, + "Snapshot deactivate validation failed"); + goto out; + } + break; case GF_SNAP_OPTION_TYPE_DELETE: ret = glusterd_snapshot_remove_prevalidate (dict, op_errstr, rsp_dict); @@ -5457,7 +5692,6 @@ glusterd_snapshot_postvalidate (dict_t *dict, int32_t op_ret, char **op_errstr, goto out; } break; - case GF_SNAP_OPTION_TYPE_DELETE: case GF_SNAP_OPTION_TYPE_RESTORE: ret = glusterd_snapshot_update_snaps_post_validate (dict, @@ -5469,7 +5703,12 @@ glusterd_snapshot_postvalidate (dict_t *dict, int32_t op_ret, char **op_errstr, goto out; } break; - + case GF_SNAP_OPTION_TYPE_ACTIVATE: + case GF_SNAP_OPTION_TYPE_DEACTIVATE: + /*Nothing to be done. But want to + * avoid the default case warning*/ + ret = 0; + break; default: gf_log (this->name, GF_LOG_WARNING, "invalid snap command"); goto out; @@ -5603,8 +5842,22 @@ glusterd_handle_snapshot_fn (rpcsvc_request_t *req) "failed: %s", err_str); } break; - case GF_SNAP_OPTION_TYPE_START: - case GF_SNAP_OPTION_TYPE_STOP: + case GF_SNAP_OPTION_TYPE_ACTIVATE: + ret = glusterd_mgmt_v3_initiate_snap_phases (req, cli_op, + dict); + if (ret) { + gf_log (this->name, GF_LOG_WARNING, + "Snapshot activate failed: %s", err_str); + } + break; + case GF_SNAP_OPTION_TYPE_DEACTIVATE: + ret = glusterd_mgmt_v3_initiate_snap_phases (req, cli_op, + dict); + if (ret) { + gf_log (this->name, GF_LOG_WARNING, + "Snapshot deactivate failed: %s", err_str); + } + break; case GF_SNAP_OPTION_TYPE_STATUS: ret = glusterd_handle_snapshot_status (req, cli_op, dict, err_str, diff --git a/xlators/mgmt/glusterd/src/glusterd-volume-ops.c b/xlators/mgmt/glusterd/src/glusterd-volume-ops.c index 504aeb839bc..083c7a036ad 100644 --- a/xlators/mgmt/glusterd/src/glusterd-volume-ops.c +++ b/xlators/mgmt/glusterd/src/glusterd-volume-ops.c @@ -1737,13 +1737,58 @@ out: } int +glusterd_start_volume (glusterd_volinfo_t *volinfo, int flags) + +{ + int ret = 0; + glusterd_brickinfo_t *brickinfo = NULL; + xlator_t *this = NULL; + glusterd_volinfo_ver_ac_t verincrement = 0; + + this = THIS; + GF_ASSERT (this); + GF_ASSERT (volinfo); + + list_for_each_entry (brickinfo, &volinfo->bricks, brick_list) { + ret = glusterd_brick_start (volinfo, brickinfo, _gf_true); + /* If 'force' try to start all bricks regardless of success or + * failure + */ + if (!(flags & GF_CLI_FLAG_OP_FORCE) && ret) + goto out; + } + + /* Increment the volinfo version only if there is a + * change in status. Force option can be used to start + * dead bricks even if the volume is in started state. + * In such case volume status will be GLUSTERD_STATUS_STARTED. + * Therefore we should not increment the volinfo version.*/ + if (GLUSTERD_STATUS_STARTED != volinfo->status) { + verincrement = GLUSTERD_VOLINFO_VER_AC_INCREMENT; + } else { + verincrement = GLUSTERD_VOLINFO_VER_AC_NONE; + } + + glusterd_set_volume_status (volinfo, GLUSTERD_STATUS_STARTED); + + ret = glusterd_store_volinfo (volinfo, verincrement); + if (ret) { + gf_log (this->name, GF_LOG_ERROR, "Failed to store volinfo of " + "%s volume", volinfo->volname); + goto out; + } +out: + gf_log (this->name, GF_LOG_TRACE, "returning %d ", ret); + return ret; +} + +int glusterd_op_start_volume (dict_t *dict, char **op_errstr) { int ret = 0; char *volname = NULL; int flags = 0; glusterd_volinfo_t *volinfo = NULL; - glusterd_brickinfo_t *brickinfo = NULL; xlator_t *this = NULL; this = THIS; @@ -1760,25 +1805,15 @@ glusterd_op_start_volume (dict_t *dict, char **op_errstr) goto out; } - list_for_each_entry (brickinfo, &volinfo->bricks, brick_list) { - ret = glusterd_brick_start (volinfo, brickinfo, _gf_true); - /* If 'force' try to start all bricks regardless of success or - * failure - */ - if (!(flags & GF_CLI_FLAG_OP_FORCE) && ret) - goto out; - } + ret = glusterd_start_volume (volinfo, flags); - glusterd_set_volume_status (volinfo, GLUSTERD_STATUS_STARTED); - - ret = glusterd_store_volinfo (volinfo, GLUSTERD_VOLINFO_VER_AC_INCREMENT); if (ret) goto out; ret = glusterd_nodesvcs_handle_graph_change (volinfo); out: - gf_log (this->name, GF_LOG_DEBUG, "returning %d ", ret); + gf_log (this->name, GF_LOG_TRACE, "returning %d ", ret); return ret; } diff --git a/xlators/mgmt/glusterd/src/glusterd.h b/xlators/mgmt/glusterd/src/glusterd.h index 7e300d93f4d..2496a4d1182 100644 --- a/xlators/mgmt/glusterd/src/glusterd.h +++ b/xlators/mgmt/glusterd/src/glusterd.h @@ -941,6 +941,7 @@ int glusterd_op_statedump_volume_args_get (dict_t *dict, char **volname, int glusterd_op_gsync_args_get (dict_t *dict, char **op_errstr, char **master, char **slave, char **host_uuid); +int glusterd_start_volume (glusterd_volinfo_t *volinfo, int flags); int glusterd_stop_volume (glusterd_volinfo_t *volinfo); /* Synctask part */ |