summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-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 */