From mboxrd@z Thu Jan 1 00:00:00 1970 From: Germano Percossi Subject: Re: [PATCH v2 1/1] add display of map information in JSON format Date: Thu, 12 May 2016 15:28:06 +0100 Message-ID: <573492F6.5060202@citrix.com> References: <1462907128-28792-1-git-send-email-tgill@redhat.com> <1462907128-28792-2-git-send-email-tgill@redhat.com> Mime-Version: 1.0 Content-Type: text/plain; charset="us-ascii"; Format="flowed" Content-Transfer-Encoding: 7bit Return-path: In-Reply-To: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: dm-devel-bounces@redhat.com Errors-To: dm-devel-bounces@redhat.com To: dm-devel@redhat.com List-Id: dm-devel.ids Hi, If there are not specific reasons to have them merged, I would rather have vendor and product split. By the way, JSON is already a great improvement over the custom parsing we are already doing so I do not want to nitpick. Cheers, Germano On 05/11/2016 06:35 PM, Christophe Varoqui wrote: > Hi, > > the json choice over xml is fine for me, so I'm ready to merge. > > Before I do so, is there a second round of review pending ? > > Are wannabe users of this new output happy with some fields being merged > (like vendor/product/rev) ? > > Best regards, > Christophe Varoqui > OpenSVC > > > On Tue, May 10, 2016 at 9:05 PM, Todd Gill > wrote: > > The patch add these commands: > > multipathd show maps json > multipathd show map $map json > > Each command will output the requested map(s) in JSON. > > For the "show maps json" command, the patch pre-allocates > INITIAL_REPLY_LEN * PRINT_JSON_MULTIPLIER(5). The JSON text > is about 5x the size of the "show maps topology" text. > > Signed-off-by: Todd Gill > > --- > libmultipath/print.c | 163 > ++++++++++++++++++++++++++++++++++++++++++++++ > libmultipath/print.h | 63 ++++++++++++++++++ > multipathd/cli.c | 3 + > multipathd/cli.h | 2 + > multipathd/cli_handlers.c | 93 ++++++++++++++++++++++++++ > multipathd/cli_handlers.h | 2 + > multipathd/main.c | 2 + > 7 files changed, 328 insertions(+) > > diff --git a/libmultipath/print.c b/libmultipath/print.c > index 7fec6e9..e92b534 100644 > --- a/libmultipath/print.c > +++ b/libmultipath/print.c > @@ -1000,6 +1000,169 @@ snprint_multipath_topology (char * buff, int > len, struct multipath * mpp, > } > > static int > +snprint_json (char * line, int len, int indent, char *json_str) > +{ > + int fwd = 0, i; > + > + for (i = 0; i < indent; i++) { > + fwd += snprintf(line + fwd, len - fwd, > PRINT_JSON_INDENT); > + if (fwd > len) > + return fwd; > + } > + > + fwd += snprintf(line + fwd, len - fwd, "%s", json_str); > + return fwd; > +} > + > +static int > +snprint_json_header (char * line, int len) > +{ > + int fwd = 0; > + > + fwd += snprint_json(line + fwd, len, 0, PRINT_JSON_START_ELEM); > + if (fwd > len) > + return fwd; > + > + fwd += snprintf(line + fwd, len - fwd, > PRINT_JSON_START_VERSION, > + PRINT_JSON_MAJOR_VERSION, > PRINT_JSON_MINOR_VERSION); > + return fwd; > +} > + > +static int > +snprint_json_elem_footer (char * line, int len, int indent, int last) > +{ > + int fwd = 0, i; > + > + for (i = 0; i < indent; i++) { > + fwd += snprintf(line + fwd, len - fwd, > PRINT_JSON_INDENT); > + if (fwd > len) > + return fwd; > + } > + > + if (last == 1) > + fwd += snprintf(line + fwd, len - fwd, "%s", > + PRINT_JSON_END_LAST); > + else > + fwd += snprintf(line + 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 + fwd, len - fwd, > 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 += 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; > + > + memset(buff, 0, len); > + fwd += snprint_json_header(buff + fwd, 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"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; > + > + memset(buff, 0, len); > + fwd += snprint_json_header(buff + fwd, 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) > { > int i; > diff --git a/libmultipath/print.h b/libmultipath/print.h > index 8bd0bbc..f8a383d 100644 > --- a/libmultipath/print.h > +++ b/libmultipath/print.h > @@ -7,6 +7,65 @@ > #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 "}" > +#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" \ > + " \"size\" : \"%S\",\n" \ > + " \"features\" : \"%f\",\n" \ > + " \"hwhandler\" : \"%h\",\n" \ > + " \"action\" : \"%A\",\n" \ > + " \"path_faults\" : %0,\n" \ > + " \"vend/prod/rev\" : \"%s\",\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_PATH "{\n" \ > + " \"uuid\" : \"%w\",\n" \ > + " \"hcil\" : \"%i\",\n" \ > + " \"dev\" : \"%d\",\n"\ > + " \"dev_t\" : \"%D\",\n" \ > + " \"dm_st\" : \"%t\",\n" \ > + " \"dev_st\" : \"%o\",\n" \ > + " \"chk_st\" : \"%T\",\n" \ > + " \"vend/prod/rev\" : > \"%s\",\n" \ > + " \"checker\" : \"%c\",\n" \ > + " \"next_check\" : \"%C\",\n" \ > + " \"pri\" : %p,\n" \ > + " \"size\" : \"%S\",\n" \ > + " \"serial\" : \"%z\",\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 +100,10 @@ int snprint_path (char *, int, char *, struct > path *, int); > 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); > diff --git a/multipathd/cli.c b/multipathd/cli.c > index d991cd0..20ee3db 100644 > --- a/multipathd/cli.c > +++ b/multipathd/cli.c > @@ -207,6 +207,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); > @@ -537,8 +538,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+MAP+FMT, NULL); > add_handler(LIST+MAP+RAW+FMT, NULL); > add_handler(LIST+CONFIG, NULL); > diff --git a/multipathd/cli.h b/multipathd/cli.h > index 84ca40f..92cb41b 100644 > --- a/multipathd/cli.h > +++ b/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 > > diff --git a/multipathd/cli_handlers.c b/multipathd/cli_handlers.c > index 8b3cb9d..19cf2ff 100644 > --- a/multipathd/cli_handlers.c > +++ b/multipathd/cli_handlers.c > @@ -156,6 +156,70 @@ show_maps_topology (char ** r, int * len, > struct vectors * vecs) > } > > 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; > + 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, reply + > maxlen - c, > + vecs); > + again = ((c - reply) == maxlen); > + > + REALLOC_REPLY(reply, again, maxlen); > + } > + *r = reply; > + *len = (int)(c - reply + 1); > + 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, reply + maxlen - > c, mpp, 1); > + again = ((c - reply) == maxlen); > + > + REALLOC_REPLY(reply, again, maxlen); > + } > + *r = reply; > + *len = (int)(c - reply + 1); > + return 0; > +} > + > +int > show_config (char ** r, int * len) > { > char * c; > @@ -291,6 +355,35 @@ 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) > +{ > + 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; > diff --git a/multipathd/cli_handlers.h b/multipathd/cli_handlers.h > index 5d51018..e838f19 100644 > --- a/multipathd/cli_handlers.h > +++ b/multipathd/cli_handlers.h > @@ -13,6 +13,8 @@ int cli_list_maps_status (void * v, char ** reply, > int * len, void * data); > 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); > diff --git a/multipathd/main.c b/multipathd/main.c > index 58e8854..33f38cd 100644 > --- a/multipathd/main.c > +++ b/multipathd/main.c > @@ -1120,9 +1120,11 @@ 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+FMT, cli_list_map_fmt); > set_handler_callback(LIST+MAP+RAW+FMT, cli_list_map_fmt); > + set_handler_callback(LIST+MAP+JSON, cli_list_map_json); > set_unlocked_handler_callback(LIST+CONFIG, cli_list_config); > set_unlocked_handler_callback(LIST+BLACKLIST, > cli_list_blacklist); > set_handler_callback(LIST+DEVICES, cli_list_devices); > -- > 2.5.5 > > -- > dm-devel mailing list > dm-devel@redhat.com > https://www.redhat.com/mailman/listinfo/dm-devel > > > > > -- > dm-devel mailing list > dm-devel@redhat.com > https://www.redhat.com/mailman/listinfo/dm-devel >