Support json format output from qemu command

QemuImgInfo is realized by parsing the output string of 'qemu-img info
**.img' line by line, it's complicated and improvment can be done. The
command 'qemu-img info **.img --output json' will produce json style
output and arguments can be parsed easily by calling json.loads. This
patch add support json format output parsing, to simplify the code and
make it more clear and readable.

Change-Id: Iefa139dc4bcea864cb86371d8a24df0e4695169c
Closes-Bug:#1590252
This commit is contained in:
Bin Zhou 2016-06-08 17:54:32 +08:00
parent dfdaaa2e31
commit bf80b23e77
2 changed files with 54 additions and 10 deletions

View File

@ -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 = [

View File

@ -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)