* [Qemu-devel] [PATCH v8 1/6] qapi: Add ImageInfoSpecific type
2013-10-09 8:46 [Qemu-devel] [PATCH v8 0/6] Provide additional info through qemu-img info Max Reitz
@ 2013-10-09 8:46 ` Max Reitz
2013-10-09 8:46 ` [Qemu-devel] [PATCH v8 2/6] block: Add bdrv_get_specific_info Max Reitz
` (5 subsequent siblings)
6 siblings, 0 replies; 8+ messages in thread
From: Max Reitz @ 2013-10-09 8:46 UTC (permalink / raw)
To: qemu-devel; +Cc: Kevin Wolf, Fam Zheng, Stefan Hajnoczi, Max Reitz
Add a new type ImageInfoSpecific as a union for image format specific
information in ImageInfo.
Signed-off-by: Max Reitz <mreitz@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
---
qapi-schema.json | 18 +++++++++++++++++-
1 file changed, 17 insertions(+), 1 deletion(-)
diff --git a/qapi-schema.json b/qapi-schema.json
index 381ffbf..246789b 100644
--- a/qapi-schema.json
+++ b/qapi-schema.json
@@ -210,6 +210,18 @@
'vm-clock-sec': 'int', 'vm-clock-nsec': 'int' } }
##
+# @ImageInfoSpecific:
+#
+# A discriminated record of image format specific information structures.
+#
+# Since: 1.7
+##
+
+{ 'union': 'ImageInfoSpecific',
+ 'data': {
+ } }
+
+##
# @ImageInfo:
#
# Information about a QEMU image file
@@ -238,6 +250,9 @@
#
# @backing-image: #optional info of the backing image (since 1.6)
#
+# @format-specific: #optional structure supplying additional format-specific
+# information (since 1.7)
+#
# Since: 1.3
#
##
@@ -248,7 +263,8 @@
'*cluster-size': 'int', '*encrypted': 'bool',
'*backing-filename': 'str', '*full-backing-filename': 'str',
'*backing-filename-format': 'str', '*snapshots': ['SnapshotInfo'],
- '*backing-image': 'ImageInfo' } }
+ '*backing-image': 'ImageInfo',
+ '*format-specific': 'ImageInfoSpecific' } }
##
# @ImageCheck:
--
1.8.3.1
^ permalink raw reply related [flat|nested] 8+ messages in thread
* [Qemu-devel] [PATCH v8 2/6] block: Add bdrv_get_specific_info
2013-10-09 8:46 [Qemu-devel] [PATCH v8 0/6] Provide additional info through qemu-img info Max Reitz
2013-10-09 8:46 ` [Qemu-devel] [PATCH v8 1/6] qapi: Add ImageInfoSpecific type Max Reitz
@ 2013-10-09 8:46 ` Max Reitz
2013-10-09 8:46 ` [Qemu-devel] [PATCH v8 3/6] block/qapi: Human-readable ImageInfoSpecific dump Max Reitz
` (4 subsequent siblings)
6 siblings, 0 replies; 8+ messages in thread
From: Max Reitz @ 2013-10-09 8:46 UTC (permalink / raw)
To: qemu-devel; +Cc: Kevin Wolf, Fam Zheng, Stefan Hajnoczi, Max Reitz
Add a function for retrieving an ImageInfoSpecific object from a block
driver.
Signed-off-by: Max Reitz <mreitz@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
---
block.c | 9 +++++++++
block/qapi.c | 3 +++
include/block/block.h | 1 +
include/block/block_int.h | 1 +
4 files changed, 14 insertions(+)
diff --git a/block.c b/block.c
index d7ca37e..43acaad 100644
--- a/block.c
+++ b/block.c
@@ -3322,6 +3322,15 @@ int bdrv_get_info(BlockDriverState *bs, BlockDriverInfo *bdi)
return drv->bdrv_get_info(bs, bdi);
}
+ImageInfoSpecific *bdrv_get_specific_info(BlockDriverState *bs)
+{
+ BlockDriver *drv = bs->drv;
+ if (drv && drv->bdrv_get_specific_info) {
+ return drv->bdrv_get_specific_info(bs);
+ }
+ return NULL;
+}
+
int bdrv_save_vmstate(BlockDriverState *bs, const uint8_t *buf,
int64_t pos, int size)
{
diff --git a/block/qapi.c b/block/qapi.c
index 782051c..ab1dd24 100644
--- a/block/qapi.c
+++ b/block/qapi.c
@@ -134,6 +134,9 @@ void bdrv_query_image_info(BlockDriverState *bs,
info->dirty_flag = bdi.is_dirty;
info->has_dirty_flag = true;
}
+ info->format_specific = bdrv_get_specific_info(bs);
+ info->has_format_specific = info->format_specific != NULL;
+
backing_filename = bs->backing_file;
if (backing_filename[0] != '\0') {
info->backing_filename = g_strdup(backing_filename);
diff --git a/include/block/block.h b/include/block/block.h
index f808550..e265124 100644
--- a/include/block/block.h
+++ b/include/block/block.h
@@ -335,6 +335,7 @@ int bdrv_get_flags(BlockDriverState *bs);
int bdrv_write_compressed(BlockDriverState *bs, int64_t sector_num,
const uint8_t *buf, int nb_sectors);
int bdrv_get_info(BlockDriverState *bs, BlockDriverInfo *bdi);
+ImageInfoSpecific *bdrv_get_specific_info(BlockDriverState *bs);
void bdrv_round_to_clusters(BlockDriverState *bs,
int64_t sector_num, int nb_sectors,
int64_t *cluster_sector_num,
diff --git a/include/block/block_int.h b/include/block/block_int.h
index 211087a..17b26b2 100644
--- a/include/block/block_int.h
+++ b/include/block/block_int.h
@@ -168,6 +168,7 @@ struct BlockDriver {
int (*bdrv_snapshot_load_tmp)(BlockDriverState *bs,
const char *snapshot_name);
int (*bdrv_get_info)(BlockDriverState *bs, BlockDriverInfo *bdi);
+ ImageInfoSpecific *(*bdrv_get_specific_info)(BlockDriverState *bs);
int (*bdrv_save_vmstate)(BlockDriverState *bs, QEMUIOVector *qiov,
int64_t pos);
--
1.8.3.1
^ permalink raw reply related [flat|nested] 8+ messages in thread
* [Qemu-devel] [PATCH v8 3/6] block/qapi: Human-readable ImageInfoSpecific dump
2013-10-09 8:46 [Qemu-devel] [PATCH v8 0/6] Provide additional info through qemu-img info Max Reitz
2013-10-09 8:46 ` [Qemu-devel] [PATCH v8 1/6] qapi: Add ImageInfoSpecific type Max Reitz
2013-10-09 8:46 ` [Qemu-devel] [PATCH v8 2/6] block: Add bdrv_get_specific_info Max Reitz
@ 2013-10-09 8:46 ` Max Reitz
2013-10-09 8:46 ` [Qemu-devel] [PATCH v8 4/6] qcow2: Add support for ImageInfoSpecific Max Reitz
` (3 subsequent siblings)
6 siblings, 0 replies; 8+ messages in thread
From: Max Reitz @ 2013-10-09 8:46 UTC (permalink / raw)
To: qemu-devel; +Cc: Kevin Wolf, Fam Zheng, Stefan Hajnoczi, Max Reitz
Add a function for generically dumping the ImageInfoSpecific information
in a human-readable format to block/qapi.c.
Use this function in bdrv_image_info_dump and qemu-io-cmds.c:info_f to
allow qemu-img info resp. qemu-io -c info to print that format specific
information.
Signed-off-by: Max Reitz <mreitz@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
---
block/qapi.c | 121 +++++++++++++++++++++++++++++++++++++++++++++++++++
include/block/qapi.h | 2 +
qemu-io-cmds.c | 9 ++++
3 files changed, 132 insertions(+)
diff --git a/block/qapi.c b/block/qapi.c
index ab1dd24..5880b3e 100644
--- a/block/qapi.c
+++ b/block/qapi.c
@@ -25,6 +25,9 @@
#include "block/qapi.h"
#include "block/block_int.h"
#include "qmp-commands.h"
+#include "qapi-visit.h"
+#include "qapi/qmp-output-visitor.h"
+#include "qapi/qmp/types.h"
/*
* Returns 0 on success, with *p_list either set to describe snapshot
@@ -426,6 +429,119 @@ void bdrv_snapshot_dump(fprintf_function func_fprintf, void *f,
}
}
+static void dump_qdict(fprintf_function func_fprintf, void *f, int indentation,
+ QDict *dict);
+static void dump_qlist(fprintf_function func_fprintf, void *f, int indentation,
+ QList *list);
+
+static void dump_qobject(fprintf_function func_fprintf, void *f,
+ int comp_indent, QObject *obj)
+{
+ switch (qobject_type(obj)) {
+ case QTYPE_QINT: {
+ QInt *value = qobject_to_qint(obj);
+ func_fprintf(f, "%" PRId64, qint_get_int(value));
+ break;
+ }
+ case QTYPE_QSTRING: {
+ QString *value = qobject_to_qstring(obj);
+ func_fprintf(f, "%s", qstring_get_str(value));
+ break;
+ }
+ case QTYPE_QDICT: {
+ QDict *value = qobject_to_qdict(obj);
+ dump_qdict(func_fprintf, f, comp_indent, value);
+ break;
+ }
+ case QTYPE_QLIST: {
+ QList *value = qobject_to_qlist(obj);
+ dump_qlist(func_fprintf, f, comp_indent, value);
+ break;
+ }
+ case QTYPE_QFLOAT: {
+ QFloat *value = qobject_to_qfloat(obj);
+ func_fprintf(f, "%g", qfloat_get_double(value));
+ break;
+ }
+ case QTYPE_QBOOL: {
+ QBool *value = qobject_to_qbool(obj);
+ func_fprintf(f, "%s", qbool_get_int(value) ? "true" : "false");
+ break;
+ }
+ case QTYPE_QERROR: {
+ QString *value = qerror_human((QError *)obj);
+ func_fprintf(f, "%s", qstring_get_str(value));
+ break;
+ }
+ case QTYPE_NONE:
+ break;
+ case QTYPE_MAX:
+ default:
+ abort();
+ }
+}
+
+static void dump_qlist(fprintf_function func_fprintf, void *f, int indentation,
+ QList *list)
+{
+ const QListEntry *entry;
+ int i = 0;
+
+ for (entry = qlist_first(list); entry; entry = qlist_next(entry), i++) {
+ qtype_code type = qobject_type(entry->value);
+ bool composite = (type == QTYPE_QDICT || type == QTYPE_QLIST);
+ const char *format = composite ? "%*s[%i]:\n" : "%*s[%i]: ";
+
+ func_fprintf(f, format, indentation * 4, "", i);
+ dump_qobject(func_fprintf, f, indentation + 1, entry->value);
+ if (!composite) {
+ func_fprintf(f, "\n");
+ }
+ }
+}
+
+static void dump_qdict(fprintf_function func_fprintf, void *f, int indentation,
+ QDict *dict)
+{
+ const QDictEntry *entry;
+
+ for (entry = qdict_first(dict); entry; entry = qdict_next(dict, entry)) {
+ qtype_code type = qobject_type(entry->value);
+ bool composite = (type == QTYPE_QDICT || type == QTYPE_QLIST);
+ const char *format = composite ? "%*s%s:\n" : "%*s%s: ";
+ char key[strlen(entry->key) + 1];
+ int i;
+
+ /* replace dashes with spaces in key (variable) names */
+ for (i = 0; entry->key[i]; i++) {
+ key[i] = entry->key[i] == '-' ? ' ' : entry->key[i];
+ }
+ key[i] = 0;
+
+ func_fprintf(f, format, indentation * 4, "", key);
+ dump_qobject(func_fprintf, f, indentation + 1, entry->value);
+ if (!composite) {
+ func_fprintf(f, "\n");
+ }
+ }
+}
+
+void bdrv_image_info_specific_dump(fprintf_function func_fprintf, void *f,
+ ImageInfoSpecific *info_spec)
+{
+ Error *local_err = NULL;
+ QmpOutputVisitor *ov = qmp_output_visitor_new();
+ QObject *obj, *data;
+
+ visit_type_ImageInfoSpecific(qmp_output_get_visitor(ov), &info_spec, NULL,
+ &local_err);
+ obj = qmp_output_get_qobject(ov);
+ assert(qobject_type(obj) == QTYPE_QDICT);
+ data = qdict_get(qobject_to_qdict(obj), "data");
+ dump_qobject(func_fprintf, f, 1, data);
+ qmp_output_visitor_cleanup(ov);
+}
+
void bdrv_image_info_dump(fprintf_function func_fprintf, void *f,
ImageInfo *info)
{
@@ -496,4 +612,9 @@ void bdrv_image_info_dump(fprintf_function func_fprintf, void *f,
func_fprintf(f, "\n");
}
}
+
+ if (info->has_format_specific) {
+ func_fprintf(f, "Format specific information:\n");
+ bdrv_image_info_specific_dump(func_fprintf, f, info->format_specific);
+ }
}
diff --git a/include/block/qapi.h b/include/block/qapi.h
index 0496cc9..9518ee4 100644
--- a/include/block/qapi.h
+++ b/include/block/qapi.h
@@ -42,6 +42,8 @@ BlockStats *bdrv_query_stats(const BlockDriverState *bs);
void bdrv_snapshot_dump(fprintf_function func_fprintf, void *f,
QEMUSnapshotInfo *sn);
+void bdrv_image_info_specific_dump(fprintf_function func_fprintf, void *f,
+ ImageInfoSpecific *info_spec);
void bdrv_image_info_dump(fprintf_function func_fprintf, void *f,
ImageInfo *info);
#endif
diff --git a/qemu-io-cmds.c b/qemu-io-cmds.c
index 8565d49..667f4e4 100644
--- a/qemu-io-cmds.c
+++ b/qemu-io-cmds.c
@@ -10,6 +10,7 @@
#include "qemu-io.h"
#include "block/block_int.h"
+#include "block/qapi.h"
#include "qemu/main-loop.h"
#define CMD_NOFILE_OK 0x01
@@ -1678,6 +1679,7 @@ static const cmdinfo_t length_cmd = {
static int info_f(BlockDriverState *bs, int argc, char **argv)
{
BlockDriverInfo bdi;
+ ImageInfoSpecific *spec_info;
char s1[64], s2[64];
int ret;
@@ -1699,6 +1701,13 @@ static int info_f(BlockDriverState *bs, int argc, char **argv)
printf("cluster size: %s\n", s1);
printf("vm state offset: %s\n", s2);
+ spec_info = bdrv_get_specific_info(bs);
+ if (spec_info) {
+ printf("Format specific information:\n");
+ bdrv_image_info_specific_dump(fprintf, stdout, spec_info);
+ qapi_free_ImageInfoSpecific(spec_info);
+ }
+
return 0;
}
--
1.8.3.1
^ permalink raw reply related [flat|nested] 8+ messages in thread
* [Qemu-devel] [PATCH v8 4/6] qcow2: Add support for ImageInfoSpecific
2013-10-09 8:46 [Qemu-devel] [PATCH v8 0/6] Provide additional info through qemu-img info Max Reitz
` (2 preceding siblings ...)
2013-10-09 8:46 ` [Qemu-devel] [PATCH v8 3/6] block/qapi: Human-readable ImageInfoSpecific dump Max Reitz
@ 2013-10-09 8:46 ` Max Reitz
2013-10-09 8:46 ` [Qemu-devel] [PATCH v8 5/6] qemu-iotests: Discard specific info in _img_info Max Reitz
` (2 subsequent siblings)
6 siblings, 0 replies; 8+ messages in thread
From: Max Reitz @ 2013-10-09 8:46 UTC (permalink / raw)
To: qemu-devel; +Cc: Kevin Wolf, Fam Zheng, Stefan Hajnoczi, Max Reitz
Add a new ImageInfoSpecificQCow2 type as a subtype of ImageInfoSpecific.
This contains the compatibility level as a string and an optional
lazy_refcounts boolean (optional means mandatory for compat >= 1.1 and
not available for compat == 0.10).
Also, add qcow2_get_specific_info, which returns this information.
Signed-off-by: Max Reitz <mreitz@redhat.com>
---
block/qcow2.c | 26 ++++++++++++++++++++++++++
qapi-schema.json | 16 ++++++++++++++++
2 files changed, 42 insertions(+)
diff --git a/block/qcow2.c b/block/qcow2.c
index 4a9888c..d59ecbd 100644
--- a/block/qcow2.c
+++ b/block/qcow2.c
@@ -1810,6 +1810,31 @@ static int qcow2_get_info(BlockDriverState *bs, BlockDriverInfo *bdi)
return 0;
}
+static ImageInfoSpecific *qcow2_get_specific_info(BlockDriverState *bs)
+{
+ BDRVQcowState *s = bs->opaque;
+ ImageInfoSpecific *spec_info = g_new(ImageInfoSpecific, 1);
+
+ *spec_info = (ImageInfoSpecific){
+ .kind = IMAGE_INFO_SPECIFIC_KIND_QCOW2,
+ .qcow2 = g_new(ImageInfoSpecificQCow2, 1),
+ };
+ if (s->qcow_version == 2) {
+ *spec_info->qcow2 = (ImageInfoSpecificQCow2){
+ .compat = g_strdup("0.10"),
+ };
+ } else if (s->qcow_version == 3) {
+ *spec_info->qcow2 = (ImageInfoSpecificQCow2){
+ .compat = g_strdup("1.1"),
+ .lazy_refcounts = s->compatible_features &
+ QCOW2_COMPAT_LAZY_REFCOUNTS,
+ .has_lazy_refcounts = true,
+ };
+ }
+
+ return spec_info;
+}
+
#if 0
static void dump_refcounts(BlockDriverState *bs)
{
@@ -2130,6 +2155,7 @@ static BlockDriver bdrv_qcow2 = {
.bdrv_snapshot_list = qcow2_snapshot_list,
.bdrv_snapshot_load_tmp = qcow2_snapshot_load_tmp,
.bdrv_get_info = qcow2_get_info,
+ .bdrv_get_specific_info = qcow2_get_specific_info,
.bdrv_save_vmstate = qcow2_save_vmstate,
.bdrv_load_vmstate = qcow2_load_vmstate,
diff --git a/qapi-schema.json b/qapi-schema.json
index 246789b..a1a81a4 100644
--- a/qapi-schema.json
+++ b/qapi-schema.json
@@ -210,6 +210,21 @@
'vm-clock-sec': 'int', 'vm-clock-nsec': 'int' } }
##
+# @ImageInfoSpecificQCow2:
+#
+# @compat: compatibility level
+#
+# @lazy-refcounts: #optional on or off; only valid for compat >= 1.1
+#
+# Since: 1.7
+##
+{ 'type': 'ImageInfoSpecificQCow2',
+ 'data': {
+ 'compat': 'str',
+ '*lazy-refcounts': 'bool'
+ } }
+
+##
# @ImageInfoSpecific:
#
# A discriminated record of image format specific information structures.
@@ -219,6 +234,7 @@
{ 'union': 'ImageInfoSpecific',
'data': {
+ 'qcow2': 'ImageInfoSpecificQCow2'
} }
##
--
1.8.3.1
^ permalink raw reply related [flat|nested] 8+ messages in thread
* [Qemu-devel] [PATCH v8 5/6] qemu-iotests: Discard specific info in _img_info
2013-10-09 8:46 [Qemu-devel] [PATCH v8 0/6] Provide additional info through qemu-img info Max Reitz
` (3 preceding siblings ...)
2013-10-09 8:46 ` [Qemu-devel] [PATCH v8 4/6] qcow2: Add support for ImageInfoSpecific Max Reitz
@ 2013-10-09 8:46 ` Max Reitz
2013-10-09 8:46 ` [Qemu-devel] [PATCH v8 6/6] qemu-iotests: Additional info from qemu-img info Max Reitz
2013-10-09 9:25 ` [Qemu-devel] [PATCH v8 0/6] Provide additional info through " Kevin Wolf
6 siblings, 0 replies; 8+ messages in thread
From: Max Reitz @ 2013-10-09 8:46 UTC (permalink / raw)
To: qemu-devel; +Cc: Kevin Wolf, Fam Zheng, Stefan Hajnoczi, Max Reitz
In _img_info, filter out additional information specific to the image
format provided by qemu-img info, since tests designed for multiple
image formats would produce different outputs for every image format
otherwise.
In a human-readable dump, that new information will always be last for
each "image information block" (multiple blocks are emitted when
inspecting the backing file chain). Every block is separated by an empty
line. Therefore, in this case, everything starting with the line "Format
specific information:" up to that empty line (or EOF, if it is the last
block) has to be stripped.
The JSON dump will always emit pretty JSON data. Therefore, the opening
and closing braces of every object will be on lines which are indented
by exactly the same amount, and all lines in between will have more
indentation. Thus, in this case, everything starting with a line
matching the regular expression /^ *"format-specific": {/ until /^ *},?/
has to be stripped, where the number of spaces at the beginning of the
respective lines is equal.
Signed-off-by: Max Reitz <mreitz@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
---
tests/qemu-iotests/common.rc | 20 +++++++++++++++++++-
1 file changed, 19 insertions(+), 1 deletion(-)
diff --git a/tests/qemu-iotests/common.rc b/tests/qemu-iotests/common.rc
index 1b22db0..227c003 100644
--- a/tests/qemu-iotests/common.rc
+++ b/tests/qemu-iotests/common.rc
@@ -197,12 +197,30 @@ _check_test_img()
_img_info()
{
+ discard=0
+ regex_json_spec_start='^ *"format-specific": \{'
$QEMU_IMG info "$@" "$TEST_IMG" 2>&1 | \
sed -e "s#$IMGPROTO:$TEST_DIR#TEST_DIR#g" \
-e "s#$TEST_DIR#TEST_DIR#g" \
-e "s#$IMGFMT#IMGFMT#g" \
-e "/^disk size:/ D" \
- -e "/actual-size/ D"
+ -e "/actual-size/ D" | \
+ while IFS='' read line; do
+ if [[ $line == "Format specific information:" ]]; then
+ discard=1
+ elif [[ $line =~ $regex_json_spec_start ]]; then
+ discard=2
+ regex_json_spec_end="^${line%%[^ ]*}\\},? *$"
+ fi
+ if [[ $discard == 0 ]]; then
+ echo "$line"
+ elif [[ $discard == 1 && ! $line ]]; then
+ echo
+ discard=0
+ elif [[ $discard == 2 && $line =~ $regex_json_spec_end ]]; then
+ discard=0
+ fi
+ done
}
_get_pids_by_name()
--
1.8.3.1
^ permalink raw reply related [flat|nested] 8+ messages in thread
* [Qemu-devel] [PATCH v8 6/6] qemu-iotests: Additional info from qemu-img info
2013-10-09 8:46 [Qemu-devel] [PATCH v8 0/6] Provide additional info through qemu-img info Max Reitz
` (4 preceding siblings ...)
2013-10-09 8:46 ` [Qemu-devel] [PATCH v8 5/6] qemu-iotests: Discard specific info in _img_info Max Reitz
@ 2013-10-09 8:46 ` Max Reitz
2013-10-09 9:25 ` [Qemu-devel] [PATCH v8 0/6] Provide additional info through " Kevin Wolf
6 siblings, 0 replies; 8+ messages in thread
From: Max Reitz @ 2013-10-09 8:46 UTC (permalink / raw)
To: qemu-devel; +Cc: Kevin Wolf, Fam Zheng, Stefan Hajnoczi, Max Reitz
Add a test for the additional information now provided by qemu-img info
when used on qcow2 images. It also tests the qemu QMP output from the
query-block command when running qemu with different runtime options
than specified in the image (ImageInfoSpecific should always refer to
the image).
Signed-off-by: Max Reitz <mreitz@redhat.com>
---
tests/qemu-iotests/065 | 125 ++++++++++++++++++++++++++++++++++++++++++
tests/qemu-iotests/065.out | 5 ++
tests/qemu-iotests/group | 1 +
tests/qemu-iotests/iotests.py | 4 ++
4 files changed, 135 insertions(+)
create mode 100755 tests/qemu-iotests/065
create mode 100644 tests/qemu-iotests/065.out
diff --git a/tests/qemu-iotests/065 b/tests/qemu-iotests/065
new file mode 100755
index 0000000..a4db717
--- /dev/null
+++ b/tests/qemu-iotests/065
@@ -0,0 +1,125 @@
+#!/usr/bin/env python2
+#
+# Test for additional information emitted by qemu-img info on qcow2
+# images
+#
+# Copyright (C) 2013 Red Hat, Inc.
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+#
+
+import os
+import re
+import json
+import iotests
+from iotests import qemu_img, qemu_img_pipe
+import unittest
+
+test_img = os.path.join(iotests.test_dir, 'test.img')
+
+class TestImageInfoSpecific(iotests.QMPTestCase):
+ '''Abstract base class for ImageInfoSpecific tests'''
+
+ def setUp(self):
+ if self.img_options is None:
+ self.skipTest('Skipping abstract test class')
+ qemu_img('create', '-f', iotests.imgfmt, '-o', self.img_options,
+ test_img, '128K')
+
+ def tearDown(self):
+ os.remove(test_img)
+
+class TestQemuImgInfo(TestImageInfoSpecific):
+ '''Abstract base class for qemu-img info tests'''
+
+ img_options = None
+ json_compare = None
+ human_compare = None
+
+ def test_json(self):
+ data = json.loads(qemu_img_pipe('info', '--output=json', test_img))
+ data = data['format-specific']
+ self.assertEqual(data['type'], iotests.imgfmt)
+ self.assertEqual(data['data'], self.json_compare)
+
+ def test_human(self):
+ data = qemu_img_pipe('info', '--output=human', test_img).split('\n')
+ data = data[(data.index('Format specific information:') + 1)
+ :data.index('')]
+ for field in data:
+ self.assertTrue(re.match('^ {4}[^ ]', field) is not None)
+ data = map(lambda line: line.strip(), data)
+ self.assertEqual(data, self.human_compare)
+
+class TestQMP(TestImageInfoSpecific):
+ '''Abstract base class for qemu QMP tests'''
+
+ img_options = None
+ qemu_options = ''
+
+ def setUp(self):
+ TestImageInfoSpecific.setUp(self)
+ self.vm = iotests.VM().add_drive(test_img, self.qemu_options)
+ self.vm.launch()
+
+ def tearDown(self):
+ self.vm.shutdown()
+ TestImageInfoSpecific.tearDown(self)
+
+ def test_qmp(self):
+ result = self.vm.qmp('query-block')['return']
+ drive = filter(lambda drive: drive['device'] == 'drive0', result)[0]
+ data = drive['inserted']['image']['format-specific']
+ self.assertEqual(data['type'], iotests.imgfmt)
+ self.assertEqual(data['data'], self.compare)
+
+@unittest.skipIf(iotests.imgfmt != 'qcow2', 'This test is qcow2-specific')
+class TestQCow2(TestQemuImgInfo):
+ '''Testing a qcow2 version 2 image'''
+ img_options = 'compat=0.10'
+ json_compare = { 'compat': '0.10' }
+ human_compare = [ 'compat: 0.10' ]
+
+@unittest.skipIf(iotests.imgfmt != 'qcow2', 'This test is qcow2-specific')
+class TestQCow3NotLazy(TestQemuImgInfo):
+ '''Testing a qcow2 version 3 image with lazy refcounts disabled'''
+ img_options = 'compat=1.1,lazy_refcounts=off'
+ json_compare = { 'compat': '1.1', 'lazy-refcounts': False }
+ human_compare = [ 'compat: 1.1', 'lazy refcounts: false' ]
+
+@unittest.skipIf(iotests.imgfmt != 'qcow2', 'This test is qcow2-specific')
+class TestQCow3Lazy(TestQemuImgInfo):
+ '''Testing a qcow2 version 3 image with lazy refcounts enabled'''
+ img_options = 'compat=1.1,lazy_refcounts=on'
+ json_compare = { 'compat': '1.1', 'lazy-refcounts': True }
+ human_compare = [ 'compat: 1.1', 'lazy refcounts: true' ]
+
+@unittest.skipIf(iotests.imgfmt != 'qcow2', 'This test is qcow2-specific')
+class TestQCow3NotLazyQMP(TestQMP):
+ '''Testing a qcow2 version 3 image with lazy refcounts disabled, opening
+ with lazy refcounts enabled'''
+ img_options = 'compat=1.1,lazy_refcounts=off'
+ qemu_options = 'lazy-refcounts=on'
+ compare = { 'compat': '1.1', 'lazy-refcounts': False }
+
+@unittest.skipIf(iotests.imgfmt != 'qcow2', 'This test is qcow2-specific')
+class TestQCow3LazyQMP(TestQMP):
+ '''Testing a qcow2 version 3 image with lazy refcounts enabled, opening
+ with lazy refcounts disabled'''
+ img_options = 'compat=1.1,lazy_refcounts=on'
+ qemu_options = 'lazy-refcounts=off'
+ compare = { 'compat': '1.1', 'lazy-refcounts': True }
+
+if __name__ == '__main__':
+ iotests.main(supported_fmts=['qcow2'])
diff --git a/tests/qemu-iotests/065.out b/tests/qemu-iotests/065.out
new file mode 100644
index 0000000..1351234
--- /dev/null
+++ b/tests/qemu-iotests/065.out
@@ -0,0 +1,5 @@
+........sss
+----------------------------------------------------------------------
+Ran 11 tests
+
+OK (skipped=3)
diff --git a/tests/qemu-iotests/group b/tests/qemu-iotests/group
index 1ad02e5..f1a68b0 100644
--- a/tests/qemu-iotests/group
+++ b/tests/qemu-iotests/group
@@ -69,3 +69,4 @@
061 rw auto
062 rw auto
063 rw auto
+065 rw auto
diff --git a/tests/qemu-iotests/iotests.py b/tests/qemu-iotests/iotests.py
index 376d6e8..fb10ff4 100644
--- a/tests/qemu-iotests/iotests.py
+++ b/tests/qemu-iotests/iotests.py
@@ -49,6 +49,10 @@ def qemu_img_verbose(*args):
'''Run qemu-img without suppressing its output and return the exit code'''
return subprocess.call(qemu_img_args + list(args))
+def qemu_img_pipe(*args):
+ '''Run qemu-img and return its output'''
+ return subprocess.Popen(qemu_img_args + list(args), stdout=subprocess.PIPE).communicate()[0]
+
def qemu_io(*args):
'''Run qemu-io and return the stdout data'''
args = qemu_io_args + list(args)
--
1.8.3.1
^ permalink raw reply related [flat|nested] 8+ messages in thread
* Re: [Qemu-devel] [PATCH v8 0/6] Provide additional info through qemu-img info
2013-10-09 8:46 [Qemu-devel] [PATCH v8 0/6] Provide additional info through qemu-img info Max Reitz
` (5 preceding siblings ...)
2013-10-09 8:46 ` [Qemu-devel] [PATCH v8 6/6] qemu-iotests: Additional info from qemu-img info Max Reitz
@ 2013-10-09 9:25 ` Kevin Wolf
6 siblings, 0 replies; 8+ messages in thread
From: Kevin Wolf @ 2013-10-09 9:25 UTC (permalink / raw)
To: Max Reitz; +Cc: Fam Zheng, qemu-devel, Stefan Hajnoczi
Am 09.10.2013 um 10:46 hat Max Reitz geschrieben:
> qemu-img info provides only pretty general information about an image.
> For any image format, there might be specific options which cannot be
> represented in a universal way; for instance, qcow2 provides the
> compatibility and lazy_refcount options whose values are certainly
> interesting but currently cannot be output by qemu-img info.
>
> Therefore, this series adds a new ImageInfoSpecific union type to
> ImageInfo which may be used by block drivers as a template for new types
> dedicated to the specific information they can provide, as well as a
> function bdrv_get_specific_info for retrieving this information. It also
> adds support to qemu-img info and qemu-io -c info to print the content
> of these specific structures.
Thanks, applied to the block branch.
Kevin
^ permalink raw reply [flat|nested] 8+ messages in thread