summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJoseph Fernandes <josferna@redhat.com>2014-04-14 19:18:41 +0530
committerVijay Bellur <vbellur@redhat.com>2014-05-02 09:27:46 -0700
commit0f56f0ce2d2e18fbb2eedf14e93b5a592f0005c3 (patch)
treee5cca809f024f8e31433bd5a8d22ae352b574a0e
parentb189bb33edc2582e53923dec51bdef0f118c3d36 (diff)
glusterd/snapshot: Activation and De-activation of snapshot
Previously, snapshots by default were activated on creation and there was no option to activate or deactivate them on demand. This will allow the user to activate and deactivate on demand. The CLI goes as follows 1) Activate the snap using a command "gluster snapshot activate <snapname> [force]" 2) Deactivate the snap using a command "gluster snapshot deactivate <snapname>" Note: Even now the snapshot will be activated during creation. Change-Id: I0946d800780f26c63fa1fcaf29aabc900140448f BUG: 1061685 Signed-off-by: Joseph Fernandes <josferna@redhat.com> Reviewed-on: http://review.gluster.org/7476 Tested-by: Gluster Build System <jenkins@build.gluster.com> Reviewed-by: Vijaikumar Mallikarjuna <vmallika@redhat.com> Reviewed-by: Vijay Bellur <vbellur@redhat.com>
-rw-r--r--cli/src/cli-cmd-parser.c156
-rw-r--r--cli/src/cli-cmd-snapshot.c8
-rw-r--r--cli/src/cli-rpc-ops.c48
-rw-r--r--rpc/xdr/src/cli1-xdr.x14
-rwxr-xr-xtests/basic/volume-snapshot.t34
-rwxr-xr-xtests/snapshot.rc13
-rw-r--r--xlators/mgmt/glusterd/src/glusterd-snapshot.c333
-rw-r--r--xlators/mgmt/glusterd/src/glusterd-volume-ops.c61
-rw-r--r--xlators/mgmt/glusterd/src/glusterd.h1
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 */