summaryrefslogtreecommitdiffstats
path: root/0169-UPBZ-1353357-json-output.patch
diff options
context:
space:
mode:
Diffstat (limited to '0169-UPBZ-1353357-json-output.patch')
-rw-r--r--0169-UPBZ-1353357-json-output.patch549
1 files changed, 549 insertions, 0 deletions
diff --git a/0169-UPBZ-1353357-json-output.patch b/0169-UPBZ-1353357-json-output.patch
new file mode 100644
index 0000000..14fa840
--- /dev/null
+++ b/0169-UPBZ-1353357-json-output.patch
@@ -0,0 +1,549 @@
+---
+ libmultipath/print.c | 222 ++++++++++++++++++++++++++++++++++++++++++++++
+ libmultipath/print.h | 61 ++++++++++++
+ multipathd/cli.c | 3
+ multipathd/cli.h | 2
+ multipathd/cli_handlers.c | 93 +++++++++++++++++++
+ multipathd/cli_handlers.h | 2
+ multipathd/main.c | 2
+ multipathd/multipathd.8 | 9 +
+ 8 files changed, 393 insertions(+), 1 deletion(-)
+
+Index: multipath-tools-130222/libmultipath/print.c
+===================================================================
+--- multipath-tools-130222.orig/libmultipath/print.c
++++ multipath-tools-130222/libmultipath/print.c
+@@ -269,6 +269,61 @@ snprint_multipath_vpr (char * buff, size
+ pp->vendor_id, pp->product_id);
+ }
+
++
++static int
++snprint_multipath_vend (char * buff, size_t len, struct multipath * mpp)
++{
++ struct pathgroup * pgp;
++ struct path * pp;
++ int i, j;
++
++ vector_foreach_slot(mpp->pg, pgp, i) {
++ if (!pgp)
++ continue;
++ vector_foreach_slot(pgp->paths, pp, j) {
++ if (strlen(pp->vendor_id))
++ return snprintf(buff, len, "%s", pp->vendor_id);
++ }
++ }
++ return snprintf(buff, len, "##");
++}
++
++static int
++snprint_multipath_prod (char * buff, size_t len, struct multipath * mpp)
++{
++ struct pathgroup * pgp;
++ struct path * pp;
++ int i, j;
++
++ vector_foreach_slot(mpp->pg, pgp, i) {
++ if (!pgp)
++ continue;
++ vector_foreach_slot(pgp->paths, pp, j) {
++ if (strlen(pp->product_id))
++ return snprintf(buff, len, "%s", pp->product_id);
++ }
++ }
++ return snprintf(buff, len, "##");
++}
++
++static int
++snprint_multipath_rev (char * buff, size_t len, struct multipath * mpp)
++{
++ struct pathgroup * pgp;
++ struct path * pp;
++ int i, j;
++
++ vector_foreach_slot(mpp->pg, pgp, i) {
++ if (!pgp)
++ continue;
++ vector_foreach_slot(pgp->paths, pp, j) {
++ if (strlen(pp->rev))
++ return snprintf(buff, len, "%s", pp->rev);
++ }
++ }
++ return snprintf(buff, len, "##");
++}
++
+ static int
+ snprint_action (char * buff, size_t len, struct multipath * mpp)
+ {
+@@ -561,6 +616,9 @@ struct multipath_data mpd[] = {
+ {'3', "total_q_time", 0, snprint_total_q_time},
+ {'4', "q_timeouts", 0, snprint_q_timeouts},
+ {'s', "vend/prod/rev", 0, snprint_multipath_vpr},
++ {'v', "vend", 0, snprint_multipath_vend},
++ {'p', "prod", 0, snprint_multipath_prod},
++ {'e', "rev", 0, snprint_multipath_rev},
+ {0, NULL, 0 , NULL}
+ };
+
+@@ -983,6 +1041,170 @@ snprint_multipath_topology (char * buff,
+ return fwd;
+ }
+
++static int
++snprint_json (char * buff, int len, int indent, char *json_str)
++{
++ int fwd = 0, i;
++
++ for (i = 0; i < indent; i++) {
++ fwd += snprintf(buff + fwd, len - fwd, PRINT_JSON_INDENT);
++ if (fwd > len)
++ return fwd;
++ }
++
++ fwd += snprintf(buff + fwd, len - fwd, "%s", json_str);
++ return fwd;
++}
++
++static int
++snprint_json_header (char * buff, int len)
++{
++ int fwd = 0;
++
++ fwd += snprint_json(buff, len, 0, PRINT_JSON_START_ELEM);
++ if (fwd > len)
++ return fwd;
++
++ fwd += snprintf(buff + fwd, len - fwd, PRINT_JSON_START_VERSION,
++ PRINT_JSON_MAJOR_VERSION, PRINT_JSON_MINOR_VERSION);
++ return fwd;
++}
++
++static int
++snprint_json_elem_footer (char * buff, int len, int indent, int last)
++{
++ int fwd = 0, i;
++
++ for (i = 0; i < indent; i++) {
++ fwd += snprintf(buff + fwd, len - fwd, PRINT_JSON_INDENT);
++ if (fwd > len)
++ return fwd;
++ }
++
++ if (last == 1)
++ fwd += snprintf(buff + fwd, len - fwd, "%s", PRINT_JSON_END_LAST_ELEM);
++ else
++ fwd += snprintf(buff + fwd, len - fwd, "%s", PRINT_JSON_END_ELEM);
++ return fwd;
++}
++
++static int
++snprint_multipath_fields_json (char * buff, int len,
++ struct multipath * mpp, int last)
++{
++ int i, j, fwd = 0;
++ struct path *pp;
++ struct pathgroup *pgp;
++
++ fwd += snprint_multipath(buff, len, PRINT_JSON_MAP, mpp, 0);
++ if (fwd > len)
++ return fwd;
++
++ fwd += snprint_json(buff + fwd, len - fwd, 2, PRINT_JSON_START_GROUPS);
++ if (fwd > len)
++ return fwd;
++
++ vector_foreach_slot (mpp->pg, pgp, i) {
++
++ pgp->selector = mpp->selector;
++ fwd += snprint_pathgroup(buff + fwd, len - fwd, PRINT_JSON_GROUP, pgp);
++ if (fwd > len)
++ return fwd;
++
++ fwd += snprintf(buff + fwd, len - fwd, PRINT_JSON_GROUP_NUM, i + 1);
++ if (fwd > len)
++ return fwd;
++
++ fwd += snprint_json(buff + fwd, len - fwd, 3, PRINT_JSON_START_PATHS);
++ if (fwd > len)
++ return fwd;
++
++ vector_foreach_slot (pgp->paths, pp, j) {
++ fwd += snprint_path(buff + fwd, len - fwd, PRINT_JSON_PATH, pp, 0);
++ if (fwd > len)
++ return fwd;
++
++ fwd += snprint_json_elem_footer(buff + fwd,
++ len - fwd, 3, j + 1 == VECTOR_SIZE(pgp->paths));
++ if (fwd > len)
++ return fwd;
++ }
++ fwd += snprint_json(buff + fwd, len - fwd, 0, PRINT_JSON_END_ARRAY);
++ if (fwd > len)
++ return fwd;
++
++ fwd += snprint_json_elem_footer(buff + fwd,
++ len - fwd, 2, i + 1 == VECTOR_SIZE(mpp->pg));
++ if (fwd > len)
++ return fwd;
++ }
++
++ fwd += snprint_json(buff + fwd, len - fwd, 0, PRINT_JSON_END_ARRAY);
++ if (fwd > len)
++ return fwd;
++
++ fwd += snprint_json_elem_footer(buff + fwd, len - fwd, 1, last);
++ return fwd;
++}
++
++int
++snprint_multipath_map_json (char * buff, int len,
++ struct multipath * mpp, int last){
++ int fwd = 0;
++
++ fwd += snprint_json_header(buff, len);
++ if (fwd > len)
++ return len;
++
++ fwd += snprint_json(buff + fwd, len - fwd, 0, PRINT_JSON_START_MAP);
++ if (fwd > len)
++ return len;
++
++ fwd += snprint_multipath_fields_json(buff + fwd, len - fwd, mpp, 1);
++ if (fwd > len)
++ return len;
++
++ fwd += snprint_json(buff + fwd, len - fwd, 0, "\n");
++ if (fwd > len)
++ return len;
++
++ fwd += snprint_json(buff + fwd, len - fwd, 0, PRINT_JSON_END_LAST);
++ if (fwd > len)
++ return len;
++ return fwd;
++}
++
++int
++snprint_multipath_topology_json (char * buff, int len, struct vectors * vecs)
++{
++ int i, fwd = 0;
++ struct multipath * mpp;
++
++ fwd += snprint_json_header(buff, len);
++ if (fwd > len)
++ return len;
++
++ fwd += snprint_json(buff + fwd, len - fwd, 1, PRINT_JSON_START_MAPS);
++ if (fwd > len)
++ return len;
++
++ vector_foreach_slot(vecs->mpvec, mpp, i) {
++ fwd += snprint_multipath_fields_json(buff + fwd, len - fwd,
++ mpp, i + 1 == VECTOR_SIZE(vecs->mpvec));
++ if (fwd > len)
++ return len;
++ }
++
++ fwd += snprint_json(buff + fwd, len - fwd, 0, PRINT_JSON_END_ARRAY);
++ if (fwd > len)
++ return len;
++
++ fwd += snprint_json(buff + fwd, len - fwd, 0, PRINT_JSON_END_LAST);
++ if (fwd > len)
++ return len;
++ return fwd;
++}
++
+ static int
+ snprint_hwentry (char * buff, int len, struct hwentry * hwe)
+ {
+Index: multipath-tools-130222/libmultipath/print.h
+===================================================================
+--- multipath-tools-130222.orig/libmultipath/print.h
++++ multipath-tools-130222/libmultipath/print.h
+@@ -7,6 +7,63 @@
+ #define PRINT_MAP_PROPS "size=%S features='%f' hwhandler='%h' wp=%r"
+ #define PRINT_PG_INDENT "policy='%s' prio=%p status=%t"
+
++#define PRINT_JSON_MULTIPLIER 5
++#define PRINT_JSON_MAJOR_VERSION 0
++#define PRINT_JSON_MINOR_VERSION 1
++#define PRINT_JSON_START_VERSION " \"major_version\": %d,\n" \
++ " \"minor_version\": %d,\n"
++#define PRINT_JSON_START_ELEM "{\n"
++#define PRINT_JSON_START_MAP " \"map\":"
++#define PRINT_JSON_START_MAPS "\"maps\": ["
++#define PRINT_JSON_START_PATHS "\"paths\": ["
++#define PRINT_JSON_START_GROUPS "\"path_groups\": ["
++#define PRINT_JSON_END_ELEM "},"
++#define PRINT_JSON_END_LAST_ELEM "}"
++#define PRINT_JSON_END_LAST "}\n"
++#define PRINT_JSON_END_ARRAY "]\n"
++#define PRINT_JSON_INDENT " "
++#define PRINT_JSON_MAP "{\n" \
++ " \"name\" : \"%n\",\n" \
++ " \"uuid\" : \"%w\",\n" \
++ " \"sysfs\" : \"%d\",\n" \
++ " \"failback\" : \"%F\",\n" \
++ " \"queueing\" : \"%Q\",\n" \
++ " \"paths\" : %N,\n" \
++ " \"write_prot\" : \"%r\",\n" \
++ " \"dm_st\" : \"%t\",\n" \
++ " \"features\" : \"%f\",\n" \
++ " \"hwhandler\" : \"%h\",\n" \
++ " \"action\" : \"%A\",\n" \
++ " \"path_faults\" : %0,\n" \
++ " \"vend\" : \"%v\",\n" \
++ " \"prod\" : \"%p\",\n" \
++ " \"rev\" : \"%e\",\n" \
++ " \"switch_grp\" : %1,\n" \
++ " \"map_loads\" : %2,\n" \
++ " \"total_q_time\" : %3,\n" \
++ " \"q_timeouts\" : %4,"
++
++#define PRINT_JSON_GROUP "{\n" \
++ " \"selector\" : \"%s\",\n" \
++ " \"pri\" : %p,\n" \
++ " \"dm_st\" : \"%t\","
++
++#define PRINT_JSON_GROUP_NUM " \"group\" : %d,\n"
++
++#define PRINT_JSON_PATH "{\n" \
++ " \"dev\" : \"%d\",\n"\
++ " \"dev_t\" : \"%D\",\n" \
++ " \"dm_st\" : \"%t\",\n" \
++ " \"dev_st\" : \"%o\",\n" \
++ " \"chk_st\" : \"%T\",\n" \
++ " \"checker\" : \"%c\",\n" \
++ " \"pri\" : %p,\n" \
++ " \"host_wwnn\" : \"%N\",\n" \
++ " \"target_wwnn\" : \"%n\",\n" \
++ " \"host_wwpn\" : \"%R\",\n" \
++ " \"target_wwpn\" : \"%r\",\n" \
++ " \"host_adapter\" : \"%a\""
++
+ #define MAX_LINE_LEN 80
+ #define MAX_LINES 64
+ #define MAX_FIELD_LEN 64
+@@ -41,6 +98,10 @@ int snprint_path (char *, int, char *, s
+ int snprint_multipath (char *, int, char *, struct multipath *, int);
+ int snprint_multipath_topology (char *, int, struct multipath * mpp,
+ int verbosity);
++int snprint_multipath_topology_json (char * buff, int len,
++ struct vectors * vecs);
++int snprint_multipath_map_json (char * buff, int len,
++ struct multipath * mpp, int last);
+ int snprint_defaults (char *, int);
+ int snprint_blacklist (char *, int);
+ int snprint_blacklist_except (char *, int);
+Index: multipath-tools-130222/multipathd/cli.c
+===================================================================
+--- multipath-tools-130222.orig/multipathd/cli.c
++++ multipath-tools-130222/multipathd/cli.c
+@@ -189,6 +189,7 @@ load_keys (void)
+ r += add_key(keys, "setprstatus", SETPRSTATUS, 0);
+ r += add_key(keys, "unsetprstatus", UNSETPRSTATUS, 0);
+ r += add_key(keys, "format", FMT, 1);
++ r += add_key(keys, "json", JSON, 0);
+
+ if (r) {
+ free_keys(keys);
+@@ -473,8 +474,10 @@ cli_init (void) {
+ add_handler(LIST+MAPS+FMT, NULL);
+ add_handler(LIST+MAPS+RAW+FMT, NULL);
+ add_handler(LIST+MAPS+TOPOLOGY, NULL);
++ add_handler(LIST+MAPS+JSON, NULL);
+ add_handler(LIST+TOPOLOGY, NULL);
+ add_handler(LIST+MAP+TOPOLOGY, NULL);
++ add_handler(LIST+MAP+JSON, NULL);
+ add_handler(LIST+CONFIG, NULL);
+ add_handler(LIST+BLACKLIST, NULL);
+ add_handler(LIST+DEVICES, NULL);
+Index: multipath-tools-130222/multipathd/cli.h
+===================================================================
+--- multipath-tools-130222.orig/multipathd/cli.h
++++ multipath-tools-130222/multipathd/cli.h
+@@ -36,6 +36,7 @@ enum {
+ __SETPRSTATUS,
+ __UNSETPRSTATUS,
+ __FMT,
++ __JSON,
+ };
+
+ #define LIST (1 << __LIST)
+@@ -74,6 +75,7 @@ enum {
+ #define SETPRSTATUS (1ULL << __SETPRSTATUS)
+ #define UNSETPRSTATUS (1ULL << __UNSETPRSTATUS)
+ #define FMT (1ULL << __FMT)
++#define JSON (1ULL << __JSON)
+
+ #define INITIAL_REPLY_LEN 1200
+
+Index: multipath-tools-130222/multipathd/cli_handlers.c
+===================================================================
+--- multipath-tools-130222.orig/multipathd/cli_handlers.c
++++ multipath-tools-130222/multipathd/cli_handlers.c
+@@ -127,6 +127,70 @@ show_maps_topology (char ** r, int * len
+ }
+
+ int
++show_maps_json (char ** r, int * len, struct vectors * vecs)
++{
++ int i;
++ struct multipath * mpp;
++ char * c;
++ char * reply;
++ unsigned int maxlen = INITIAL_REPLY_LEN *
++ PRINT_JSON_MULTIPLIER * VECTOR_SIZE(vecs->mpvec);
++ int again = 1;
++
++ vector_foreach_slot(vecs->mpvec, mpp, i) {
++ if (update_multipath(vecs, mpp->alias, 0)) {
++ return 1;
++ }
++ }
++
++ reply = MALLOC(maxlen);
++
++ while (again) {
++ if (!reply)
++ return 1;
++
++ c = reply;
++
++ c += snprint_multipath_topology_json(c, maxlen, vecs);
++ again = ((c - reply) == maxlen);
++
++ REALLOC_REPLY(reply, again, maxlen);
++ }
++ *r = reply;
++ *len = (int)(c - reply);
++ return 0;
++}
++
++int
++show_map_json (char ** r, int * len, struct multipath * mpp,
++ struct vectors * vecs)
++{
++ char * c;
++ char * reply;
++ unsigned int maxlen = INITIAL_REPLY_LEN;
++ int again = 1;
++
++ if (update_multipath(vecs, mpp->alias, 0))
++ return 1;
++ reply = MALLOC(maxlen);
++
++ while (again) {
++ if (!reply)
++ return 1;
++
++ c = reply;
++
++ c += snprint_multipath_map_json(c, maxlen, mpp, 1);
++ again = ((c - reply) == maxlen);
++
++ REALLOC_REPLY(reply, again, maxlen);
++ }
++ *r = reply;
++ *len = (int)(c - reply);
++ return 0;
++}
++
++int
+ show_config (char ** r, int * len)
+ {
+ char * c;
+@@ -239,6 +303,35 @@ cli_list_maps_topology (void * v, char *
+ }
+
+ int
++cli_list_map_json (void * v, char ** reply, int * len, void * data)
++{
++ struct multipath * mpp;
++ struct vectors * vecs = (struct vectors *)data;
++ char * param = get_keyparam(v, MAP);
++
++ param = convert_dev(param, 0);
++ get_path_layout(vecs->pathvec, 0);
++ mpp = find_mp_by_str(vecs->mpvec, param);
++
++ if (!mpp)
++ return 1;
++
++ condlog(3, "list multipath json %s (operator)", param);
++
++ return show_map_json(reply, len, mpp, vecs);
++}
++
++int
++cli_list_maps_json (void * v, char ** reply, int * len, void * data)
++{
++ struct vectors * vecs = (struct vectors *)data;
++
++ condlog(3, "list multipaths json (operator)");
++
++ return show_maps_json(reply, len, vecs);
++}
++
++int
+ cli_list_wildcards (void * v, char ** reply, int * len, void * data)
+ {
+ char * c;
+Index: multipath-tools-130222/multipathd/cli_handlers.h
+===================================================================
+--- multipath-tools-130222.orig/multipathd/cli_handlers.h
++++ multipath-tools-130222/multipathd/cli_handlers.h
+@@ -10,6 +10,8 @@ int cli_list_maps_status (void * v, char
+ int cli_list_maps_stats (void * v, char ** reply, int * len, void * data);
+ int cli_list_map_topology (void * v, char ** reply, int * len, void * data);
+ int cli_list_maps_topology (void * v, char ** reply, int * len, void * data);
++int cli_list_map_json (void * v, char ** reply, int * len, void * data);
++int cli_list_maps_json (void * v, char ** reply, int * len, void * data);
+ int cli_list_config (void * v, char ** reply, int * len, void * data);
+ int cli_list_blacklist (void * v, char ** reply, int * len, void * data);
+ int cli_list_devices (void * v, char ** reply, int * len, void * data);
+Index: multipath-tools-130222/multipathd/main.c
+===================================================================
+--- multipath-tools-130222.orig/multipathd/main.c
++++ multipath-tools-130222/multipathd/main.c
+@@ -981,7 +981,9 @@ uxlsnrloop (void * ap)
+ set_handler_callback(LIST+MAPS+RAW+FMT, cli_list_maps_raw);
+ set_handler_callback(LIST+MAPS+TOPOLOGY, cli_list_maps_topology);
+ set_handler_callback(LIST+TOPOLOGY, cli_list_maps_topology);
++ set_handler_callback(LIST+MAPS+JSON, cli_list_maps_json);
+ set_handler_callback(LIST+MAP+TOPOLOGY, cli_list_map_topology);
++ set_handler_callback(LIST+MAP+JSON, cli_list_map_json);
+ set_handler_callback(LIST+CONFIG, cli_list_config);
+ set_handler_callback(LIST+BLACKLIST, cli_list_blacklist);
+ set_handler_callback(LIST+DEVICES, cli_list_devices);
+Index: multipath-tools-130222/multipathd/multipathd.8
+===================================================================
+--- multipath-tools-130222.orig/multipathd/multipathd.8
++++ multipath-tools-130222/multipathd/multipathd.8
+@@ -53,11 +53,15 @@ using a format string with multipath for
+ Show the status of all multipath devices that the multipathd is monitoring.
+ .TP
+ .B list|show maps|multipaths stats
+-Show some statistics of all multipath devices that the multipathd is monitoring.
++Show some statistics of all multipath devices that multipathd is monitoring.
+ .TP
+ .B list|show maps|multipaths topology
+ Show the current multipath topology. Same as "multipath \-ll".
+ .TP
++.B list|show maps|multipaths json
++Show the multipath devices that multipathd is monitoring, using JSON
++formatted output.
++.TP
+ .B list|show topology
+ Show the current multipath topology. Same as "multipath \-ll".
+ .TP
+@@ -65,6 +69,9 @@ Show the current multipath topology. Sam
+ Show topology of a single multipath device specified by $map, e.g. 36005076303ffc56200000000000010aa.
+ This map could be obtained from "list maps".
+ .TP
++.B list|show map|multipath $map json
++Show a single multipath device specified by $map, using JSON formatted output.
++.TP
+ .B list|show wildcards
+ Show the format wildcards used in interactive commands taking $format
+ .TP