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