From cffe1de37453f81992047408e4c4ce5e35e21434 Mon Sep 17 00:00:00 2001 From: Sachin Pandit Date: Thu, 13 Feb 2014 03:41:28 +0530 Subject: CLI/snapshot : Snapshot info CLI changes snapshot info [(snapname | volume )]. Snapshot info will list all the basic information. Syntax : ** gluster snapshot info ** This will list all the snap object along with that it also prints the snaps volume name, UUID and status. ** gluster snapshot info ** This will list only the mentioned snap object and also snap volume information along with that ** gluster snapshot info volume ** This will list all the snaps present in the mentioned volume. Change-Id: I1e92774cb08eaebbfe141b9b47d1a887d76916a4 Signed-off-by: Sachin Pandit Reviewed-on: http://review.gluster.org/6996 Reviewed-by: Rajesh Joseph Tested-by: Rajesh Joseph --- cli/src/cli-cmd-parser.c | 252 ++++++------------ cli/src/cli-cmd-snapshot.c | 3 +- cli/src/cli-rpc-ops.c | 649 ++++++++++++++++++++------------------------- rpc/xdr/src/cli1-xdr.h | 3 +- 4 files changed, 362 insertions(+), 545 deletions(-) diff --git a/cli/src/cli-cmd-parser.c b/cli/src/cli-cmd-parser.c index 62c383c44..2505bbc7f 100644 --- a/cli/src/cli-cmd-parser.c +++ b/cli/src/cli-cmd-parser.c @@ -2956,170 +2956,80 @@ cli_snap_create_parse (dict_t *dict, const char **words, int wordcount, out : return ret; } - -/* snapshot list [ | -s | -c ] [-d] - * cmdi is command index which contains number of standard arguments in - * command, here cmdi is 2 i.e "gluster snapshot list" +/* snapshot info [(snapname | volume )] + * @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. + * @arg-3, cmdi : command index, here cmdi is "2" (gluster snapshot info) + * + * return value : -1 on failure + * 0 on success */ int -cli_snap_list_parse (dict_t *dict, const char **words, int wordcount, - unsigned int cmdi) -{ - int ret = -1; - int loop_ret = -1; - int64_t actual_vol_count = 0; - int64_t i = 0; - int64_t vol_count = 0; - int vol_start_index = -1; - int8_t snap_details = 0; - const char *snap_name = NULL; - const char *cg_name = NULL; - const char *vol_name = NULL; - char key[256] = ""; +cli_snap_info_parse (dict_t *dict, const char **words, int wordcount, + unsigned int cmdi) { + + int ret = -1; - GF_ASSERT (dict); GF_ASSERT (words); - GF_ASSERT (wordcount >= cmdi); - /* if command is "gluster snapshot list*/ + GF_ASSERT (dict); + + if (wordcount > 4 || wordcount < cmdi) { + gf_log ("", GF_LOG_ERROR, "Invalid syntax"); + goto out; + } + if (wordcount == cmdi) { - ret = dict_set_int8 (dict, "snap-details", snap_details); + ret = 0; + goto out; + } + + /* If 3rd word is not "volume", then it must + * be snap-name. + */ + if (strcmp (words[cmdi], "volume") != 0) { + ret = dict_set_str (dict, "snapname", + (char *)words[cmdi]); if (ret) { - gf_log("", GF_LOG_ERROR, "Failed to set snap-details"); + gf_log ("cli", GF_LOG_ERROR, "Unable to save " + "snap-name %s", words[cmdi]); + goto out; + } + + /* Once snap name is parsed, if we encounter any other + * word then fail it. Invalid Syntax. + * example : snapshot info word + */ + if ((cmdi + 1) != wordcount) { ret = -1; + gf_log ("cli", GF_LOG_ERROR, "Invalid Syntax"); goto out; } + ret = 0; goto out; + /* No need to continue the parsing once we + * get the snap-name + */ } - 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"); - ret = -1; - 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 number of volumes greater than 1"); - ret = -1; - goto out; - } - /* word followed by -s is snapname */ - snap_name = words[i]; - } 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"); - ret = -1; - 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"); - ret = -1; - 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 3rd word is "volume", then check if next word + * is present. As, "snapshot info volume" is an + * invalid command. + */ + if ((cmdi + 1) == wordcount) { + ret = -1; + gf_log ("cli", GF_LOG_ERROR, "Invalid Syntax"); + goto out; } - ret = dict_set_int8 (dict, "snap-details", snap_details); + ret = dict_set_str (dict, "volname", (char *)words[wordcount - 1]); if (ret) { - gf_log("", GF_LOG_ERROR, "Failed to set snap-details"); + gf_log ("", GF_LOG_ERROR, "Count not save " + "volume name %s", words[wordcount - 1]); goto out; } - /* 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"); - ret = -1; - goto out; - } - ret = dict_set_str(dict, "cgname", (char *)cg_name); - if (ret) { - gf_log("", GF_LOG_ERROR, - "Failed to set CG name %s", 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, "snapname", - (char *)snap_name); - if (ret) { - gf_log ("", GF_LOG_ERROR, - "Failed to set snap name %s", - snap_name); - ret = -1; - goto out; - } - } - - /* fill volume name in dictionary */ - for (i = 0; i < vol_count; ++i) { - vol_name = (char*) words[vol_start_index + i]; - /* check if volume name is repeated */ - snprintf (key, sizeof (key), "vol%ld", actual_vol_count); - ret = dict_set_str (dict, key, (char *)vol_name); - if (ret) { - gf_log("", GF_LOG_ERROR, - "Failed to set Volume Name %s", - vol_name); - goto out; - } - actual_vol_count++; - } - ret = dict_set_int64 (dict, "vol-count", actual_vol_count); - if (ret) { - gf_log("", GF_LOG_ERROR, "Failed to set Volume Count"); - ret = -1; - } - } -out: +out : return ret; } @@ -3471,10 +3381,9 @@ cli_cmd_snapshot_parse (const char **words, int wordcount, dict_t **options, gf1_cli_snapshot type = GF_SNAP_OPTION_TYPE_NONE; unsigned int cmdi = 0; char *w = NULL; - int i = 0; char *opwords[] = {"create", "delete", "restore", "start", "stop", "list", "status", - "config", NULL}; + "config", "info", NULL}; GF_ASSERT (words); GF_ASSERT (options); @@ -3502,6 +3411,8 @@ cli_cmd_snapshot_parse (const char **words, int wordcount, dict_t **options, type = GF_SNAP_OPTION_TYPE_CREATE; if (!strcmp (w, "list")) type = GF_SNAP_OPTION_TYPE_LIST; + if (!strcmp (w, "info")) + type = GF_SNAP_OPTION_TYPE_INFO; if (!strcmp (w, "delete")) type = GF_SNAP_OPTION_TYPE_DELETE; if (!strcmp (w, "config")) @@ -3509,6 +3420,8 @@ cli_cmd_snapshot_parse (const char **words, int wordcount, dict_t **options, if (!strcmp (w, "restore")) type = GF_SNAP_OPTION_TYPE_RESTORE; + cmdi = 2; + /* Check which op is intended */ switch (type) { case GF_SNAP_OPTION_TYPE_CREATE: @@ -3526,7 +3439,6 @@ cli_cmd_snapshot_parse (const char **words, int wordcount, dict_t **options, w = str_getunamb (words[2], opwords); if (w) goto out; - cmdi = 2; ret = cli_snap_create_parse (dict, words, wordcount, cmdi); @@ -3537,35 +3449,21 @@ cli_cmd_snapshot_parse (const char **words, int wordcount, dict_t **options, } break; } - case GF_SNAP_OPTION_TYPE_LIST: - { - /* snapshot list [ | [-s ] - * | -c ] [-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; - } - } - - ret = cli_snap_list_parse (dict, words, - wordcount, cmdi); + case GF_SNAP_OPTION_TYPE_INFO: + { + /* Syntax : + * gluster snapshot info ([snap-name] | [vol ]) + */ + ret = cli_snap_info_parse (dict, words, wordcount, + cmdi); + if (ret) { + gf_log ("cli", GF_LOG_ERROR, "Failed to parse " + "snapshot list command"); + goto out; + } + break; + } - if (ret) { - gf_log ("", GF_LOG_ERROR, - "list command parsing failed."); - goto out; - } - break; - } case GF_SNAP_OPTION_TYPE_DELETE: { /*syntax: diff --git a/cli/src/cli-cmd-snapshot.c b/cli/src/cli-cmd-snapshot.c index 44dbf8a7c..b5b438804 100644 --- a/cli/src/cli-cmd-snapshot.c +++ b/cli/src/cli-cmd-snapshot.c @@ -91,8 +91,7 @@ struct cli_cmd snapshot_cmds[] = { cli_cmd_snapshot_cbk, "Snapshot Restore." }, - { "snapshot list [ | [-s ]" - " | -c ] [-d]", + { "snapshot info [(snap-name | volume )]", cli_cmd_snapshot_cbk, "Snapshot List." }, diff --git a/cli/src/cli-rpc-ops.c b/cli/src/cli-rpc-ops.c index e9c24fe21..340752aa8 100644 --- a/cli/src/cli-rpc-ops.c +++ b/cli/src/cli-rpc-ops.c @@ -281,7 +281,7 @@ gf_cli_output_pool_list (dict_t *dict, int count) else connected_str = "Disconnected"; - cli_out ("%s\t%-8s\t%s ", uuid_buf, hostname_buf, + cli_out ("%s\t%-9s\t%s ", uuid_buf, hostname_buf, connected_str); i++; } @@ -7530,342 +7530,6 @@ out: return ret; } - -/*Function to list the snap "gluster snapshot list" */ -static int -list_snap_of_volume (dict_t *dict_n, char *prefix_str) { - uint64_t snapcount_total = 0 ; - uint64_t snapcount = 0 ; - char buffer[PATH_MAX] = "" ; - char *get_buffer = NULL; - int8_t detail = 0 ; - uint64_t i = 0 ; - int ret = -1 ; - uint64_t snap_available = 0 ; - - 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.err_str", prefix_str); - if (ret < 0) { - goto out; - } - - ret = dict_get_str (dict_n, buffer, &get_buffer); - if (ret == 0) { - cli_out ("%s",get_buffer); - ret = 0; - goto out; - } - - ret = snprintf (buffer, sizeof(buffer), "%s.volname", 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){ - ret = 0; - goto out; - } - cli_out ("\n%-28s %s %s", "Volume Name", ":", 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_uint64 (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; - } - - /* "snap-count-total" holds number of snapshots taken - * whereas "snap-count" holds number of snapshots to - * be displayed - * Ex : gluster snapshot list vol1 -s snap1 - * Here "snap-count-total" contains number of snapshots - * of volume "vol1", whereas "snap-count" is 1 here, - * as we are displaying details of only 1 snap "snap1" - */ - ret = snprintf (buffer, sizeof (buffer), - "%s.snap-count-total", prefix_str); - if (ret < 0) { - goto out; - } - - ret = dict_get_uint64 (dict_n, buffer, &snapcount_total); - if (!ret) - cli_out ("%-28s %s %ld", "Number of snaps taken", ":", - snapcount_total); - else - gf_log ("", GF_LOG_ERROR, "Failed to get snapcount total"); - - ret = snprintf (buffer, sizeof (buffer), - "%s.snap-available", prefix_str); - if (ret < 0) { - goto out; - } - - ret = dict_get_uint64 (dict_n, buffer, &snap_available); - if (!ret) - cli_out ("%-28s %s %ld", "Number of snaps available", - ":", snap_available); - else - gf_log ("", GF_LOG_ERROR, "Failed to get snap-available"); - - - for (i = 0 ; i < snapcount; i++) { - /* get snapname "snaplist.vol-{0..}.snap-{0..}.snapname" */ - ret = snprintf (buffer, sizeof(buffer), - "%s.snap-%ld.snapname", 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 ("\n\t%-17s %s %s", "Snap Name", ":", - get_buffer); - else - cli_out ("\n\t%-17s %s %s", "Snap Name", ":", - "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 ("\t%-17s %s %s", "Snap Time", ":", - get_buffer); - else - cli_out ("\t%-17s %s %s", "Snap Time", ":", - "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("\t%-17s %s %s", "Snap UUID", ":", - get_buffer); - else - cli_out("\t%-17s %s %s", "Snap UUID", ":", - "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("\t%-17s %s %s", "CG Name", ":", - get_buffer); - else - cli_out("\t%-17s %s %s","CG Name", ":", - "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("\t%-17s %s %s", "CG ID", ":", - get_buffer); - else - cli_out("\t%-17s %s %s", "CG ID", ":", - "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 ("\t%-17s %s %s", "Snap Description", ":", - get_buffer); - else - cli_out ("\t%-17s %s %s", "Snap Description", ":", - "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 ("\t%-17s %s %s", "Snap Status", ":", - get_buffer); - else - cli_out ("\t%-17s %s %s", "Snap Status", ":", - "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 = 0 ; - uint64_t i = 0 ; - - 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.cg-0.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.cg-0.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.cg-0.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.cg-0.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.cg-0.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.cg-0.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 = 0; - uint64_t i = 0; - 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%ld", 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; -} - int32_t cli_snapshot_remove_reply (gf_cli_rsp *rsp, dict_t *dict, call_frame_t *frame) { @@ -8053,6 +7717,274 @@ out: return ret; } +/* This function is used to print the volume related information + * of a snap. + * + * arg - 0, dict : Response Dictionary. + * arg - 1, prefix str : snaplist.snap{0..}.vol{0..}.* + */ +int +cli_get_each_volinfo_in_snap (dict_t *dict, char *keyprefix, + gf_boolean_t snap_driven) { + char key[PATH_MAX] = ""; + char *get_buffer = NULL; + int value = 0; + int ret = -1; + char indent[5] = "\t"; + + GF_ASSERT (dict); + GF_ASSERT (keyprefix); + + if (snap_driven) { + ret = snprintf (key, sizeof (key), "%s.volname", keyprefix); + if (ret < 0) { + goto out; + } + + ret = dict_get_str (dict, key, &get_buffer); + if (ret) { + gf_log ("cli", GF_LOG_ERROR, "Failed to get %s", key); + goto out; + } + cli_out ("%s%-12s %s", indent, "Volume Name:", get_buffer); + + ret = snprintf (key, sizeof (key), + "%s.origin-volname", keyprefix); + if (ret < 0) { + goto out; + } + + ret = dict_get_str (dict, key, &get_buffer); + if (ret) { + gf_log ("cli", GF_LOG_WARNING, "Failed to get %s", key); + cli_out ("%-12s", "Origin:"); + } + cli_out ("%s%-12s %s", indent, "Origin:", get_buffer); + + ret = snprintf (key, sizeof (key), + "%s.snaps-available", keyprefix); + if (ret < 0) { + goto out; + } + + ret = dict_get_int32 (dict, key, &value); + if (ret) { + gf_log ("cli", GF_LOG_ERROR, "Failed to get %s", key); + goto out; + } + cli_out ("%s%-12s %d", indent, "Available:", value); + } + + ret = snprintf (key, sizeof (key), "%s.vol-id", keyprefix); + if (ret < 0) { + goto out; + } + + ret = dict_get_str (dict, key, &get_buffer); + if (ret) { + gf_log ("cli", GF_LOG_ERROR, "Failed to get %s", key); + goto out; + } + cli_out ("%s%-12s %s", indent, "UUID:", get_buffer); +out : + return ret; +} + +/* This function is used to print snap related information + * arg - 0, dict : Response dictionary. + * arg - 1, prefix_str : snaplist.snap{0..}.* + */ +int +cli_get_volinfo_in_snap (dict_t *dict, char *keyprefix) { + + char key[PATH_MAX] = ""; + int i = 0; + int volcount = 0; + int ret = -1; + + GF_ASSERT (dict); + GF_ASSERT (keyprefix); + + ret = snprintf (key, sizeof (key), "%s.vol-count", keyprefix); + if (ret < 0) { + goto out; + } + + ret = dict_get_int32 (dict, key, &volcount); + for (i = 1 ; i <= volcount ; i++) { + ret = snprintf (key, sizeof (key), + "%s.vol%d", keyprefix, i); + if (ret < 0) { + goto out; + } + ret = cli_get_each_volinfo_in_snap (dict, key, _gf_true); + if (ret) { + gf_log ("cli", GF_LOG_ERROR, "Could not list " + "details of volume in a snap"); + goto out; + } + cli_out (" "); + } + +out : + return ret; +} + +int +cli_get_each_snap_info (dict_t *dict, char *prefix_str, + gf_boolean_t snap_driven) { + char key_buffer[PATH_MAX] = ""; + char *get_buffer = NULL; + int ret = -1; + char indent[5] = ""; + + GF_ASSERT (dict); + GF_ASSERT (prefix_str); + + if (!snap_driven) + strcat (indent, "\t"); + + ret = snprintf (key_buffer, sizeof (key_buffer), "%s.snap-name", + prefix_str); + if (ret < 0 ) { + goto out; + } + + ret = dict_get_str (dict, key_buffer, &get_buffer); + if (ret) { + gf_log ("cli", GF_LOG_ERROR, "Unable to fetch snap-name %s ", + key_buffer); + goto out; + } + cli_out ("%s%-12s %s", indent, "Snapshot:", get_buffer); + + ret = snprintf (key_buffer, sizeof (key_buffer), "%s.snap-desc", + prefix_str); + if (ret < 0 ) { + goto out; + } + + ret = dict_get_str (dict, key_buffer, &get_buffer); + if (!ret) { + /* Ignore error for description */ + cli_out ("%s%-12s %s", indent, "Desc:", get_buffer); + } + + ret = snprintf (key_buffer, sizeof (key_buffer), "%s.snap-time", + prefix_str); + if (ret < 0 ) { + goto out; + } + + ret = dict_get_str (dict, key_buffer, &get_buffer); + if (ret) { + gf_log ("cli", GF_LOG_ERROR, "Unable to fetch snap-time %s ", + prefix_str); + goto out; + } + cli_out ("%s%-12s %s", indent, "Created:", get_buffer); + + if (snap_driven) { + cli_out ("%-12s", "Volumes:"); + ret = cli_get_volinfo_in_snap (dict, prefix_str); + if (ret) { + gf_log ("cli", GF_LOG_ERROR, "Unable to list details " + "of the snaps"); + goto out; + } + } +out : + return ret; +} + +/* This is a generic function to print snap related information. + * arg - 0, dict : Response Dictionary + */ +int +cli_call_snapshot_info (dict_t *dict, gf_boolean_t bool_snap_driven) { + int snap_count = 0; + char key[PATH_MAX] = ""; + int ret = -1; + int i = 0; + + GF_ASSERT (dict); + + ret = dict_get_int32 (dict, "snap-count", &snap_count); + if (ret) { + gf_log ("cli", GF_LOG_ERROR, "Unable to get snap-count"); + goto out; + } + + for (i = 1 ; i <= snap_count ; i++) { + ret = snprintf (key, sizeof (key), "snap%d", i); + if (ret < 0) { + goto out; + } + ret = cli_get_each_snap_info (dict, key, bool_snap_driven); + if (ret) { + gf_log ("cli", GF_LOG_ERROR, + "Unable to print snap details"); + goto out; + } + } +out : + return ret; +} + +int +cli_get_snaps_in_volume (dict_t *dict) { + int ret = -1; + int i = 0; + int count = 0; + char key[PATH_MAX] = ""; + char *get_buffer = NULL; + + GF_ASSERT (dict); + + ret = dict_get_str (dict, "origin-volname", &get_buffer); + if (ret) { + gf_log ("cli", GF_LOG_ERROR, "Could not fetch origin-volname"); + goto out; + } + cli_out ("%-12s %s", "Volume Name:", get_buffer); + + ret = dict_get_int32 (dict, "snaps-available", &count); + if (ret) { + gf_log ("cli", GF_LOG_ERROR, "Could not fetch snaps-available"); + goto out; + } + cli_out ("%-12s %d", "Available:", count); + + ret = dict_get_int32 (dict, "snap-count", &count); + if (ret) { + gf_log ("cli", GF_LOG_ERROR, "Could not fetch snap-count"); + goto out; + } + for (i = 1 ; i <= count ; i++) { + snprintf (key, sizeof (key), "snap%d", i); + ret = cli_get_each_snap_info (dict, key, _gf_false); + if (ret) { + gf_log ("cli", GF_LOG_ERROR, + "Unable to print snap details"); + goto out; + } + + ret = snprintf (key, sizeof (key), "snap%d.vol1", i); + if (ret < 0) { + goto out; + } + ret = cli_get_each_volinfo_in_snap (dict, key, _gf_false); + if (ret) { + gf_log ("cli", GF_LOG_ERROR, "Could not get volume " + "related information"); + goto out; + } + + cli_out (" "); + } +out : + return ret; +} int gf_cli_snapshot_cbk (struct rpc_req *req, struct iovec *iov, int count, void *myframe) @@ -8065,6 +7997,7 @@ gf_cli_snapshot_cbk (struct rpc_req *req, struct iovec *iov, int32_t type = 0; int64_t volcount = -1; call_frame_t *frame = NULL; + gf_boolean_t snap_driven = _gf_false; if (req->rpc_status == -1) { ret = -1; @@ -8166,7 +8099,7 @@ gf_cli_snapshot_cbk (struct rpc_req *req, struct iovec *iov, ret = 0; break; - case GF_SNAP_OPTION_TYPE_LIST: + case GF_SNAP_OPTION_TYPE_INFO: if (rsp.op_ret) { cli_err ("Snapshot list : failed: %s", rsp.op_errstr ? rsp.op_errstr : @@ -8175,40 +8108,26 @@ gf_cli_snapshot_cbk (struct rpc_req *req, struct iovec *iov, 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){ - /* if "snaplist.vol-count" is not present then check - * whether "snaplist.cg-0.vol-count" is present - */ - ret = dict_get_int64 (dict, "snaplist.cg-0.vol-count", - &volcount); + snap_driven = dict_get_str_boolean (dict, "snap-driven", + _gf_false); + if (snap_driven == _gf_true) { + ret = cli_call_snapshot_info (dict, snap_driven); if (ret) { - gf_log ("", GF_LOG_ERROR, "Could not fetch" - " cg-volcount"); + gf_log ("cli", GF_LOG_ERROR, + "Snapshot info failed"); goto out; } - ret = list_snap_of_cg (dict); + } else if (snap_driven == _gf_false) { + ret = cli_get_snaps_in_volume (dict); if (ret) { - gf_log ("", GF_LOG_ERROR, - "Could not list snaps present in CG"); - } - goto out; - } - if (volcount >= 1) { - ret = call_list_snap_of_volume (dict); - if (ret) { - gf_log ("", GF_LOG_ERROR, - "Could not list snaps of volume"); + gf_log ("cli", GF_LOG_ERROR, + "Snapshot info failed"); goto out; } } - else { - cli_out ("Snapshots not present"); - } - break; + break; + + case GF_SNAP_OPTION_TYPE_CONFIG: ret = cli_snapshot_config_display (dict, &rsp); diff --git a/rpc/xdr/src/cli1-xdr.h b/rpc/xdr/src/cli1-xdr.h index dfde3e20d..598ddbded 100644 --- a/rpc/xdr/src/cli1-xdr.h +++ b/rpc/xdr/src/cli1-xdr.h @@ -179,13 +179,14 @@ enum gf1_cli_snapshot { GF_SNAP_OPTION_TYPE_LIST = 6, GF_SNAP_OPTION_TYPE_STATUS = 7, GF_SNAP_OPTION_TYPE_CONFIG = 8, + GF_SNAP_OPTION_TYPE_INFO = 9, }; typedef enum gf1_cli_snapshot gf1_cli_snapshot; enum gf1_cli_snapshot_config { GF_SNAP_CONFIG_TYPE_NONE = 0, GF_SNAP_CONFIG_TYPE_SET = 0 + 1, - GF_SNAP_CONFIG_DISPLAY = 0 + 2 + GF_SNAP_CONFIG_DISPLAY = 0 + 2, }; typedef enum gf1_cli_snapshot_config gf1_cli_snapshot_config; -- cgit