[Qemu-devel] [PATCH V4 2/2] qemu-img: Add json output option to the info command.
This option --output=[human|json] make qemu-img info output on human or JSON representation at the choice of the user. example: { snapshots: [ { vm-clock-nsec: 20637102488, name: vm-20120821145509, date-sec: 1345553709, date-nsec: 220289000, id: 1, vm-state-size: 96522745 }, { vm-clock-nsec: 46028210866, name: vm-20120821154059, date-sec: 1345556459, date-nsec: 171392000, id: 2, vm-state-size: 101208714 } ], virtual-size: 1073741824, filename: snap.qcow2, cluster-size: 65536, format: qcow2, actual-size: 985587712, dirty-flag: false } Signed-off-by: Benoit Canet ben...@irqsave.net --- Makefile |3 +- qemu-img.c | 252 +--- 2 files changed, 210 insertions(+), 45 deletions(-) diff --git a/Makefile b/Makefile index ab82ef3..9ba064b 100644 --- a/Makefile +++ b/Makefile @@ -160,7 +160,8 @@ tools-obj-y = $(oslib-obj-y) $(trace-obj-y) qemu-tool.o qemu-timer.o \ iohandler.o cutils.o iov.o async.o tools-obj-$(CONFIG_POSIX) += compatfd.o -qemu-img$(EXESUF): qemu-img.o $(tools-obj-y) $(block-obj-y) +qemu-img$(EXESUF): qemu-img.o $(tools-obj-y) $(block-obj-y) $(qapi-obj-y) \ + qapi-visit.o qapi-types.o qemu-nbd$(EXESUF): qemu-nbd.o $(tools-obj-y) $(block-obj-y) qemu-io$(EXESUF): qemu-io.o cmd.o $(tools-obj-y) $(block-obj-y) diff --git a/qemu-img.c b/qemu-img.c index 80cfb9b..1591898 100644 --- a/qemu-img.c +++ b/qemu-img.c @@ -21,12 +21,16 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ +#include qapi-visit.h +#include qapi/qmp-output-visitor.h +#include qjson.h #include qemu-common.h #include qemu-option.h #include qemu-error.h #include osdep.h #include sysemu.h #include block_int.h +#include getopt.h #include stdio.h #ifdef _WIN32 @@ -84,6 +88,7 @@ static void help(void) '-p' show progress of command (only certain commands)\n '-S' indicates the consecutive number of bytes that must contain only zeros\n for qemu-img to create a sparse image during conversion\n + '--output' takes the format in which the output must be done (human or json)\n \n Parameters to check subcommand:\n '-r' tries to repair any inconsistencies that are found during the check.\n @@ -1083,7 +1088,6 @@ out: return 0; } - static void dump_snapshots(BlockDriverState *bs) { QEMUSnapshotInfo *sn_tab, *sn; @@ -1102,21 +1106,188 @@ static void dump_snapshots(BlockDriverState *bs) g_free(sn_tab); } -static int img_info(int argc, char **argv) +static void collect_snapshots(BlockDriverState *bs , ImageInfo *info) +{ +int i, sn_count; +QEMUSnapshotInfo *sn_tab = NULL; +SnapshotInfoList *sn_info_list, *cur_item = NULL; +sn_count = bdrv_snapshot_list(bs, sn_tab); + +for (i = 0; i sn_count; i++) { +info-has_snapshots = true; +sn_info_list = g_new0(SnapshotInfoList, 1); + +sn_info_list-value= g_new0(SnapshotInfo, 1); +sn_info_list-value-id= g_strdup(sn_tab[i].id_str); +sn_info_list-value-name = g_strdup(sn_tab[i].name); +sn_info_list-value-vm_state_size = sn_tab[i].vm_state_size; +sn_info_list-value-date_sec = sn_tab[i].date_sec; +sn_info_list-value-date_nsec = sn_tab[i].date_nsec; +sn_info_list-value-vm_clock_nsec = sn_tab[i].vm_clock_nsec; + +/* XXX: waiting for the qapi to support GSList */ +if (!cur_item) { +info-snapshots = cur_item = sn_info_list; +} else { +cur_item-next = sn_info_list; +cur_item = sn_info_list; +} + +} + +g_free(sn_tab); +} + +static void dump_json_image_info(ImageInfo *info) +{ +Error *errp = NULL; +QString *str; +QmpOutputVisitor *ov = qmp_output_visitor_new(); +QObject *obj; +visit_type_ImageInfo(qmp_output_get_visitor(ov), + info, NULL, errp); +obj = qmp_output_get_qobject(ov); +str = qobject_to_json_pretty(obj); +assert(str != NULL); +printf(%s\n, qstring_get_str(str)); +qobject_decref(obj); +qmp_output_visitor_cleanup(ov); +QDECREF(str); +} + +static void collect_backing_file_format(ImageInfo *info, char *filename) +{ +BlockDriverState *bs = NULL; +bs = bdrv_new_open(filename, NULL, + BDRV_O_FLAGS | BDRV_O_NO_BACKING); +if (!bs) { +return; +} +info-backing_filename_format = +g_strdup(bdrv_get_format_name(bs)); +bdrv_delete(bs); +info-has_backing_filename_format = true; +} + +static void collect_image_info(BlockDriverState *bs, + ImageInfo *info, +
Re: [Qemu-devel] [PATCH V4 2/2] qemu-img: Add json output option to the info command.
On 08/22/2012 06:45 AM, Benoît Canet wrote: This option --output=[human|json] make qemu-img info output on human or JSON representation at the choice of the user. @@ -1083,7 +1088,6 @@ out: return 0; } - static void dump_snapshots(BlockDriverState *bs) { Spurious whitespace change. +static int img_info(int argc, char **argv) +{ +int c; +bool human = false, json = false; +const char *filename, *fmt, *output; +BlockDriverState *bs; +ImageInfo *info; fmt = NULL; +output = NULL; for(;;) { -c = getopt(argc, argv, f:h); +int option_index = 0; +static struct option long_options[] = { +{help, no_argument, 0, 'h'}, +{format, required_argument, 0, 'f'}, +{output, required_argument, 0, 'm'}, I would define a constant, such as 'enum {OPTION_FORMAT=256};', so that you don't risk future confusion... +{0, 0, 0, 0} +}; +c = getopt_long(argc, argv, f:h, ...if we later do add an 'm' short option. +long_options, option_index); if (c == -1) { break; } @@ -1128,6 +1299,9 @@ static int img_info(int argc, char **argv) case 'f': fmt = optarg; break; +case 'm': Given the above, this would reuse your new named value. @@ -1135,52 +1309,42 @@ static int img_info(int argc, char **argv) } filename = argv[optind++]; +if (output !strncmp(output, json, strlen(json))) { Why strncmp? It ignores trailing garbage (as in --output=jsonoops). Stick to strcmp. +json = true; +} else if (output !strncmp(output, human, strlen(human))) { And again. +human = true; +} else { +fprintf(stderr, +Error: --output must be used with human or json as argument.\n); +return 1; +} If we get here, and --output=... was not given, then both human and json are false. That's a problem, since... + +if (human) { +dump_human_image_info(info); +dump_snapshots(bs); } -bdrv_get_backing_filename(bs, backing_filename, sizeof(backing_filename)); -if (backing_filename[0] != '\0') { -bdrv_get_full_backing_filename(bs, backing_filename2, - sizeof(backing_filename2)); -printf(backing file: %s, backing_filename); -if (strcmp(backing_filename, backing_filename2) != 0) { -printf( (actual path: %s), backing_filename2); -} -putchar('\n'); + +if (json) { +collect_snapshots(bs, info); +dump_json_image_info(info); } -dump_snapshots(bs); + +qapi_free_ImageInfo(info); ...you will end up with no output. You want to default to human output for back-compat to older usage. -- Eric Blake ebl...@redhat.com+1-919-301-3266 Libvirt virtualization library http://libvirt.org signature.asc Description: OpenPGP digital signature