From: Wenchao Xia <xiawenc@linux.vnet.ibm.com>
To: qemu-devel@nongnu.org
Cc: pbonzini@redhat.com, aliguori@us.ibm.com,
stefanha@linux.vnet.ibm.com,
Wenchao Xia <xiawenc@linux.vnet.ibm.com>
Subject: [Qemu-devel] [PATCH] let qemu-img info genereate json output
Date: Fri, 27 Jul 2012 18:20:48 +0800 [thread overview]
Message-ID: <1343384448-21828-1-git-send-email-xiawenc@linux.vnet.ibm.com> (raw)
This patch would add option -j in qemu-img info command, which
would generate json output in stdout.
Signed-off-by: Wenchao Xia <xiawenc@linux.vnet.ibm.com>
---
qemu-img.c | 306 +++++++++++++++++++++++++++++++++++++++++++++++++++--------
1 files changed, 264 insertions(+), 42 deletions(-)
diff --git a/qemu-img.c b/qemu-img.c
index 80cfb9b..a514c17 100644
--- a/qemu-img.c
+++ b/qemu-img.c
@@ -33,6 +33,9 @@
#include <windows.h>
#endif
+#include "qint.h"
+#include "qjson.h"
+
typedef struct img_cmd_t {
const char *name;
int (*handler)(int argc, char **argv);
@@ -84,6 +87,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"
+ " '-j' try get json output, which would be in stdout, only valid in info command\n"
"\n"
"Parameters to check subcommand:\n"
" '-r' tries to repair any inconsistencies that are found during the check.\n"
@@ -1102,21 +1106,210 @@ static void dump_snapshots(BlockDriverState *bs)
g_free(sn_tab);
}
+/* string must be allocated on heap */
+struct img_infos {
+ char *filename;
+ char *fmt;
+ uint64_t total_sectors;
+ int64_t allocated_size;
+ int32 enc_flag;
+ BlockDriverInfo *bdi;
+ char *backing_filename;
+ char *backing_filename_full;
+ QEMUSnapshotInfo *sn_tab;
+ int nb_sns;
+};
+
+static void img_infos_init(struct img_infos *pinfo)
+{
+ memset(pinfo, 0, sizeof(struct img_infos));
+}
+
+#define TRY_FREE(p) { \
+ if ((p) != NULL) { \
+ g_free((p)); \
+ (p) = NULL; \
+ } \
+}
+static void img_infos_uninit(struct img_infos *pinfo)
+{
+ TRY_FREE(pinfo->filename);
+ TRY_FREE(pinfo->fmt);
+ TRY_FREE(pinfo->bdi);
+ TRY_FREE(pinfo->backing_filename);
+ TRY_FREE(pinfo->backing_filename_full);
+ TRY_FREE(pinfo->sn_tab);
+}
+
+static void snapshot_info_to_list(QList *qlist, QEMUSnapshotInfo *sn)
+{
+ char buf[128];
+ QInt *qint;
+ QString *qstr;
+ QDict *qdic = qdict_new();
+
+ qstr = qstring_from_str(sn->id_str);
+ qdict_put_obj(qdic, "id", QOBJECT(qstr));
+ qstr = qstring_from_str(sn->name);
+ qdict_put_obj(qdic, "name", QOBJECT(qstr));
+
+ snprintf(buf, sizeof(buf), "%ld", sn->vm_state_size);
+ qstr = qstring_from_str(buf);
+ qdict_put_obj(qdic, "vm_state_size", QOBJECT(qstr));
+
+ qint = qint_from_int(sn->date_sec);
+ qdict_put_obj(qdic, "date_sec", QOBJECT(qint));
+ qint = qint_from_int(sn->date_nsec);
+ qdict_put_obj(qdic, "date_nsec", QOBJECT(qint));
+ snprintf(buf, sizeof(buf), "%ld", sn->vm_clock_nsec);
+ qstr = qstring_from_str(buf);
+ qdict_put_obj(qdic, "vm_clock_nsec", QOBJECT(qstr));
+ qlist_append(qlist, qdic);
+}
+
+static void img_infos_print_json(struct img_infos *pinfo, int ret)
+{
+ char buf[128];
+ QInt *qint;
+ QDict *qdic, *qdic_all;
+ QString *qstr;
+ QList *qlist;
+ int i;
+
+ qdic_all = qdict_new();
+
+ qint = qint_from_int(ret);
+ qdict_put_obj(qdic_all, "return", QOBJECT(qint));
+ if (ret != 0) {
+ goto print;
+ }
+
+ qdic = qdict_new();
+ if (pinfo->filename != NULL) {
+ qstr = qstring_from_str(pinfo->filename);
+ qdict_put_obj(qdic, "filename", QOBJECT(qstr));
+ }
+ if (pinfo->fmt != NULL) {
+ qstr = qstring_from_str(pinfo->fmt);
+ qdict_put_obj(qdic, "fmt", QOBJECT(qstr));
+ }
+ snprintf(buf, sizeof(buf), "%ld", pinfo->total_sectors * 512);
+ qstr = qstring_from_str(buf);
+ qdict_put_obj(qdic, "virtual_size", QOBJECT(qstr));
+ snprintf(buf, sizeof(buf), "%ld", pinfo->allocated_size);
+ qstr = qstring_from_str(buf);
+ qdict_put_obj(qdic, "actual_size", QOBJECT(qstr));
+ qint = qint_from_int(pinfo->enc_flag);
+ qdict_put_obj(qdic, "encrypted", QOBJECT(qint));
+
+ if (pinfo->bdi != NULL) {
+ qint = qint_from_int(pinfo->bdi->cluster_size);
+ qdict_put_obj(qdic, "cluster_size", QOBJECT(qint));
+ qint = qint_from_int(pinfo->bdi->is_dirty);
+ qdict_put_obj(qdic, "dirty_flag", QOBJECT(qint));
+ }
+
+ if (pinfo->backing_filename != NULL) {
+ qstr = qstring_from_str(pinfo->backing_filename);
+ qdict_put_obj(qdic, "backing_filename", QOBJECT(qstr));
+ if ((pinfo->backing_filename != NULL) &&
+ (0 != strcmp(pinfo->backing_filename,
+ pinfo->backing_filename_full))
+ ) {
+ qstr = qstring_from_str(pinfo->backing_filename_full);
+ qdict_put_obj(qdic, "backing_filename_full", QOBJECT(qstr));
+ }
+ }
+
+ qlist = qlist_new();
+ i = 0;
+ while (i < pinfo->nb_sns) {
+ snapshot_info_to_list(qlist, &(pinfo->sn_tab[i]));
+ i++;
+ }
+ qdict_put_obj(qdic, "snapshot_list", QOBJECT(qlist));
+
+ qdict_put_obj(qdic_all, "information", QOBJECT(qdic));
+
+ print:
+ qstr = qobject_to_json_pretty(QOBJECT(qdic_all));
+ printf("%s\n", qstring_get_str(qstr));
+ qobject_decref(QOBJECT(qstr));
+
+ qobject_decref(QOBJECT(qdic_all));
+}
+
+static void img_infos_print(struct img_infos *pinfo)
+{
+ char size_buf[128], dsize_buf[128], buf[256];
+ int i;
+ QEMUSnapshotInfo *sn;
+
+ get_human_readable_size(size_buf, sizeof(size_buf),
+ pinfo->total_sectors * 512);
+ if (pinfo->allocated_size < 0) {
+ snprintf(dsize_buf, sizeof(dsize_buf), "unavailable");
+ } else {
+ get_human_readable_size(dsize_buf, sizeof(dsize_buf),
+ pinfo->allocated_size);
+ }
+
+ printf("image: %s\n"
+ "file format: %s\n"
+ "virtual size: %s (%" PRId64 " bytes)\n"
+ "disk size: %s\n",
+ pinfo->filename, pinfo->fmt, size_buf,
+ (pinfo->total_sectors * 512),
+ dsize_buf);
+
+ if (pinfo->enc_flag > 0) {
+ printf("encrypted: yes\n");
+ }
+
+ if (pinfo->bdi != NULL) {
+ if (pinfo->bdi->cluster_size != 0) {
+ printf("cluster_size: %d\n", pinfo->bdi->cluster_size);
+ }
+ if (pinfo->bdi->is_dirty) {
+ printf("cleanly shut down: no\n");
+ }
+ }
+
+ if (pinfo->backing_filename != NULL) {
+ printf("backing file: %s", pinfo->backing_filename);
+ if ((pinfo->backing_filename != NULL) &&
+ (0 != strcmp(pinfo->backing_filename,
+ pinfo->backing_filename_full))
+ ) {
+ printf(" (actual path: %s)", pinfo->backing_filename_full);
+ }
+ putchar('\n');
+ }
+
+ if (pinfo->nb_sns <= 0) {
+ return;
+ }
+
+ printf("Snapshot list:\n");
+ printf("%s\n", bdrv_snapshot_dump(buf, sizeof(buf), NULL));
+ for (i = 0; i < pinfo->nb_sns; i++) {
+ sn = &(pinfo->sn_tab[i]);
+ printf("%s\n", bdrv_snapshot_dump(buf, sizeof(buf), sn));
+ }
+}
+
+#define FILENAME_LEN_MAX (1024)
static int img_info(int argc, char **argv)
{
int c;
const char *filename, *fmt;
BlockDriverState *bs;
- char size_buf[128], dsize_buf[128];
- uint64_t total_sectors;
- int64_t allocated_size;
- char backing_filename[1024];
- char backing_filename2[1024];
- BlockDriverInfo bdi;
+ int json_flag = 0, ret = 0;
+ struct img_infos my_img_infos;
fmt = NULL;
for(;;) {
- c = getopt(argc, argv, "f:h");
+ c = getopt(argc, argv, "f:h:j");
if (c == -1) {
break;
}
@@ -1128,6 +1321,9 @@ static int img_info(int argc, char **argv)
case 'f':
fmt = optarg;
break;
+ case 'j':
+ json_flag = 1;
+ break;
}
}
if (optind >= argc) {
@@ -1135,50 +1331,76 @@ static int img_info(int argc, char **argv)
}
filename = argv[optind++];
+ img_infos_init(&my_img_infos);
+ my_img_infos.filename = strdup(filename);
+
bs = bdrv_new_open(filename, fmt, BDRV_O_FLAGS | BDRV_O_NO_BACKING);
if (!bs) {
- return 1;
+ ret = 1;
+ goto output;
}
- bdrv_get_geometry(bs, &total_sectors);
- get_human_readable_size(size_buf, sizeof(size_buf), total_sectors * 512);
- allocated_size = bdrv_get_allocated_file_size(bs);
- if (allocated_size < 0) {
- snprintf(dsize_buf, sizeof(dsize_buf), "unavailable");
- } else {
- get_human_readable_size(dsize_buf, sizeof(dsize_buf),
- allocated_size);
+
+ my_img_infos.fmt = strdup(bdrv_get_format_name(bs));
+
+ bdrv_get_geometry(bs, &(my_img_infos.total_sectors));
+ my_img_infos.allocated_size = bdrv_get_allocated_file_size(bs);
+
+ my_img_infos.enc_flag = bdrv_is_encrypted(bs);
+ my_img_infos.bdi = g_malloc(sizeof(BlockDriverInfo));
+ if (my_img_infos.bdi == NULL) {
+ ret = -1;
+ goto output;
}
- printf("image: %s\n"
- "file format: %s\n"
- "virtual size: %s (%" PRId64 " bytes)\n"
- "disk size: %s\n",
- filename, bdrv_get_format_name(bs), size_buf,
- (total_sectors * 512),
- dsize_buf);
- if (bdrv_is_encrypted(bs)) {
- printf("encrypted: yes\n");
+ if (bdrv_get_info(bs, my_img_infos.bdi) < 0) {
+ g_free(my_img_infos.bdi);
+ my_img_infos.bdi = NULL;
}
- if (bdrv_get_info(bs, &bdi) >= 0) {
- if (bdi.cluster_size != 0) {
- printf("cluster_size: %d\n", bdi.cluster_size);
+
+ my_img_infos.backing_filename = g_malloc(FILENAME_LEN_MAX);
+ if (my_img_infos.backing_filename == NULL) {
+ ret = -1;
+ goto output;
+ }
+ memset(my_img_infos.backing_filename, 0, FILENAME_LEN_MAX);
+ bdrv_get_backing_filename(bs, my_img_infos.backing_filename,
+ FILENAME_LEN_MAX);
+ if (my_img_infos.backing_filename[0] != '\0') {
+ my_img_infos.backing_filename_full = g_malloc(FILENAME_LEN_MAX);
+ if (my_img_infos.backing_filename_full == NULL) {
+ ret = -1;
+ goto output;
}
- if (bdi.is_dirty) {
- printf("cleanly shut down: no\n");
+ memset(my_img_infos.backing_filename_full, 0, FILENAME_LEN_MAX);
+ bdrv_get_full_backing_filename(bs, my_img_infos.backing_filename_full,
+ FILENAME_LEN_MAX);
+ if (my_img_infos.backing_filename_full[0] == '\0') {
+ g_free(my_img_infos.backing_filename_full);
+ my_img_infos.backing_filename_full = NULL;
}
+ } else {
+ g_free(my_img_infos.backing_filename);
+ my_img_infos.backing_filename = NULL;
}
- 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');
+
+ my_img_infos.nb_sns = bdrv_snapshot_list(bs, &(my_img_infos.sn_tab));
+
+ output:
+ if ((ret != 0) && (json_flag == 0)) {
+ goto clean;
}
- dump_snapshots(bs);
- bdrv_delete(bs);
- return 0;
+
+ if (json_flag > 0) {
+ img_infos_print_json(&my_img_infos, ret);
+ } else {
+ img_infos_print(&my_img_infos);
+ }
+
+ clean:
+ if (bs != NULL) {
+ bdrv_delete(bs);
+ }
+ img_infos_uninit(&my_img_infos);
+ return ret;
}
#define SNAPSHOT_LIST 1
--
1.7.1
next reply other threads:[~2012-07-27 10:22 UTC|newest]
Thread overview: 9+ messages / expand[flat|nested] mbox.gz Atom feed top
2012-07-27 10:20 Wenchao Xia [this message]
2012-07-27 10:33 ` [Qemu-devel] [PATCH] let qemu-img info genereate json output Daniel P. Berrange
2012-07-27 10:49 ` Paolo Bonzini
2012-07-27 10:52 ` Daniel P. Berrange
2012-07-27 13:52 ` Anthony Liguori
2012-07-27 13:50 ` Anthony Liguori
2012-08-15 8:49 ` Benoît Canet
2012-08-15 13:17 ` Eric Blake
2012-07-30 14:34 ` Stefan Hajnoczi
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=1343384448-21828-1-git-send-email-xiawenc@linux.vnet.ibm.com \
--to=xiawenc@linux.vnet.ibm.com \
--cc=aliguori@us.ibm.com \
--cc=pbonzini@redhat.com \
--cc=qemu-devel@nongnu.org \
--cc=stefanha@linux.vnet.ibm.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).