cb8e9e
From ca1a22bec82e5cb2f7ed2ec88d55bdc9e5a0dca1 Mon Sep 17 00:00:00 2001
cb8e9e
From: Rajesh Joseph <rjoseph@redhat.com>
cb8e9e
Date: Wed, 26 Aug 2015 08:28:59 +0530
cb8e9e
Subject: [PATCH 316/320] gluster/cli: snapshot delete all does not work with xml
cb8e9e
cb8e9e
Problem: snapshot delete all command fails with --xml option
cb8e9e
Fix: Provided xml support for delete all command
cb8e9e
cb8e9e
Change-Id: I77cad131473a9160e188c783f442b6a38a37f758
cb8e9e
BUG: 1245077
cb8e9e
Signed-off-by: Rajesh Joseph <rjoseph@redhat.com>
cb8e9e
Reviewed-on: http://review.gluster.org/12027
cb8e9e
Tested-by: NetBSD Build System <jenkins@build.gluster.org>
cb8e9e
Tested-by: Gluster Build System <jenkins@build.gluster.com>
cb8e9e
Reviewed-by: Avra Sengupta <asengupt@redhat.com>
cb8e9e
Reviewed-on: https://code.engineering.redhat.com/gerrit/56628
cb8e9e
---
cb8e9e
 cli/src/cli-cmd-parser.c                      |    4 +-
cb8e9e
 cli/src/cli-rpc-ops.c                         |  141 ++++++++----
cb8e9e
 cli/src/cli-xml-output.c                      |  298 +++++++++++++++++++------
cb8e9e
 cli/src/cli.h                                 |   18 ++
cb8e9e
 rpc/xdr/src/cli1-xdr.x                        |    6 +-
cb8e9e
 xlators/mgmt/glusterd/src/glusterd-snapshot.c |   11 +-
cb8e9e
 6 files changed, 357 insertions(+), 121 deletions(-)
cb8e9e
cb8e9e
diff --git a/cli/src/cli-cmd-parser.c b/cli/src/cli-cmd-parser.c
cb8e9e
index 0f7b5be..0d3ca29 100644
cb8e9e
--- a/cli/src/cli-cmd-parser.c
cb8e9e
+++ b/cli/src/cli-cmd-parser.c
cb8e9e
@@ -4311,7 +4311,7 @@ cli_snap_delete_parse (dict_t *dict, const char **words, int wordcount,
cb8e9e
                 }
cb8e9e
         }
cb8e9e
 
