summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSachin Pandit <spandit@redhat.com>2013-10-15 15:41:56 +0530
committershishir gowda <sgowda@redhat.com>2013-11-15 12:38:59 +0530
commitda3a265c36b1326405dafce98b29d7c72001a7e9 (patch)
tree6b1cd92cd5d3ec24b499d1f4140be7af26e50f77
parentb1e9fab5de8ab45987b2eed9bfd12a1eb188707b (diff)
CLI : snapshot list cli interface
$gluster snapshot list *prints snaps of all volume* $gluster snapshot list -d *prints snaps of all volume with details* $gluster snapshot list vol1 *prints snaps of volume "vol1"* $gluster snapshot list vol1 -d *prints snaps of volume "vol1" with details* $gluster snapshot list vol1 vol2 *prints snaps of volume "vol1" & "vol2" $gluster snapshot list vol1 vol2 -d *prints snaps of volume "vol1" & "vol2" with details* $gluster snapshot list -c cgname *prints snaps of all volume present in the group "cgname"* $gluster snapshot list -c cgname -d *prints snaps of all volume present in the group "cgname" with details* ** As of now you wont be able to see any output as actual snap create is not integrated ** Change-Id: I60eeafc715a51f1c564a270bb4124368038012b1 Signed-off-by: Sachin Pandit <spandit@redhat.com>
-rw-r--r--cli/src/cli-cmd-parser.c193
-rw-r--r--cli/src/cli-cmd-snapshot.c10
-rw-r--r--cli/src/cli-rpc-ops.c369
3 files changed, 518 insertions, 54 deletions
diff --git a/cli/src/cli-cmd-parser.c b/cli/src/cli-cmd-parser.c
index 87d29972b..b05fad315 100644
--- a/cli/src/cli-cmd-parser.c
+++ b/cli/src/cli-cmd-parser.c
@@ -2972,6 +2972,142 @@ out:
return ret;
}
+/* snapshot list [<volnames> | <volname> -s <snapname> | -c <cgname>] [-d]
+ * cmdi is command index which contains number of standard arguments in
+ * command, here cmdi is 2 i.e "gluster snapshot list"
+ */
+int
+cli_snap_list_parse (dict_t *dict, const char **words, int wordcount, int cmdi)
+{
+ int ret = -1;
+ int i = 0;
+ int64_t vol_count = 0;
+ int vol_start_index = -1;
+ int8_t snap_details = 0;
+ char *snap_name = NULL;
+ char *cg_name = NULL;
+ char *vol_name = NULL;
+ char key[256] = "";
+
+ GF_ASSERT (dict);
+ GF_ASSERT (words);
+ GF_ASSERT (wordcount >= cmdi);
+ /* if command is "gluster snapshot list*/
+ if (wordcount == cmdi) {
+ ret = 0;
+ goto out;
+ }
+
+ for (i = cmdi; i < wordcount; ++i) {
+ if (strcmp (words[i], "-d") == 0) {
+ if (snap_details == 1) {
+ /* If option is already set */
+ gf_log("", GF_LOG_ERROR,
+ "snap_details already set");
+ goto out;
+ }
+ snap_details = 1;
+ } else if (strcmp (words[i], "-s") == 0) {
+ if ((wordcount - 1) == i || (snap_name != NULL)
+ || vol_count != 1 || strcmp (words[++i], "-d") == 0
+ || strcmp (words[i], "-c") == 0) {
+ /* if -s is not followed by a valid snap_name
+ * or if snap_name is already parsed
+ * or number of volname specified
+ * is not equal to 1
+ */
+ gf_log("", GF_LOG_ERROR, "Invalid snap_name"
+ " or snap_name already parsed"
+ " or volname specified is not equal 1");
+ goto out;
+ }
+ snap_name = words[i]; // word followed by -s is snapname
+ } else if (strcmp (words[i], "-c") == 0) {
+ if ((wordcount - 1) == i || (cg_name != NULL)
+ || strcmp (words[++i], "-d") == 0
+ || strcmp (words[i], "-s") == 0) {
+ /* if -c is not followed by a valid cg_name
+ * or if cg_name is already parsed
+ */
+ gf_log("", GF_LOG_ERROR, "Invalid cg_name"
+ " or cg_name already parsed");
+ goto out;
+ }
+ cg_name = words[i];
+ } else {
+ if (vol_count != 0) {
+ /* if vol names already set */
+ gf_log("", GF_LOG_ERROR,
+ "Vol Names already set");
+ goto out;
+ }
+
+ vol_start_index = i;
+ vol_count = 1;
+
+ while (++i < wordcount) {
+ if ((strcmp (words[i], "-d") == 0) ||
+ (strcmp (words[i], "-s") == 0) ||
+ (strcmp (words[i], "-c") == 0)) {
+ /*if option -d, -s or -c is given after volname
+ *then go back in index to parse this option
+ *again
+ */
+ --i;
+ break;
+ }
+ ++vol_count;
+ }
+ }
+ }
+
+ /* if CG name is present in the command then fill it to dictionary */
+ if (cg_name != NULL) {
+ if (snap_name != NULL || vol_count != 0) {
+ /* When -s option or volume name is given along
+ * with -c option. Details of single snap belonging
+ * to a CG is not supported.
+ */
+ gf_log("", GF_LOG_ERROR, "details of single snap"
+ " belonging to a CG is not supported");
+ goto out;
+ }
+ ret = dict_set_str(dict, "cg_name", cg_name);
+ if (ret) {
+ gf_log("", GF_LOG_ERROR, "Failed to set cg_name");
+ goto out;
+ }
+ } else {
+ /* if snap name is present in the command
+ * then fill it to dictionary
+ */
+ if (snap_name != NULL) {
+ ret = dict_set_str (dict, "snap_name", snap_name);
+ if (ret) {
+ gf_log ("", GF_LOG_ERROR,
+ "Failed to set snap_name");
+ goto out;
+ }
+ }
+
+ ret = dict_set_int64 (dict, "vol_count", vol_count);
+ /* fill volume name in dictionary */
+ for (i = 0; i < vol_count; ++i) {
+ vol_name = words[vol_start_index + i];
+ snprintf (key, sizeof (key), "vol%d", i);
+ ret = dict_set_str (dict, key, vol_name);
+ if (ret) {
+ gf_log("", GF_LOG_ERROR,
+ "Failed to set vol_name");
+ goto out;
+ }
+ }
+ }
+out:
+ return ret;
+}
+
+
int32_t
cli_cmd_snapshot_parse (const char **words, int wordcount, dict_t **options)
{
@@ -2979,8 +3115,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;
int32_t cmdi = 0;
- char *opwords[] = {"create", NULL};
+ char *opwords[] = {"create", "list", NULL};
char *w = NULL;
+ int i = 0;
GF_ASSERT (words);
GF_ASSERT (options);
@@ -2989,23 +3126,14 @@ cli_cmd_snapshot_parse (const char **words, int wordcount, dict_t **options)
if (!dict)
goto out;
- /* syntax:
- * snapshot create <volnames> [-n <snap-name/cg-name>] [-d <description>]
- */
/* Lowest wordcount possible */
if (wordcount < 2) {
- gf_log ("", GF_LOG_ERROR, "Invalid command: Not enough arguments");
+ gf_log ("", GF_LOG_ERROR,
+ "Invalid command: Not enough arguments");
goto out;
}
- /* In cases where the vol-name is not given
- * parsing fails. volname cannot be an opword.
- * and that is what this check verifies */
- w = str_getunamb (words[2], opwords);
- if (w)
- goto out;
-
w = str_getunamb (words[1], opwords);
if (!w) {
/* Checks if the operation is a valid operation */
@@ -3015,6 +3143,16 @@ cli_cmd_snapshot_parse (const char **words, int wordcount, dict_t **options)
/* Check which op is intended */
if (strcmp (w, "create") == 0) {
+ /*syntax:
+ *snapshot create <volnames> [-n <snap-name/cg-name>] [-d <description>]
+ */
+
+ /* In cases where the vol-name is not given
+ * parsing fails. volname cannot be an opword.
+ * and that is what this check verifies */
+ w = str_getunamb (words[2], opwords);
+ if (w)
+ goto out;
type = GF_SNAP_OPTION_TYPE_CREATE;
cmdi = 1;
ret = dict_set_int32 (dict, "type", type);
@@ -3031,6 +3169,37 @@ cli_cmd_snapshot_parse (const char **words, int wordcount, dict_t **options)
"create command parsing failed.");
goto out;
}
+ } else if (strcmp (w, "list") == 0) {
+ /* snapshot list [<volnames> | <volname> [-s <snapname>]
+ * | -c <cgname>] [-d] */
+ /* check if arguments contains any Keyword */
+ cmdi = 2;
+ for (i = cmdi ; i < wordcount ; i++) {
+ w = str_getunamb (words[i], opwords);
+ if (w) {
+ /*Checks if the operation is a valid operation*/
+ cli_out ("Usage of Keyword in wrong place");
+ gf_log ("", GF_LOG_ERROR, "Opword Mismatch");
+ goto out;
+ }
+ }
+ type = GF_SNAP_OPTION_TYPE_LIST;
+ ret = dict_set_int32 (dict, "type" , type);
+
+ if (ret) {
+ gf_log ("" , GF_LOG_ERROR,
+ "Failed to set type.");
+ goto out;
+ }
+
+ ret = cli_snap_list_parse (dict, words,
+ wordcount, cmdi);
+
+ if (ret) {
+ gf_log ("", GF_LOG_ERROR,
+ "list command parsing failed.");
+ goto out;
+ }
} else {
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 cc1fb3c90..afe8bf901 100644
--- a/cli/src/cli-cmd-snapshot.c
+++ b/cli/src/cli-cmd-snapshot.c
@@ -75,13 +75,17 @@ out:
struct cli_cmd snapshot_cmds[] = {
{ "snapshot help",
cli_cmd_snapshot_help_cbk,
- "display help for snapshot commands"},
-
+ "display help for snapshot commands"
+ },
{"snapshot create <volnames> [-n <snap-name/cg-name>] [-d <description>]",
cli_cmd_snapshot_cbk,
"Snapshot Create."
},
-
+ {"snapshot list [<volnames> | <volname> [-s <snapname>]"
+ " | -c <cgname> ] [-d]",
+ cli_cmd_snapshot_cbk,
+ "Snapshot List."
+ },
{ NULL, NULL, NULL }
};
diff --git a/cli/src/cli-rpc-ops.c b/cli/src/cli-rpc-ops.c
index b100f2d62..50eeda3d2 100644
--- a/cli/src/cli-rpc-ops.c
+++ b/cli/src/cli-rpc-ops.c
@@ -7518,18 +7518,282 @@ out:
return ret;
}
+
+/*Function to list the snap "gluster snapshot list" */
+static int
+list_snap_of_volume (dict_t *dict_n, char *prefix_str) {
+ int64_t snapcount = -1 ;
+ char buffer[PATH_MAX] = "" ;
+ char *get_buffer = NULL;
+ int8_t detail = 0 ;
+ int64_t i = 0 ;
+ int ret = -1 ;
+
+ GF_ASSERT (dict_n);
+ GF_ASSERT (prefix_str);
+
+ if (!dict_n) {
+ ret = -1;
+ goto out;
+ }
+
+ /* Check if volname is present.
+ * if volume not present then display that volume doesnot exist
+ * and try to fetch next volume mentioned
+ */
+ ret = snprintf (buffer, sizeof(buffer), "%s.vol_name", prefix_str);
+ if (ret < 0) { /* Negative value is an error */
+ goto out;
+ }
+ ret = dict_get_str (dict_n, buffer, &get_buffer);
+ if (get_buffer == NULL){
+ cli_out ("Volume doesnot exist");
+ goto out;
+ }
+ cli_out ("Vol Name : %s", get_buffer);
+ /* if Volume is present then get the snapcount.
+ * string is "snaplist.vol{0..}.snap_count.
+ */
+ ret = snprintf (buffer, sizeof(buffer),
+ "%s.snap_count", prefix_str);
+ if (ret < 0) { /* Negative value is an error */
+ goto out;
+ }
+ ret = dict_get_int64 (dict_n, buffer, &snapcount);
+ if (ret) {
+ gf_log("", GF_LOG_ERROR, "Could not fetch snapcount");
+ goto out;
+ }
+
+ /* To check if the user has given "-d" option */
+ ret = dict_get_int8 (dict_n, "snap_details", &detail);
+ if (ret) {
+ gf_log ("",GF_LOG_ERROR, "could not get snap_details status");
+ goto out;
+ }
+
+ cli_out ("Number of Snaps Taken : %ld", snapcount);
+ for (i = 0 ; i < snapcount; i++) {
+ /* get snapname "snaplist.vol{0..}.snap{0..}.snap_name" */
+ ret = snprintf (buffer, sizeof(buffer),
+ "%s.snap%ld.snap_name", prefix_str,i);
+ if (ret < 0) { /* Negative value is an error */
+ goto out;
+ }
+ ret = dict_get_str (dict_n, buffer, &get_buffer);
+ if (!ret)
+ cli_out ("\tSnap Name : %s",get_buffer);
+ else
+ cli_out ("\tSnap Name : %s","Does not exist");
+
+ ret = snprintf (buffer, sizeof(buffer),
+ "%s.snap%ld.snap_time", prefix_str, i);
+ if (ret < 0) { /* Negative value is an error */
+ goto out;
+ }
+ ret = dict_get_str (dict_n, buffer, &get_buffer);
+ if (!ret)
+ cli_out ("\tSnap Time : %s",get_buffer);
+ else
+ cli_out ("\tSnap Time : %s","Does not exist");
+
+
+ ret = snprintf (buffer, sizeof(buffer), "%s.snap%ld.snap_id"
+ , prefix_str, i);
+ if (ret < 0) { /* Negative value is an error */
+ goto out;
+ }
+ ret = dict_get_str (dict_n, buffer, &get_buffer);
+ if (!ret)
+ cli_out("\tSnap ID : %s",get_buffer);
+ else
+ cli_out("\tSnap ID : %s","Does not exist");
+
+ if(detail == 0) {
+ /* if snap_details is set to zero
+ * then we can skip the additional information part
+ */
+ continue;
+ }
+ ret = snprintf (buffer, sizeof(buffer),
+ "%s.snap%ld.cg_name", prefix_str, i);
+ if (ret < 0) { /* Negative value is an error */
+ goto out;
+ }
+ ret = dict_get_str (dict_n, buffer, &get_buffer);
+ if (!ret)
+ cli_out("\tCG Name : %s",get_buffer);
+ else
+ cli_out("\tCG Name : %s","Does not exist");
+
+ ret = snprintf (buffer, sizeof(buffer),
+ "%s.snap%ld.cg_id", prefix_str, i);
+ if (ret < 0) { /* Negative value is an error */
+ goto out;
+ }
+ ret = dict_get_str (dict_n, buffer, &get_buffer);
+ if (!ret)
+ cli_out("\tCG ID : %s",get_buffer);
+ else
+ cli_out("\tCG ID : %s","Does not exist");
+
+ ret = snprintf (buffer, sizeof(buffer),
+ "%s.snap%ld.snap_desc", prefix_str, i);
+ if (ret < 0) { /* Negative value is an error */
+ goto out;
+ }
+ ret = dict_get_str (dict_n, buffer, &get_buffer);
+ if (!ret)
+ cli_out ("\tSnap Description : %s",get_buffer);
+ else
+ cli_out ("\tSnap Description : %s",
+ "Description not present");
+
+ ret = snprintf (buffer, sizeof(buffer),
+ "%s.snap%ld.snap_status", prefix_str, i);
+ if (ret < 0) { /* Negative value is an error */
+ goto out;
+ }
+ ret = dict_get_str (dict_n, buffer, &get_buffer);
+ if (!ret)
+ cli_out ("\tSnap Status : %s",get_buffer);
+ else
+ cli_out ("\tSnap Status : %s","Does not exist");
+ ret = 0;
+ }
+
+out :
+ return ret;
+}
+
+/* Function to list snap present in CG */
+static int
+list_snap_of_cg (dict_t *dict) {
+ int ret = -1 ;
+ int8_t detail = 0 ;
+ char *get_buffer = NULL;
+ char cg_name_list[PATH_MAX] = "" ;
+ int64_t cg_volcount = -1 ;
+ int64_t i = -1 ;
+
+ GF_ASSERT(dict);
+
+ /* As listing snaps of single CG is supported as of now
+ * the string "snaplist.cg0" is directly included
+ * or else we can keep that string in some variable
+ * and use the same variable every where
+ */
+ ret = dict_get_int8 (dict, "snap_details", &detail);
+ if (ret) {
+ gf_log ("", GF_LOG_ERROR, "could not get snap_details status");
+ goto out;
+ }
+
+ ret = dict_get_str (dict, "snaplist.cg0.cg_name", &get_buffer);
+ if (ret) {
+ /* if cg_name is not present then exit, it is not necessary
+ * to check other details if cg_name is not present
+ */
+ cli_out ("CG Name : %s","Does not exist");
+ gf_log ("", GF_LOG_ERROR, "Could not get cg_name");
+ goto out;
+ }
+ cli_out ("CG Name : %s", get_buffer);
+
+ ret = dict_get_str (dict, "snaplist.cg0.cg_id", &get_buffer);
+ if (!ret)
+ cli_out ("CG ID : %s",get_buffer);
+ else
+ cli_out ("CG ID : %s","Does not exist");
+
+ if (detail == 1) {
+ ret = dict_get_str (dict, "snaplist.cg0.cg_desc", &get_buffer);
+ if (!ret)
+ cli_out ("CG Description : %s",
+ get_buffer);
+ else
+ cli_out ("CG Description : %s",
+ "Does not exist");
+
+ ret = dict_get_str (dict, "snaplist.cg0.cg_status",
+ &get_buffer);
+ if (!ret)
+ cli_out ("CG Status : %s", get_buffer);
+ else
+ cli_out ("CG Status : %s",
+ "Does not exist");
+
+ }
+
+ ret = dict_get_int64 (dict, "snaplist.cg0.vol_count", &cg_volcount);
+ if (ret) {
+ gf_log ("", GF_LOG_ERROR, "Could not fetch cg_volcount");
+ goto out;
+ }
+ /* list the snaps of each volume present in a CG*/
+ for (i = 0 ; i < cg_volcount ; i++){
+ ret = snprintf (cg_name_list, sizeof(cg_name_list),
+ "snaplist.cg0.vol%ld",i);
+ if (ret < 0) { /* Negative value is an error */
+ goto out;
+ }
+ ret = list_snap_of_volume (dict, cg_name_list);
+ if (ret) {
+ gf_log("", GF_LOG_ERROR, "Failed to list the"
+ " information of snaps of volume present in CG");
+ }
+ }
+out :
+ return ret;
+}
+
+/* This function calls list_snap_of_volume */
+static int
+call_list_snap_of_volume(dict_t *dict){
+ int ret = -1;
+ int64_t volcount = -1;
+ int i = -1;
+ char vol_name_prefix[PATH_MAX] = "";
+
+ ret = dict_get_int64 (dict, "snaplist.vol_count", &volcount);
+ if (ret) {
+ gf_log ("", GF_LOG_ERROR, "Could not fetch volcount");
+ goto out;
+ }
+ for (i = 0 ; i < volcount ; i++) {
+ /* list the snap of each volume
+ * vol_name_prefix = "snaplist.vol{0..}"
+ */
+ ret = snprintf (vol_name_prefix, sizeof(vol_name_prefix),
+ "snaplist.vol%d", i);
+ if (ret < 0) { /* Negative value is an error */
+ goto out;
+ }
+ ret = list_snap_of_volume (dict, vol_name_prefix);
+ if (ret) {
+ gf_log("", GF_LOG_ERROR,
+ "Failed to list information of snaps of volume");
+ }
+ /* If we fail to print information of one volume
+ * then try to fetch information of next volume
+ */
+ }
+out :
+ return ret;
+}
+
int
gf_cli_snapshot_cbk (struct rpc_req *req, struct iovec *iov,
int count, void *myframe)
{
- int ret = -1;
- gf_cli_rsp rsp = {0, };
- dict_t *dict = NULL;
- char *snap_name = NULL;
- char *cg_name = NULL;
- int32_t type = 0;
- int32_t volcount = 0;
- call_frame_t *frame = NULL;
+ int ret = -1;
+ gf_cli_rsp rsp = {0, };
+ dict_t *dict = NULL;
+ char *snap_name = NULL;
+ char *cg_name = NULL;
+ int32_t type = 0;
+ int64_t volcount = -1;
+ call_frame_t *frame = NULL;
if (req->rpc_status == -1) {
ret = -1;
@@ -7564,47 +7828,74 @@ gf_cli_snapshot_cbk (struct rpc_req *req, struct iovec *iov,
}
switch (type) {
- case GF_SNAP_OPTION_TYPE_CREATE:
- if (rsp.op_ret) {
- cli_err("snapshot create: failed: %s",
- rsp.op_errstr ? rsp.op_errstr :
- "Please check log file for details");
- ret = rsp.op_ret;
- goto out;
- }
+ case GF_SNAP_OPTION_TYPE_CREATE:
+ if (rsp.op_ret) {
+ cli_err("snapshot create: failed: %s",
+ rsp.op_errstr ? rsp.op_errstr :
+ "Please check log file for details");
+ ret = rsp.op_ret;
+ goto out;
+ }
- ret = dict_get_int32 (dict, "volcount", &volcount);
- if (ret) {
- gf_log (frame->this->name, GF_LOG_ERROR,
- "failed to get volcount");
- goto out;
- }
+ ret = dict_get_int64 (dict, "volcount", &volcount);
+ if (ret) {
+ gf_log (frame->this->name, GF_LOG_ERROR,
+ "failed to get volcount");
+ goto out;
+ }
- if (volcount > 1) {
- if (dict_get_str (dict, "cg-name",
- &cg_name) != 0)
- cg_name = "???";
+ if (volcount > 1) {
+ if (dict_get_str (dict, "cg-name",
+ &cg_name) != 0)
+ cg_name = "???";
- cli_out ("snapshot create: %s: consistency "
- "group created successfully",
- cg_name);
- } else {
- if (dict_get_str (dict, "snap-name",
- &snap_name) != 0)
- snap_name = "???";
+ cli_out ("snapshot create: %s: consistency "
+ "group created successfully",
+ cg_name);
+ } else {
+ if (dict_get_str (dict, "snap-name",
+ &snap_name) != 0)
+ snap_name = "???";
- cli_out ("snapshot create: %s: "
- "snap created successfully",
- snap_name);
+ cli_out ("snapshot create: %s: "
+ "snap created successfully",
+ snap_name);
}
break;
- default:
- cli_err ("Unknown command executed");
+ case GF_SNAP_OPTION_TYPE_LIST:
+ if (rsp.op_ret) {
+ cli_err ("Snapshot list : failed: %s",
+ rsp.op_errstr ? rsp.op_errstr :
+ "Please check log file for details");
+ ret = rsp.op_ret;
+ goto out;
+ }
+
+ /* get the vol_count
+ * if vol_count = 0, then there must be presence of CG
+ */
+ ret = dict_get_int64 (dict, "snaplist.vol_count", &volcount);
+ if (ret){
+ gf_log("", GF_LOG_ERROR, "Could not fetch volcount");
ret = -1;
goto out;
- }
+ }
+ if (volcount >= 1) {
+ ret = call_list_snap_of_volume (dict);
+ } else {
+ /* get the volumes present in CG
+ * and list snap of each volume
+ */
+ ret = list_snap_of_cg (dict);
+ }
+ break;
+ default:
+ cli_err ("Unknown command executed");
+ ret = -1;
+ goto out;
+ }
out:
if (dict)
dict_unref (dict);