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>
This commit is contained in:
Joseph Fernandes 2014-04-14 19:18:41 +05:30 committed by Vijay Bellur
parent b189bb33ed
commit 0f56f0ce2d
9 changed files with 601 additions and 67 deletions

View File

@ -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;

View File

@ -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 }
};

View File

@ -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",

View File

@ -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 {

View File

@ -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

View File

@ -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()
{

View File

@ -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
@ -4008,6 +4075,134 @@ out:
return ret;
}
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)
@ -5219,6 +5414,27 @@ glusterd_snapshot (dict_t *dict, char **op_errstr, dict_t *rsp_dict)
goto out;
}
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:
@ -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,

View File

@ -1736,6 +1736,52 @@ out:
return ret;
}
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)
{
@ -1743,7 +1789,6 @@ glusterd_op_start_volume (dict_t *dict, char **op_errstr)
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;
}

View File

@ -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 */