cb8e9e
-        ret = dict_set_int32 (dict, "delete-cmd", cmd);
cb8e9e
+        ret = dict_set_int32 (dict, "sub-cmd", cmd);
cb8e9e
         if (ret) {
cb8e9e
                 gf_log ("cli", GF_LOG_ERROR, "Could not save "
cb8e9e
                         "type of snapshot delete");
cb8e9e
@@ -4391,7 +4391,7 @@ cli_snap_status_parse (dict_t *dict, const char **words, int wordcount)
cb8e9e
 
cb8e9e
 out:
cb8e9e
         if (ret == 0) {
cb8e9e
-                ret = dict_set_int32 (dict, "status-cmd", cmd);
cb8e9e
+                ret = dict_set_int32 (dict, "sub-cmd", cmd);
cb8e9e
                 if (ret) {
cb8e9e
                         gf_log ("cli", GF_LOG_ERROR, "Could not save cmd "
cb8e9e
                                 "of snapshot status");
cb8e9e
diff --git a/cli/src/cli-rpc-ops.c b/cli/src/cli-rpc-ops.c
cb8e9e
index fd76df7..413a326 100644
cb8e9e
--- a/cli/src/cli-rpc-ops.c
cb8e9e
+++ b/cli/src/cli-rpc-ops.c
cb8e9e
@@ -8694,17 +8694,32 @@ cli_snapshot_remove_reply (gf_cli_rsp *rsp, dict_t *dict, call_frame_t *frame)
cb8e9e
         GF_ASSERT (rsp);
cb8e9e
         GF_ASSERT (dict);
cb8e9e
 
cb8e9e
-        if (rsp->op_ret) {
cb8e9e
-                cli_err ("snapshot delete: failed: %s",
cb8e9e
-                        rsp->op_errstr ? rsp->op_errstr :
cb8e9e
-                        "Please check log file for details");
cb8e9e
-                ret = rsp->op_ret;
cb8e9e
-                goto out;
cb8e9e
-        }
cb8e9e
+        local = frame->local;
cb8e9e
 
cb8e9e
-        ret = dict_get_int32 (dict, "delete-cmd", &delete_cmd);
cb8e9e
+        ret = dict_get_int32 (dict, "sub-cmd", &delete_cmd);
cb8e9e
         if (ret) {
cb8e9e
-                gf_log ("cli", GF_LOG_ERROR, "Could not get delete-cmd");
cb8e9e
+                gf_log ("cli", GF_LOG_ERROR, "Could not get sub-cmd");
cb8e9e
+                goto end;
cb8e9e
+        }
cb8e9e
+
cb8e9e
+        if ((global_state->mode & GLUSTER_MODE_XML) &&
cb8e9e
+            (delete_cmd == GF_SNAP_DELETE_TYPE_SNAP)) {
cb8e9e
+                ret = cli_xml_output_snap_delete_begin (local, rsp->op_ret,
cb8e9e
+                                                        rsp->op_errno,
cb8e9e
+                                                        rsp->op_errstr);
cb8e9e
+                if (ret) {
cb8e9e
+                        gf_log ("cli", GF_LOG_ERROR, "Failed to create "
cb8e9e
+                                "xml output for delete");
cb8e9e
+                        goto end;
cb8e9e
+                }
cb8e9e
+        }
cb8e9e
+
cb8e9e
+
cb8e9e
+        if (rsp->op_ret && !(global_state->mode & GLUSTER_MODE_XML)) {
cb8e9e
+                        cli_err ("snapshot delete: failed: %s",
cb8e9e
+                                  rsp->op_errstr ? rsp->op_errstr :
cb8e9e
+                                 "Please check log file for details");
cb8e9e
+                ret = rsp->op_ret;
cb8e9e
                 goto out;
cb8e9e
         }
cb8e9e
 
cb8e9e
@@ -8727,17 +8742,37 @@ cli_snapshot_remove_reply (gf_cli_rsp *rsp, dict_t *dict, call_frame_t *frame)
cb8e9e
                 goto out;
cb8e9e
         }
cb8e9e
 
cb8e9e
-        ret = dict_get_str (dict, "snapname", &snap_name);
cb8e9e
-        if (ret) {
cb8e9e
-                gf_log ("cli", GF_LOG_ERROR, "Failed to get snapname");
cb8e9e
-                goto out;
cb8e9e
-        }
cb8e9e
+        if (global_state->mode & GLUSTER_MODE_XML) {
cb8e9e
+                ret = cli_xml_snapshot_delete (local->writer, local->doc,
cb8e9e
+                                               dict, rsp);
cb8e9e
+                if (ret) {
cb8e9e
+                        gf_log ("cli", GF_LOG_ERROR, "Failed to create "
cb8e9e
+                                "xml output for snapshot delete command");
cb8e9e
+                        goto out;
cb8e9e
+                }
cb8e9e
+                /* Error out in case of the op already failed */
cb8e9e
+                if (rsp->op_ret) {
cb8e9e
+                        ret = rsp->op_ret;
cb8e9e
+                        goto out;
cb8e9e
+                }
cb8e9e
+        } else {
cb8e9e
+                ret = dict_get_str (dict, "snapname", &snap_name);
cb8e9e
+                if (ret) {
cb8e9e
+                        gf_log ("cli", GF_LOG_ERROR, "Failed to get snapname");
cb8e9e
+                        goto out;
cb8e9e
+                }
cb8e9e
 
cb8e9e
-        cli_out ("snapshot delete: %s: snap removed successfully",
cb8e9e
-                 snap_name);
cb8e9e
+                cli_out ("snapshot delete: %s: snap removed successfully",
cb8e9e
+                         snap_name);
cb8e9e
+        }
cb8e9e
         ret = 0;
cb8e9e
 
cb8e9e
 out:
cb8e9e
+        if ((global_state->mode & GLUSTER_MODE_XML) &&
cb8e9e
+            (delete_cmd == GF_SNAP_DELETE_TYPE_SNAP)) {
cb8e9e
+                ret = cli_xml_output_snap_delete_end (local);
cb8e9e
+        }
cb8e9e
+end:
cb8e9e
         return ret;
cb8e9e
 }
cb8e9e
 
cb8e9e
@@ -9465,8 +9500,8 @@ cli_populate_req_dict_for_delete (dict_t *snap_dict, dict_t *dict, size_t index)
cb8e9e
         GF_ASSERT (snap_dict);
cb8e9e
         GF_ASSERT (dict);
cb8e9e
 
cb8e9e
-        ret = dict_set_int32 (snap_dict, "delete-cmd",
cb8e9e
-                              GF_SNAP_DELETE_TYPE_SNAP);
cb8e9e
+        ret = dict_set_int32 (snap_dict, "sub-cmd",
cb8e9e
+                              GF_SNAP_DELETE_TYPE_ITER);
cb8e9e
         if (ret) {
cb8e9e
                 gf_log ("cli", GF_LOG_ERROR, "Could not save command "
cb8e9e
                         "type in snap dictionary");
cb8e9e
@@ -9518,7 +9553,7 @@ cli_populate_req_dict_for_status (dict_t *snap_dict, dict_t *dict, int index) {
cb8e9e
         GF_ASSERT (snap_dict);
cb8e9e
         GF_ASSERT (dict);
cb8e9e
 
cb8e9e
-        ret = dict_set_uint32 (snap_dict, "status-cmd",
cb8e9e
+        ret = dict_set_uint32 (snap_dict, "sub-cmd",
cb8e9e
                                GF_SNAP_STATUS_TYPE_SNAP);
cb8e9e
         if (ret) {
cb8e9e
                 gf_log ("cli", GF_LOG_ERROR, "Could not save command "
cb8e9e
@@ -9605,7 +9640,7 @@ cli_snapshot_status (dict_t *dict, gf_cli_rsp *rsp,
cb8e9e
                 goto out;
cb8e9e
         }
cb8e9e
 
cb8e9e
-        ret = dict_get_int32 (dict, "status-cmd", &status_cmd);
cb8e9e
+        ret = dict_get_int32 (dict, "sub-cmd", &status_cmd);
cb8e9e
         if (ret) {
cb8e9e
                 gf_log ("cli", GF_LOG_ERROR, "Could not fetch status type");
cb8e9e
                 goto out;
cb8e9e
@@ -9690,9 +9725,10 @@ gf_cli_snapshot_cbk (struct rpc_req *req, struct iovec *iov,
cb8e9e
                 goto out;
cb8e9e
         }
cb8e9e
 
cb8e9e
-        /* Snapshot status command is handled separately */
cb8e9e
+        /* Snapshot status and delete command is handled separately */
cb8e9e
         if (global_state->mode & GLUSTER_MODE_XML &&
cb8e9e
-            GF_SNAP_OPTION_TYPE_STATUS != type) {
cb8e9e
+            GF_SNAP_OPTION_TYPE_STATUS != type &&
cb8e9e
+            GF_SNAP_OPTION_TYPE_DELETE != type) {
cb8e9e
                 ret = cli_xml_output_snapshot (type, dict, rsp.op_ret,
cb8e9e
                                                rsp.op_errno, rsp.op_errstr);
cb8e9e
                 if (ret) {
cb8e9e
@@ -9958,10 +9994,10 @@ gf_cli_snapshot_for_delete (call_frame_t *frame, xlator_t *this,
cb8e9e
 
cb8e9e
         options = data;
cb8e9e
 
cb8e9e
-        ret = dict_get_int32 (local->dict, "delete-cmd", &cmd);
cb8e9e
+        ret = dict_get_int32 (local->dict, "sub-cmd", &cmd);
cb8e9e
         if (ret) {
cb8e9e
                 gf_log ("cli", GF_LOG_ERROR, "Failed to get "
cb8e9e
-                        "delete-cmd");
cb8e9e
+                        "sub-cmd");
cb8e9e
                 goto out;
cb8e9e
         }
cb8e9e
 
cb8e9e
@@ -9979,7 +10015,18 @@ gf_cli_snapshot_for_delete (call_frame_t *frame, xlator_t *this,
cb8e9e
                 goto out;
cb8e9e
         }
cb8e9e
 
cb8e9e
-        if (snapcount == 0) {
cb8e9e
+        if (global_state->mode & GLUSTER_MODE_XML) {
cb8e9e
+#ifdef HAVE_LIB_XML
cb8e9e
+                ret = xmlTextWriterWriteFormatElement (local->writer,
cb8e9e
+                                                (xmlChar *)"snapCount",
cb8e9e
+                                                "%d", snapcount);
cb8e9e
+                if (ret) {
cb8e9e
+                        gf_log ("cli", GF_LOG_ERROR, "Failed to write "
cb8e9e
+                                "xml element \"snapCount\"");
cb8e9e
+                        goto out;
cb8e9e
+                }
cb8e9e
+#endif /* HAVE_LIB_XML */
cb8e9e
+        } else if (snapcount == 0) {
cb8e9e
                 cli_out ("No snapshots present");
cb8e9e
                 goto out;
cb8e9e
         }
cb8e9e
@@ -10072,9 +10119,9 @@ gf_cli_snapshot_for_status (call_frame_t *frame, xlator_t *this,
cb8e9e
         local = frame->local;
cb8e9e
         options = data;
cb8e9e
 
cb8e9e
-        ret = dict_get_int32 (local->dict, "status-cmd", &cmd);
cb8e9e
+        ret = dict_get_int32 (local->dict, "sub-cmd", &cmd);
cb8e9e
         if (ret) {
cb8e9e
-                gf_log ("cli", GF_LOG_ERROR, "Failed to get status-cmd");
cb8e9e
+                gf_log ("cli", GF_LOG_ERROR, "Failed to get sub-cmd");
cb8e9e
                 goto out;
cb8e9e
         }
cb8e9e
 
cb8e9e
@@ -10093,7 +10140,7 @@ gf_cli_snapshot_for_status (call_frame_t *frame, xlator_t *this,
cb8e9e
                 goto out;
cb8e9e
         }
cb8e9e
 
cb8e9e
-        if (snapcount == 0) {
cb8e9e
+        if (snapcount == 0 && !(global_state->mode & GLUSTER_MODE_XML)) {
cb8e9e
                 cli_out ("No snapshots present");
cb8e9e
         }
cb8e9e
 
cb8e9e
@@ -10164,12 +10211,11 @@ gf_cli_snapshot (call_frame_t *frame, xlator_t *this,
cb8e9e
 
cb8e9e
         ret = dict_get_int32 (local->dict, "type", &type);
cb8e9e
 
cb8e9e
-        if (GF_SNAP_OPTION_TYPE_STATUS == type &&
cb8e9e
-            global_state->mode & GLUSTER_MODE_XML) {
cb8e9e
-                ret = cli_xml_output_snap_status_begin (local, 0, 0, NULL);
cb8e9e
+        if (global_state->mode & GLUSTER_MODE_XML) {
cb8e9e
+                ret = cli_xml_snapshot_begin_composite_op (local);
cb8e9e
                 if (ret) {
cb8e9e
-                        gf_log ("cli", GF_LOG_ERROR, "Error creating xml "
cb8e9e
-                                "output");
cb8e9e
+                        gf_log ("cli", GF_LOG_ERROR, "Failed to begin "
cb8e9e
+                                "snapshot xml composite op");
cb8e9e
                         goto out;
cb8e9e
                 }
cb8e9e
         }
cb8e9e
@@ -10182,7 +10228,7 @@ gf_cli_snapshot (call_frame_t *frame, xlator_t *this,
cb8e9e
         if (ret) {
cb8e9e
                 gf_log ("cli", GF_LOG_ERROR, "cli_to_glusterd for "
cb8e9e
                         "snapshot failed");
cb8e9e
-                goto out;
cb8e9e
+                goto xmlend;
cb8e9e
         }
cb8e9e
 
cb8e9e
         if (GF_SNAP_OPTION_TYPE_STATUS == type) {
cb8e9e
@@ -10190,17 +10236,9 @@ gf_cli_snapshot (call_frame_t *frame, xlator_t *this,
cb8e9e
                 if (ret) {
cb8e9e
                         gf_log ("cli", GF_LOG_ERROR, "cli to glusterd "
cb8e9e
                                 "for snapshot status command failed");
cb8e9e
-                        goto out;
cb8e9e
                 }
cb8e9e
 
cb8e9e
-                if (global_state->mode & GLUSTER_MODE_XML) {
cb8e9e
-                        ret = cli_xml_output_snap_status_end (local);
cb8e9e
-                        if (ret) {
cb8e9e
-                                gf_log ("cli", GF_LOG_ERROR, "Error creating "
cb8e9e
-                                        "xml output");
cb8e9e
-                                goto out;
cb8e9e
-                        }
cb8e9e
-                }
cb8e9e
+                goto xmlend;
cb8e9e
         }
cb8e9e
 
cb8e9e
         if (GF_SNAP_OPTION_TYPE_DELETE == type) {
cb8e9e
@@ -10208,12 +10246,22 @@ gf_cli_snapshot (call_frame_t *frame, xlator_t *this,
cb8e9e
                 if (ret) {
cb8e9e
                         gf_log ("cli", GF_LOG_ERROR, "cli to glusterd "
cb8e9e
                                 "for snapshot delete command failed");
cb8e9e
-                        goto out;
cb8e9e
                 }
cb8e9e
+
cb8e9e
+                goto xmlend;
cb8e9e
         }
cb8e9e
 
cb8e9e
         ret = 0;
cb8e9e
 
cb8e9e
+xmlend:
cb8e9e
+        if (global_state->mode & GLUSTER_MODE_XML) {
cb8e9e
+                ret = cli_xml_snapshot_end_composite_op (local);
cb8e9e
+                if (ret) {
cb8e9e
+                        gf_log ("cli", GF_LOG_ERROR, "Failed to end "
cb8e9e
+                                "snapshot xml composite op");
cb8e9e
+                        goto out;
cb8e9e
+                }
cb8e9e
+        }
cb8e9e
 out:
cb8e9e
         if (ret && local && GF_SNAP_OPTION_TYPE_STATUS == type) {
cb8e9e
                 tmp_ret = dict_get_str (local->dict, "op_err_str", &err_str);
cb8e9e
@@ -10229,6 +10277,11 @@ out:
cb8e9e
         gf_log ("cli", GF_LOG_DEBUG, "Returning %d", ret);
cb8e9e
 
cb8e9e
         GF_FREE (req.dict.dict_val);
cb8e9e
+
cb8e9e
+        if (global_state->mode & GLUSTER_MODE_XML) {
cb8e9e
+                /* XML mode handles its own error */
cb8e9e
+                ret = 0;
cb8e9e
+        }
cb8e9e
         return ret;
cb8e9e
 }
cb8e9e
 
cb8e9e
diff --git a/cli/src/cli-xml-output.c b/cli/src/cli-xml-output.c
cb8e9e
index b558a9a..9960635 100644
cb8e9e
--- a/cli/src/cli-xml-output.c
cb8e9e
+++ b/cli/src/cli-xml-output.c
cb8e9e
@@ -4101,65 +4101,6 @@ out:
cb8e9e
         return ret;
cb8e9e
 }
cb8e9e
 
cb8e9e
-/* This function will generate snapshot delete output in xml format.
cb8e9e
- *
cb8e9e
- * @param writer        xmlTextWriterPtr
cb8e9e
- * @param doc           xmlDocPtr
cb8e9e
- * @param dict          dict containing delete output
cb8e9e
- *
cb8e9e
- * @return 0 on success and -1 on failure
cb8e9e
- */
cb8e9e
-static int
cb8e9e
-cli_xml_snapshot_delete (xmlTextWriterPtr writer, xmlDocPtr doc, dict_t *dict)
cb8e9e
-{
cb8e9e
-        int     ret             = -1;
cb8e9e
-        char   *str_value       = NULL;
cb8e9e
-
cb8e9e
-        GF_ASSERT (writer);
cb8e9e
-        GF_ASSERT (doc);
cb8e9e
-        GF_ASSERT (dict);
cb8e9e
-
cb8e9e
-        /* <snapDelete> */
cb8e9e
-        ret = xmlTextWriterStartElement (writer, (xmlChar *)"snapDelete");
cb8e9e
-        XML_RET_CHECK_AND_GOTO (ret, out);
cb8e9e
-
cb8e9e
-        /* <snapshot> */
cb8e9e
-        ret = xmlTextWriterStartElement (writer, (xmlChar *)"snapshot");
cb8e9e
-        XML_RET_CHECK_AND_GOTO (ret, out);
cb8e9e
-
cb8e9e
-        ret = dict_get_str (dict, "snapname", &str_value);
cb8e9e
-        if (ret) {
cb8e9e
-                gf_log ("cli", GF_LOG_ERROR, "Failed to get snap name");
cb8e9e
-                goto out;
cb8e9e
-        }
cb8e9e
-
cb8e9e
-        ret = xmlTextWriterWriteFormatElement (writer, (xmlChar *) "name",
cb8e9e
-                                               "%s", str_value);
cb8e9e
-        XML_RET_CHECK_AND_GOTO (ret, out);
cb8e9e
-
cb8e9e
-        ret = dict_get_str (dict, "snapuuid", &str_value);
cb8e9e
-        if (ret) {
cb8e9e
-                gf_log ("cli", GF_LOG_ERROR, "Failed to get snap uuid");
cb8e9e
-                goto out;
cb8e9e
-        }
cb8e9e
-
cb8e9e
-        ret = xmlTextWriterWriteFormatElement (writer, (xmlChar *) "uuid",
cb8e9e
-                                               "%s", str_value);
cb8e9e
-        XML_RET_CHECK_AND_GOTO (ret, out);
cb8e9e
-
cb8e9e
-        /* </snapshot> */
cb8e9e
-        ret = xmlTextWriterEndElement (writer);
cb8e9e
-        XML_RET_CHECK_AND_GOTO (ret, out);
cb8e9e
-
cb8e9e
-        /* </snapDelete> */
cb8e9e
-        ret = xmlTextWriterEndElement (writer);
cb8e9e
-        XML_RET_CHECK_AND_GOTO (ret, out);
cb8e9e
-
cb8e9e
-        ret = 0;
cb8e9e
-out:
cb8e9e
-
cb8e9e
-        return ret;
cb8e9e
-}
cb8e9e
 
cb8e9e
 /* This function will generate snapshot restore output in xml format.
cb8e9e
  *
cb8e9e
@@ -4908,7 +4849,7 @@ cli_xml_snapshot_status (xmlTextWriterPtr writer, xmlDocPtr doc, dict_t *dict)
cb8e9e
         ret = xmlTextWriterStartElement (writer, (xmlChar *)"snapStatus");
cb8e9e
         XML_RET_CHECK_AND_GOTO (ret, out);
cb8e9e
 
cb8e9e
-        ret = dict_get_int32 (dict, "status-cmd", &status_cmd);
cb8e9e
+        ret = dict_get_int32 (dict, "sub-cmd", &status_cmd);
cb8e9e
         if (ret) {
cb8e9e
                 gf_log ("cli", GF_LOG_ERROR, "Could not fetch status type");
cb8e9e
                 goto out;
cb8e9e
@@ -5338,6 +5279,81 @@ out:
cb8e9e
 }
cb8e9e
 #endif /* HAVE_LIB_XML */
cb8e9e
 
cb8e9e
+/* This function will generate snapshot delete output in xml format.
cb8e9e
+ *
cb8e9e
+ * @param writer        xmlTextWriterPtr
cb8e9e
+ * @param doc           xmlDocPtr
cb8e9e
+ * @param dict          dict containing delete output
cb8e9e
+ * @param rsp           cli response
cb8e9e
+ *
cb8e9e
+ * @return 0 on success and -1 on failure
cb8e9e
+ */
cb8e9e
+int
cb8e9e
+cli_xml_snapshot_delete (xmlTextWriterPtr writer, xmlDocPtr doc, dict_t *dict,
cb8e9e
+                         gf_cli_rsp *rsp)
cb8e9e
+{
cb8e9e
+        int     ret             = -1;
cb8e9e
+#ifdef HAVE_LIB_XML
cb8e9e
+        char   *str_value       = NULL;
cb8e9e
+
cb8e9e
+        GF_ASSERT (writer);
cb8e9e
+        GF_ASSERT (doc);
cb8e9e
+        GF_ASSERT (dict);
cb8e9e
+
cb8e9e
+        /* <snapshot> */
cb8e9e
+        ret = xmlTextWriterStartElement (writer, (xmlChar *)"snapshot");
cb8e9e
+        XML_RET_CHECK_AND_GOTO (ret, out);
cb8e9e
+
cb8e9e
+        ret = dict_get_str (dict, "snapname", &str_value);
cb8e9e
+        if (ret) {
cb8e9e
+                gf_log ("cli", GF_LOG_ERROR, "Failed to get snap name");
cb8e9e
+                goto xmlend;
cb8e9e
+        }
cb8e9e
+
cb8e9e
+        if (!rsp->op_ret) {
cb8e9e
+                ret = xmlTextWriterWriteFormatElement (writer,
cb8e9e
+                                                       (xmlChar *) "status",
cb8e9e
+                                                       "Success");
cb8e9e
+                XML_RET_CHECK_AND_GOTO (ret, xmlend);
cb8e9e
+        } else {
cb8e9e
+                ret = xmlTextWriterWriteFormatElement (writer,
cb8e9e
+                                                       (xmlChar *) "status",
cb8e9e
+                                                       "Failure");
cb8e9e
+                XML_RET_CHECK_AND_GOTO (ret, xmlend);
cb8e9e
+
cb8e9e
+                ret = cli_xml_output_common (writer, rsp->op_ret,
cb8e9e
+                                             rsp->op_errno,
cb8e9e
+                                             rsp->op_errstr);
cb8e9e
+                XML_RET_CHECK_AND_GOTO (ret, xmlend);
cb8e9e
+        }
cb8e9e
+
cb8e9e
+
cb8e9e
+        ret = xmlTextWriterWriteFormatElement (writer, (xmlChar *) "name",
cb8e9e
+                                               "%s", str_value);
cb8e9e
+        XML_RET_CHECK_AND_GOTO (ret, xmlend);
cb8e9e
+
cb8e9e
+        ret = dict_get_str (dict, "snapuuid", &str_value);
cb8e9e
+        if (ret) {
cb8e9e
+                gf_log ("cli", GF_LOG_ERROR, "Failed to get snap uuid");
cb8e9e
+                goto xmlend;
cb8e9e
+        }
cb8e9e
+
cb8e9e
+        ret = xmlTextWriterWriteFormatElement (writer, (xmlChar *) "uuid",
cb8e9e
+                                               "%s", str_value);
cb8e9e
+        XML_RET_CHECK_AND_GOTO (ret, out);
cb8e9e
+
cb8e9e
+xmlend:
cb8e9e
+        /* </snapshot> */
cb8e9e
+        ret = xmlTextWriterEndElement (writer);
cb8e9e
+        XML_RET_CHECK_AND_GOTO (ret, out);
cb8e9e
+
cb8e9e
+#endif /* HAVE_LIB_XML */
cb8e9e
+        ret = 0;
cb8e9e
+out:
cb8e9e
+
cb8e9e
+        return ret;
cb8e9e
+}
cb8e9e
+
cb8e9e
 int
cb8e9e
 cli_xml_output_snap_status_begin (cli_local_t *local, int op_ret, int op_errno,
cb8e9e
                                   char *op_errstr)
cb8e9e
@@ -5396,6 +5412,70 @@ out:
cb8e9e
 #endif
cb8e9e
 }
cb8e9e
 
cb8e9e
+int
cb8e9e
+cli_xml_output_snap_delete_begin (cli_local_t *local, int op_ret, int op_errno,
cb8e9e
+                                  char *op_errstr)
cb8e9e
+{
cb8e9e
+#if (HAVE_LIB_XML)
cb8e9e
+        int ret = -1;
cb8e9e
+        int delete_cmd = -1;
cb8e9e
+
cb8e9e
+        GF_ASSERT (local);
cb8e9e
+
cb8e9e
+        ret = cli_begin_xml_output (&(local->writer), &(local->doc));
cb8e9e
+        XML_RET_CHECK_AND_GOTO (ret, out);
cb8e9e
+
cb8e9e
+        ret = dict_get_int32 (local->dict, "sub-cmd", &delete_cmd);
cb8e9e
+        if (ret) {
cb8e9e
+                gf_log ("cli", GF_LOG_ERROR, "Failed to get sub-cmd");
cb8e9e
+                goto out;
cb8e9e
+        }
cb8e9e
+
cb8e9e
+        ret = cli_xml_output_common (local->writer, op_ret, op_errno,
cb8e9e
+                                             op_errstr);
cb8e9e
+        XML_RET_CHECK_AND_GOTO (ret, out);
cb8e9e
+
cb8e9e
+        /* <snapStatus> */
cb8e9e
+        ret = xmlTextWriterStartElement (local->writer,
cb8e9e
+                                         (xmlChar *) "snapDelete");
cb8e9e
+        XML_RET_CHECK_AND_GOTO (ret, out);
cb8e9e
+
cb8e9e
+        /* <snapshots> */
cb8e9e
+        ret = xmlTextWriterStartElement (local->writer, (xmlChar *)"snapshots");
cb8e9e
+        XML_RET_CHECK_AND_GOTO (ret, out);
cb8e9e
+
cb8e9e
+out:
cb8e9e
+        gf_log ("cli", GF_LOG_TRACE, "Returning %d", ret);
cb8e9e
+        return ret;
cb8e9e
+#else
cb8e9e
+        return 0;
cb8e9e
+#endif
cb8e9e
+}
cb8e9e
+
cb8e9e
+int
cb8e9e
+cli_xml_output_snap_delete_end (cli_local_t *local)
cb8e9e
+{
cb8e9e
+#if (HAVE_LIB_XML)
cb8e9e
+        int     ret = -1;
cb8e9e
+
cb8e9e
+        GF_ASSERT (local);
cb8e9e
+
cb8e9e
+        /* </snapshots> */
cb8e9e
+        ret = xmlTextWriterEndElement (local->writer);
cb8e9e
+        XML_RET_CHECK_AND_GOTO (ret, out);
cb8e9e
+
cb8e9e
+        /* </snapDelete> */
cb8e9e
+        ret = xmlTextWriterEndElement (local->writer);
cb8e9e
+        XML_RET_CHECK_AND_GOTO(ret, out);
cb8e9e
+
cb8e9e
+        ret = cli_end_xml_output (local->writer, local->doc);
cb8e9e
+out:
cb8e9e
+        gf_log ("cli", GF_LOG_TRACE, "Returning %d", ret);
cb8e9e
+        return ret;
cb8e9e
+#else
cb8e9e
+        return 0;
cb8e9e
+#endif
cb8e9e
+}
cb8e9e
 /* This function will generate xml output for all the snapshot commands
cb8e9e
  *
cb8e9e
  * @param cmd_type      command type
cb8e9e
@@ -5446,14 +5526,6 @@ cli_xml_output_snapshot (int cmd_type, dict_t *dict, int op_ret,
cb8e9e
                         goto out;
cb8e9e
                 }
cb8e9e
                 break;
cb8e9e
-        case GF_SNAP_OPTION_TYPE_DELETE:
cb8e9e
-                ret = cli_xml_snapshot_delete (writer, doc, dict);
cb8e9e
-                if (ret) {
cb8e9e
-                        gf_log ("cli", GF_LOG_ERROR, "Failed to create "
cb8e9e
-                                "xml output for snapshot delete command");
cb8e9e
-                        goto out;
cb8e9e
-                }
cb8e9e
-                break;
cb8e9e
         case GF_SNAP_OPTION_TYPE_RESTORE:
cb8e9e
                 ret = cli_xml_snapshot_restore (writer, doc, dict);
cb8e9e
                 if (ret) {
cb8e9e
@@ -5525,6 +5597,96 @@ out:
cb8e9e
 }
cb8e9e
 
cb8e9e
 int
cb8e9e
+cli_xml_snapshot_begin_composite_op (cli_local_t *local)
cb8e9e
+{
cb8e9e
+        int ret         = -1;
cb8e9e
+#ifdef HAVE_LIB_XML
cb8e9e
+        int cmd         = -1;
cb8e9e
+        int type        =  -1;
cb8e9e
+
cb8e9e
+        ret = dict_get_int32 (local->dict, "sub-cmd", &cmd);
cb8e9e
+        if (ret) {
cb8e9e
+                gf_log ("cli", GF_LOG_ERROR, "Failed to get "
cb8e9e
+                        "sub-cmd");
cb8e9e
+                ret = 0;
cb8e9e
+                goto out;
cb8e9e
+        }
cb8e9e
+
cb8e9e
+        if (cmd == GF_SNAP_STATUS_TYPE_SNAP ||
cb8e9e
+            cmd == GF_SNAP_DELETE_TYPE_SNAP){
cb8e9e
+                ret = 0;
cb8e9e
+                goto out;
cb8e9e
+        }
cb8e9e
+
cb8e9e
+        ret = dict_get_int32 (local->dict, "type", &type);
cb8e9e
+        if (ret) {
cb8e9e
+                gf_log ("cli", GF_LOG_ERROR, "Failed to get snapshot "
cb8e9e
+                        "command type from dictionary");
cb8e9e
+                goto out;
cb8e9e
+        }
cb8e9e
+
cb8e9e
+        if (GF_SNAP_OPTION_TYPE_STATUS == type)
cb8e9e
+                ret = cli_xml_output_snap_status_begin (local, 0, 0, NULL);
cb8e9e
+        else if (GF_SNAP_OPTION_TYPE_DELETE == type)
cb8e9e
+                ret = cli_xml_output_snap_delete_begin (local, 0, 0, NULL);
cb8e9e
+
cb8e9e
+        if (ret) {
cb8e9e
+                gf_log ("cli", GF_LOG_ERROR, "Error creating xml output");
cb8e9e
+                goto out;
cb8e9e
+        }
cb8e9e
+
cb8e9e
+#endif /* HAVE_LIB_XML */
cb8e9e
+        ret = 0;
cb8e9e
+out:
cb8e9e
+        return ret;
cb8e9e
+}
cb8e9e
+
cb8e9e
+int
cb8e9e
+cli_xml_snapshot_end_composite_op (cli_local_t *local)
cb8e9e
+{
cb8e9e
+        int ret         = -1;
cb8e9e
+#ifdef HAVE_LIB_XML
cb8e9e
+        int cmd         = -1;
cb8e9e
+        int type        = -1;
cb8e9e
+
cb8e9e
+        ret = dict_get_int32 (local->dict, "sub-cmd", &cmd);
cb8e9e
+        if (ret) {
cb8e9e
+                gf_log ("cli", GF_LOG_ERROR, "Failed to get "
cb8e9e
+                        "sub-cmd");
cb8e9e
+                ret = 0;
cb8e9e
+                goto out;
cb8e9e
+        }
cb8e9e
+
cb8e9e
+        if (cmd == GF_SNAP_STATUS_TYPE_SNAP ||
cb8e9e
+            cmd == GF_SNAP_DELETE_TYPE_SNAP){
cb8e9e
+                ret = 0;
cb8e9e
+                goto out;
cb8e9e
+        }
cb8e9e
+
cb8e9e
+        ret = dict_get_int32 (local->dict, "type", &type);
cb8e9e
+        if (ret) {
cb8e9e
+                gf_log ("cli", GF_LOG_ERROR, "Failed to get snapshot "
cb8e9e
+                        "command type from dictionary");
cb8e9e
+                goto out;
cb8e9e
+        }
cb8e9e
+
cb8e9e
+        if (GF_SNAP_OPTION_TYPE_STATUS == type)
cb8e9e
+                ret = cli_xml_output_snap_status_end (local);
cb8e9e
+        else if (GF_SNAP_OPTION_TYPE_DELETE == type)
cb8e9e
+                ret = cli_xml_output_snap_delete_end (local);
cb8e9e
+
cb8e9e
+        if (ret) {
cb8e9e
+                gf_log ("cli", GF_LOG_ERROR, "Error creating xml "
cb8e9e
+                                "output");
cb8e9e
+                goto out;
cb8e9e
+        }
cb8e9e
+#endif /* HAVE_LIB_XML */
cb8e9e
+        ret = 0;
cb8e9e
+out:
cb8e9e
+        return ret;
cb8e9e
+}
cb8e9e
+
cb8e9e
+int
cb8e9e
 cli_xml_snapshot_status_single_snap (cli_local_t *local, dict_t *dict,
cb8e9e
                                      char *key)
cb8e9e
 {
cb8e9e
diff --git a/cli/src/cli.h b/cli/src/cli.h
cb8e9e
index d831af0..a971d02 100644
cb8e9e
--- a/cli/src/cli.h
cb8e9e
+++ b/cli/src/cli.h
cb8e9e
@@ -428,6 +428,24 @@ int
cb8e9e
 cli_xml_output_vol_status_tasks_detail (cli_local_t *local, dict_t *dict);
cb8e9e
 
cb8e9e
 int
cb8e9e
+cli_xml_output_common (xmlTextWriterPtr writer, int op_ret, int op_errno,
cb8e9e
+                       char *op_errstr);
cb8e9e
+int
cb8e9e
+cli_xml_snapshot_delete (xmlTextWriterPtr writer, xmlDocPtr doc, dict_t *dict,
cb8e9e
+                        gf_cli_rsp *rsp);
cb8e9e
+int
cb8e9e
+cli_xml_snapshot_begin_composite_op (cli_local_t *local);
cb8e9e
+
cb8e9e
+int
cb8e9e
+cli_xml_snapshot_end_composite_op (cli_local_t *local);
cb8e9e
+
cb8e9e
+int
cb8e9e
+cli_xml_output_snap_delete_begin (cli_local_t *local, int op_ret, int op_errno,
cb8e9e
+                                  char *op_errstr);
cb8e9e
+int
cb8e9e
+cli_xml_output_snap_delete_end (cli_local_t *local);
cb8e9e
+
cb8e9e
+int
cb8e9e
 cli_xml_output_snap_status_begin (cli_local_t *local, int op_ret, int op_errno,
cb8e9e
                                   char *op_errstr);
cb8e9e
 int
cb8e9e
diff --git a/rpc/xdr/src/cli1-xdr.x b/rpc/xdr/src/cli1-xdr.x
cb8e9e
index 34f324f..73863ae 100644
cb8e9e
--- a/rpc/xdr/src/cli1-xdr.x
cb8e9e
+++ b/rpc/xdr/src/cli1-xdr.x
cb8e9e
@@ -189,13 +189,15 @@ enum gf1_cli_snapshot_config {
cb8e9e
 enum  gf1_cli_snapshot_status {
cb8e9e
         GF_SNAP_STATUS_TYPE_ALL = 0,
cb8e9e
         GF_SNAP_STATUS_TYPE_SNAP,
cb8e9e
-        GF_SNAP_STATUS_TYPE_VOL
cb8e9e
+        GF_SNAP_STATUS_TYPE_VOL,
cb8e9e
+        GF_SNAP_STATUS_TYPE_ITER
cb8e9e
 };
cb8e9e
 
cb8e9e
 enum gf1_cli_snapshot_delete {
cb8e9e
         GF_SNAP_DELETE_TYPE_ALL  = 0,
cb8e9e
         GF_SNAP_DELETE_TYPE_SNAP = 1,
cb8e9e
-        GF_SNAP_DELETE_TYPE_VOL  = 2
cb8e9e
+        GF_SNAP_DELETE_TYPE_VOL  = 2,
cb8e9e
+        GF_SNAP_DELETE_TYPE_ITER = 3
cb8e9e
 };
cb8e9e
 
cb8e9e
 struct gf_cli_req {
cb8e9e
diff --git a/xlators/mgmt/glusterd/src/glusterd-snapshot.c b/xlators/mgmt/glusterd/src/glusterd-snapshot.c
cb8e9e
index 6f10ebc..089eb61 100644
cb8e9e
--- a/xlators/mgmt/glusterd/src/glusterd-snapshot.c
cb8e9e
+++ b/xlators/mgmt/glusterd/src/glusterd-snapshot.c
cb8e9e
@@ -5506,15 +5506,16 @@ glusterd_handle_snapshot_delete (rpcsvc_request_t *req, glusterd_op_t op,
cb8e9e
         GF_ASSERT (err_str);
cb8e9e
         GF_VALIDATE_OR_GOTO (this->name, op_errno, out);
cb8e9e
 
cb8e9e
-        ret = dict_get_int32 (dict, "delete-cmd", &delete_cmd);
cb8e9e
+        ret = dict_get_int32 (dict, "sub-cmd", &delete_cmd);
cb8e9e
         if (ret) {
cb8e9e
                 gf_msg (this->name, GF_LOG_ERROR, 0,
cb8e9e
-                        GD_MSG_COMMAND_NOT_FOUND, "Failed to get delete-cmd");
cb8e9e
+                        GD_MSG_COMMAND_NOT_FOUND, "Failed to get sub-cmd");
cb8e9e
                 goto out;
cb8e9e
         }
cb8e9e
 
cb8e9e
         switch (delete_cmd) {
cb8e9e
         case GF_SNAP_DELETE_TYPE_SNAP:
cb8e9e
+        case GF_SNAP_DELETE_TYPE_ITER:
cb8e9e
                 ret = glusterd_handle_snapshot_delete_type_snap (req, op, dict,
cb8e9e
                                                                  err_str,
cb8e9e
                                                                  op_errno, len);
cb8e9e
@@ -5647,7 +5648,7 @@ glusterd_snapshot_status_prevalidate (dict_t *dict, char **op_errstr,
cb8e9e
                 goto out;
cb8e9e
         }
cb8e9e
 
cb8e9e
-        ret = dict_get_int32 (dict, "status-cmd", &cmd);
cb8e9e
+        ret = dict_get_int32 (dict, "sub-cmd", &cmd);
cb8e9e
         if (ret) {
cb8e9e
                 gf_msg (this->name, GF_LOG_ERROR, 0,
cb8e9e
                         GD_MSG_DICT_GET_FAILED,
cb8e9e
@@ -7531,7 +7532,7 @@ glusterd_snapshot_status_commit (dict_t *dict, char **op_errstr,
cb8e9e
         conf = this->private;
cb8e9e
 
cb8e9e
         GF_ASSERT (conf);
cb8e9e
-        ret = dict_get_int32 (dict, "status-cmd", &cmd);
cb8e9e
+        ret = dict_get_int32 (dict, "sub-cmd", &cmd);
cb8e9e
         if (ret) {
cb8e9e
                 gf_msg (this->name, GF_LOG_ERROR, 0,
cb8e9e
                         GD_MSG_DICT_GET_FAILED,
cb8e9e
@@ -7539,7 +7540,7 @@ glusterd_snapshot_status_commit (dict_t *dict, char **op_errstr,
cb8e9e
                 goto out;
cb8e9e
         }
cb8e9e
 
cb8e9e
-        ret = dict_set_int32 (rsp_dict, "status-cmd", cmd);
cb8e9e
+        ret = dict_set_int32 (rsp_dict, "sub-cmd", cmd);
cb8e9e
         if (ret) {
cb8e9e
                 gf_msg (this->name, GF_LOG_ERROR, 0,
cb8e9e
                         GD_MSG_DICT_SET_FAILED,
cb8e9e
-- 
cb8e9e
1.7.1
cb8e9e