@@ -434,7 +434,7 @@ get_usage(zpool_help_t idx)
434
434
case HELP_EVENTS :
435
435
return (gettext ("\tevents [-vHf [pool] | -c]\n" ));
436
436
case HELP_GET :
437
- return (gettext ("\tget [-Hp ] [-o \"all\" | field[,...]] "
437
+ return (gettext ("\tget [-jHp ] [-o \"all\" | field[,...]] "
438
438
"<\"all\" | property[,...]> <pool> ...\n" ));
439
439
case HELP_SET :
440
440
return (gettext ("\tset <property=value> <pool>\n"
@@ -892,6 +892,89 @@ print_spare_list(nvlist_t *nv, int indent)
892
892
}
893
893
}
894
894
895
+ /*
896
+ * Generates an nvlist with output version for every command based on params.
897
+ * Purpose of this is to add a version of JSON output, considering the schema
898
+ * format might be updated for each command in future.
899
+ *
900
+ * Schema:
901
+ *
902
+ * "output_version": {
903
+ * "command": string,
904
+ * "vers_major": integer,
905
+ * "vers_minor": integer,
906
+ * }
907
+ */
908
+ static nvlist_t *
909
+ zpool_json_schema (int maj_v , int min_v )
910
+ {
911
+ char cmd [MAX_CMD_LEN ];
912
+ nvlist_t * sch = fnvlist_alloc ();
913
+ nvlist_t * ov = fnvlist_alloc ();
914
+
915
+ snprintf (cmd , MAX_CMD_LEN , "zpool %s" , current_command -> name );
916
+ fnvlist_add_string (ov , "command" , cmd );
917
+ fnvlist_add_uint32 (ov , "vers_major" , maj_v );
918
+ fnvlist_add_uint32 (ov , "vers_minor" , min_v );
919
+ fnvlist_add_nvlist (sch , "output_version" , ov );
920
+ fnvlist_free (ov );
921
+ return (sch );
922
+ }
923
+
924
+ static void
925
+ fill_pool_info (nvlist_t * list , zpool_handle_t * zhp , boolean_t addtype )
926
+ {
927
+ char value [ZFS_MAXPROPLEN ];
928
+ uint64_t txg ;
929
+ nvlist_t * config = zpool_get_config (zhp , NULL );
930
+ uint64_t guid = fnvlist_lookup_uint64 (config , ZPOOL_CONFIG_POOL_GUID );
931
+
932
+ fnvlist_add_string (list , "name" , zpool_get_name (zhp ));
933
+ if (addtype )
934
+ fnvlist_add_string (list , "type" , "POOL" );
935
+ fnvlist_add_string (list , "state" , zpool_get_state_str (zhp ));
936
+ snprintf (value , ZFS_MAXPROPLEN , "%llu" , (u_longlong_t )guid );
937
+ fnvlist_add_string (list , "guid" , value );
938
+ if (nvlist_lookup_uint64 (config , "txg" , & txg ) == 0 ) {
939
+ snprintf (value , ZFS_MAXPROPLEN , "%llu" , (u_longlong_t )txg );
940
+ fnvlist_add_string (list , "txg" , value );
941
+ }
942
+ fnvlist_add_string (list , "spa_version" , SPA_VERSION_STRING );
943
+ fnvlist_add_string (list , "zpl_version" , ZPL_VERSION_STRING );
944
+ }
945
+
946
+ static void
947
+ fill_vdev_info (nvlist_t * list , zpool_handle_t * zhp , char * name )
948
+ {
949
+ boolean_t spare , l2c , log ;
950
+ const char * path , * phys , * devid ;
951
+ nvlist_t * nvdev = zpool_find_vdev (zhp , name , & spare , & l2c , & log );
952
+
953
+ fnvlist_add_string (list , "name" , name );
954
+ fnvlist_add_string (list , "type" , "VDEV" );
955
+ if (nvdev ) {
956
+ const char * type = fnvlist_lookup_string (nvdev ,
957
+ ZPOOL_CONFIG_TYPE );
958
+ if (type )
959
+ fnvlist_add_string (list , "vdev_type" , type );
960
+ uint64_t guid = fnvlist_lookup_uint64 (nvdev , ZPOOL_CONFIG_GUID );
961
+ if (guid ) {
962
+ char buf [ZFS_MAXPROPLEN ];
963
+ snprintf (buf , ZFS_MAXPROPLEN , "%llu" , (u_longlong_t )guid );
964
+ fnvlist_add_string (list , "guid" , buf );
965
+ }
966
+
967
+ if (nvlist_lookup_string (nvdev , ZPOOL_CONFIG_PATH , & path ) == 0 )
968
+ fnvlist_add_string (list , "path" , path );
969
+ if (nvlist_lookup_string (nvdev , ZPOOL_CONFIG_PHYS_PATH ,
970
+ & phys ) == 0 )
971
+ fnvlist_add_string (list , "phys_path" , phys );
972
+ if (nvlist_lookup_string (nvdev , ZPOOL_CONFIG_DEVID ,
973
+ & devid ) == 0 )
974
+ fnvlist_add_string (list , "devid" , devid );
975
+ }
976
+ }
977
+
895
978
static boolean_t
896
979
prop_list_contains_feature (nvlist_t * proplist )
897
980
{
@@ -10243,35 +10326,6 @@ zpool_do_history(int argc, char **argv)
10243
10326
return (ret );
10244
10327
}
10245
10328
10246
- /*
10247
- * Generates an nvlist with output version for every command based on params.
10248
- * Purpose of this is to add a version of JSON output, considering the schema
10249
- * format might be updated for each command in future.
10250
- *
10251
- * Schema:
10252
- *
10253
- * "output_version": {
10254
- * "command": string,
10255
- * "vers_major": integer,
10256
- * "vers_minor": integer,
10257
- * }
10258
- */
10259
- static nvlist_t *
10260
- zpool_json_schema (int maj_v , int min_v )
10261
- {
10262
- char cmd [MAX_CMD_LEN ];
10263
- nvlist_t * sch = fnvlist_alloc ();
10264
- nvlist_t * ov = fnvlist_alloc ();
10265
-
10266
- snprintf (cmd , MAX_CMD_LEN , "zpool %s" , current_command -> name );
10267
- fnvlist_add_string (ov , "command" , cmd );
10268
- fnvlist_add_uint32 (ov , "vers_major" , maj_v );
10269
- fnvlist_add_uint32 (ov , "vers_minor" , min_v );
10270
- fnvlist_add_nvlist (sch , "output_version" , ov );
10271
-
10272
- return (sch );
10273
- }
10274
-
10275
10329
typedef struct ev_opts {
10276
10330
int verbose ;
10277
10331
int scripted ;
@@ -10666,6 +10720,17 @@ get_callback_vdev(zpool_handle_t *zhp, char *vdevname, void *data)
10666
10720
zprop_get_cbdata_t * cbp = (zprop_get_cbdata_t * )data ;
10667
10721
char value [ZFS_MAXPROPLEN ];
10668
10722
zprop_source_t srctype ;
10723
+ nvlist_t * props , * item , * d ;
10724
+ props = item = d = NULL ;
10725
+
10726
+ if (cbp -> cb_json ) {
10727
+ d = fnvlist_lookup_nvlist (cbp -> cb_jsobj , "data" );
10728
+ if (d == NULL ) {
10729
+ fprintf (stderr , "data obj not found.\n" );
10730
+ exit (1 );
10731
+ }
10732
+ props = fnvlist_alloc ();
10733
+ }
10669
10734
10670
10735
for (zprop_list_t * pl = cbp -> cb_proplist ; pl != NULL ;
10671
10736
pl = pl -> pl_next ) {
@@ -10687,9 +10752,21 @@ get_callback_vdev(zpool_handle_t *zhp, char *vdevname, void *data)
10687
10752
if (zpool_get_vdev_prop (zhp , vdevname , pl -> pl_prop ,
10688
10753
prop_name , value , sizeof (value ), & srctype ,
10689
10754
cbp -> cb_literal ) == 0 ) {
10690
- zprop_print_one_property (vdevname , cbp , prop_name ,
10691
- value , srctype , NULL , NULL );
10755
+ zprop_collect_property (vdevname , cbp , prop_name ,
10756
+ value , srctype , NULL , NULL , props );
10757
+ }
10758
+ }
10759
+
10760
+ if (cbp -> cb_json ) {
10761
+ if (!nvlist_empty (props )) {
10762
+ item = fnvlist_alloc ();
10763
+ fill_vdev_info (item , zhp , vdevname );
10764
+ fnvlist_add_nvlist (item , "properties" , props );
10765
+ fnvlist_add_nvlist (d , vdevname , item );
10766
+ fnvlist_add_nvlist (cbp -> cb_jsobj , "data" , d );
10767
+ fnvlist_free (item );
10692
10768
}
10769
+ fnvlist_free (props );
10693
10770
}
10694
10771
10695
10772
return (0 );
@@ -10733,8 +10810,18 @@ get_callback(zpool_handle_t *zhp, void *data)
10733
10810
zprop_source_t srctype ;
10734
10811
zprop_list_t * pl ;
10735
10812
int vid ;
10813
+ int err = 0 ;
10814
+ nvlist_t * props , * item , * d ;
10815
+ props = item = d = NULL ;
10736
10816
10737
10817
if (cbp -> cb_type == ZFS_TYPE_VDEV ) {
10818
+ if (cbp -> cb_json ) {
10819
+ nvlist_t * pool = fnvlist_alloc ();
10820
+ fill_pool_info (pool , zhp , B_FALSE );
10821
+ fnvlist_add_nvlist (cbp -> cb_jsobj , "pool" , pool );
10822
+ fnvlist_free (pool );
10823
+ }
10824
+
10738
10825
if (strcmp (cbp -> cb_vdevs .cb_names [0 ], "all-vdevs" ) == 0 ) {
10739
10826
for_each_vdev (zhp , get_callback_vdev_cb , data );
10740
10827
} else {
@@ -10754,6 +10841,14 @@ get_callback(zpool_handle_t *zhp, void *data)
10754
10841
}
10755
10842
} else {
10756
10843
assert (cbp -> cb_type == ZFS_TYPE_POOL );
10844
+ if (cbp -> cb_json ) {
10845
+ d = fnvlist_lookup_nvlist (cbp -> cb_jsobj , "data" );
10846
+ if (d == NULL ) {
10847
+ fprintf (stderr , "data obj not found.\n" );
10848
+ exit (1 );
10849
+ }
10850
+ props = fnvlist_alloc ();
10851
+ }
10757
10852
for (pl = cbp -> cb_proplist ; pl != NULL ; pl = pl -> pl_next ) {
10758
10853
/*
10759
10854
* Skip the special fake placeholder. This will also
@@ -10771,9 +10866,9 @@ get_callback(zpool_handle_t *zhp, void *data)
10771
10866
value , sizeof (value ), & srctype ) != 0 )
10772
10867
continue ;
10773
10868
10774
- zprop_print_one_property ( zpool_get_name ( zhp ),
10775
- cbp , pl -> pl_user_prop , value , srctype ,
10776
- NULL , NULL );
10869
+ err = zprop_collect_property (
10870
+ zpool_get_name ( zhp ), cbp , pl -> pl_user_prop ,
10871
+ value , srctype , NULL , NULL , props );
10777
10872
} else if (pl -> pl_prop == ZPROP_INVAL &&
10778
10873
(zpool_prop_feature (pl -> pl_user_prop ) ||
10779
10874
zpool_prop_unsupported (pl -> pl_user_prop ))) {
@@ -10782,21 +10877,41 @@ get_callback(zpool_handle_t *zhp, void *data)
10782
10877
if (zpool_prop_get_feature (zhp ,
10783
10878
pl -> pl_user_prop , value ,
10784
10879
sizeof (value )) == 0 ) {
10785
- zprop_print_one_property (
10880
+ err = zprop_collect_property (
10786
10881
zpool_get_name (zhp ), cbp ,
10787
10882
pl -> pl_user_prop , value , srctype ,
10788
- NULL , NULL );
10883
+ NULL , NULL , props );
10789
10884
}
10790
10885
} else {
10791
10886
if (zpool_get_prop (zhp , pl -> pl_prop , value ,
10792
10887
sizeof (value ), & srctype ,
10793
10888
cbp -> cb_literal ) != 0 )
10794
10889
continue ;
10795
10890
10796
- zprop_print_one_property (zpool_get_name (zhp ),
10797
- cbp , zpool_prop_to_name (pl -> pl_prop ),
10798
- value , srctype , NULL , NULL );
10891
+ err = zprop_collect_property (
10892
+ zpool_get_name (zhp ), cbp ,
10893
+ zpool_prop_to_name (pl -> pl_prop ),
10894
+ value , srctype , NULL , NULL , props );
10895
+ }
10896
+ if (err != 0 )
10897
+ return (err );
10898
+ }
10899
+
10900
+ if (cbp -> cb_json ) {
10901
+ if (!nvlist_empty (props )) {
10902
+ char buf [256 ];
10903
+ item = fnvlist_alloc ();
10904
+ fill_pool_info (item , zhp , B_TRUE );
10905
+ fnvlist_add_nvlist (item , "properties" , props );
10906
+ uint64_t guid = fnvlist_lookup_uint64 (
10907
+ zpool_get_config (zhp , NULL ),
10908
+ ZPOOL_CONFIG_POOL_GUID );
10909
+ snprintf (buf , 256 , "%llu" , (u_longlong_t )guid );
10910
+ fnvlist_add_nvlist (d , buf , item );
10911
+ fnvlist_add_nvlist (cbp -> cb_jsobj , "data" , d );
10912
+ fnvlist_free (item );
10799
10913
}
10914
+ fnvlist_free (props );
10800
10915
}
10801
10916
}
10802
10917
@@ -10824,6 +10939,7 @@ zpool_do_get(int argc, char **argv)
10824
10939
int c , i ;
10825
10940
char * propstr = NULL ;
10826
10941
char * vdev = NULL ;
10942
+ nvlist_t * data ;
10827
10943
10828
10944
cb .cb_first = B_TRUE ;
10829
10945
@@ -10840,14 +10956,21 @@ zpool_do_get(int argc, char **argv)
10840
10956
current_prop_type = cb .cb_type ;
10841
10957
10842
10958
/* check options */
10843
- while ((c = getopt (argc , argv , ":Hpo :" )) != -1 ) {
10959
+ while ((c = getopt (argc , argv , ":jHpo :" )) != -1 ) {
10844
10960
switch (c ) {
10845
10961
case 'p' :
10846
10962
cb .cb_literal = B_TRUE ;
10847
10963
break ;
10848
10964
case 'H' :
10849
10965
cb .cb_scripted = B_TRUE ;
10850
10966
break ;
10967
+ case 'j' :
10968
+ cb .cb_json = B_TRUE ;
10969
+ cb .cb_jsobj = zpool_json_schema (0 , 1 );
10970
+ data = fnvlist_alloc ();
10971
+ fnvlist_add_nvlist (cb .cb_jsobj , "data" , data );
10972
+ fnvlist_free (data );
10973
+ break ;
10851
10974
case 'o' :
10852
10975
memset (& cb .cb_columns , 0 , sizeof (cb .cb_columns ));
10853
10976
i = 0 ;
@@ -10970,6 +11093,9 @@ zpool_do_get(int argc, char **argv)
10970
11093
ret = for_each_pool (argc , argv , B_TRUE , & cb .cb_proplist , cb .cb_type ,
10971
11094
cb .cb_literal , get_callback , & cb );
10972
11095
11096
+ if (cb .cb_json )
11097
+ zcmd_print_json (cb .cb_jsobj );
11098
+
10973
11099
if (cb .cb_proplist == & fake_name )
10974
11100
zprop_free_list (fake_name .pl_next );
10975
11101
else
0 commit comments