diff --git a/oslo_utils/imageutils.py b/oslo_utils/imageutils.py index 245a384b..a9bb3bbd 100644 --- a/oslo_utils/imageutils.py +++ b/oslo_utils/imageutils.py @@ -19,8 +19,13 @@ Helper methods to deal with images. .. versionadded:: 3.1 + +.. versionchanged:: 3.14.0 + add paramter format. + """ +import json import re from oslo_utils._i18n import _ @@ -33,6 +38,8 @@ class QemuImgInfo(object): The instance of :class:`QemuImgInfo` has properties: `image`, `backing_file`, `file_format`, `virtual_size`, `cluster_size`, `disk_size`, `snapshots` and `encrypted`. + The parameter format can be set to 'json' or 'human'. With 'json' format + output, qemu image information will be parsed more easily and readable. """ BACKING_FILE_RE = re.compile((r"^(.*?)\s*\(actual\s+path\s*:" r"\s+(.*?)\)\s*$"), re.I) @@ -40,16 +47,27 @@ class QemuImgInfo(object): SIZE_RE = re.compile(r"(\d*\.?\d+)(\w+)?(\s*\(\s*(\d+)\s+bytes\s*\))?", re.I) - def __init__(self, cmd_output=None): - details = self._parse(cmd_output or '') - self.image = details.get('image') - self.backing_file = details.get('backing_file') - self.file_format = details.get('file_format') - self.virtual_size = details.get('virtual_size') - self.cluster_size = details.get('cluster_size') - self.disk_size = details.get('disk_size') - self.snapshots = details.get('snapshot_list', []) - self.encrypted = details.get('encrypted') + def __init__(self, cmd_output=None, format='human'): + if format == 'json': + details = json.loads(cmd_output or '{}') + self.image = details.get('filename') + self.backing_file = details.get('backing-filename') + self.file_format = details.get('format') + self.virtual_size = details.get('virtual-size') + self.cluster_size = details.get('cluster-size') + self.disk_size = details.get('actual-size') + self.snapshots = details.get('snapshots', []) + self.encrypted = details.get('encrypted') + else: + details = self._parse(cmd_output or '') + self.image = details.get('image') + self.backing_file = details.get('backing_file') + self.file_format = details.get('file_format') + self.virtual_size = details.get('virtual_size') + self.cluster_size = details.get('cluster_size') + self.disk_size = details.get('disk_size') + self.snapshots = details.get('snapshot_list', []) + self.encrypted = details.get('encrypted') def __str__(self): lines = [ diff --git a/oslo_utils/tests/test_imageutils.py b/oslo_utils/tests/test_imageutils.py index 5c328fe4..532c455d 100644 --- a/oslo_utils/tests/test_imageutils.py +++ b/oslo_utils/tests/test_imageutils.py @@ -199,3 +199,29 @@ class ImageUtilsBlankTestCase(test_base.BaseTestCase): image_info = imageutils.QemuImgInfo() self.assertEqual(str(image_info), example_output) self.assertEqual(len(image_info.snapshots), 0) + + +class ImageUtilsJSONTestCase(test_base.BaseTestCase): + def test_qemu_img_info_json_format(self): + img_output = '''{ + "virtual-size": 41126400, + "filename": "fake_img", + "cluster-size": 65536, + "format": "qcow2", + "actual-size": 13168640 + }''' + image_info = imageutils.QemuImgInfo(img_output, format='json') + self.assertEqual(41126400, image_info.virtual_size) + self.assertEqual('fake_img', image_info.image) + self.assertEqual(65536, image_info.cluster_size) + self.assertEqual('qcow2', image_info.file_format) + self.assertEqual(13168640, image_info.disk_size) + + def test_qemu_img_info_json_format_blank(self): + img_output = '{}' + image_info = imageutils.QemuImgInfo(img_output, format='json') + self.assertIsNone(image_info.virtual_size) + self.assertIsNone(image_info.image) + self.assertIsNone(image_info.cluster_size) + self.assertIsNone(image_info.file_format) + self.assertIsNone(image_info.disk_size)