diff options
Diffstat (limited to 'cli/src/cli-xml-output.c')
| -rw-r--r-- | cli/src/cli-xml-output.c | 1577 |
1 files changed, 1424 insertions, 153 deletions
diff --git a/cli/src/cli-xml-output.c b/cli/src/cli-xml-output.c index 419cae20a..d8884d44b 100644 --- a/cli/src/cli-xml-output.c +++ b/cli/src/cli-xml-output.c @@ -1,22 +1,12 @@ /* - Copyright (c) 2010-2011 Gluster, Inc. <http://www.gluster.com> - This file is part of GlusterFS. - - GlusterFS is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published - by the Free Software Foundation; either version 3 of the License, - or (at your option) any later version. - - GlusterFS is distributed in the hope that it will be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see - <http://www.gnu.org/licenses/>. -*/ + Copyright (c) 2010-2012 Red Hat, Inc. <http://www.redhat.com> + This file is part of GlusterFS. + This file is licensed to you under your choice of the GNU Lesser + General Public License, version 3 or any later version (LGPLv3 or + later), or the GNU General Public License, version 2 (GPLv2), in all + cases as published by the Free Software Foundation. +*/ #include <stdlib.h> #include "cli.h" #include "cli1-xdr.h" @@ -25,6 +15,39 @@ #include "syscall.h" +enum gf_task_types { + GF_TASK_TYPE_REBALANCE, + GF_TASK_TYPE_REMOVE_BRICK +}; + +/* + * IMPORTANT NOTE: + * All exported functions in this file which use libxml need use a + * #if (HAVE_LIB_XML), #else, #endif + * For eg, + * int exported_func () { + * #if (HAVE_LIB_XML) + * <Stuff using libxml> + * #else + * return 0; + * #endif + * } + * + * All other functions, which are called internally within this file need to be + * within #if (HAVE_LIB_XML), #endif statements + * For eg, + * #if (HAVE_LIB_XML) + * int internal_func () + * { + * } + * #endif + * + * Following the above formate ensures that all xml related code is compliled + * only when libxml2 is present, and also keeps the rest of the codebase free + * of #if (HAVE_LIB_XML) + */ + + #if (HAVE_LIB_XML) #include <libxml/encoding.h> @@ -40,18 +63,11 @@ }while (0) \ int -cli_begin_xml_output (xmlTextWriterPtr *writer, xmlBufferPtr *buf) +cli_begin_xml_output (xmlTextWriterPtr *writer, xmlDocPtr *doc) { int ret = -1; - *buf = xmlBufferCreateSize (8192); - if (*buf == NULL) { - ret = -1; - goto out; - } - xmlBufferSetAllocationScheme (*buf, XML_BUFFER_ALLOC_DOUBLEIT); - - *writer = xmlNewTextWriterMemory (*buf, 0); + *writer = xmlNewTextWriterDoc (doc, 0); if (writer == NULL) { ret = -1; goto out; @@ -70,7 +86,7 @@ out: } int -cli_end_xml_output (xmlTextWriterPtr writer, xmlBufferPtr buf) +cli_end_xml_output (xmlTextWriterPtr writer, xmlDocPtr doc) { int ret = -1; @@ -81,10 +97,12 @@ cli_end_xml_output (xmlTextWriterPtr writer, xmlBufferPtr buf) ret = xmlTextWriterEndDocument (writer); XML_RET_CHECK_AND_GOTO (ret, out); - cli_out ("%s", (const char *)buf->content); + + /* Dump xml document to stdout and pretty format it */ + xmlSaveFormatFileEnc ("-", doc, "UTF-8", 1); xmlFreeTextWriter (writer); - xmlBufferFree (buf); + xmlFreeDoc (doc); out: gf_log ("cli", GF_LOG_DEBUG, "Returning %d", ret); @@ -106,23 +124,25 @@ cli_xml_output_common (xmlTextWriterPtr writer, int op_ret, int op_errno, XML_RET_CHECK_AND_GOTO (ret, out); ret = xmlTextWriterWriteFormatElement (writer, (xmlChar *)"opErrstr", - "%s", op_errstr); + "%s", op_errstr); XML_RET_CHECK_AND_GOTO (ret, out); out: gf_log ("cli", GF_LOG_DEBUG, "Returning %d", ret); return ret; } +#endif int cli_xml_output_str (char *op, char *str, int op_ret, int op_errno, char *op_errstr) { +#if (HAVE_LIB_XML) int ret = -1; xmlTextWriterPtr writer = NULL; - xmlBufferPtr buf = NULL; + xmlDocPtr doc = NULL; - ret = cli_begin_xml_output (&writer, &buf); + ret = cli_begin_xml_output (&writer, &doc); if (ret) goto out; @@ -130,22 +150,32 @@ cli_xml_output_str (char *op, char *str, int op_ret, int op_errno, if (ret) goto out; - ret = xmlTextWriterWriteFormatElement (writer, (xmlChar *)"cliOp", - "%s", op); - XML_RET_CHECK_AND_GOTO (ret, out); + if (op) { + ret = xmlTextWriterWriteFormatElement (writer, + (xmlChar *)"cliOp", + "%s", op); + XML_RET_CHECK_AND_GOTO (ret, out); + } - ret = xmlTextWriterWriteFormatElement (writer, (xmlChar *)"output", - "%s", str); - XML_RET_CHECK_AND_GOTO (ret, out); + if (str) { + ret = xmlTextWriterWriteFormatElement (writer, + (xmlChar *)"output", + "%s", str); + XML_RET_CHECK_AND_GOTO (ret, out); + } - ret = cli_end_xml_output (writer, buf); + ret = cli_end_xml_output (writer, doc); out: gf_log ("cli", GF_LOG_DEBUG, "Returning %d", ret); return ret; +#else + return 0; +#endif } -void +#if (HAVE_LIB_XML) +int cli_xml_output_data_pair (dict_t *this, char *key, data_t *value, void *data) { @@ -157,36 +187,48 @@ cli_xml_output_data_pair (dict_t *this, char *key, data_t *value, ret = xmlTextWriterWriteFormatElement (*writer, (xmlChar *)key, "%s", value->data); - return; + return ret; } +#endif int cli_xml_output_dict ( char *op, dict_t *dict, int op_ret, int op_errno, char *op_errstr) { +#if (HAVE_LIB_XML) int ret = -1; xmlTextWriterPtr writer = NULL; - xmlBufferPtr buf = NULL; + xmlDocPtr doc = NULL; - ret = cli_begin_xml_output (&writer, &buf); + ret = cli_begin_xml_output (&writer, &doc); if (ret) goto out; + + ret = cli_xml_output_common (writer, op_ret, op_errno, op_errstr); + if (ret) + goto out; + /* <"op"> */ ret = xmlTextWriterStartElement (writer, (xmlChar *)op); XML_RET_CHECK_AND_GOTO (ret, out); - dict_foreach (dict, cli_xml_output_data_pair, &writer); + if (dict) + dict_foreach (dict, cli_xml_output_data_pair, &writer); /* </"op"> */ ret = xmlTextWriterEndElement (writer); XML_RET_CHECK_AND_GOTO (ret, out); - ret = cli_end_xml_output (writer, buf); + ret = cli_end_xml_output (writer, doc); out: gf_log ("cli", GF_LOG_DEBUG, "Returning %d", ret); return ret; +#else + return 0; +#endif } +#if (HAVE_LIB_XML) int cli_xml_output_vol_status_common (xmlTextWriterPtr writer, dict_t *dict, int brick_index, int *online, @@ -222,15 +264,6 @@ cli_xml_output_vol_status_common (xmlTextWriterPtr writer, dict_t *dict, XML_RET_CHECK_AND_GOTO (ret, out); memset (key, 0, sizeof (key)); - snprintf (key, sizeof (key), "brick%d.port", brick_index); - ret = dict_get_int32 (dict, key, &port); - if (ret) - goto out; - ret = xmlTextWriterWriteFormatElement (writer, (xmlChar *)"port", - "%d", port); - XML_RET_CHECK_AND_GOTO (ret, out); - - memset (key, 0, sizeof (key)); snprintf (key, sizeof (key), "brick%d.status", brick_index); ret = dict_get_int32 (dict, key, &status); if (ret) @@ -241,6 +274,27 @@ cli_xml_output_vol_status_common (xmlTextWriterPtr writer, dict_t *dict, *online = status; memset (key, 0, sizeof (key)); + snprintf (key, sizeof (key), "brick%d.port", brick_index); + ret = dict_get_int32 (dict, key, &port); + if (ret) + goto out; + + /* If the process is either offline or doesn't provide a port (shd) + * port = "N/A" + * else print the port number of the process. + */ + + if (*online == 1 && port != 0) + ret = xmlTextWriterWriteFormatElement (writer, + (xmlChar *)"port", + "%d", port); + else + ret = xmlTextWriterWriteFormatElement (writer, + (xmlChar *)"port", + "%s", "N/A"); + XML_RET_CHECK_AND_GOTO (ret, out); + + memset (key, 0, sizeof (key)); snprintf (key, sizeof (key), "brick%d.pid", brick_index); ret = dict_get_int32 (dict, key, &pid); if (ret) @@ -1277,14 +1331,276 @@ out: gf_log ("cli", GF_LOG_DEBUG, "Returning %d", ret); return ret; } +#endif int -cli_xml_output_vol_status (dict_t *dict, int op_ret, int op_errno, - char *op_errstr) +cli_xml_output_vol_status_begin (cli_local_t *local, int op_ret, int op_errno, + char *op_errstr) { +#if (HAVE_LIB_XML) + int ret = -1; + + 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); + + /* <volStatus> */ + ret = xmlTextWriterStartElement (local->writer, + (xmlChar *) "volStatus"); + XML_RET_CHECK_AND_GOTO (ret, out); + + /* <volumes> */ + ret = xmlTextWriterStartElement (local->writer, (xmlChar *)"volumes"); + XML_RET_CHECK_AND_GOTO (ret, out); + +out: + gf_log ("cli", GF_LOG_DEBUG, "Returning %d", ret); + return ret; +#else + return 0; +#endif +} + +int +cli_xml_output_vol_status_end (cli_local_t *local) +{ +#if (HAVE_LIB_XML) + int ret = -1; + + /* </volumes> */ + ret = xmlTextWriterEndElement (local->writer); + XML_RET_CHECK_AND_GOTO (ret, out); + + /* </volStatus> */ + 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_DEBUG, "Returning %d", ret); + return ret; +#else + return 0; +#endif +} + +#if (HAVE_LIB_XML) +int +cli_xml_output_remove_brick_task_params (xmlTextWriterPtr writer, dict_t *dict, + char *prefix) +{ + int ret = -1; + char key[1024] = {0,}; + int count = 0; + int i = 0; + char *brick = NULL; + + /* <params> */ + ret = xmlTextWriterStartElement (writer, (xmlChar *)"params"); + XML_RET_CHECK_AND_GOTO (ret, out); + + snprintf (key, sizeof (key), "%s.count", prefix); + ret = dict_get_int32 (dict, key, &count); + if (ret) + goto out; + + for (i = 1; i <= count; i++) { + memset (key, 0, sizeof (key)); + snprintf (key, sizeof (key), "%s.brick%d", prefix, i); + ret = dict_get_str (dict, key, &brick); + if (ret) + goto out; + ret = xmlTextWriterWriteFormatElement (writer, + (xmlChar *)"brick", + "%s", brick); + XML_RET_CHECK_AND_GOTO (ret, out); + brick = NULL; + } + + /* </param> */ + ret = xmlTextWriterEndElement (writer); + +out: + gf_log ("cli", GF_LOG_DEBUG, "Returning %d", ret); + return ret; +} + +int +cli_xml_output_replace_brick_task_params (xmlTextWriterPtr writer, dict_t *dict, + char *prefix) +{ + + int ret = -1; + char key[1024] = {0,}; + char *brick = NULL; + + /* <params> */ + ret = xmlTextWriterStartElement (writer, (xmlChar *)"params"); + XML_RET_CHECK_AND_GOTO (ret, out); + + snprintf (key, sizeof (key), "%s.src-brick", prefix); + ret = dict_get_str (dict, key, &brick); + if (ret) + goto out; + ret = xmlTextWriterWriteFormatElement (writer, (xmlChar *)"srcBrick", + "%s", brick); + XML_RET_CHECK_AND_GOTO (ret, out); + + + memset (key, 0, sizeof (key)); + snprintf (key, sizeof (key), "%s.dst-brick", prefix); + ret = dict_get_str (dict, key, &brick); + if (ret) + goto out; + ret = xmlTextWriterWriteFormatElement (writer, (xmlChar *)"dstBrick", + "%s", brick); + XML_RET_CHECK_AND_GOTO (ret, out); + + + /* </param> */ + ret = xmlTextWriterEndElement (writer); + +out: + gf_log ("cli", GF_LOG_DEBUG, "Returning %d", ret); + return ret; +} + +int +cli_xml_output_vol_status_tasks (cli_local_t *local, dict_t *dict) { + int ret = -1; + char *task_type = NULL; + char *task_id_str = NULL; + int status = 0; + int tasks = 0; + char key[1024] = {0,}; + int i = 0; + + /* <tasks> */ + ret = xmlTextWriterStartElement (local->writer, (xmlChar *)"tasks"); + XML_RET_CHECK_AND_GOTO (ret, out); + + ret = dict_get_int32 (dict, "tasks", &tasks); + if (ret) + goto out; + + for (i = 0; i < tasks; i++) { + /* <task> */ + ret = xmlTextWriterStartElement (local->writer, + (xmlChar *)"task"); + XML_RET_CHECK_AND_GOTO (ret, out); + + memset (key, 0, sizeof (key)); + snprintf (key, sizeof (key), "task%d.type", i); + ret = dict_get_str (dict, key, &task_type); + if (ret) + goto out; + ret = xmlTextWriterWriteFormatElement (local->writer, + (xmlChar *)"type", + "%s", task_type); + XML_RET_CHECK_AND_GOTO (ret, out); + + memset (key, 0, sizeof (key)); + snprintf (key, sizeof (key), "task%d.id", i); + ret = dict_get_str (dict, key, &task_id_str); + if (ret) + goto out; + ret = xmlTextWriterWriteFormatElement (local->writer, + (xmlChar *)"id", + "%s", task_id_str); + XML_RET_CHECK_AND_GOTO (ret, out); + + memset (key, 0, sizeof (key)); + snprintf (key, sizeof (key), "task%d.status", i); + ret = dict_get_int32 (dict, key, &status); + if (ret) + goto out; + ret = xmlTextWriterWriteFormatElement (local->writer, + (xmlChar *)"status", + "%d", status); + XML_RET_CHECK_AND_GOTO (ret, out); + + if (!strcmp (task_type, "Replace brick")) { + if (status) { + status = GF_DEFRAG_STATUS_COMPLETE; + } else { + status = GF_DEFRAG_STATUS_STARTED; + } + } + + ret = xmlTextWriterWriteFormatElement (local->writer, + (xmlChar *)"statusStr", + "%s", + cli_vol_task_status_str[status]); + + XML_RET_CHECK_AND_GOTO (ret, out); + + memset (key, 0, sizeof (key)); + snprintf (key, sizeof (key), "task%d", i); + if (!strcmp (task_type, "Replace brick")) { + ret = cli_xml_output_replace_brick_task_params + (local->writer, dict, key); + if (ret) + goto out; + } else if (!strcmp (task_type, "Remove brick")) { + ret = cli_xml_output_remove_brick_task_params + (local->writer, dict, key); + if (ret) + goto out; + } + + + /* </task> */ + ret = xmlTextWriterEndElement (local->writer); + XML_RET_CHECK_AND_GOTO (ret, out); + } + + /* </tasks> */ + ret = xmlTextWriterEndElement (local->writer); + +out: + gf_log ("cli", GF_LOG_DEBUG, "Returning %d", ret); + return ret; +} + +int +cli_xml_output_vol_status_tasks_detail (cli_local_t *local, dict_t *dict) +{ + int ret = -1; + char *volname = NULL; + + /*<volume>*/ + ret = xmlTextWriterStartElement (local->writer, (xmlChar *)"volume"); + XML_RET_CHECK_AND_GOTO (ret, out); + + ret = dict_get_str (dict, "volname", &volname); + if (ret) + goto out; + ret = xmlTextWriterWriteFormatElement (local->writer, + (xmlChar *)"volName", "%s", + volname); + XML_RET_CHECK_AND_GOTO (ret, out); + + ret = cli_xml_output_vol_status_tasks (local, dict); + if (ret) + goto out; + + /* </volume> */ + ret = xmlTextWriterEndElement (local->writer); + XML_RET_CHECK_AND_GOTO (ret, out); + +out: + return ret; +} +#endif + +int +cli_xml_output_vol_status (cli_local_t *local, dict_t *dict) +{ +#if (HAVE_LIB_XML) int ret = -1; - xmlTextWriterPtr writer = NULL; - xmlBufferPtr buf = NULL; char *volname = NULL; int brick_count = 0; int brick_index_max = -1; @@ -1295,30 +1611,25 @@ cli_xml_output_vol_status (dict_t *dict, int op_ret, int op_errno, gf_boolean_t node_present = _gf_true; int i; - ret = cli_begin_xml_output (&writer, &buf); - if (ret) - goto out; - - ret = cli_xml_output_common (writer, op_ret, op_errno, op_errstr); - if (ret) - goto out; - /* <volStatus> */ - ret = xmlTextWriterStartElement (writer, (xmlChar *)"volStatus"); + /* <volume> */ + ret = xmlTextWriterStartElement (local->writer, (xmlChar *)"volume"); XML_RET_CHECK_AND_GOTO (ret, out); ret = dict_get_str (dict, "volname", &volname); if (ret) goto out; - ret = xmlTextWriterWriteFormatElement (writer, (xmlChar *)"volName", - "%s", volname); + ret = xmlTextWriterWriteFormatElement (local->writer, + (xmlChar *)"volName", "%s", + volname); XML_RET_CHECK_AND_GOTO (ret, out); ret = dict_get_int32 (dict, "count", &brick_count); if (ret) goto out; - ret = xmlTextWriterWriteFormatElement (writer, (xmlChar *)"nodeCount", - "%d", brick_count); + ret = xmlTextWriterWriteFormatElement (local->writer, + (xmlChar *)"nodeCount", "%d", + brick_count); if (ret) goto out; @@ -1337,10 +1648,11 @@ cli_xml_output_vol_status (dict_t *dict, int op_ret, int op_errno, for (i = 0; i <= index_max; i++) { /* <node> */ - ret = xmlTextWriterStartElement (writer, (xmlChar *)"node"); + ret = xmlTextWriterStartElement (local->writer, + (xmlChar *)"node"); XML_RET_CHECK_AND_GOTO (ret, out); - ret = cli_xml_output_vol_status_common (writer, dict, i, + ret = cli_xml_output_vol_status_common (local->writer, dict, i, &online, &node_present); if (ret) { if (node_present) @@ -1351,7 +1663,7 @@ cli_xml_output_vol_status (dict_t *dict, int op_ret, int op_errno, switch (cmd & GF_CLI_STATUS_MASK) { case GF_CLI_STATUS_DETAIL: - ret = cli_xml_output_vol_status_detail (writer, + ret = cli_xml_output_vol_status_detail (local->writer, dict, i); if (ret) goto out; @@ -1360,7 +1672,7 @@ cli_xml_output_vol_status (dict_t *dict, int op_ret, int op_errno, case GF_CLI_STATUS_MEM: if (online) { ret = cli_xml_output_vol_status_mem - (writer, dict, i); + (local->writer, dict, i); if (ret) goto out; } @@ -1369,7 +1681,7 @@ cli_xml_output_vol_status (dict_t *dict, int op_ret, int op_errno, case GF_CLI_STATUS_CLIENTS: if (online) { ret = cli_xml_output_vol_status_clients - (writer, dict, i); + (local->writer, dict, i); if (ret) goto out; } @@ -1378,7 +1690,7 @@ cli_xml_output_vol_status (dict_t *dict, int op_ret, int op_errno, case GF_CLI_STATUS_INODE: if (online) { ret = cli_xml_output_vol_status_inode - (writer, dict, i); + (local->writer, dict, i); if (ret) goto out; } @@ -1387,7 +1699,7 @@ cli_xml_output_vol_status (dict_t *dict, int op_ret, int op_errno, case GF_CLI_STATUS_FD: if (online) { ret = cli_xml_output_vol_status_fd - (writer, dict, i); + (local->writer, dict, i); if (ret) goto out; } @@ -1396,35 +1708,43 @@ cli_xml_output_vol_status (dict_t *dict, int op_ret, int op_errno, case GF_CLI_STATUS_CALLPOOL: if (online) { ret = cli_xml_output_vol_status_callpool - (writer, dict, i); + (local->writer, dict, i); if (ret) goto out; } break; - default: break; } /* </node> */ - ret = xmlTextWriterEndElement (writer); + ret = xmlTextWriterEndElement (local->writer); XML_RET_CHECK_AND_GOTO (ret, out); } - /* </volStatus> */ - ret = xmlTextWriterEndElement (writer); - XML_RET_CHECK_AND_GOTO (ret, out); + /* Tasks are only present when a normal volume status call is done on a + * single volume or on all volumes + */ + if (((cmd & GF_CLI_STATUS_MASK) == GF_CLI_STATUS_NONE) && + (cmd & (GF_CLI_STATUS_VOL|GF_CLI_STATUS_ALL))) { + ret = cli_xml_output_vol_status_tasks (local, dict); + if (ret) + goto out; + } - gf_log ("cli", GF_LOG_DEBUG, "Returning %d", ret); - ret = cli_end_xml_output (writer, buf); - if (ret) - goto out; + /* </volume> */ + ret = xmlTextWriterEndElement (local->writer); + XML_RET_CHECK_AND_GOTO (ret, out); out: gf_log ("cli", GF_LOG_DEBUG, "Returning %d", ret); return ret; +#else + return 0; +#endif } +#if (HAVE_LIB_XML) int cli_xml_output_vol_top_rw_perf (xmlTextWriterPtr writer, dict_t *dict, int brick_index, int member_index) @@ -1529,14 +1849,16 @@ out: gf_log ("cli", GF_LOG_DEBUG, "Returning %d", ret); return ret; } +#endif int cli_xml_output_vol_top (dict_t *dict, int op_ret, int op_errno, char *op_errstr) { +#if (HAVE_LIB_XML) int ret = -1; xmlTextWriterPtr writer = NULL; - xmlBufferPtr buf = NULL; + xmlDocPtr doc = NULL; int brick_count = 0; int top_op = GF_CLI_TOP_NONE; char *brick_name = NULL; @@ -1550,7 +1872,7 @@ cli_xml_output_vol_top (dict_t *dict, int op_ret, int op_errno, int i = 0; int j = 0; - ret = cli_begin_xml_output (&writer, &buf); + ret = cli_begin_xml_output (&writer, &doc); if (ret) goto out; @@ -1639,8 +1961,6 @@ cli_xml_output_vol_top (dict_t *dict, int op_ret, int op_errno, case GF_CLI_TOP_WRITE: case GF_CLI_TOP_OPENDIR: case GF_CLI_TOP_READDIR: - if (!members) - continue; break; @@ -1666,9 +1986,6 @@ cli_xml_output_vol_top (dict_t *dict, int op_ret, int op_errno, "%f", time_taken); } - if (!members) - continue; - break; default: @@ -1698,13 +2015,17 @@ cli_xml_output_vol_top (dict_t *dict, int op_ret, int op_errno, /* </volTop> */ ret = xmlTextWriterEndElement (writer); XML_RET_CHECK_AND_GOTO (ret, out); - ret = cli_end_xml_output (writer, buf); + ret = cli_end_xml_output (writer, doc); out: gf_log ("cli", GF_LOG_DEBUG, "Returning %d", ret); return ret; +#else + return 0; +#endif } +#if (HAVE_LIB_XML) int cli_xml_output_vol_profile_stats (xmlTextWriterPtr writer, dict_t *dict, int brick_index, int interval) @@ -1880,14 +2201,16 @@ out: gf_log ("cli", GF_LOG_DEBUG, "Returning %d", ret); return ret; } +#endif int cli_xml_output_vol_profile (dict_t *dict, int op_ret, int op_errno, char *op_errstr) { +#if (HAVE_LIB_XML) int ret = -1; xmlTextWriterPtr writer = NULL; - xmlBufferPtr buf = NULL; + xmlDocPtr doc = NULL; char *volname = NULL; int op = GF_CLI_STATS_NONE; int brick_count = 0; @@ -1896,7 +2219,7 @@ cli_xml_output_vol_profile (dict_t *dict, int op_ret, int op_errno, char key[1024] = {0,}; int i = 0; - ret = cli_begin_xml_output (&writer, &buf); + ret = cli_begin_xml_output (&writer, &doc); if (ret) goto out; @@ -1976,26 +2299,29 @@ cont: ret = xmlTextWriterEndElement (writer); XML_RET_CHECK_AND_GOTO (ret, out); - ret = cli_end_xml_output (writer, buf); + ret = cli_end_xml_output (writer, doc); out: gf_log ("cli", GF_LOG_DEBUG, "Returning %d", ret); return ret; - +#else + return 0; +#endif } int cli_xml_output_vol_list (dict_t *dict, int op_ret, int op_errno, char *op_errstr) { +#if (HAVE_LIB_XML) int ret = -1; xmlTextWriterPtr writer = NULL; - xmlBufferPtr buf = NULL; + xmlDocPtr doc = NULL; int count = 0; char *volname = NULL; char key[1024] = {0,}; int i = 0; - ret = cli_begin_xml_output (&writer, &buf); + ret = cli_begin_xml_output (&writer, &doc); if (ret) goto out; @@ -2030,12 +2356,16 @@ cli_xml_output_vol_list (dict_t *dict, int op_ret, int op_errno, ret = xmlTextWriterEndElement (writer); XML_RET_CHECK_AND_GOTO (ret, out); - ret = cli_end_xml_output (writer, buf); + ret = cli_end_xml_output (writer, doc); out: gf_log ("cli", GF_LOG_DEBUG, "Returning %d", ret); return ret; +#else + return 0; +#endif } +#if (HAVE_LIB_XML) int cli_xml_output_vol_info_option (xmlTextWriterPtr writer, char *substr, char *optstr, char *valstr) @@ -2080,23 +2410,44 @@ out: return ret; } +struct tmp_xml_option_logger { + char *key; + xmlTextWriterPtr writer; +}; + +static int +_output_vol_info_option (dict_t *d, char *k, data_t *v, + void *data) +{ + int ret = 0; + char *ptr = NULL; + struct tmp_xml_option_logger *tmp = NULL; + + tmp = data; + + ptr = strstr (k, "option."); + if (!ptr) + goto out; + + if (!v) { + ret = -1; + goto out; + } + ret = cli_xml_output_vol_info_option (tmp->writer, tmp->key, k, + v->data); + +out: + return ret; +} + int cli_xml_output_vol_info_options (xmlTextWriterPtr writer, dict_t *dict, char *prefix) { int ret = -1; int opt_count = 0; - data_pair_t *pairs = 0; - data_t *value = 0; - char *ptr = NULL; char key[1024] = {0,}; - int i = 0; - - pairs = dict->members_list; - if (!pairs) { - ret = -1; - goto out; - } + struct tmp_xml_option_logger tmp = {0,}; snprintf (key, sizeof (key), "%s.opt_count", prefix); ret = dict_get_int32 (dict, key, &opt_count); @@ -2109,25 +2460,14 @@ cli_xml_output_vol_info_options (xmlTextWriterPtr writer, dict_t *dict, /* <options> */ ret = xmlTextWriterStartElement (writer, (xmlChar *)"options"); XML_RET_CHECK_AND_GOTO (ret, out); - while (i < opt_count) { - snprintf (key, sizeof (key), "%s.option.", prefix); - while (pairs) { - ptr = strstr (pairs->key, "option."); - if (ptr) { - value = pairs->value; - if (!value) { - ret = -1; - goto out; - } - ret = cli_xml_output_vol_info_option - (writer, key, pairs->key, value->data); - if (ret) - goto out; - } - pairs = pairs->next; - } - i++; - } + snprintf (key, sizeof (key), "%s.option.", prefix); + + tmp.key = key; + tmp.writer = writer; + ret = dict_foreach (dict, _output_vol_info_option, &tmp); + if (ret) + goto out; + /* </options> */ ret = xmlTextWriterEndElement (writer); XML_RET_CHECK_AND_GOTO (ret, out); @@ -2135,14 +2475,17 @@ out: gf_log ("cli", GF_LOG_DEBUG, "Returning %d", ret); return ret; } +#endif int cli_xml_output_vol_info (cli_local_t *local, dict_t *dict) { +#if (HAVE_LIB_XML) int ret = 0; int count = 0; char *volname = NULL; char *volume_id = NULL; + char *uuid = NULL; int type = 0; int status = 0; int brick_count = 0; @@ -2154,7 +2497,9 @@ cli_xml_output_vol_info (cli_local_t *local, dict_t *dict) char key[1024] = {0,}; int i = 0; int j = 1; - + char *caps = NULL; + int k __attribute__((unused)) = 0; + char *snap_volume = NULL; ret = dict_get_int32 (dict, "count", &count); if (ret) @@ -2187,23 +2532,30 @@ cli_xml_output_vol_info (cli_local_t *local, dict_t *dict) XML_RET_CHECK_AND_GOTO (ret, out); memset (key, 0, sizeof (key)); - snprintf (key, sizeof (key), "volume%d.type", i); - ret = dict_get_int32 (dict, key, &type); + snprintf (key, sizeof (key), "volume%d.status", i); + ret = dict_get_int32 (dict, key, &status); if (ret) goto out; ret = xmlTextWriterWriteFormatElement (local->writer, - (xmlChar *)"type", - "%d", type); + (xmlChar *)"status", + "%d", status); XML_RET_CHECK_AND_GOTO (ret, out); memset (key, 0, sizeof (key)); - snprintf (key, sizeof (key), "volume%d.status", i); - ret = dict_get_int32 (dict, key, &status); + snprintf (key, sizeof (key), "volume%d.snap_volume", i); + ret = dict_get_str (dict, key, &snap_volume); if (ret) goto out; - ret = xmlTextWriterWriteFormatElement (local->writer, - (xmlChar *)"status", - "%d", status); + if (snap_volume) { + ret = xmlTextWriterWriteFormatElement (local->writer, + (xmlChar *)"snapVol", + "%s", snap_volume); + XML_RET_CHECK_AND_GOTO (ret, out); + } + + ret =xmlTextWriterWriteFormatElement + (local->writer, (xmlChar *)"statusStr", "%s", + cli_vol_status_str[status]); XML_RET_CHECK_AND_GOTO (ret, out); memset (key, 0, sizeof (key)); @@ -2247,6 +2599,25 @@ cli_xml_output_vol_info (cli_local_t *local, dict_t *dict) XML_RET_CHECK_AND_GOTO (ret, out); memset (key, 0, sizeof (key)); + snprintf (key, sizeof (key), "volume%d.type", i); + ret = dict_get_int32 (dict, key, &type); + if (ret) + goto out; + /* For Distributed-(stripe,replicate,stipe-replicate) types */ + if ((type > 0) && (dist_count < brick_count)) + type += 3; + ret = xmlTextWriterWriteFormatElement (local->writer, + (xmlChar *)"type", + "%d", type); + XML_RET_CHECK_AND_GOTO (ret, out); + + ret = xmlTextWriterWriteFormatElement (local->writer, + (xmlChar *)"typeStr", + "%s", + cli_vol_type_str[type]); + XML_RET_CHECK_AND_GOTO (ret, out); + + memset (key, 0, sizeof (key)); snprintf (key, sizeof (key), "volume%d.transport", i); ret = dict_get_int32 (dict, key, &transport); if (ret) @@ -2256,20 +2627,95 @@ cli_xml_output_vol_info (cli_local_t *local, dict_t *dict) "%d", transport); XML_RET_CHECK_AND_GOTO (ret, out); +#ifdef HAVE_BD_XLATOR + /* <xlators> */ + ret = xmlTextWriterStartElement (local->writer, + (xmlChar *)"xlators"); + XML_RET_CHECK_AND_GOTO (ret, out); + + for (k = 0; ; k++) { + memset (key, 0, sizeof (key)); + snprintf (key, sizeof (key),"volume%d.xlator%d", i, k); + ret = dict_get_str (dict, key, &caps); + if (ret) + break; + + /* <xlator> */ + ret = xmlTextWriterStartElement (local->writer, + (xmlChar *)"xlator"); + XML_RET_CHECK_AND_GOTO (ret, out); + + ret = xmlTextWriterWriteFormatElement + (local->writer, (xmlChar *)"name", "%s", caps); + XML_RET_CHECK_AND_GOTO (ret, out); + + /* <capabilities> */ + ret = xmlTextWriterStartElement (local->writer, + (xmlChar *) + "capabilities"); + XML_RET_CHECK_AND_GOTO (ret, out); + + j = 0; + for (j = 0; ;j++) { + memset (key, 0, sizeof (key)); + snprintf (key, sizeof (key), + "volume%d.xlator%d.caps%d", i, k, j); + ret = dict_get_str (dict, key, &caps); + if (ret) + break; + ret = xmlTextWriterWriteFormatElement + (local->writer, (xmlChar *)"capability", + "%s", caps); + XML_RET_CHECK_AND_GOTO (ret, out); + } + /* </capabilities> */ + ret = xmlTextWriterEndElement (local->writer); + XML_RET_CHECK_AND_GOTO (ret, out); + /* </xlator> */ + ret = xmlTextWriterEndElement (local->writer); + XML_RET_CHECK_AND_GOTO (ret, out); + } + ret = xmlTextWriterFullEndElement (local->writer); + XML_RET_CHECK_AND_GOTO (ret, out); + /* </xlators> */ +#else + caps = 0; /* Avoid compiler warnings when BD not enabled */ +#endif + j = 1; + /* <bricks> */ ret = xmlTextWriterStartElement (local->writer, (xmlChar *)"bricks"); XML_RET_CHECK_AND_GOTO (ret, out); while (j <= brick_count) { + ret = xmlTextWriterStartElement + (local->writer, (xmlChar *)"brick"); + XML_RET_CHECK_AND_GOTO (ret, out); + + memset (key, 0, sizeof (key)); + snprintf (key, sizeof (key), "volume%d.brick%d.uuid", + i, j); + ret = dict_get_str (dict, key, &uuid); + if (ret) + goto out; + ret = xmlTextWriterWriteFormatAttribute + (local->writer, (xmlChar *)"uuid", "%s", + uuid); + XML_RET_CHECK_AND_GOTO (ret, out); + memset (key, 0, sizeof (key)); snprintf (key, sizeof (key), "volume%d.brick%d", i, j); ret = dict_get_str (dict, key, &brick); if (ret) goto out; - ret = xmlTextWriterWriteFormatElement - (local->writer, (xmlChar *)"brick", "%s", - brick); + ret = xmlTextWriterWriteFormatString + (local->writer, "%s", brick); + XML_RET_CHECK_AND_GOTO (ret, out); + + /* </brick> */ + ret = xmlTextWriterEndElement (local->writer); XML_RET_CHECK_AND_GOTO (ret, out); + j++; } /* </bricks> */ @@ -2287,24 +2733,30 @@ cli_xml_output_vol_info (cli_local_t *local, dict_t *dict) ret = xmlTextWriterEndElement (local->writer); XML_RET_CHECK_AND_GOTO (ret, out); } - GF_FREE (local->get_vol.volname); - local->get_vol.volname = gf_strdup (volname); - local->vol_count += count; + if (volname) { + GF_FREE (local->get_vol.volname); + local->get_vol.volname = gf_strdup (volname); + local->vol_count += count; + } out: gf_log ("cli", GF_LOG_DEBUG, "Returning %d", ret); return ret; +#else + return 0; +#endif } int cli_xml_output_vol_info_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->buf)); + ret = cli_begin_xml_output (&(local->writer), &(local->doc)); if (ret) goto out; @@ -2327,11 +2779,15 @@ cli_xml_output_vol_info_begin (cli_local_t *local, int op_ret, int op_errno, out: gf_log ("cli", GF_LOG_DEBUG, "Returning %d", ret); return ret; +#else + return 0; +#endif } int cli_xml_output_vol_info_end (cli_local_t *local) { +#if (HAVE_LIB_XML) int ret = -1; GF_ASSERT (local); @@ -2348,11 +2804,14 @@ cli_xml_output_vol_info_end (cli_local_t *local) ret = xmlTextWriterEndElement (local->writer); XML_RET_CHECK_AND_GOTO (ret, out); - ret = cli_end_xml_output (local->writer, local->buf); + ret = cli_end_xml_output (local->writer, local->doc); out: gf_log ("cli", GF_LOG_ERROR, "Returning %d", ret); return ret; +#else + return 0; +#endif } int @@ -2360,9 +2819,10 @@ cli_xml_output_vol_quota_limit_list (char *volname, char *limit_list, int op_ret, int op_errno, char *op_errstr) { +#if (HAVE_LIB_XML) int ret = -1; xmlTextWriterPtr writer = NULL; - xmlBufferPtr buf = NULL; + xmlDocPtr doc = NULL; int64_t size = 0; int64_t limit_value = 0; int i = 0; @@ -2380,7 +2840,7 @@ cli_xml_output_vol_quota_limit_list (char *volname, char *limit_list, GF_ASSERT (volname); GF_ASSERT (limit_list); - ret = cli_begin_xml_output (&writer, &buf); + ret = cli_begin_xml_output (&writer, &doc); if (ret) goto out; @@ -2490,12 +2950,823 @@ cont: ret = xmlTextWriterEndElement (writer); XML_RET_CHECK_AND_GOTO (ret, out); - ret = cli_end_xml_output (writer, buf); + ret = cli_end_xml_output (writer, doc); out: GF_FREE (size_str); gf_log ("cli", GF_LOG_DEBUG, "Returning %d", ret); return ret; +#else + return 0; +#endif +} + +int +cli_xml_output_peer_status (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; + int count = 0; + char *uuid = NULL; + char *hostname = NULL; + int connected = 0; + int state_id = 0; + char *state_str = NULL; + int i = 1; + char key[1024] = {0,}; + + ret = cli_begin_xml_output (&writer, &doc); + if (ret) + goto out; + + ret = cli_xml_output_common (writer, op_ret, op_errno, op_errstr); + if (ret) + goto out; + + /* <peerStatus> */ + ret = xmlTextWriterStartElement (writer, (xmlChar *)"peerStatus"); + XML_RET_CHECK_AND_GOTO (ret, out); + + if (!dict) + goto cont; + + ret = dict_get_int32 (dict, "count", &count); + if (ret) + goto out; + + while (i <= count) { + /* <peer> */ + ret = xmlTextWriterStartElement (writer, (xmlChar *)"peer"); + XML_RET_CHECK_AND_GOTO (ret, out); + + memset (key, 0, sizeof (key)); + snprintf (key, sizeof (key), "friend%d.uuid", i); + ret = dict_get_str (dict, key, &uuid); + if (ret) + goto out; + + ret = xmlTextWriterWriteFormatElement (writer, + (xmlChar *)"uuid", + "%s", uuid); + XML_RET_CHECK_AND_GOTO (ret, out); + + memset (key, 0, sizeof (key)); + snprintf (key, sizeof (key), "friend%d.hostname", i); + ret = dict_get_str (dict, key, &hostname); + if (ret) + goto out; + + ret = xmlTextWriterWriteFormatElement (writer, + (xmlChar *)"hostname", + "%s", hostname); + XML_RET_CHECK_AND_GOTO (ret, out); + + memset (key, 0, sizeof (key)); + snprintf (key, sizeof (key), "friend%d.connected", i); + ret = dict_get_int32 (dict, key, &connected); + if (ret) + goto out; + + ret = xmlTextWriterWriteFormatElement (writer, + (xmlChar *)"connected", + "%d", connected); + XML_RET_CHECK_AND_GOTO (ret, out); + + memset (key, 0, sizeof (key)); + snprintf (key, sizeof (key), "friend%d.stateId", i); + ret = dict_get_int32 (dict, key, &state_id); + if (!ret) { + /* ignore */ + + ret = xmlTextWriterWriteFormatElement (writer, + (xmlChar *)"state", "%d", state_id); + XML_RET_CHECK_AND_GOTO (ret, out); + } + + memset (key, 0, sizeof (key)); + snprintf (key, sizeof (key), "friend%d.state", i); + ret = dict_get_str (dict, key, &state_str); + if (!ret) { + /* ignore */ + + ret = xmlTextWriterWriteFormatElement (writer, + (xmlChar *)"stateStr", "%s", state_str); + XML_RET_CHECK_AND_GOTO (ret, out); + } + + /* </peer> */ + ret = xmlTextWriterEndElement (writer); + XML_RET_CHECK_AND_GOTO (ret, out); + + i++; + } + +cont: + /* </peerStatus> */ + ret = xmlTextWriterEndElement (writer); + XML_RET_CHECK_AND_GOTO (ret, out); + + ret = cli_end_xml_output (writer, doc); + +out: + gf_log ("cli", GF_LOG_DEBUG, "Returning %d", ret); + return ret; +#else + return 0; +#endif +} + +#if (HAVE_LIB_XML) +/* Used for rebalance stop/status, remove-brick status */ +int +cli_xml_output_vol_rebalance_status (xmlTextWriterPtr writer, dict_t *dict, + enum gf_task_types task_type) +{ + int ret = -1; + int count = 0; + char *node_name = NULL; + char *node_uuid = NULL; + uint64_t files = 0; + uint64_t size = 0; + uint64_t lookups = 0; + int status_rcd = 0; + uint64_t failures = 0; + uint64_t skipped = 0; + uint64_t total_files = 0; + uint64_t total_size = 0; + uint64_t total_lookups = 0; + uint64_t total_failures = 0; + uint64_t total_skipped = 0; + char key[1024] = {0,}; + int i = 0; + int overall_status = -1; + double elapsed = 0; + double overall_elapsed = 0; + + if (!dict) { + ret = 0; + goto out; + } + + ret = dict_get_int32 (dict, "count", &count); + if (ret) + goto out; + ret = xmlTextWriterWriteFormatElement (writer, (xmlChar *)"nodeCount", + "%d", count); + XML_RET_CHECK_AND_GOTO (ret, out); + + while (i < count) { + i++; + + /* <node> */ + ret = xmlTextWriterStartElement (writer, (xmlChar *)"node"); + XML_RET_CHECK_AND_GOTO (ret, out); + + memset (key, 0, sizeof (key)); + snprintf (key, sizeof (key), "node-name-%d", i); + ret = dict_get_str (dict, key, &node_name); + if (ret) + goto out; + ret = xmlTextWriterWriteFormatElement (writer, + (xmlChar *)"nodeName", + "%s", node_name); + + memset (key, 0, sizeof (key)); + snprintf (key, sizeof (key), "node-uuid-%d", i); + ret = dict_get_str (dict, key, &node_uuid); + if (ret) + goto out; + ret = xmlTextWriterWriteFormatElement (writer, + (xmlChar *)"id", + "%s", node_uuid); + XML_RET_CHECK_AND_GOTO (ret, out); + + memset (key, 0, sizeof (key)); + snprintf (key, sizeof (key), "files-%d", i); + ret = dict_get_uint64 (dict, key, &files); + if (ret) + goto out; + total_files += files; + ret = xmlTextWriterWriteFormatElement (writer, + (xmlChar *)"files", + "%"PRIu64, files); + XML_RET_CHECK_AND_GOTO (ret, out); + + memset (key, 0, sizeof (key)); + snprintf (key, sizeof (key), "size-%d", i); + ret = dict_get_uint64 (dict, key, &size); + if (ret) + goto out; + total_size += size; + ret = xmlTextWriterWriteFormatElement (writer, + (xmlChar *)"size", + "%"PRIu64,size); + XML_RET_CHECK_AND_GOTO (ret, out); + + memset (key, 0, sizeof (key)); + snprintf (key, sizeof (key), "lookups-%d", i); + ret = dict_get_uint64 (dict, key, &lookups); + if (ret) + goto out; + total_lookups += lookups; + ret = xmlTextWriterWriteFormatElement (writer, + (xmlChar *)"lookups", + "%"PRIu64, lookups); + XML_RET_CHECK_AND_GOTO (ret, out); + + memset (key, 0, sizeof (key)); + snprintf (key, sizeof (key), "failures-%d", i); + ret = dict_get_uint64 (dict, key, &failures); + if (ret) + goto out; + total_failures += failures; + ret = xmlTextWriterWriteFormatElement (writer, + (xmlChar *)"failures", + "%"PRIu64, failures); + XML_RET_CHECK_AND_GOTO (ret, out); + + /* skipped-%d is not available for remove brick in dict, + so using failures as skipped count in case of remove-brick + similar to logic used in CLI(non xml output) */ + if (task_type == GF_TASK_TYPE_REBALANCE) { + memset (key, 0, sizeof (key)); + snprintf (key, sizeof (key), "skipped-%d", i); + } + else { + memset (key, 0, sizeof (key)); + snprintf (key, sizeof (key), "failures-%d", i); + } + + ret = dict_get_uint64 (dict, key, &skipped); + if (ret) + goto out; + total_skipped += skipped; + ret = xmlTextWriterWriteFormatElement (writer, + (xmlChar *)"skipped", + "%"PRIu64, skipped); + XML_RET_CHECK_AND_GOTO (ret, out); + + memset (key, 0, sizeof (key)); + snprintf (key, sizeof (key), "status-%d", i); + ret = dict_get_int32 (dict, key, &status_rcd); + if (ret) + goto out; + ret = xmlTextWriterWriteFormatElement (writer, + (xmlChar *)"status", + "%d", status_rcd); + XML_RET_CHECK_AND_GOTO (ret, out); + + ret = xmlTextWriterWriteFormatElement (writer, + (xmlChar *)"statusStr", + "%s", + cli_vol_task_status_str[status_rcd]); + + memset (key, 0, 256); + snprintf (key, 256, "run-time-%d", i); + ret = dict_get_double (dict, key, &elapsed); + if (ret) + goto out; + ret = xmlTextWriterWriteFormatElement (writer, + (xmlChar *)"runtime", + "%.2f", elapsed); + XML_RET_CHECK_AND_GOTO (ret, out); + + if (elapsed > overall_elapsed) { + overall_elapsed = elapsed; + } + + if (-1 == overall_status) + overall_status = status_rcd; + else if ((GF_DEFRAG_STATUS_COMPLETE == overall_status || + status_rcd > overall_status) && + (status_rcd != GF_DEFRAG_STATUS_COMPLETE)) + overall_status = status_rcd; + XML_RET_CHECK_AND_GOTO (ret, out); + + /* </node> */ + ret = xmlTextWriterEndElement (writer); + XML_RET_CHECK_AND_GOTO (ret, out); + } + + /* Aggregate status */ + /* <aggregate> */ + ret = xmlTextWriterStartElement (writer, (xmlChar *)"aggregate"); + XML_RET_CHECK_AND_GOTO (ret, out); + + ret = xmlTextWriterWriteFormatElement (writer,(xmlChar *)"files", + "%"PRIu64, total_files); + XML_RET_CHECK_AND_GOTO (ret, out); + + ret = xmlTextWriterWriteFormatElement (writer,(xmlChar *)"size", + "%"PRIu64, total_size); + XML_RET_CHECK_AND_GOTO (ret, out); + + ret = xmlTextWriterWriteFormatElement (writer,(xmlChar *)"lookups", + "%"PRIu64, total_lookups); + XML_RET_CHECK_AND_GOTO (ret, out); + + ret = xmlTextWriterWriteFormatElement (writer,(xmlChar *)"failures", + "%"PRIu64, total_failures); + XML_RET_CHECK_AND_GOTO (ret, out); + + ret = xmlTextWriterWriteFormatElement (writer,(xmlChar *)"skipped", + "%"PRIu64, total_skipped); + XML_RET_CHECK_AND_GOTO (ret, out); + + ret = xmlTextWriterWriteFormatElement (writer,(xmlChar *)"status", + "%d", overall_status); + XML_RET_CHECK_AND_GOTO (ret, out); + + ret = xmlTextWriterWriteFormatElement (writer,(xmlChar *)"statusStr", + "%s", + cli_vol_task_status_str[overall_status]); + XML_RET_CHECK_AND_GOTO (ret, out); + + ret = xmlTextWriterWriteFormatElement (writer,(xmlChar *)"runtime", + "%.2f", overall_elapsed); + XML_RET_CHECK_AND_GOTO (ret, out); + + /* </aggregate> */ + ret = xmlTextWriterEndElement (writer); + XML_RET_CHECK_AND_GOTO (ret, out); + +out: + gf_log ("cli", GF_LOG_DEBUG, "Returning %d", ret); + return ret; +} +#endif + +int +cli_xml_output_vol_rebalance (gf_cli_defrag_type op, 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; + char *task_id_str = NULL; + + ret = cli_begin_xml_output (&writer, &doc); + if (ret) + goto out; + + ret = cli_xml_output_common (writer, op_ret, op_errno, op_errstr); + if (ret) + goto out; + + /* <volRebalance> */ + ret = xmlTextWriterStartElement (writer, (xmlChar *)"volRebalance"); + XML_RET_CHECK_AND_GOTO (ret, out); + + ret = dict_get_str (dict, GF_REBALANCE_TID_KEY, &task_id_str); + if (ret == 0) { + ret = xmlTextWriterWriteFormatElement (writer, + (xmlChar *)"task-id", + "%s", task_id_str); + XML_RET_CHECK_AND_GOTO (ret, out); + } + + ret = xmlTextWriterWriteFormatElement (writer, (xmlChar *)"op", + "%d", op); + XML_RET_CHECK_AND_GOTO (ret, out); + + if ((GF_DEFRAG_CMD_STOP == op) || (GF_DEFRAG_CMD_STATUS == op)) { + ret = cli_xml_output_vol_rebalance_status (writer, dict, + GF_TASK_TYPE_REBALANCE); + if (ret) + goto out; + } + + /* </volRebalance> */ + ret = xmlTextWriterEndElement (writer); + XML_RET_CHECK_AND_GOTO (ret, out); + + + ret = cli_end_xml_output (writer, doc); + +out: + gf_log ("cli", GF_LOG_DEBUG, "Returning %d", ret); + return ret; +#else + return 0; +#endif +} + +int +cli_xml_output_vol_remove_brick (gf_boolean_t status_op, 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; + char *task_id_str = NULL; + + ret = cli_begin_xml_output (&writer, &doc); + if (ret) + goto out; + + ret = cli_xml_output_common (writer, op_ret, op_errno, op_errstr); + if (ret) + goto out; + + /* <volRemoveBrick> */ + ret = xmlTextWriterStartElement (writer, (xmlChar *)"volRemoveBrick"); + XML_RET_CHECK_AND_GOTO (ret, out); + + ret = dict_get_str (dict, GF_REMOVE_BRICK_TID_KEY, &task_id_str); + if (ret == 0) { + ret = xmlTextWriterWriteFormatElement (writer, + (xmlChar *)"task-id", + "%s", task_id_str); + XML_RET_CHECK_AND_GOTO (ret, out); + } + + if (status_op) { + ret = cli_xml_output_vol_rebalance_status (writer, dict, + GF_TASK_TYPE_REMOVE_BRICK); + if (ret) + goto out; + } + + /* </volRemoveBrick> */ + ret = xmlTextWriterEndElement (writer); + XML_RET_CHECK_AND_GOTO (ret, out); + + + ret = cli_end_xml_output (writer, doc); + +out: + gf_log ("cli", GF_LOG_DEBUG, "Returning %d", ret); + return ret; +#else + return 0; +#endif +} + +int +cli_xml_output_vol_replace_brick (gf1_cli_replace_op op, dict_t *dict, + int op_ret, int op_errno, char *op_errstr) +{ +#if (HAVE_LIB_XML) + int ret = -1; + int status = 0; + uint64_t files = 0; + char *current_file = 0; + char *task_id_str = NULL; + xmlTextWriterPtr writer = NULL; + xmlDocPtr doc = NULL; + + ret = cli_begin_xml_output (&writer, &doc); + if (ret) + goto out; + + ret = cli_xml_output_common (writer, op_ret, op_errno, op_errstr); + if (ret) + goto out; + + /* <volReplaceBrick> */ + ret = xmlTextWriterStartElement (writer, (xmlChar *)"volReplaceBrick"); + XML_RET_CHECK_AND_GOTO (ret, out); + + ret = dict_get_str (dict, GF_REPLACE_BRICK_TID_KEY, &task_id_str); + if (ret == 0) { + ret = xmlTextWriterWriteFormatElement (writer, + (xmlChar *)"task-id", + "%s", task_id_str); + XML_RET_CHECK_AND_GOTO (ret, out); + } + + ret = xmlTextWriterWriteFormatElement (writer, (xmlChar *)"op", + "%d", op); + XML_RET_CHECK_AND_GOTO (ret, out); + + if (GF_REPLACE_OP_STATUS == op) { + ret = dict_get_int32 (dict, "status", &status); + if (ret) + goto out; + ret = xmlTextWriterWriteFormatElement (writer, + (xmlChar *)"status", + "%d", status); + XML_RET_CHECK_AND_GOTO (ret, out); + + ret = dict_get_uint64 (dict, "files", &files); + if (ret) + goto out; + ret = xmlTextWriterWriteFormatElement (writer, + (xmlChar *)"files", + "%"PRIu64, files); + XML_RET_CHECK_AND_GOTO (ret, out); + + if (status) + goto cont; + + ret = dict_get_str (dict, "current_file", ¤t_file); + if (ret) + goto out; + ret = xmlTextWriterWriteFormatElement (writer, + (xmlChar *)"currentFile", + "%s", current_file); + XML_RET_CHECK_AND_GOTO (ret, out); + } +cont: + /* </volReplaceBrick> */ + ret = xmlTextWriterEndElement (writer); + XML_RET_CHECK_AND_GOTO (ret, out); + + ret = cli_end_xml_output (writer, doc); + +out: + gf_log ("cli", GF_LOG_DEBUG, "Returning %d", ret); + return ret; +#else + return 0; +#endif +} + +int +cli_xml_output_vol_create (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; + char *volname = NULL; + char *volid = NULL; + + ret = cli_begin_xml_output (&writer, &doc); + if (ret) + goto out; + + ret = cli_xml_output_common (writer, op_ret, op_errno, op_errstr); + if (ret) + goto out; + + if (dict) { + /* <volCreate> */ + ret = xmlTextWriterStartElement (writer, + (xmlChar *)"volCreate"); + 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", &volname); + if (ret) + goto out; + ret = xmlTextWriterWriteFormatElement (writer, + (xmlChar *) "name", + "%s", volname); + XML_RET_CHECK_AND_GOTO (ret, out); + + ret = dict_get_str (dict, "volume-id", &volid); + if (ret) + goto out; + ret = xmlTextWriterWriteFormatElement (writer, (xmlChar *)"id", + "%s", volid); + XML_RET_CHECK_AND_GOTO (ret, out); + + /* </volume> */ + ret = xmlTextWriterEndElement (writer); + XML_RET_CHECK_AND_GOTO (ret, out); + + /* </volCreate> */ + ret = xmlTextWriterEndElement (writer); + XML_RET_CHECK_AND_GOTO (ret, out); + } + + ret = cli_end_xml_output (writer, doc); + +out: + gf_log ("cli", GF_LOG_DEBUG, "Returning %d", ret); + return ret; +#else + return 0; +#endif +} + +int +cli_xml_output_generic_volume (char *op, 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; + char *volname = NULL; + char *volid = NULL; + + GF_ASSERT (op); + + ret = cli_begin_xml_output (&writer, &doc); + if (ret) + goto out; + + ret = cli_xml_output_common (writer, op_ret, op_errno, op_errstr); + if (ret) + goto out; + + if (dict) { + /* <"op"> */ + ret = xmlTextWriterStartElement (writer, (xmlChar *)op); + 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", &volname); + if (ret) + goto out; + ret = xmlTextWriterWriteFormatElement (writer, + (xmlChar *) "name", + "%s", volname); + XML_RET_CHECK_AND_GOTO (ret, out); + + ret = dict_get_str (dict, "vol-id", &volid); + if (ret) + goto out; + ret = xmlTextWriterWriteFormatElement (writer, (xmlChar *)"id", + "%s", volid); + XML_RET_CHECK_AND_GOTO (ret, out); + + /* </volume> */ + ret = xmlTextWriterEndElement (writer); + XML_RET_CHECK_AND_GOTO (ret, out); + + /* </"op"> */ + ret = xmlTextWriterEndElement (writer); + XML_RET_CHECK_AND_GOTO (ret, out); + } + + ret = cli_end_xml_output (writer, doc); + +out: + gf_log ("cli", GF_LOG_DEBUG, "Returning %d", ret); + return ret; +#else + return 0; +#endif +} + +#if (HAVE_LIB_XML) +int +cli_xml_output_vol_gsync_status (dict_t *dict, xmlTextWriterPtr writer) +{ + char master_key[PATH_MAX] = ""; + char slave_key[PATH_MAX] = ""; + char status_key[PATH_MAX] = ""; + char node_key[PATH_MAX] = ""; + char *master = NULL; + char *slave = NULL; + char *status = NULL; + char *node = NULL; + int ret = -1; + int gsync_count = 0; + int i = 1; + + ret = dict_get_int32 (dict, "gsync-count", &gsync_count); + if (ret) + goto out; + + for (i=1; i <= gsync_count; i++) { + snprintf (node_key, sizeof(node_key), "node%d", i); + snprintf (master_key, sizeof(master_key), "master%d", i); + snprintf (slave_key, sizeof(slave_key), "slave%d", i); + snprintf (status_key, sizeof(status_key), "status%d", i); + + ret = dict_get_str (dict, node_key, &node); + if (ret) + goto out; + + ret = dict_get_str (dict, master_key, &master); + if (ret) + goto out; + + ret = dict_get_str (dict, slave_key, &slave); + if (ret) + goto out; + + ret = dict_get_str (dict, status_key, &status); + if (ret) + goto out; + + /* <pair> */ + ret = xmlTextWriterStartElement (writer, (xmlChar *)"pair"); + XML_RET_CHECK_AND_GOTO (ret, out); + + ret = xmlTextWriterWriteFormatElement (writer, + (xmlChar *)"node", + "%s", node); + XML_RET_CHECK_AND_GOTO (ret, out); + + ret = xmlTextWriterWriteFormatElement (writer, + (xmlChar *)"master", + "%s", master); + XML_RET_CHECK_AND_GOTO (ret, out); + + ret = xmlTextWriterWriteFormatElement (writer, + (xmlChar *)"slave", + "%s", slave); + XML_RET_CHECK_AND_GOTO (ret, out); + + ret = xmlTextWriterWriteFormatElement (writer, + (xmlChar *)"status", + "%s", status); + XML_RET_CHECK_AND_GOTO (ret, out); + + /* </pair> */ + ret = xmlTextWriterEndElement (writer); + XML_RET_CHECK_AND_GOTO (ret, out); + + } + +out: + gf_log ("cli",GF_LOG_DEBUG, "Returning %d", ret); + return ret; } +#endif + +int +cli_xml_output_vol_gsync (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; + char *master = NULL; + char *slave = NULL; + int type = 0; + GF_ASSERT (dict); + + ret = cli_begin_xml_output (&writer, &doc); + if (ret) + goto out; + + ret = cli_xml_output_common (writer, op_ret, op_errno, op_errstr); + if (ret) + goto out; + + /* <geoRep> */ + ret = xmlTextWriterStartElement (writer, (xmlChar *)"geoRep"); + XML_RET_CHECK_AND_GOTO (ret, out); + + ret = dict_get_int32 (dict, "type", &type); + if (ret) { + gf_log ("cli", GF_LOG_ERROR, "Failed to get type"); + goto out; + } + + ret = xmlTextWriterWriteFormatElement (writer, (xmlChar *)"type", + "%d", type); + XML_RET_CHECK_AND_GOTO (ret, out); + + switch (type) { + case GF_GSYNC_OPTION_TYPE_START: + case GF_GSYNC_OPTION_TYPE_STOP: + if (dict_get_str (dict, "master", &master) != 0) + master = "???"; + if (dict_get_str (dict, "slave", &slave) != 0) + slave = "???"; + + ret = xmlTextWriterWriteFormatElement (writer, + (xmlChar *)"master", + "%s", master); + XML_RET_CHECK_AND_GOTO (ret, out); + + ret = xmlTextWriterWriteFormatElement (writer, + (xmlChar *)"slave", + "%s", slave); + XML_RET_CHECK_AND_GOTO (ret, out); + + break; + + case GF_GSYNC_OPTION_TYPE_CONFIG: + break; + case GF_GSYNC_OPTION_TYPE_STATUS: + ret = cli_xml_output_vol_gsync_status(dict, writer); + break; + default: + ret = 0; + break; + } + + /* </geoRep> */ + ret = xmlTextWriterEndElement (writer); + XML_RET_CHECK_AND_GOTO (ret, out); + + ret = cli_end_xml_output (writer, doc); +out: + gf_log ("cli",GF_LOG_DEBUG, "Returning %d", ret); + return ret; +#else + return 0; #endif +} |
