diff options
Diffstat (limited to '0169-UPBZ-1353357-json-output.patch')
-rw-r--r-- | 0169-UPBZ-1353357-json-output.patch | 549 |
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 |