diff options
| author | Rajesh Joseph <rjoseph@redhat.com> | 2014-05-05 13:37:34 +0530 | 
|---|---|---|
| committer | Vijay Bellur <vbellur@redhat.com> | 2014-07-12 09:50:25 -0700 | 
| commit | 656e6b38189d14c440a46d4d69b5ddfc5d8cfffc (patch) | |
| tree | 6c8b5c8125258816b18e79cd0e342014892d4cbe /cli/src | |
| parent | 99685f18f190a73f2a46478cac0b09f4c59834b1 (diff) | |
cli/snapshot: provide --xml support for all snapshot command
Now --xml option can be used with all snapshot command. It
will form the cli output in xml form.
Change-Id: Ifc0ac31d2a9f91e136e87f3b51a629df7dba94e8
BUG: 1096610
Signed-off-by: Rajesh Joseph <rjoseph@redhat.com>
Reviewed-on: http://review.gluster.org/7663
Reviewed-by: Sachin Pandit <spandit@redhat.com>
Reviewed-by: Vijaikumar Mallikarjuna <vmallika@redhat.com>
Tested-by: Gluster Build System <jenkins@build.gluster.com>
Reviewed-by: Vijay Bellur <vbellur@redhat.com>
Diffstat (limited to 'cli/src')
| -rw-r--r-- | cli/src/cli-rpc-ops.c | 170 | ||||
| -rw-r--r-- | cli/src/cli-xml-output.c | 1464 | ||||
| -rw-r--r-- | cli/src/cli.h | 11 | 
3 files changed, 1585 insertions, 60 deletions
diff --git a/cli/src/cli-rpc-ops.c b/cli/src/cli-rpc-ops.c index 43db8358bcf..0575440e486 100644 --- a/cli/src/cli-rpc-ops.c +++ b/cli/src/cli-rpc-ops.c @@ -8105,9 +8105,9 @@ cli_call_snapshot_info (dict_t *dict, gf_boolean_t bool_snap_driven) {          GF_ASSERT (dict); -        ret = dict_get_int32 (dict, "snap-count", &snap_count); +        ret = dict_get_int32 (dict, "snapcount", &snap_count);          if (ret) { -                gf_log ("cli", GF_LOG_ERROR, "Unable to get snap-count"); +                gf_log ("cli", GF_LOG_ERROR, "Unable to get snapcount");                  goto out;          } @@ -8149,9 +8149,9 @@ cli_get_snaps_in_volume (dict_t *dict) {          }          cli_out (INDENT_MAIN_HEAD "%s", "Volume Name", ":", get_buffer); -        ret = dict_get_int32 (dict, "snap-count", &avail); +        ret = dict_get_int32 (dict, "snapcount", &avail);          if (ret) { -                gf_log ("cli", GF_LOG_ERROR, "Could not fetch snap-count"); +                gf_log ("cli", GF_LOG_ERROR, "Could not fetch snapcount");                  goto out;          }          cli_out (INDENT_MAIN_HEAD "%d", "Snaps Taken", ":", avail); @@ -8199,7 +8199,7 @@ cli_snapshot_list (dict_t *dict) {          GF_ASSERT (dict); -        ret = dict_get_int32 (dict, "snap-count", &snapcount); +        ret = dict_get_int32 (dict, "snapcount", &snapcount);          if (ret) {                  gf_log ("cli", GF_LOG_ERROR, "Could not fetch snap count");                  goto out; @@ -8527,11 +8527,22 @@ cli_snapshot_status (dict_t *dict, gf_cli_rsp *rsp,                  goto out;          } -        ret = cli_get_single_snap_status (dict, key); -        if (ret) { -                gf_log ("cli", GF_LOG_ERROR, "Could not fetch " -                        "status of snap"); -                goto out; +        if (global_state->mode & GLUSTER_MODE_XML) { +                ret = cli_xml_snapshot_status_per_snap (local->writer, +                                                        local->doc, +                                                        dict, key); +                if (ret) { +                        gf_log ("cli", GF_LOG_ERROR, "Failed to create " +                                "xml output for snapshot status"); +                        goto out; +                } +        } else { +                ret = cli_get_single_snap_status (dict, key); +                if (ret) { +                        gf_log ("cli", GF_LOG_ERROR, "Could not fetch " +                                "status of snap"); +                        goto out; +                }          }          ret = 0; @@ -8585,6 +8596,18 @@ gf_cli_snapshot_cbk (struct rpc_req *req, struct iovec *iov,                  goto out;          } +        /* Snapshot status command is handled separately */ +        if (global_state->mode & GLUSTER_MODE_XML && +            GF_SNAP_OPTION_TYPE_STATUS != type) { +                ret = cli_xml_output_snapshot (type, dict, rsp.op_ret, +                                               rsp.op_errno, rsp.op_errstr); +                if (ret) { +                        gf_log ("cli", GF_LOG_ERROR, "Error outputting to xml"); +                } + +                goto out; +        } +          switch (type) {          case GF_SNAP_OPTION_TYPE_CREATE:                  if (rsp.op_ret) { @@ -8801,72 +8824,80 @@ gf_cli_snapshot_for_status (call_frame_t *frame, xlator_t *this,          int              snapcount      =  0;          int              i              =  0; -        if (!frame || !this || !data) +        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, "status-cmd", &cmd); +        if (ret) { +                gf_log ("cli", GF_LOG_ERROR, "Failed to get status-cmd");                  goto out; +        } -        if (frame->local) { -                local = frame->local; -        } else { +        /* Snapshot status of single snap (i.e. GF_SNAP_STATUS_TYPE_SNAP) +         * is already handled. Therefore we can return from here. +         * If want to get status of all snaps in the system or volume then +         * we should get them one by one.*/ +        if (cmd == GF_SNAP_STATUS_TYPE_SNAP) { +                ret = 0;                  goto out;          } -        options = data; +        ret = dict_get_int32 (local->dict, "status.snapcount", &snapcount); +        if (ret) { +                gf_log ("cli", GF_LOG_ERROR, "Could not get snapcount"); +                goto out; +        } -        ret = dict_get_int32 (local->dict, "status-cmd", &cmd); +        if (snapcount == 0) { +                cli_out ("No snapshots present"); +        } -        if (cmd == GF_SNAP_STATUS_TYPE_ALL || -            cmd == GF_SNAP_STATUS_TYPE_VOL) { +        for (i = 0 ; i < snapcount; i++) { +                ret = -1; -                ret = dict_get_int32 (local->dict, "status.snapcount", -                                      &snapcount); -                if (ret) { -                        gf_log ("cli", GF_LOG_ERROR, "Could not get snapcount"); +                snap_dict = dict_new(); +                if (!snap_dict)                          goto out; -                } -                if (snapcount == 0) { -                        cli_out ("No snapshots present"); +                ret = cli_populate_req_dict_for_status (snap_dict, +                                local->dict, i); +                if (ret) { +                        gf_log ("cli", GF_LOG_ERROR, "Could not " +                                        "populate snap request dictionary"); +                        goto out;                  } -                for (i = 0 ; i < snapcount; i++) { -                        ret = -1; - -                        snap_dict = dict_new(); -                        if (!snap_dict) -                                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); -                        ret = cli_populate_req_dict_for_status (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); - -                        /* Ignore the return value and error for snapshot -                         * status of type "ALL" or "VOL" -                         * -                         * Scenario : There might be case where status command -                         * and delete command might be issued at the same time. -                         * In that case when status tried to fetch detail of -                         * snap which has been deleted by concurrent command, -                         * then it will show snapshot not present. Which will -                         * not be appropriate. -                         */ -                        dict_unref (snap_dict); -                } +                /* Ignore the return value and error for snapshot +                 * status of type "ALL" or "VOL" +                 * +                 * Scenario : There might be case where status command +                 * and delete command might be issued at the same time. +                 * In that case when status tried to fetch detail of +                 * snap which has been deleted by concurrent command, +                 * then it will show snapshot not present. Which will +                 * not be appropriate. +                 */ +                dict_unref (snap_dict); +                snap_dict = NULL;          } -out: -        return ret; -        if (ret && snap_dict) +        ret = 0; +out: +        if (snap_dict)                  dict_unref (snap_dict); + +        return ret;  }  int32_t @@ -8894,6 +8925,16 @@ gf_cli_snapshot (call_frame_t *frame, xlator_t *this,          ret = dict_get_int32 (local->dict, "type", &type); +        if (GF_SNAP_OPTION_TYPE_STATUS == type && +            global_state->mode & GLUSTER_MODE_XML) { +                ret = cli_xml_output_snap_status_begin (local, 0, 0, NULL); +                if (ret) { +                        gf_log ("cli", GF_LOG_ERROR, "Error creating xml " +                                "output"); +                        goto out; +                } +        } +          ret = cli_to_glusterd (&req, frame, gf_cli_snapshot_cbk,                                 (xdrproc_t) xdr_gf_cli_req, options, @@ -8912,6 +8953,15 @@ gf_cli_snapshot (call_frame_t *frame, xlator_t *this,                                  "for snapshot status command failed");                          goto out;                  } + +                if (global_state->mode & GLUSTER_MODE_XML) { +                        ret = cli_xml_output_snap_status_end (local); +                        if (ret) { +                                gf_log ("cli", GF_LOG_ERROR, "Error creating " +                                        "xml output"); +                                goto out; +                        } +                }          }          ret = 0; diff --git a/cli/src/cli-xml-output.c b/cli/src/cli-xml-output.c index 1bf4e874647..dd38a51c6c0 100644 --- a/cli/src/cli-xml-output.c +++ b/cli/src/cli-xml-output.c @@ -3853,3 +3853,1467 @@ out:          return 0;  #endif  } + +#if (HAVE_LIB_XML) +/* This function will generate snapshot create output in xml format. + * + * @param writer        xmlTextWriterPtr + * @param doc           xmlDocPtr + * @param dict          dict containing create output + * + * @return 0 on success and -1 on failure + */ +static int +cli_xml_snapshot_create (xmlTextWriterPtr writer, xmlDocPtr doc, dict_t *dict) +{ +        int     ret             = -1; +        char   *str_value       = NULL; + +        GF_ASSERT (writer); +        GF_ASSERT (doc); +        GF_ASSERT (dict); + +        /* <snapCreate> */ +        ret = xmlTextWriterStartElement (writer, (xmlChar *)"snapCreate"); +        XML_RET_CHECK_AND_GOTO (ret, out); + +        /* <snapshot> */ +        ret = xmlTextWriterStartElement (writer, (xmlChar *)"snapshot"); +        XML_RET_CHECK_AND_GOTO (ret, out); + +        ret = dict_get_str (dict, "snapname", &str_value); +        if (ret) { +                gf_log ("cli", GF_LOG_ERROR, "Failed to get snap name"); +                goto out; +        } + +        ret = xmlTextWriterWriteFormatElement (writer, (xmlChar *) "name", +                                               "%s", str_value); +        XML_RET_CHECK_AND_GOTO (ret, out); + +        ret = dict_get_str (dict, "snapuuid", &str_value); +        if (ret) { +                gf_log ("cli", GF_LOG_ERROR, "Failed to get snap uuid"); +                goto out; +        } + +        ret = xmlTextWriterWriteFormatElement (writer, (xmlChar *) "uuid", +                                               "%s", str_value); +        XML_RET_CHECK_AND_GOTO (ret, out); + +        /* </snapshot> */ +        ret = xmlTextWriterEndElement (writer); +        XML_RET_CHECK_AND_GOTO (ret, out); + +        /* </snapCreate> */ +        ret = xmlTextWriterEndElement (writer); +        XML_RET_CHECK_AND_GOTO (ret, out); + +        ret = 0; +out: +        return ret; +} + +/* This function will generate snapshot delete output in xml format. + * + * @param writer        xmlTextWriterPtr + * @param doc           xmlDocPtr + * @param dict          dict containing delete output + * + * @return 0 on success and -1 on failure + */ +static int +cli_xml_snapshot_delete (xmlTextWriterPtr writer, xmlDocPtr doc, dict_t *dict) +{ +        int     ret             = -1; +        char   *str_value       = NULL; + +        GF_ASSERT (writer); +        GF_ASSERT (doc); +        GF_ASSERT (dict); + +        /* <snapDelete> */ +        ret = xmlTextWriterStartElement (writer, (xmlChar *)"snapDelete"); +        XML_RET_CHECK_AND_GOTO (ret, out); + +        /* <snapshot> */ +        ret = xmlTextWriterStartElement (writer, (xmlChar *)"snapshot"); +        XML_RET_CHECK_AND_GOTO (ret, out); + +        ret = dict_get_str (dict, "snapname", &str_value); +        if (ret) { +                gf_log ("cli", GF_LOG_ERROR, "Failed to get snap name"); +                goto out; +        } + +        ret = xmlTextWriterWriteFormatElement (writer, (xmlChar *) "name", +                                               "%s", str_value); +        XML_RET_CHECK_AND_GOTO (ret, out); + +        ret = dict_get_str (dict, "snapuuid", &str_value); +        if (ret) { +                gf_log ("cli", GF_LOG_ERROR, "Failed to get snap uuid"); +                goto out; +        } + +        ret = xmlTextWriterWriteFormatElement (writer, (xmlChar *) "uuid", +                                               "%s", str_value); +        XML_RET_CHECK_AND_GOTO (ret, out); + +        /* </snapshot> */ +        ret = xmlTextWriterEndElement (writer); +        XML_RET_CHECK_AND_GOTO (ret, out); + +        /* </snapDelete> */ +        ret = xmlTextWriterEndElement (writer); +        XML_RET_CHECK_AND_GOTO (ret, out); + +        ret = 0; +out: + +        return ret; +} + +/* This function will generate snapshot restore output in xml format. + * + * @param writer        xmlTextWriterPtr + * @param doc           xmlDocPtr + * @param dict          dict containing restore output + * + * @return 0 on success and -1 on failure + */ +static int +cli_xml_snapshot_restore (xmlTextWriterPtr writer, xmlDocPtr doc, dict_t *dict) +{ +        int     ret             = -1; +        char   *str_value       = NULL; + +        GF_ASSERT (writer); +        GF_ASSERT (doc); +        GF_ASSERT (dict); + +        /* <snapRestore> */ +        ret = xmlTextWriterStartElement (writer, (xmlChar *)"snapRestore"); +        XML_RET_CHECK_AND_GOTO (ret, out); + +        /* <volume> */ +        ret = xmlTextWriterStartElement (writer, (xmlChar *)"volume"); +        XML_RET_CHECK_AND_GOTO (ret, out); + +        ret = dict_get_str (dict, "volname", &str_value); +        if (ret) { +                gf_log ("cli", GF_LOG_ERROR, "Failed to get vol name"); +                goto out; +        } + +        ret = xmlTextWriterWriteFormatElement (writer, (xmlChar *) "name", +                                               "%s", str_value); +        XML_RET_CHECK_AND_GOTO (ret, out); + +        ret = dict_get_str (dict, "volid", &str_value); +        if (ret) { +                gf_log ("cli", GF_LOG_ERROR, "Failed to get volume id"); +                goto out; +        } + +        ret = xmlTextWriterWriteFormatElement (writer, (xmlChar *) "uuid", +                                               "%s", str_value); +        XML_RET_CHECK_AND_GOTO (ret, out); + +        /* </volume> */ +        ret = xmlTextWriterEndElement (writer); +        XML_RET_CHECK_AND_GOTO (ret, out); + + +        /* <snapshot> */ +        ret = xmlTextWriterStartElement (writer, (xmlChar *)"snapshot"); +        XML_RET_CHECK_AND_GOTO (ret, out); + +        ret = dict_get_str (dict, "snapname", &str_value); +        if (ret) { +                gf_log ("cli", GF_LOG_ERROR, "Failed to get snap name"); +                goto out; +        } + +        ret = xmlTextWriterWriteFormatElement (writer, (xmlChar *) "name", +                                               "%s", str_value); +        XML_RET_CHECK_AND_GOTO (ret, out); + +        ret = dict_get_str (dict, "snapuuid", &str_value); +        if (ret) { +                gf_log ("cli", GF_LOG_ERROR, "Failed to get snap uuid"); +                goto out; +        } + +        ret = xmlTextWriterWriteFormatElement (writer, (xmlChar *) "uuid", +                                               "%s", str_value); +        XML_RET_CHECK_AND_GOTO (ret, out); + +        /* </snapshot> */ +        ret = xmlTextWriterEndElement (writer); +        XML_RET_CHECK_AND_GOTO (ret, out); + +        /* </snapRestore> */ +        ret = xmlTextWriterEndElement (writer); +        XML_RET_CHECK_AND_GOTO (ret, out); + +        ret = 0; +out: + +        return ret; +} + +/* This function will generate snapshot list output in xml format. + * + * @param writer        xmlTextWriterPtr + * @param doc           xmlDocPtr + * @param dict          dict containing list output + * + * @return 0 on success and -1 on failure + */ +static int +cli_xml_snapshot_list (xmlTextWriterPtr writer, xmlDocPtr doc, dict_t *dict) +{ +        int     ret             = -1; +        int     i               = 0; +        int     snapcount       = 0; +        char   *str_value       = NULL; +        char    key[PATH_MAX]   = ""; + +        GF_ASSERT (writer); +        GF_ASSERT (doc); +        GF_ASSERT (dict); + +        /* <snapList> */ +        ret = xmlTextWriterStartElement (writer, (xmlChar *)"snapList"); +        XML_RET_CHECK_AND_GOTO (ret, out); + +        ret = dict_get_int32 (dict, "snapcount", &snapcount); +        if (ret) { +                gf_log ("cli", GF_LOG_ERROR, "Failed to get snapcount"); +                goto out; +        } + +        ret = xmlTextWriterWriteFormatElement (writer, (xmlChar *) "count", +                                               "%d", snapcount); +        XML_RET_CHECK_AND_GOTO (ret, out); + +        for (i = 1; i <= snapcount; ++i) { +                ret = snprintf (key, sizeof (key), "snapname%d", i); +                if (ret < 0) { +                        goto out; +                } + +                ret = dict_get_str (dict, key, &str_value); +                if (ret) { +                        gf_log ("cli", GF_LOG_ERROR, "Could not get %s ", key); +                        goto out; +                } else { +                        ret = xmlTextWriterWriteFormatElement (writer, +                                        (xmlChar *)"snapshot", "%s", str_value); +                        XML_RET_CHECK_AND_GOTO (ret, out); +                } +        } + +        /* </snapList> */ +        ret = xmlTextWriterEndElement (writer); +        XML_RET_CHECK_AND_GOTO (ret, out); + +        ret = 0; +out: + +        return ret; +} + +/* This function will generate xml output for origin volume + * of the given snapshot. + * + * @param writer        xmlTextWriterPtr + * @param doc           xmlDocPtr + * @param dict          dict containing info output + * @param keyprefix     prefix for dictionary key + * + * @return 0 on success and -1 on failure + */ +static int +cli_xml_snapshot_info_orig_vol (xmlTextWriterPtr writer, xmlDocPtr doc, +                                dict_t *dict, char *keyprefix) +{ +        int     ret             = -1; +        int     value           = 0; +        char   *buffer          = NULL; +        char    key [PATH_MAX]  = ""; + +        GF_ASSERT (dict); +        GF_ASSERT (keyprefix); +        GF_ASSERT (writer); +        GF_ASSERT (doc); + +        /* <originVolume> */ +        ret = xmlTextWriterStartElement (writer, (xmlChar *)"originVolume"); +        XML_RET_CHECK_AND_GOTO (ret, out); + +        snprintf (key, sizeof (key), "%sorigin-volname", keyprefix); + +        ret = dict_get_str (dict, key, &buffer); +        if (ret) { +                gf_log ("cli", GF_LOG_WARNING, "Failed to get %s", key); +                goto out; +        } + +        ret = xmlTextWriterWriteFormatElement (writer, (xmlChar *) "name", +                                               "%s", buffer); +        XML_RET_CHECK_AND_GOTO (ret, out); + +        snprintf (key, sizeof (key), "%ssnapcount", keyprefix); + +        ret = dict_get_int32 (dict, key, &value); +        if (ret) { +                gf_log ("cli", GF_LOG_ERROR, "Failed to get %s", key); +                goto out; +        } + +        ret = xmlTextWriterWriteFormatElement (writer, (xmlChar *) "snapCount", +                                               "%d", value); +        XML_RET_CHECK_AND_GOTO (ret, out); + +        snprintf (key, sizeof (key), "%ssnaps-available", keyprefix); + +        ret = dict_get_int32 (dict, key, &value); +        if (ret) { +                gf_log ("cli", GF_LOG_ERROR, "Failed to get %s", key); +                goto out; +        } + +        ret = xmlTextWriterWriteFormatElement (writer, +                                (xmlChar *) "snapRemaining", "%d", value); +        XML_RET_CHECK_AND_GOTO (ret, out); + +        /* </originVolume> */ +        ret = xmlTextWriterEndElement (writer); +        XML_RET_CHECK_AND_GOTO (ret, out); + +        ret = 0; +out: +        return ret; +} + +/* This function will generate xml output of snapshot volume info. + * + * @param writer        xmlTextWriterPtr + * @param doc           xmlDocPtr + * @param dict          dict containing info output + * @param keyprefix     key prefix for dictionary + * @param snap_driven   boolean to check if output is based of volume + *                      or snapshot + * + * @return 0 on success and -1 on failure + */ +static int +cli_xml_snapshot_info_snap_vol (xmlTextWriterPtr writer, xmlDocPtr doc, +                                dict_t *dict, char *keyprefix, +                                gf_boolean_t snap_driven) +{ +        char            key [PATH_MAX]          = ""; +        char           *buffer                  = NULL; +        int             value                   = 0; +        int             ret                     = -1; + +        GF_ASSERT (dict); +        GF_ASSERT (keyprefix); +        GF_ASSERT (writer); +        GF_ASSERT (doc); + +        /* <snapVolume> */ +        ret = xmlTextWriterStartElement (writer, (xmlChar *)"snapVolume"); +        XML_RET_CHECK_AND_GOTO (ret, out); + +        snprintf (key, sizeof (key), "%s.volname", keyprefix); + +        ret = dict_get_str (dict, key, &buffer); +        if (ret) { +                gf_log ("cli", GF_LOG_ERROR, "Failed to get %s", key); +                goto out; +        } + +        ret = xmlTextWriterWriteFormatElement (writer, (xmlChar *) "name", +                                               "%s", buffer); +        XML_RET_CHECK_AND_GOTO (ret, out); + +        snprintf (key, sizeof (key), "%s.vol-status", keyprefix); + +        ret = dict_get_str (dict, key, &buffer); +        if (ret) { +                gf_log ("cli", GF_LOG_ERROR, "Failed to get %s", key); +                goto out; +        } + +        ret = xmlTextWriterWriteFormatElement (writer, (xmlChar *) "status", +                                               "%s", buffer); +        XML_RET_CHECK_AND_GOTO (ret, out); + +        /* If the command is snap_driven then we need to show origin volume +         * info. Else this is shown in the start of info display.*/ +        if (snap_driven) { +                snprintf (key, sizeof (key), "%s.", keyprefix); +                ret = cli_xml_snapshot_info_orig_vol (writer, doc, dict, key); +                if (ret) { +                        gf_log ("cli", GF_LOG_ERROR, "Failed to create " +                                "xml output for snapshot's origin volume"); +                        goto out; +                } +        } + +        /* </snapVolume> */ +        ret = xmlTextWriterEndElement (writer); +        XML_RET_CHECK_AND_GOTO (ret, out); + +        ret = 0; +out: +        return ret; +} + +/* This function will generate snapshot info of individual snapshot + * in xml format. + * + * @param writer        xmlTextWriterPtr + * @param doc           xmlDocPtr + * @param dict          dict containing info output + * @param keyprefix     key prefix for dictionary + * @param snap_driven   boolean to check if output is based of volume + *                      or snapshot + * + * @return 0 on success and -1 on failure + */ +static int +cli_xml_snapshot_info_per_snap (xmlTextWriterPtr writer, xmlDocPtr doc, +                                dict_t *dict, char *keyprefix, +                                gf_boolean_t snap_driven) +{ +        char            key_buffer[PATH_MAX]    = ""; +        char           *buffer                  = NULL; +        int             volcount                = 0; +        int             ret                     = -1; +        int             i                       = 0; + +        GF_ASSERT (dict); +        GF_ASSERT (keyprefix); +        GF_ASSERT (writer); +        GF_ASSERT (doc); + +        /* <snapshot> */ +        ret = xmlTextWriterStartElement (writer, (xmlChar *)"snapshot"); +        XML_RET_CHECK_AND_GOTO (ret, out); + +        snprintf (key_buffer, sizeof (key_buffer), "%s.snapname", +                  keyprefix); + +        ret = dict_get_str (dict, key_buffer, &buffer); +        if (ret) { +                gf_log ("cli", GF_LOG_ERROR, "Unable to fetch snapname %s ", +                        key_buffer); +                goto out; +        } + +        ret = xmlTextWriterWriteFormatElement (writer, (xmlChar *) "name", +                                               "%s", buffer); +        XML_RET_CHECK_AND_GOTO (ret, out); + +        snprintf (key_buffer, sizeof (key_buffer), "%s.snap-id", keyprefix); + +        ret = dict_get_str (dict, key_buffer, &buffer); +        if (ret) { +                gf_log ("cli", GF_LOG_ERROR, "Unable to fetch snap-id %s ", +                                key_buffer); +                goto out; +        } + +        ret = xmlTextWriterWriteFormatElement (writer, (xmlChar *) "uuid", +                                               "%s", buffer); +        XML_RET_CHECK_AND_GOTO (ret, out); + +        snprintf (key_buffer, sizeof (key_buffer), "%s.snap-desc", keyprefix); + +        ret = dict_get_str (dict, key_buffer, &buffer); +        if (!ret) { +                ret = xmlTextWriterWriteFormatElement (writer, +                                                (xmlChar *) "description", +                                                "%s", buffer); +                XML_RET_CHECK_AND_GOTO (ret, out); +        } + +        snprintf (key_buffer, sizeof (key_buffer), "%s.snap-time", keyprefix); + +        ret = dict_get_str (dict, key_buffer, &buffer); +        if (ret) { +                gf_log ("cli", GF_LOG_ERROR, "Unable to fetch snap-time %s ", +                                keyprefix); +                goto out; +        } + +        ret = xmlTextWriterWriteFormatElement (writer, +                                               (xmlChar *) "createTime", +                                               "%s", buffer); +        XML_RET_CHECK_AND_GOTO (ret, out); + +        snprintf (key_buffer, sizeof (key_buffer), "%s.vol-count", keyprefix); +        ret = dict_get_int32 (dict, key_buffer, &volcount); +        if (ret) { +                gf_log ("cli", GF_LOG_ERROR, "Fail to get snap vol count"); +                goto out; +        } + +        ret = xmlTextWriterWriteFormatElement (writer, +                                               (xmlChar *) "volCount", +                                               "%d", volcount); +        XML_RET_CHECK_AND_GOTO (ret, out); + +        ret = dict_get_int32 (dict, key_buffer, &volcount); +        /* Display info of each snapshot volume */ +        for (i = 1 ; i <= volcount ; i++) { +                snprintf (key_buffer, sizeof (key_buffer), "%s.vol%d", +                          keyprefix, i); + +                ret = cli_xml_snapshot_info_snap_vol (writer, doc, dict, +                                                      key_buffer, snap_driven); +                if (ret) { +                        gf_log ("cli", GF_LOG_ERROR, "Could not list " +                                        "details of volume in a snap"); +                        goto out; +                } +        } + +        /* </snapshot> */ +        ret = xmlTextWriterEndElement (writer); +        XML_RET_CHECK_AND_GOTO (ret, out); +out: +        return ret; +} + +/* This function will generate snapshot info output in xml format. + * + * @param writer        xmlTextWriterPtr + * @param doc           xmlDocPtr + * @param dict          dict containing info output + * + * @return 0 on success and -1 on failure + */ +static int +cli_xml_snapshot_info (xmlTextWriterPtr writer, xmlDocPtr doc, dict_t *dict) +{ +        int             ret             = -1; +        int             i               = 0; +        int             snapcount       = 0; +        char            key [PATH_MAX]  = ""; +        char           *str_value       = NULL; +        gf_boolean_t    snap_driven     = _gf_false; + +        GF_ASSERT (writer); +        GF_ASSERT (doc); +        GF_ASSERT (dict); + +        /* <snapInfo> */ +        ret = xmlTextWriterStartElement (writer, (xmlChar *)"snapInfo"); +        XML_RET_CHECK_AND_GOTO (ret, out); + +        snap_driven = dict_get_str_boolean (dict, "snap-driven", _gf_false); + +        /* If the approach is volume based then we should display orgin volume +         * information first followed by per snap info*/ +        if (!snap_driven) { +                ret = cli_xml_snapshot_info_orig_vol (writer, doc, dict, ""); +                if (ret) { +                        gf_log ("cli", GF_LOG_ERROR, "Failed to create " +                                "xml output for snapshot's origin volume"); +                        goto out; +                } +        } + +        ret = dict_get_int32 (dict, "snapcount", &snapcount); +        if (ret) { +                gf_log ("cli", GF_LOG_ERROR, "Failed to get snapcount"); +                goto out; +        } + +        ret = xmlTextWriterWriteFormatElement (writer, (xmlChar *) "count", +                                               "%d", snapcount); +        XML_RET_CHECK_AND_GOTO (ret, out); + +        /* <snapshots> */ +        ret = xmlTextWriterStartElement (writer, (xmlChar *)"snapshots"); +        XML_RET_CHECK_AND_GOTO (ret, out); + +        /* Get snapshot info of individual snapshots */ +        for (i = 1; i <= snapcount; ++i) { +                snprintf (key, sizeof (key), "snap%d", i); + +                ret = cli_xml_snapshot_info_per_snap (writer, doc, dict, +                                                      key, snap_driven); +                if (ret) { +                        gf_log ("cli", GF_LOG_ERROR, "Could not get %s ", key); +                        goto out; +                } +        } + +        /* </snapshots> */ +        ret = xmlTextWriterEndElement (writer); +        XML_RET_CHECK_AND_GOTO (ret, out); + +        /* </snapInfo> */ +        ret = xmlTextWriterEndElement (writer); +        XML_RET_CHECK_AND_GOTO (ret, out); + +        ret = 0; +out: + +        return ret; +} + +/* This function will generate snapshot status of individual + * snapshot volume in xml format. + * + * @param writer        xmlTextWriterPtr + * @param doc           xmlDocPtr + * @param dict          dict containing status output + * @param keyprefix     key prefix for dictionary + * + * @return 0 on success and -1 on failure + */ +static int +cli_xml_snapshot_volume_status (xmlTextWriterPtr writer, xmlDocPtr doc, +                                dict_t *dict, const char *keyprefix) +{ +        int     ret             = -1; +        int     brickcount      = 0; +        int     i               = 0; +        int     value           = 0; +        int     pid             = 0; +        char   *buffer          = NULL; +        char    key[PATH_MAX]   = ""; + +        GF_ASSERT (writer); +        GF_ASSERT (doc); +        GF_ASSERT (dict); +        GF_ASSERT (keyprefix); + +        snprintf (key, sizeof (key), "%s.brickcount", keyprefix); + +        ret = dict_get_int32 (dict, key, &brickcount); +        if (ret) { +                gf_log ("cli", GF_LOG_ERROR, "Failed to fetch brickcount"); +                goto out; +        } + +        ret = xmlTextWriterWriteFormatElement (writer, (xmlChar *) "brickCount", +                                               "%d", brickcount); +        XML_RET_CHECK_AND_GOTO (ret, out); + +        /* Get status of every brick belonging to the snapshot volume */ +        for (i = 0 ; i < brickcount ; i++) { +                /* <snapInfo> */ +                ret = xmlTextWriterStartElement (writer, (xmlChar *)"brick"); +                XML_RET_CHECK_AND_GOTO (ret, out); + +                snprintf (key, sizeof (key), "%s.brick%d.path", keyprefix, i); + +                ret = dict_get_str (dict, key, &buffer); +                if (ret) { +                        gf_log ("cli", GF_LOG_INFO, "Unable to get Brick Path"); +                        goto out; +                } + +                ret = xmlTextWriterWriteFormatElement (writer, +                                        (xmlChar *) "path", "%s", buffer); +                XML_RET_CHECK_AND_GOTO (ret, out); + +                snprintf (key, sizeof (key), "%s.brick%d.vgname", +                          keyprefix, i); + +                ret = dict_get_str (dict, key, &buffer); +                if (ret) { +                        gf_log ("cli", GF_LOG_INFO, +                                "Unable to get Volume Group"); +                        goto out; +                } + +                ret = xmlTextWriterWriteFormatElement (writer, +                                        (xmlChar *) "volumeGroup", +                                        "%s", buffer); +                XML_RET_CHECK_AND_GOTO (ret, out); + +                snprintf (key, sizeof (key), "%s.brick%d.status", keyprefix, i); + +                ret = dict_get_str (dict, key, &buffer); +                if (ret) { +                        gf_log ("cli", GF_LOG_ERROR, +                                "Unable to get Brick Running"); +                        goto out; +                } + +                snprintf (key, sizeof (key), "%s.brick%d.pid", keyprefix, i); + +                ret = dict_get_int32 (dict, key, &pid); +                if (ret) { +                        gf_log ("cli", GF_LOG_ERROR, "Unable to get pid"); +                        goto out; +                } + +                ret = xmlTextWriterWriteFormatElement (writer, +                                        (xmlChar *) "pid", "%d", pid); +                XML_RET_CHECK_AND_GOTO (ret, out); + +                snprintf (key, sizeof (key), "%s.brick%d.data", keyprefix, i); + +                ret = dict_get_str (dict, key, &buffer); +                if (ret) { +                        gf_log ("cli", GF_LOG_ERROR, +                                        "Unable to get Data Percent"); +                        goto out; +                } + +                ret = xmlTextWriterWriteFormatElement (writer, +                                                       (xmlChar *) "lvUsage", +                                                       "%s", buffer); +                XML_RET_CHECK_AND_GOTO (ret, out); + +                snprintf (key, sizeof (key), "%s.brick%d.lvsize", +                          keyprefix, i); +                ret = dict_get_str (dict, key, &buffer); +                if (ret) { +                        gf_log ("cli", GF_LOG_INFO, "Unable to get LV Size"); +                        goto out; +                } + +                /* Truncate any newline character */ +                buffer = strtok (buffer, "\n"); + +                ret = xmlTextWriterWriteFormatElement (writer, +                                                       (xmlChar *) "lvSize", +                                                       "%s", buffer); +                XML_RET_CHECK_AND_GOTO (ret, out); + +                /* </brick> */ +                ret = xmlTextWriterEndElement (writer); +                XML_RET_CHECK_AND_GOTO (ret, out); +        } + +out: +        return ret; +} + +/* This function will generate snapshot status of individual + * snapshot in xml format. + * + * @param writer        xmlTextWriterPtr + * @param doc           xmlDocPtr + * @param dict          dict containing status output + * + * @return 0 on success and -1 on failure + */ +int +cli_xml_snapshot_status_per_snap (xmlTextWriterPtr writer, xmlDocPtr doc, +                                  dict_t *dict, const char *keyprefix) +{ +        int     ret             = -1; +        int     snapcount       = 0; +        int     volcount        = 0; +        int     i               = 0; +        char   *buffer          = NULL; +        char    key [PATH_MAX]  = ""; + +        GF_ASSERT (writer); +        GF_ASSERT (doc); +        GF_ASSERT (dict); +        GF_ASSERT (keyprefix); + +        ret = xmlTextWriterStartElement (writer, (xmlChar *)"snapshot"); +        XML_RET_CHECK_AND_GOTO (ret, out); + +        snprintf (key, sizeof (key), "%s.snapname", keyprefix); + +        ret = dict_get_str (dict, key, &buffer); +        if (ret) { +                gf_log ("cli", GF_LOG_ERROR, "Unable to get snapname"); +                goto out; +        } + +        ret = xmlTextWriterWriteFormatElement (writer, (xmlChar *) "name", +                                               "%s", buffer); +        XML_RET_CHECK_AND_GOTO (ret, out); + +        snprintf (key, sizeof (key), "%s.uuid", keyprefix); + +        ret = dict_get_str (dict, key, &buffer); +        if (ret) { +                gf_log ("cli", GF_LOG_ERROR, "Unable to get snap UUID"); +                goto out; +        } + +        ret = xmlTextWriterWriteFormatElement (writer, (xmlChar *) "uuid", +                                               "%s", buffer); +        XML_RET_CHECK_AND_GOTO (ret, out); + +        snprintf (key, sizeof (key), "%s.volcount", keyprefix); + +        ret = dict_get_int32 (dict, key, &volcount); +        if (ret) { +                gf_log ("cli", GF_LOG_ERROR, "Unable to get volume count"); +                goto out; +        } + +        ret = xmlTextWriterWriteFormatElement (writer, (xmlChar *) "volCount", +                                               "%d", volcount); +        XML_RET_CHECK_AND_GOTO (ret, out); + +        /* Get snapshot status of individual snapshot volume */ +        for (i = 0 ; i < volcount ; i++) { +                /* <volume> */ +                ret = xmlTextWriterStartElement (writer, (xmlChar *)"volume"); +                XML_RET_CHECK_AND_GOTO (ret, out); + +                snprintf (key, sizeof (key), "%s.vol%d", keyprefix, i); + +                ret = cli_xml_snapshot_volume_status (writer, doc, +                                                             dict, key); +                if (ret) { +                        gf_log ("cli", GF_LOG_ERROR, +                                        "Could not get snap volume status"); +                        goto out; +                } + +                /* </volume> */ +                ret = xmlTextWriterEndElement (writer); +                XML_RET_CHECK_AND_GOTO (ret, out); +        } + +        /* </snapshot> */ +        ret = xmlTextWriterEndElement (writer); +        XML_RET_CHECK_AND_GOTO (ret, out); + +        ret = 0; +out: +        return ret; +} + +/* This function will generate snapshot status output in xml format. + * + * @param writer        xmlTextWriterPtr + * @param doc           xmlDocPtr + * @param dict          dict containing status output + * + * @return 0 on success and -1 on failure + */ +static int +cli_xml_snapshot_status (xmlTextWriterPtr writer, xmlDocPtr doc, dict_t *dict) +{ +        int     ret             = -1; +        int     snapcount       = 0; +        int     i               = 0; +        int     status_cmd      = 0; +        char   *str_value       = NULL; +        char    key [PATH_MAX]  = ""; + +        GF_ASSERT (writer); +        GF_ASSERT (doc); +        GF_ASSERT (dict); + +        /* <snapStatus> */ +        ret = xmlTextWriterStartElement (writer, (xmlChar *)"snapStatus"); +        XML_RET_CHECK_AND_GOTO (ret, out); + +        ret = dict_get_int32 (dict, "status-cmd", &status_cmd); +        if (ret) { +                gf_log ("cli", GF_LOG_ERROR, "Could not fetch status type"); +                goto out; +        } + +        if (GF_SNAP_STATUS_TYPE_SNAP == status_cmd) { +                snapcount = 1; +        } else { +                ret = dict_get_int32 (dict, "status.snapcount", &snapcount); +                if (ret) { +                        gf_log ("cli", GF_LOG_ERROR, "Could not get snapcount"); +                        goto out; +                } + +                ret = xmlTextWriterWriteFormatElement (writer, +                                                       (xmlChar *) "count", +                                                       "%d", snapcount); +                XML_RET_CHECK_AND_GOTO (ret, out); +        } + +        for (i = 0 ; i < snapcount; i++) { +                snprintf (key, sizeof (key), "status.snap%d", i); + +                ret = cli_xml_snapshot_status_per_snap (writer, doc, +                                                               dict, key); +                if (ret < 0) { +                        gf_log ("cli", GF_LOG_ERROR, "failed to create xml " +                                "output for snapshot status"); +                        goto out; +                } +        } + +        /* </snapStatus> */ +        ret = xmlTextWriterEndElement (writer); +        XML_RET_CHECK_AND_GOTO (ret, out); + +        ret = 0; +out: + +        return ret; +} + +/* This function will generate snapshot config show output in xml format. + * + * @param writer        xmlTextWriterPtr + * @param doc           xmlDocPtr + * @param dict          dict containing status output + * + * @return 0 on success and -1 on failure + */ +static int +cli_xml_snapshot_config_show (xmlTextWriterPtr writer, +                              xmlDocPtr doc, dict_t *dict) +{ +        int             ret             = -1; +        uint64_t        i               = 0; +        uint64_t        value           = 0; +        uint64_t        volcount        = 0; +        char            buf[PATH_MAX]   = ""; +        char           *str_value       = NULL; + +        GF_ASSERT (writer); +        GF_ASSERT (doc); +        GF_ASSERT (dict); + +        /* <systemConfig> */ +        ret = xmlTextWriterStartElement (writer, +                        (xmlChar *)"systemConfig"); +        XML_RET_CHECK_AND_GOTO (ret, out); + +        ret = dict_get_uint64 (dict, "snap-max-hard-limit", &value); +        if (ret) { +                gf_log ("cli", GF_LOG_ERROR, "Failed to get " +                        "snap-max-hard-limit"); +                goto out; +        } + +        ret = xmlTextWriterWriteFormatElement (writer, +                        (xmlChar *) "hardLimit", "%"PRIu64, value); +        XML_RET_CHECK_AND_GOTO (ret, out); + +        ret = dict_get_uint64 (dict, "snap-max-soft-limit", &value); +        if (ret) { +                gf_log ("cli", GF_LOG_ERROR, "Failed to get " +                        "snap-max-soft-limit"); +                goto out; +        } + +        ret = xmlTextWriterWriteFormatElement (writer, +                        (xmlChar *) "softLimit", +                        "%"PRIu64"%%", value); +        XML_RET_CHECK_AND_GOTO (ret, out); + +        ret = dict_get_str (dict, "auto-delete", &str_value); +        if (ret) { +                gf_log ("cli", GF_LOG_ERROR, "Could not fetch auto-delet"); +                goto out; +        } + +        ret = xmlTextWriterWriteFormatElement (writer, +                        (xmlChar *) "autoDelete", "%s", str_value); +        XML_RET_CHECK_AND_GOTO (ret, out); + +        /* </systemConfig> */ +        ret = xmlTextWriterEndElement (writer); +        XML_RET_CHECK_AND_GOTO (ret, out); + +        /* <volumeConfig> */ +        ret = xmlTextWriterStartElement (writer, (xmlChar *)"volumeConfig"); +        XML_RET_CHECK_AND_GOTO (ret, out); + +        ret = dict_get_uint64 (dict, "voldisplaycount", &volcount); +        if (ret) { +                gf_log ("cli", GF_LOG_ERROR, "Could not fetch volcount"); +                goto out; +        } + +        /* Get config of all the volumes */ +        for (i = 0; i < volcount; i++) { +                /* <volume> */ +                ret = xmlTextWriterStartElement (writer, (xmlChar *)"volume"); +                XML_RET_CHECK_AND_GOTO (ret, out); + +                snprintf (buf, sizeof(buf), "volume%"PRIu64"-volname", i); +                ret = dict_get_str (dict, buf, &str_value); +                if (ret) { +                        gf_log ("cli", GF_LOG_ERROR, "Could not fetch %s", buf); +                        goto out; +                } + +                ret = xmlTextWriterWriteFormatElement (writer, +                                (xmlChar *) "name", "%s", str_value); +                XML_RET_CHECK_AND_GOTO (ret, out); + + +                snprintf (buf, sizeof(buf), +                                "volume%"PRIu64"-snap-max-hard-limit", i); +                ret = dict_get_uint64 (dict, buf, &value); +                if (ret) { +                        gf_log ("cli", GF_LOG_ERROR, "Could not fetch %s", buf); +                        goto out; +                } + +                ret = xmlTextWriterWriteFormatElement (writer, +                                (xmlChar *) "hardLimit", "%"PRIu64, value); +                XML_RET_CHECK_AND_GOTO (ret, out); + +                snprintf (buf, sizeof(buf), +                                "volume%"PRIu64"-active-hard-limit", i); +                ret = dict_get_uint64 (dict, buf, &value); +                if (ret) { +                        gf_log ("cli", GF_LOG_ERROR, "Could not fetch" +                                " effective snap_max_hard_limit for " +                                "%s", str_value); +                        goto out; +                } + +                ret = xmlTextWriterWriteFormatElement (writer, +                                (xmlChar *) "effectiveHardLimit", +                                "%"PRIu64, value); +                XML_RET_CHECK_AND_GOTO (ret, out); + +                snprintf (buf, sizeof(buf), +                                "volume%"PRIu64"-snap-max-soft-limit", i); +                ret = dict_get_uint64 (dict, buf, &value); +                if (ret) { +                        gf_log ("cli", GF_LOG_ERROR, "Could not fetch %s", buf); +                        goto out; +                } + +                ret = xmlTextWriterWriteFormatElement (writer, +                                        (xmlChar *) "softLimit", +                                        "%"PRIu64, value); +                XML_RET_CHECK_AND_GOTO (ret, out); + +                /* </volume> */ +                ret = xmlTextWriterEndElement (writer); +                XML_RET_CHECK_AND_GOTO (ret, out); +        } + +        /* </volume> */ +        ret = xmlTextWriterEndElement (writer); +        XML_RET_CHECK_AND_GOTO (ret, out); + +        ret = 0; +out: +        return ret; +} + +/* This function will generate snapshot config set output in xml format. + * + * @param writer        xmlTextWriterPtr + * @param doc           xmlDocPtr + * @param dict          dict containing status output + * + * @return 0 on success and -1 on failure + */ +static int +cli_xml_snapshot_config_set (xmlTextWriterPtr writer, xmlDocPtr doc, +                             dict_t *dict) +{ +        int             ret             = -1; +        uint64_t        hard_limit      = 0; +        uint64_t        soft_limit      = 0; +        char           *volname         = NULL; +        char           *auto_delete     = NULL; + +        GF_ASSERT (writer); +        GF_ASSERT (doc); +        GF_ASSERT (dict); + +        /* This is optional parameter therefore ignore the error */ +        ret = dict_get_uint64 (dict, "snap-max-hard-limit", &hard_limit); +        /* This is optional parameter therefore ignore the error */ +        ret = dict_get_uint64 (dict, "snap-max-soft-limit", &soft_limit); +        ret = dict_get_str (dict, "auto-delete", &auto_delete); + +        if (!hard_limit && !soft_limit && !auto_delete) { +                ret = -1; +                gf_log ("cli", GF_LOG_ERROR, "At least one option from " +                        "snap-max-hard-limit, snap-max-soft-limit and " +                        "auto-delete should be set"); +                goto out; +        } + +        /* Ignore the error, as volname is optional */ +        ret = dict_get_str (dict, "volname", &volname); + +        if (NULL == volname) { +                /* <systemConfig> */ +                ret = xmlTextWriterStartElement (writer, +                                                 (xmlChar *)"systemConfig"); +        } else { +                /* <volumeConfig> */ +                ret = xmlTextWriterStartElement (writer, +                                                 (xmlChar *)"volumeConfig"); +                XML_RET_CHECK_AND_GOTO (ret, out); + +                ret = xmlTextWriterWriteFormatElement (writer, +                                (xmlChar *) "name", "%s", volname); +        } + +        XML_RET_CHECK_AND_GOTO (ret, out); + +        if (hard_limit) { +                ret = xmlTextWriterWriteFormatElement (writer, +                                                (xmlChar *) "newHardLimit", +                                                "%"PRIu64, hard_limit); +                XML_RET_CHECK_AND_GOTO (ret, out); +        } + +        if (soft_limit) { +                ret = xmlTextWriterWriteFormatElement (writer, +                                (xmlChar *) "newSoftLimit", +                                "%"PRIu64, soft_limit); +                XML_RET_CHECK_AND_GOTO (ret, out); +        } + +        if (auto_delete) { +                ret = xmlTextWriterWriteFormatElement (writer, +                                (xmlChar *) "autoDelete", "%s", auto_delete); +                XML_RET_CHECK_AND_GOTO (ret, out); +        } + +        /* </volumeConfig> or </systemConfig> */ +        ret = xmlTextWriterEndElement (writer); +        XML_RET_CHECK_AND_GOTO (ret, out); + +        ret = 0; +out: +        return ret; +} + +/* This function will generate snapshot config output in xml format. + * + * @param writer        xmlTextWriterPtr + * @param doc           xmlDocPtr + * @param dict          dict containing config output + * + * @return 0 on success and -1 on failure + */ +static int +cli_xml_snapshot_config (xmlTextWriterPtr writer, xmlDocPtr doc, dict_t *dict) +{ +        int             ret             = -1; +        int             config_command  = 0; + +        GF_ASSERT (writer); +        GF_ASSERT (doc); +        GF_ASSERT (dict); + +        /* <snapConfig> */ +        ret = xmlTextWriterStartElement (writer, (xmlChar *)"snapConfig"); +        XML_RET_CHECK_AND_GOTO (ret, out); + +        ret = dict_get_int32 (dict, "config-command", &config_command); +        if (ret) { +                gf_log ("cli", GF_LOG_ERROR, "Could not fetch config type"); +                goto out; +        } + +        switch (config_command) { +        case GF_SNAP_CONFIG_TYPE_SET: +                ret = cli_xml_snapshot_config_set (writer, doc, dict); +                if (ret) { +                        gf_log ("cli", GF_LOG_ERROR, "Failed to create xml " +                                "output for snapshot config set command"); +                        goto out; +                } + +                break; +        case GF_SNAP_CONFIG_DISPLAY: +                ret = cli_xml_snapshot_config_show (writer, doc, dict); +                if (ret) { +                        gf_log ("cli", GF_LOG_ERROR, "Failed to create xml " +                                "output for snapshot config show command"); +                        goto out; +                } +                break; +        default: +                gf_log ("cli", GF_LOG_ERROR, "Uknown config command :%d", +                        config_command); +                ret = -1; +                goto out; +        } + +        /* </snapConfig> */ +        ret = xmlTextWriterEndElement (writer); +        XML_RET_CHECK_AND_GOTO (ret, out); + +        ret = 0; +out: + +        return ret; +} + +/* This function will generate snapshot activate or + * deactivate output in xml format. + * + * @param writer        xmlTextWriterPtr + * @param doc           xmlDocPtr + * @param dict          dict containing activate or deactivate output + * + * @return 0 on success and -1 on failure + */ +static int +cli_xml_snapshot_activate_deactivate (xmlTextWriterPtr writer, xmlDocPtr doc, +                                      dict_t *dict, int cmd) +{ +        int     ret     = -1; +        char   *buffer  = NULL; +        char   *tag     = NULL; + +        GF_ASSERT (writer); +        GF_ASSERT (doc); +        GF_ASSERT (dict); + +        if (GF_SNAP_OPTION_TYPE_ACTIVATE == cmd) { +                tag = "snapActivate"; +        } else if (GF_SNAP_OPTION_TYPE_DEACTIVATE == cmd) { +                tag = "snapDeactivate"; +        } else { +                gf_log ("cli", GF_LOG_ERROR, "invalid command %d", cmd); +                goto out; +        } + +        /* <snapActivate> or <snapDeactivate> */ +        ret = xmlTextWriterStartElement (writer, (xmlChar *)tag); +        XML_RET_CHECK_AND_GOTO (ret, out); + +        /* <snapshot> */ +        ret = xmlTextWriterStartElement (writer, (xmlChar *)"snapshot"); +        XML_RET_CHECK_AND_GOTO (ret, out); + +        ret = dict_get_str (dict, "snapname", &buffer); +        if (ret) { +                gf_log ("cli", GF_LOG_ERROR, "Failed to get snap name"); +                goto out; +        } + +        ret = xmlTextWriterWriteFormatElement (writer, (xmlChar *) "name", +                                               "%s", buffer); +        XML_RET_CHECK_AND_GOTO (ret, out); + +        ret = dict_get_str (dict, "snapuuid", &buffer); +        if (ret) { +                gf_log ("cli", GF_LOG_ERROR, "Failed to get snap uuid"); +                goto out; +        } + +        ret = xmlTextWriterWriteFormatElement (writer, (xmlChar *) "uuid", +                                               "%s", buffer); +        XML_RET_CHECK_AND_GOTO (ret, out); + +        /* </snapshot> */ +        ret = xmlTextWriterEndElement (writer); +        XML_RET_CHECK_AND_GOTO (ret, out); + + +        /* </snapActivate> or </snapDeactivate> */ +        ret = xmlTextWriterEndElement (writer); +        XML_RET_CHECK_AND_GOTO (ret, out); + +        ret = 0; +out: + +        return ret; +} +#endif /* HAVE_LIB_XML */ + +int +cli_xml_output_snap_status_begin (cli_local_t *local, int op_ret, int op_errno, +                                  char *op_errstr) +{ +#if (HAVE_LIB_XML) +        int                     ret = -1; + +        GF_ASSERT (local); + +        ret = cli_begin_xml_output (&(local->writer), &(local->doc)); +        XML_RET_CHECK_AND_GOTO (ret, out); + +        ret = cli_xml_output_common (local->writer, op_ret, op_errno, +                                     op_errstr); +        XML_RET_CHECK_AND_GOTO (ret, out); + +        /* <snapStatus> */ +        ret = xmlTextWriterStartElement (local->writer, +                                         (xmlChar *) "snapStatus"); +        XML_RET_CHECK_AND_GOTO (ret, out); + +        /* <snapshots> */ +        ret = xmlTextWriterStartElement (local->writer, (xmlChar *)"snapshots"); +        XML_RET_CHECK_AND_GOTO (ret, out); + +out: +        gf_log ("cli", GF_LOG_TRACE, "Returning %d", ret); +        return ret; +#else +        return 0; +#endif +} + +int +cli_xml_output_snap_status_end (cli_local_t *local) +{ +#if (HAVE_LIB_XML) +        int     ret = -1; + +        GF_ASSERT (local); + +        /* </snapshots> */ +        ret = xmlTextWriterEndElement (local->writer); +        XML_RET_CHECK_AND_GOTO (ret, out); + +        /* </snapStatus> */ +        ret = xmlTextWriterEndElement (local->writer); +        XML_RET_CHECK_AND_GOTO(ret, out); + +        ret = cli_end_xml_output (local->writer, local->doc); +out: +        gf_log ("cli", GF_LOG_TRACE, "Returning %d", ret); +        return ret; +#else +        return 0; +#endif +} + +/* This function will generate xml output for all the snapshot commands + * + * @param cmd_type      command type + * @param dict          dict containing snapshot command output + * @param op_ret        return value of the snapshot command + * @param op_errno      errno for the snapshot command + * @param op_errstr     error string for the snapshot command + * + * @return 0 on success and -1 on failure + */ +int +cli_xml_output_snapshot (int cmd_type, dict_t *dict, int op_ret, +                         int op_errno, char *op_errstr) +{ +#if (HAVE_LIB_XML) +        int                     ret     = -1; +        xmlTextWriterPtr        writer  = NULL; +        xmlDocPtr               doc     = NULL; + +        GF_ASSERT (dict); + +        ret = cli_begin_xml_output (&writer, &doc); +        if (ret) { +                gf_log ("cli", GF_LOG_ERROR, "Failed to output " +                        "xml begin block"); +                goto out; +        } + +        ret = cli_xml_output_common (writer, op_ret, op_errno, op_errstr); +        if (ret) { +                gf_log ("cli", GF_LOG_ERROR, "Failed to output " +                        "xml common block"); +                goto out; +        } + +        /* In case of command failure just printing the error message is good +         * enough */ +        if (0 != op_ret) { +                goto end; +        } + +        switch (cmd_type) { +        case GF_SNAP_OPTION_TYPE_CREATE: +                ret = cli_xml_snapshot_create (writer, doc, dict); +                if (ret) { +                        gf_log ("cli", GF_LOG_ERROR, "Failed to create " +                                "xml output for snapshot create command"); +                        goto out; +                } +                break; +        case GF_SNAP_OPTION_TYPE_DELETE: +                ret = cli_xml_snapshot_delete (writer, doc, dict); +                if (ret) { +                        gf_log ("cli", GF_LOG_ERROR, "Failed to create " +                                "xml output for snapshot delete command"); +                        goto out; +                } +                break; +        case GF_SNAP_OPTION_TYPE_RESTORE: +                ret = cli_xml_snapshot_restore (writer, doc, dict); +                if (ret) { +                        gf_log ("cli", GF_LOG_ERROR, "Failed to create " +                                "xml output for snapshot restore command"); +                        goto out; +                } +                break; +        case GF_SNAP_OPTION_TYPE_LIST: +                ret = cli_xml_snapshot_list (writer, doc, dict); +                if (ret) { +                        gf_log ("cli", GF_LOG_ERROR, "Failed to create " +                                "xml output for snapshot list command"); +                        goto out; +                } +                break; +        case GF_SNAP_OPTION_TYPE_STATUS: +                ret = cli_xml_snapshot_status (writer, doc, dict); +                if (ret) { +                        gf_log ("cli", GF_LOG_ERROR, "Failed to create" +                                "xml output for snapshot status command"); +                        goto out; +                } +                break; +        case GF_SNAP_OPTION_TYPE_INFO: +                ret = cli_xml_snapshot_info (writer, doc, dict); +                if (ret) { +                        gf_log ("cli", GF_LOG_ERROR, "Failed to create " +                                "xml output for snapshot info command"); +                        goto out; +                } +                break; +        case GF_SNAP_OPTION_TYPE_ACTIVATE: +        case GF_SNAP_OPTION_TYPE_DEACTIVATE: +                ret = cli_xml_snapshot_activate_deactivate (writer, doc, +                                                            dict, cmd_type); +                if (ret) { +                        gf_log ("cli", GF_LOG_ERROR, "Failed to create " +                                "xml output for snapshot config command"); +                } +                break; +        case GF_SNAP_OPTION_TYPE_CONFIG: +                ret = cli_xml_snapshot_config (writer, doc, dict); +                if (ret) { +                        gf_log ("cli", GF_LOG_ERROR, "Failed to create " +                                "xml output for snapshot config command"); +                } +                break; +        default: +                gf_log ("cli", GF_LOG_ERROR, +                        "Unexpected snapshot command: %d", cmd_type); +                goto out; +        } + +end: +        ret = cli_end_xml_output (writer, doc); +        if (ret) { +                gf_log ("cli", GF_LOG_ERROR, "Failed to output " +                        "xml end block"); +                goto out; +        } + +        ret = 0; +out: +        return ret; +#else +        return 0; +#endif /* HAVE_LIB_XML */ +} diff --git a/cli/src/cli.h b/cli/src/cli.h index a1a78eca2bc..74d35992680 100644 --- a/cli/src/cli.h +++ b/cli/src/cli.h @@ -388,6 +388,17 @@ cli_xml_output_vol_gsync (dict_t *dict, int op_ret, int op_errno,  int  cli_xml_output_vol_status_tasks_detail (cli_local_t *local, dict_t *dict); +int +cli_xml_output_snap_status_begin (cli_local_t *local, int op_ret, int op_errno, +                                  char *op_errstr); +int +cli_xml_output_snap_status_end (cli_local_t *local); +int +cli_xml_snapshot_status_per_snap (xmlTextWriterPtr writer, xmlDocPtr doc, +                                  dict_t *dict, const char *keyprefix); +int +cli_xml_output_snapshot (int cmd_type, dict_t *dict, int op_ret, +                         int op_errno, char *op_errstr);  char *  is_server_debug_xlator (void *myframe);  | 
