diff options
| -rw-r--r-- | cli/src/cli-cmd-parser.c | 73 | ||||
| -rw-r--r-- | cli/src/cli-cmd-snapshot.c | 2 | ||||
| -rw-r--r-- | cli/src/cli-rpc-ops.c | 216 | ||||
| -rw-r--r-- | rpc/xdr/src/cli1-xdr.x | 6 | ||||
| -rw-r--r-- | tests/bugs/bug-1087203.t | 61 | ||||
| -rw-r--r-- | tests/bugs/bug-1112613.t | 49 | ||||
| -rwxr-xr-x | tests/snapshot.rc | 66 | ||||
| -rw-r--r-- | xlators/mgmt/glusterd/src/glusterd-snapshot.c | 211 | 
8 files changed, 588 insertions, 96 deletions
diff --git a/cli/src/cli-cmd-parser.c b/cli/src/cli-cmd-parser.c index b4dc3fe49bd..4811293dbb8 100644 --- a/cli/src/cli-cmd-parser.c +++ b/cli/src/cli-cmd-parser.c @@ -3422,7 +3422,7 @@ cli_snap_info_parse (dict_t *dict, const char **words, int wordcount)          GF_ASSERT (dict);          if (wordcount > 4 || wordcount < cmdi) { -                gf_log ("", GF_LOG_ERROR, "Invalid syntax"); +                gf_log ("cli", GF_LOG_ERROR, "Invalid syntax");                  goto out;          } @@ -3473,7 +3473,7 @@ cli_snap_info_parse (dict_t *dict, const char **words, int wordcount)          ret = dict_set_str (dict, "volname", (char *)words[wordcount - 1]);          if (ret) { -                gf_log ("", GF_LOG_ERROR, "Count not save " +                gf_log ("cli", GF_LOG_ERROR, "Could not save "                          "volume name %s", words[wordcount - 1]);                  goto out;          } @@ -3634,34 +3634,71 @@ cli_snap_delete_parse (dict_t *dict, const char **words, int wordcount,          int             ret             =       -1;          const char      *question       =       NULL; +        int32_t         cmd             =       -1; +        unsigned int    cmdi            =       2;          gf_answer_t     answer          =       GF_ANSWER_NO; -        question = "Deleting snap will erase all the information about " -                   "the snap. Do you still want to continue?"; -          GF_ASSERT (words);          GF_ASSERT (dict); -        if (wordcount != 3) { +        if (wordcount > 4 || wordcount <= cmdi) {                  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 snapname %s", -                        words[2]); -                goto out; +        question = "Deleting snap will erase all the information about " +                   "the snap. Do you still want to continue?"; + +        if (strcmp (words [cmdi], "all") == 0) { +                ret = 0; +                cmd = GF_SNAP_DELETE_TYPE_ALL; +        } else if (strcmp (words [cmdi], "volume") == 0) { +                if (++cmdi == wordcount) { +                        ret = -1; +                        gf_log ("cli", GF_LOG_ERROR, "Invalid Syntax"); +                        goto out; +                } + +                ret = dict_set_str (dict, "volname", +                                    (char *)words[cmdi]); +                if (ret) { +                        gf_log ("cli", GF_LOG_ERROR, "Could not save " +                                "volume name %s", words[wordcount - 1]); +                        goto out; +                } +                cmd = GF_SNAP_DELETE_TYPE_VOL; +        } else { +                ret = dict_set_str (dict, "snapname", (char *)words[cmdi]); +                if (ret) { +                        gf_log ("cli", GF_LOG_ERROR, "Unable to save " +                                "snapname %s", words[2]); +                        goto out; +                } +                cmd = GF_SNAP_DELETE_TYPE_SNAP;          } -        answer = cli_cmd_get_confirmation (state, question); -        if (GF_ANSWER_NO == answer) { -                ret = 1; -                gf_log ("cli", GF_LOG_DEBUG, "User cancelled " -                        "snapshot delete operation for snap %s", -                        (char *)words[2]); +        if ((cmdi + 1) != wordcount) { +                ret = -1; +                gf_log ("cli", GF_LOG_ERROR, "Invalid Syntax");                  goto out;          } + +        if (cmd == GF_SNAP_DELETE_TYPE_SNAP) { +                answer = cli_cmd_get_confirmation (state, question); +                if (GF_ANSWER_NO == answer) { +                        ret = 1; +                        gf_log ("cli", GF_LOG_DEBUG, "User cancelled " +                                "snapshot delete operation for snap %s", +                                (char *)words[2]); +                        goto out; +                } +        } + +        ret = dict_set_int32 (dict, "delete-cmd", cmd); +        if (ret) { +                gf_log ("cli", GF_LOG_ERROR, "Could not save " +                        "type of snapshot delete"); +        }  out:          return ret;  } @@ -4000,7 +4037,7 @@ cli_cmd_snapshot_parse (const char **words, int wordcount, dict_t **options,                                          "activate", "deactivate", "list",                                          "status", "config", "info", NULL};          char               *invalid_snapnames[] = {"description", "force", -                                                  "volume", NULL}; +                                                  "volume", "all", NULL};          GF_ASSERT (words);          GF_ASSERT (options); diff --git a/cli/src/cli-cmd-snapshot.c b/cli/src/cli-cmd-snapshot.c index 1fb4e5e634c..07d04595b06 100644 --- a/cli/src/cli-cmd-snapshot.c +++ b/cli/src/cli-cmd-snapshot.c @@ -108,7 +108,7 @@ struct cli_cmd snapshot_cmds[] = {            cli_cmd_snapshot_cbk,            "Snapshot Config."          }, -        {"snapshot delete <snapname>", +        {"snapshot delete (all | snapname | volume <volname>)",            cli_cmd_snapshot_cbk,            "Snapshot Delete."          }, diff --git a/cli/src/cli-rpc-ops.c b/cli/src/cli-rpc-ops.c index a240f376f7f..268f5434a75 100644 --- a/cli/src/cli-rpc-ops.c +++ b/cli/src/cli-rpc-ops.c @@ -7721,11 +7721,14 @@ out:  }  int32_t -cli_snapshot_remove_reply (gf_cli_rsp *rsp, dict_t *dict) +cli_snapshot_remove_reply (gf_cli_rsp *rsp, dict_t *dict, call_frame_t *frame)  { -        int32_t       ret        = -1; -        char         *snap_name  = NULL; +        int32_t         ret             = -1; +        char            *snap_name      = NULL; +        int32_t         delete_cmd      = -1; +        cli_local_t     *local          = NULL; +        GF_ASSERT (frame);          GF_ASSERT (rsp);          GF_ASSERT (dict); @@ -7737,6 +7740,31 @@ cli_snapshot_remove_reply (gf_cli_rsp *rsp, dict_t *dict)                  goto out;          } +        ret = dict_get_int32 (dict, "delete-cmd", &delete_cmd); +        if (ret) { +                gf_log ("cli", GF_LOG_ERROR, "Could not get delete-cmd"); +                goto out; +        } + +        if (delete_cmd == GF_SNAP_DELETE_TYPE_ALL || +            delete_cmd == GF_SNAP_DELETE_TYPE_VOL) { +                local = ((call_frame_t *) frame) -> local; +                if (!local) { +                        ret = -1; +                        gf_log ("cli", GF_LOG_ERROR, "frame->local is NULL"); +                        goto out; +                } + +                /* During first call back of snapshot delete of type +                 * ALL and VOL, We will get the snapcount and snapnames. +                 * Hence to make the subsequent rpc calls for individual +                 * snapshot delete, We need to save it in local dictionary. +                 */ +                dict_copy (dict, local->dict); +                ret = 0; +                goto out; +        } +          ret = dict_get_str (dict, "snapname", &snap_name);          if (ret) {                  gf_log ("cli", GF_LOG_ERROR, "Failed to get snapname"); @@ -8455,6 +8483,60 @@ out:          return ret;  } +int32_t +cli_populate_req_dict_for_delete (dict_t *snap_dict, dict_t *dict, size_t index) +{ +        int32_t         ret             = -1; +        char            key[PATH_MAX]   = ""; +        char            *buffer         = NULL; +        int             type            = 0; +        int             snapcount       = 0; + +        GF_ASSERT (snap_dict); +        GF_ASSERT (dict); + +        ret = dict_set_int32 (snap_dict, "delete-cmd", +                              GF_SNAP_DELETE_TYPE_SNAP); +        if (ret) { +                gf_log ("cli", GF_LOG_ERROR, "Could not save command " +                        "type in snap dictionary"); +                goto out; +        } + +        ret = snprintf (key, sizeof (key), "snapname%lu", index); +        if (ret < 0) { +                goto out; +        } + +        ret = dict_get_str (dict, key, &buffer); +        if (ret) { +                gf_log ("cli", GF_LOG_ERROR, "Failed to get snapname"); +                goto out; +        } + +        ret = dict_set_dynstr_with_alloc (snap_dict, "snapname", buffer); +        if (ret) { +                gf_log ("cli", GF_LOG_ERROR, "Failed to save snapname"); +                goto out; +        } + +        ret = dict_set_int32 (snap_dict, "type", GF_SNAP_OPTION_TYPE_DELETE); +        if (ret) { +                gf_log ("cli", GF_LOG_ERROR, "Failed to save command type"); +                goto out; +        } + +        ret = dict_set_dynstr_with_alloc (snap_dict, "cmd-str", +                                       "snapshot delete"); +        if (ret) { +                gf_log ("cli", GF_LOG_ERROR, +                        "Could not save command string as delete"); +                goto out; +        } +out: +        return ret; +} +  int  cli_populate_req_dict_for_status (dict_t *snap_dict, dict_t *dict, int index) {          int             ret             =       -1; @@ -8820,7 +8902,7 @@ gf_cli_snapshot_cbk (struct rpc_req *req, struct iovec *iov,                  break;          case GF_SNAP_OPTION_TYPE_DELETE: -                ret = cli_snapshot_remove_reply (&rsp, dict); +                ret = cli_snapshot_remove_reply (&rsp, dict, frame);                  if (ret) {                          gf_log ("cli", GF_LOG_ERROR,                                  "Failed to delete snap"); @@ -8854,6 +8936,123 @@ out:  }  int32_t +gf_cli_snapshot_for_delete (call_frame_t *frame, xlator_t *this, +                            void *data) +{ +        gf_cli_req      req                     = {{0,}}; +        dict_t          *options                = NULL; +        int32_t         ret                     = -1; +        int32_t         cmd                     = -1; +        cli_local_t     *local                  = NULL; +        dict_t          *snap_dict              = NULL; +        int32_t         snapcount               = 0; +        int             i                       = 0; +        char            question[PATH_MAX]      = ""; +        char            *volname                = NULL; +        gf_answer_t     answer                  = GF_ANSWER_NO; + +        GF_VALIDATE_OR_GOTO ("cli", frame,  out); +        GF_VALIDATE_OR_GOTO ("cli", frame->local, out); +        GF_VALIDATE_OR_GOTO ("cli", this, out); +        GF_VALIDATE_OR_GOTO ("cli", data, out); + +        local = frame->local; + +        options = data; + +        ret = dict_get_int32 (local->dict, "delete-cmd", &cmd); +        if (ret) { +                gf_log ("cli", GF_LOG_ERROR, "Failed to get " +                        "delete-cmd"); +                goto out; +        } + +        /* No need multiple RPCs for individual snapshot delete*/ +        if (cmd == GF_SNAP_DELETE_TYPE_SNAP) { +                ret = 0; +                goto out; +        } + +        ret = dict_get_int32 (local->dict, "snapcount", +                              &snapcount); +        if (ret) { +                gf_log ("cli", GF_LOG_ERROR, "Could not get " +                        "snapcount"); +                goto out; +        } + +        if (snapcount == 0) { +                cli_out ("No snapshots present"); +                goto out; +        } + +        if (cmd == GF_SNAP_DELETE_TYPE_ALL) { +                snprintf (question, sizeof (question), "System contains %d " +                          "snapshot(s).\nDo you still " +                          "want to continue and delete them? ", +                           snapcount); +        } else { +                ret = dict_get_str (local->dict, "volname", &volname); +                if (ret) { +                        gf_log ("cli", GF_LOG_ERROR, "Failed to fetch " +                                "volname from local dictionary"); +                        goto out; +                } + +                snprintf (question, sizeof (question), "Volume (%s) contains " +                          "%d snapshot(s).\nDo you still want to " +                           "continue and delete them? ", volname, +                           snapcount); +        } + +        answer = cli_cmd_get_confirmation (global_state, question); +        if (GF_ANSWER_NO == answer) { +                ret = 0; +                gf_log ("cli", GF_LOG_DEBUG, "User cancelled " +                        "snapshot delete operation for snap delete"); +                goto out; +        } + +        for (i = 1 ; i <= snapcount ; i++) { +                ret = -1; + +                snap_dict = dict_new(); +                if (!snap_dict) +                        goto out; + +                ret = cli_populate_req_dict_for_delete (snap_dict, +                                                       local->dict, i); +                if (ret) { +                        gf_log ("cli", GF_LOG_ERROR, "Could not " +                                "populate snap request dictionary"); +                        goto out; +                } + +                ret = cli_to_glusterd (&req, frame, +                                gf_cli_snapshot_cbk, +                                (xdrproc_t) xdr_gf_cli_req, snap_dict, +                                GLUSTER_CLI_SNAP, this, cli_rpc_prog, +                                NULL); +                if (ret) { +                        /* Fail the operation if deleting one of the +                         * snapshots is failed +                         */ +                        gf_log ("cli", GF_LOG_ERROR, "cli_to_glusterd " +                                "for snapshot delete failed"); +                        goto out; +                } +                dict_unref (snap_dict); +                snap_dict = NULL; +        } + +out: +        if (snap_dict) +                dict_unref (snap_dict); + +        return ret; +} + +int32_t  gf_cli_snapshot_for_status (call_frame_t *frame, xlator_t *this,                              void *data)  { @@ -9007,6 +9206,15 @@ gf_cli_snapshot (call_frame_t *frame, xlator_t *this,                  }          } +        if (GF_SNAP_OPTION_TYPE_DELETE == type) { +                ret = gf_cli_snapshot_for_delete (frame, this, data); +                if (ret) { +                        gf_log ("cli", GF_LOG_ERROR, "cli to glusterd " +                                "for snapshot delete command failed"); +                        goto out; +                } +        } +          ret = 0;  out: diff --git a/rpc/xdr/src/cli1-xdr.x b/rpc/xdr/src/cli1-xdr.x index 3a9841934cb..f7bfcf469d5 100644 --- a/rpc/xdr/src/cli1-xdr.x +++ b/rpc/xdr/src/cli1-xdr.x @@ -172,6 +172,12 @@ enum  gf1_cli_snapshot_status {          GF_SNAP_STATUS_TYPE_VOL  }; +enum gf1_cli_snapshot_delete { +        GF_SNAP_DELETE_TYPE_ALL  = 0, +        GF_SNAP_DELETE_TYPE_SNAP = 1, +        GF_SNAP_DELETE_TYPE_VOL  = 2 +}; +  struct gf_cli_req {          opaque  dict<>;  }; diff --git a/tests/bugs/bug-1087203.t b/tests/bugs/bug-1087203.t index 585ecf440ac..e41d601fb66 100644 --- a/tests/bugs/bug-1087203.t +++ b/tests/bugs/bug-1087203.t @@ -5,50 +5,12 @@  . $(dirname $0)/../snapshot.rc  . $(dirname $0)/../cluster.rc -function config_validate () -{ -        local var=$1 -        $CLI_1 snapshot config | grep "^$var" | sed 's/.*: //' -} - -function snap_create () -{ -        local limit=$1; -        local i=0 -        while [ $i -lt $limit ] -        do -                $CLI_1 snapshot create snap$i ${V0} -                i=$[$i+1] -        done -} - -function snap_delete () -{ -        local limit=$1; -        local i=0 -        while [ $i -lt $limit ] -        do -                $CLI_1 snapshot delete snap$i -                i=$[$i+1] -        done -} - -function get_snap_count () -{ -        $CLI_1 snapshot list | wc -l -} -  function get_volume_info ()  {          local var=$1          $CLI_1 volume info $V0 | grep "^$var" | sed 's/.*: //'  } -function is_snapshot_present () -{ -        $CLI_1 snapshot list -} -  cleanup;  TEST verify_lvm_version @@ -94,7 +56,7 @@ TEST $CLI_1 snapshot config $V0 snap-max-hard-limit 10  # Validating auto-delete feature  # Make sure auto-delete is disabled by default -EXPECT 'disable' config_validate 'auto-delete' +EXPECT 'disable' snap_config CLI_1 'auto-delete'  # Test for invalid value for auto-delete  TEST ! $CLI_1 snapshot config auto-delete test @@ -103,36 +65,39 @@ TEST $CLI_1 snapshot config snap-max-hard-limit 6  TEST $CLI_1 snapshot config snap-max-soft-limit 50  # Create 4 snapshots -TEST snap_create 4; +snap_index=1 +snap_count=4 +TEST snap_create CLI_1 $V0 $snap_index $snap_count  # If auto-delete is disabled then oldest snapshot  # should not be deleted automatically. -EXPECT '4' get_snap_count; +EXPECT '4' get_snap_count CLI_1; -TEST snap_delete 4; +TEST snap_delete CLI_1 $snap_index $snap_count;  # After all those 4 snaps are deleted, There will not be any snaps present -EXPECT 'No snapshots present' is_snapshot_present; +EXPECT '0' get_snap_count CLI_1;  TEST $CLI_1 snapshot config auto-delete enable +  # auto-delete is already enabled, Hence expect a failure.  TEST ! $CLI_1 snapshot config auto-delete on  # Testing other boolean values with auto-delete  TEST $CLI_1 snapshot config auto-delete off -EXPECT 'off' config_validate 'auto-delete' +EXPECT 'off' snap_config CLI_1 'auto-delete'  TEST $CLI_1 snapshot config auto-delete true -EXPECT 'true' config_validate 'auto-delete' +EXPECT 'true' snap_config CLI_1 'auto-delete'  # Try to create 4 snaps again, As auto-delete is enabled  # oldest snap should be deleted and snapcount should be 3 -TEST snap_create 4; -EXPECT '3' get_snap_count; +TEST snap_create CLI_1 $V0 $snap_index $snap_count; +EXPECT '3' get_snap_count CLI_1;  TEST $CLI_1 snapshot config auto-delete disable -EXPECT 'disable' config_validate 'auto-delete' +EXPECT 'disable' snap_config CLI_1 'auto-delete'  cleanup; diff --git a/tests/bugs/bug-1112613.t b/tests/bugs/bug-1112613.t new file mode 100644 index 00000000000..17302eaa427 --- /dev/null +++ b/tests/bugs/bug-1112613.t @@ -0,0 +1,49 @@ +#!/bin/bash + +. $(dirname $0)/../include.rc +. $(dirname $0)/../volume.rc +. $(dirname $0)/../snapshot.rc +. $(dirname $0)/../cluster.rc + +cleanup; + +V1="patchy2" + +TEST verify_lvm_version; +TEST launch_cluster 2 +TEST setup_lvm 2 + +TEST $CLI_1 peer probe $H2 +EXPECT_WITHIN $PROBE_TIMEOUT 1 peer_count + +TEST $CLI_1 volume create $V0 $H1:$L1 +TEST $CLI_1 volume start $V0 +TEST $CLI_1 volume create $V1 $H2:$L2 +TEST $CLI_1 volume start $V1 + +# Create 3 snapshots for volume $V0 +snap_count=3 +snap_index=1 +TEST snap_create CLI_1 $V0 $snap_index $snap_count; + +# Create 3 snapshots for volume $V1 +snap_count=4 +snap_index=11 +TEST snap_create CLI_1 $V1 $snap_index $snap_count; + +EXPECT '3' get_snap_count CLI_1 $V0; +EXPECT '4' get_snap_count CLI_1 $V1; +EXPECT '7' get_snap_count CLI_1 + +TEST $CLI_1 snapshot delete volume $V0 +EXPECT '0' get_snap_count CLI_1 $V0; +EXPECT '4' get_snap_count CLI_1 $V1; +EXPECT '4' get_snap_count CLI_1 + +TEST $CLI_1 snapshot delete all +EXPECT '0' get_snap_count CLI_1 $V0; +EXPECT '0' get_snap_count CLI_1 $V1; +EXPECT '0' get_snap_count CLI_1 + +cleanup; + diff --git a/tests/snapshot.rc b/tests/snapshot.rc index a208fa3d410..408b5a72a0c 100755 --- a/tests/snapshot.rc +++ b/tests/snapshot.rc @@ -318,3 +318,69 @@ function volume_exists() {                  return 0          fi  } + +# arg-1 : From which node the command should be trigerred +#         Ex : $CLI_1, $CLI_2, etc. +# arg-2 : Volume name +# arg-3 : Starting index for the snapname "snap$i" +# arg-4 : Number of snapshots to be taken +function snap_create() +{ +        eval local cli_index=\$$1 +        local volname=$2 +        local i=$3 +        local limit=$[$i + $4] + +        while [ $i -lt $limit ] +        do +                $cli_index snapshot create snap$i $volname +                i=$[$i+1] +        done +} + +# arg-1 : From which node the command should be trigerred +#         Ex : $CLI_1. $CLI_2, etc. +# arg-2 : Volume name. +function get_snap_count() +{ +        eval local cli_index=\$$1 +        local volname=$2 + + +        if [ -z "$2" ] +        then +                $cli_index snapshot list | grep -v "No snapshots present"\ +                                         | wc -l +        else +                $cli_index snapshot list $volname\ +                                         | grep -v "No snapshots present"\ +                                         | wc -l +        fi +} + +# arg-1 : From which node the command should be trigerred +#         Ex : $CLI_1, $CLI_2, etc. +# arg-2 : Starting index for the snapname "snap$i" +# arg-3 : Number of snapshots to be deleted. +function snap_delete() +{ +        eval local cli_index=\$$1 +        local i=$2 +        local limit=$[$i + $3] + +        while [ $i -lt $limit ] +        do +                $cli_index snapshot delete snap$i +                i=$[$i+1] +        done +} + +# arg-1 : From which node the command should be triggered +#         Ex : $CLI_1, $CLI_2, etc. +# arg-2 : key value +function snap_config() +{ +        eval local cli_index=\$$1 +        local var=$2 +        $cli_index snapshot config | grep "^$var" | sed 's/.*: //' +} diff --git a/xlators/mgmt/glusterd/src/glusterd-snapshot.c b/xlators/mgmt/glusterd/src/glusterd-snapshot.c index f32b3140612..ae91f67fd2d 100644 --- a/xlators/mgmt/glusterd/src/glusterd-snapshot.c +++ b/xlators/mgmt/glusterd/src/glusterd-snapshot.c @@ -3123,15 +3123,10 @@ glusterd_snapshot_get_vol_snapnames (dict_t *dict, glusterd_volinfo_t *volinfo)          list_for_each_entry_safe (snap_vol, tmp_vol,                                    &volinfo->snap_volumes, snapvol_list) {                  snapcount++; -                snapname = gf_strdup (snap_vol->snapshot->snapname); -                if (!snapname) { -                        gf_log (this->name, GF_LOG_ERROR, -                                "strdup failed"); -                        ret = -1; -                        goto out; -                }                  snprintf (key, sizeof (key), "snapname%d", snapcount); -                ret = dict_set_dynstr (dict, key, snapname); + +                ret = dict_set_dynstr_with_alloc (dict, key, +                                                  snap_vol->snapshot->snapname);                  if (ret) {                          gf_log (this->name, GF_LOG_ERROR, "Failed to "                                  "set %s", key); @@ -4472,23 +4467,104 @@ out:          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 - * - * @param req           RPC request object - * @param op            gluster operation - * @param dict          dictionary containing snapshot remove request - * @param err_str       In case of an err this string should be populated - * @param len           length of err_str buffer - * - * @return              Negative value on Failure and 0 in success - */ -int -glusterd_handle_snapshot_remove (rpcsvc_request_t *req, glusterd_op_t op, -                                 dict_t *dict, char *err_str, size_t len) +int32_t +glusterd_handle_snapshot_delete_vol (dict_t *dict, char *err_str, int len)  { -        int                      ret            = -1; +        int32_t                 ret             = -1; +        int32_t                 i               = 0; +        glusterd_volinfo_t      *snap_volinfo   = NULL; +        glusterd_volinfo_t      *volinfo        = NULL; +        glusterd_volinfo_t      *temp_volinfo   = NULL; +        char                    key[PATH_MAX]   =  ""; +        xlator_t                *this           = NULL; +        char                    *volname        = NULL; + +        this = THIS; +        GF_ASSERT (this); +        GF_ASSERT (dict); + +        ret = dict_get_str (dict, "volname", &volname); +        if (ret) { +                gf_log (this->name, GF_LOG_ERROR, "Failed to get " +                        "volume name"); +                goto out; +        } + +        ret = glusterd_volinfo_find (volname, &volinfo); +        if (ret) { +                snprintf (err_str, len, "Volume (%s) does not exist", volname); +                gf_log (this->name, GF_LOG_ERROR, "Failed to get volinfo of " +                        "volume %s", volname); +                goto out; +        } + +        ret = glusterd_snapshot_get_vol_snapnames (dict, volinfo); +        if (ret) { +                gf_log (this->name, GF_LOG_ERROR, +                        "Failed to get snapshot list for volume %s", volname); +                goto out; +        } + +        ret = 0; +out: +        return ret; +} + +int32_t +glusterd_handle_snapshot_delete_all (dict_t *dict) +{ +        int32_t         ret             = -1; +        int32_t         i               =  0; +        char            key[PATH_MAX]   =  ""; +        glusterd_conf_t *priv           = NULL; +        glusterd_snap_t *snap           = NULL; +        glusterd_snap_t *tmp_snap       = NULL; +        xlator_t        *this           = NULL; + +        this = THIS; +        GF_ASSERT (this); +        priv = this->private; +        GF_ASSERT (priv); + +        GF_ASSERT (dict); + +        list_for_each_entry_safe (snap, tmp_snap, &priv->snapshots, snap_list) { +                /* indexing from 1 to n, to keep it uniform with other code +                 * paths +                 */ +                i++; +                ret = snprintf (key, sizeof (key), "snapname%d", i); +                if (ret < 0) { +                        goto out; +                } + +                ret = dict_set_dynstr_with_alloc (dict, key, snap->snapname); +                if (ret) { +                        gf_log (this->name, GF_LOG_ERROR, "Could not save " +                                "snap name"); +                        goto out; +                } +        } + +        ret = dict_set_int32 (dict, "snapcount", i); +        if (ret) { +                gf_log (this->name, GF_LOG_ERROR, "Could not save snapcount"); +                goto out; +        } + +        ret = 0; + +out: +        return ret; +} + +int32_t +glusterd_handle_snapshot_delete_type_snap (rpcsvc_request_t *req, +                                           glusterd_op_t op, +                                           dict_t *dict, char *err_str, +                                           size_t len) +{ +        int32_t                 ret             = -1;          int64_t                  volcount       = 0;          char                    *snapname       = NULL;          char                    *volname        = NULL; @@ -4499,6 +4575,7 @@ glusterd_handle_snapshot_remove (rpcsvc_request_t *req, glusterd_op_t op,          xlator_t                *this           = NULL;          this = THIS; +        GF_ASSERT (this);          GF_ASSERT (req);          GF_ASSERT (dict); @@ -4553,6 +4630,90 @@ glusterd_handle_snapshot_remove (rpcsvc_request_t *req, glusterd_op_t op,          }          ret = 0; + +out : +        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 + * + * @param req           RPC request object + * @param op            gluster operation + * @param dict          dictionary containing snapshot remove request + * @param err_str       In case of an err this string should be populated + * @param len           length of err_str buffer + * + * @return              Negative value on Failure and 0 in success + */ +int +glusterd_handle_snapshot_delete (rpcsvc_request_t *req, glusterd_op_t op, +                                 dict_t *dict, char *err_str, size_t len) +{ +        int                      ret            = -1; +        xlator_t                *this           = NULL; +        int32_t                  delete_cmd     = -1; + +        this = THIS; + +        GF_ASSERT (this); + +        GF_ASSERT (req); +        GF_ASSERT (dict); +        GF_ASSERT (err_str); + +        ret = dict_get_int32 (dict, "delete-cmd", &delete_cmd); +        if (ret) { +                gf_log (this->name, GF_LOG_ERROR, "Failed to get delete-cmd"); +                goto out; +        } + +        switch (delete_cmd) { +        case GF_SNAP_DELETE_TYPE_SNAP: +                ret = glusterd_handle_snapshot_delete_type_snap (req, op, dict, +                                                                 err_str, len); +                if (ret) { +                        gf_log (this->name, GF_LOG_ERROR, "Failed to handle " +                                "snapshot delete for type SNAP"); +                        goto out; +                } +                break; + +        case GF_SNAP_DELETE_TYPE_ALL: +                ret = glusterd_handle_snapshot_delete_all (dict); +                if (ret) { +                        gf_log (this->name, GF_LOG_ERROR, "Failed to handle " +                                "snapshot delete for type ALL"); +                        goto out; +                } +                break; + +        case GF_SNAP_DELETE_TYPE_VOL: +                ret = glusterd_handle_snapshot_delete_vol (dict, err_str, len); +                if (ret) { +                        gf_log (this->name, GF_LOG_ERROR, "Failed to handle " +                                "snapshot delete for type VOL"); +                        goto out; +                } +                break; + +        default: +                gf_log (this->name, GF_LOG_ERROR, "Wrong snapshot delete type"); +                break; +        } + +        if ( ret == 0 && (delete_cmd == GF_SNAP_DELETE_TYPE_ALL || +                          delete_cmd == GF_SNAP_DELETE_TYPE_VOL)) { +                ret = glusterd_op_send_cli_response (op, 0, 0, req, dict, +                                                     err_str); +                if (ret) { +                        gf_log (this->name, GF_LOG_ERROR, "Failed to send cli " +                                "response"); +                        goto out; +                } +        } +        ret = 0;  out:          return ret;  } @@ -7347,7 +7508,7 @@ glusterd_handle_snapshot_fn (rpcsvc_request_t *req)                  }                  break;          case GF_SNAP_OPTION_TYPE_DELETE: -                ret = glusterd_handle_snapshot_remove (req, cli_op, dict, +                ret = glusterd_handle_snapshot_delete (req, cli_op, dict,                                                         err_str,                                                         sizeof (err_str));                  if (ret) {  | 
