qcow2_format.py: support dumping metadata in JSON format

Implementation of dumping QCOW2 image metadata.
The sample output:
{
    "Header_extensions": [
        {
            "name": "Feature table",
            "magic": 1745090647,
            "length": 192,
            "data_str": "<binary>"
        },
        {
            "name": "Bitmaps",
            "magic": 595929205,
            "length": 24,
            "data": {
                "nb_bitmaps": 2,
                "reserved32": 0,
                "bitmap_directory_size": 64,
                "bitmap_directory_offset": 1048576,
                "bitmap_directory": [
                    {
                        "name": "bitmap-1",
                        "bitmap_table_offset": 589824,
                        "bitmap_table_size": 1,
                        "flags": 2,
                        "type": 1,
                        "granularity_bits": 15,
                        "name_size": 8,
                        "extra_data_size": 0,
                        "bitmap_table": [
                            {
                                "type": "serialized",
                                "offset": 655360
                            },
                            ...

Suggested-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
Signed-off-by: Andrey Shinkevich <andrey.shinkevich@virtuozzo.com>
Reviewed-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
Message-Id: <1596742557-320265-11-git-send-email-andrey.shinkevich@virtuozzo.com>
Signed-off-by: Eric Blake <eblake@redhat.com>
This commit is contained in:
Andrey Shinkevich 2020-08-06 22:35:56 +03:00 committed by Eric Blake
parent b4e927799c
commit 4edcca5741

View file

@ -19,6 +19,15 @@
import struct
import string
import json
class ComplexEncoder(json.JSONEncoder):
def default(self, obj):
if hasattr(obj, 'to_json'):
return obj.to_json()
else:
return json.JSONEncoder.default(self, obj)
class Qcow2Field:
@ -110,6 +119,10 @@ class Qcow2Struct(metaclass=Qcow2StructMeta):
for i, field in enumerate(self.fields))
def dump(self, is_json=False):
if is_json:
print(json.dumps(self.to_json(), indent=4, cls=ComplexEncoder))
return
for f in self.fields:
value = self.__dict__[f[2]]
if isinstance(f[1], str):
@ -445,6 +458,10 @@ class QcowHeader(Qcow2Struct):
fd.write(buf)
def dump_extensions(self, is_json=False):
if is_json:
print(json.dumps(self.extensions, indent=4, cls=ComplexEncoder))
return
for ex in self.extensions:
print('Header extension:')
ex.dump()