Use the json format output of qemu-img info

Support for the human format by oslo_utils.imageutils.QemuImgInfo was
deprecated since oslo.utils 4.9.1 [1]. This change replaces the human
format with the json format which will be used by default.

[1] 73eb0673f627aad382e08a816191b637af436465

Backport note: The json format is preferable because it allows access
to format specific details (since oslo.utils 4.1.0).  These details
are not present when the default 'human' format is used.  See change
I133da07a5a9628b8a9 for details.

Closes-Bug: #1940540
Change-Id: Ia0353204abf849467106ee08982d1271de23101a
(cherry picked from commit c0d2e7ebd8)
(cherry picked from commit 11b0f97a01)
(cherry picked from commit 4cef5c0c42)
(cherry picked from commit 9810c05e74)
(cherry picked from commit 60a5de1f6d)
This commit is contained in:
Takashi Kajinami 2021-07-06 21:48:44 +09:00 committed by Brian Rosmaita
parent d061455d4f
commit 6a1260ea80
5 changed files with 193 additions and 167 deletions

View File

@ -122,7 +122,7 @@ def from_qemu_img_disk_format(disk_format):
def qemu_img_info(path, run_as_root=True, force_share=False):
"""Return an object containing the parsed output from qemu-img info."""
cmd = ['env', 'LC_ALL=C', 'qemu-img', 'info']
cmd = ['env', 'LC_ALL=C', 'qemu-img', 'info', '--output=json']
if force_share:
if qemu_img_supports_force_share():
cmd.append('--force-share')
@ -136,7 +136,7 @@ def qemu_img_info(path, run_as_root=True, force_share=False):
cmd = cmd[2:]
out, _err = utils.execute(*cmd, run_as_root=run_as_root,
prlimit=QEMU_IMG_LIMITS)
info = imageutils.QemuImgInfo(out)
info = imageutils.QemuImgInfo(out, format='json')
# From Cinder's point of view, any 'luks' formatted images
# should be treated as 'raw'.

View File

@ -41,7 +41,8 @@ class TestQemuImgInfo(test.TestCase):
output = image_utils.qemu_img_info(test_path)
mock_exec.assert_called_once_with('env', 'LC_ALL=C', 'qemu-img',
'info', test_path, run_as_root=True,
'info', '--output=json', test_path,
run_as_root=True,
prlimit=image_utils.QEMU_IMG_LIMITS)
self.assertEqual(mock_info.return_value, output)
@ -58,7 +59,8 @@ class TestQemuImgInfo(test.TestCase):
force_share=False,
run_as_root=False)
mock_exec.assert_called_once_with('env', 'LC_ALL=C', 'qemu-img',
'info', test_path, run_as_root=False,
'info', '--output=json', test_path,
run_as_root=False,
prlimit=image_utils.QEMU_IMG_LIMITS)
self.assertEqual(mock_info.return_value, output)
@ -73,8 +75,8 @@ class TestQemuImgInfo(test.TestCase):
mock_os.name = 'nt'
output = image_utils.qemu_img_info(test_path)
mock_exec.assert_called_once_with('qemu-img', 'info', test_path,
run_as_root=True,
mock_exec.assert_called_once_with('qemu-img', 'info', '--output=json',
test_path, run_as_root=True,
prlimit=image_utils.QEMU_IMG_LIMITS)
self.assertEqual(mock_info.return_value, output)

View File

@ -335,102 +335,112 @@ NFS_CONFIG4 = {'max_over_subscription_ratio': 20.0,
'nas_secure_file_permissions': 'false',
'nas_secure_file_operations': 'true'}
QEMU_IMG_INFO_OUT1 = """image: %(volid)s
file format: raw
virtual size: %(size_gb)sG (%(size_b)s bytes)
disk size: 173K
"""
QEMU_IMG_INFO_OUT1 = """{
"filename": "%(volid)s",
"format": "raw",
"virtual-size": %(size_b)s,
"actual-size": 173000
}"""
QEMU_IMG_INFO_OUT2 = """image: %(volid)s
file format: qcow2
virtual size: %(size_gb)sG (%(size_b)s bytes)
disk size: 196K
cluster_size: 65536
Format specific information:
compat: 1.1
lazy refcounts: false
refcount bits: 16
corrupt: false
"""
QEMU_IMG_INFO_OUT2 = """{
"filename": "%(volid)s",
"format": "qcow2",
"virtual-size": %(size_b)s,
"actual-size": 196000,
"cluster-size": 65536,
"format-specific": {
"compat": "1.1",
"lazy-refcounts": false,
"refcount-bits": 16,
"corrupt": false
}
}"""
QEMU_IMG_INFO_OUT3 = """image: volume-%(volid)s.%(snapid)s
file format: qcow2
virtual size: %(size_gb)sG (%(size_b)s bytes)
disk size: 196K
cluster_size: 65536
backing file: volume-%(volid)s
backing file format: qcow2
Format specific information:
compat: 1.1
lazy refcounts: false
refcount bits: 16
corrupt: false
"""
QEMU_IMG_INFO_OUT3 = """{
"filename": "volume-%(volid)s.%(snapid)s",
"format": "qcow2",
"virtual-size": %(size_b)s,
"actual-size": 196000,
"cluster-size": 65536,
"backing-filename": "volume-%(volid)s",
"backing-filename-format": "qcow2",
"format-specific": {
"compat": "1.1",
"lazy-refcounts": false,
"refcount-bits": 16,
"corrupt": false
}
}"""
QEMU_IMG_INFO_OUT4 = """image: volume-%(volid)s.%(snapid)s
file format: raw
virtual size: %(size_gb)sG (%(size_b)s bytes)
disk size: 196K
cluster_size: 65536
backing file: volume-%(volid)s
backing file format: raw
Format specific information:
compat: 1.1
lazy refcounts: false
refcount bits: 16
corrupt: false
"""
QEMU_IMG_INFO_OUT4 = """{
"filename": "volume-%(volid)s.%(snapid)s",
"format": "raw",
"virtual-size": %(size_b)s,
"actual-size": 196000,
"cluster-size": 65536,
"backing-filename": "volume-%(volid)s",
"backing-filename-format": "raw"
}"""
QEMU_IMG_INFO_OUT5 = """image: volume-%(volid)s.%(snapid)s
file format: qcow2
virtual size: %(size_gb)sG (%(size_b)s bytes)
disk size: 196K
encrypted: yes
cluster_size: 65536
backing file: volume-%(volid)s
backing file format: raw
Format specific information:
compat: 1.1
lazy refcounts: false
refcount bits: 16
encrypt:
ivgen alg: plain64
hash alg: sha256
cipher alg: aes-256
uuid: 386f8626-33f0-4683-a517-78ddfe385e33
format: luks
cipher mode: xts
slots:
[0]:
active: true
iters: 1892498
key offset: 4096
stripes: 4000
[1]:
active: false
key offset: 262144
[2]:
active: false
key offset: 520192
[3]:
active: false
key offset: 778240
[4]:
active: false
key offset: 1036288
[5]:
active: false
key offset: 1294336
[6]:
active: false
key offset: 1552384
[7]:
active: false
key offset: 1810432
payload offset: 2068480
master key iters: 459347
corrupt: false
"""
QEMU_IMG_INFO_OUT5 = """{
"filename": "volume-%(volid)s.%(snapid)s",
"format": "qcow2",
"virtual-size": %(size_b)s,
"actual-size": 196000,
"encrypted": true,
"cluster-size": 65536,
"backing-filename": "volume-%(volid)s",
"backing-filename-format": "raw",
"format-specific": {
"type": "luks",
"data": {
"ivgen-alg": "plain64",
"hash-alg": "sha256",
"cipher-alg": "aes-256",
"uuid": "386f8626-33f0-4683-a517-78ddfe385e33",
"cipher-mode": "xts",
"slots": [
{
"active": true,
"iters": 1892498,
"key offset": 4096,
"stripes": 4000
},
{
"active": false,
"key offset": 262144
},
{
"active": false,
"key offset": 520192
},
{
"active": false,
"key offset": 778240
},
{
"active": false,
"key offset": 1036288
},
{
"active": false,
"key offset": 1294336
},
{
"active": false,
"key offset": 1552384
},
{
"active": false,
"key offset": 1810432
}
],
"payload-offset": 2068480,
"master-key-iters": 459347
},
"corrupt": false
}
}"""
@ddt.ddt
@ -1312,7 +1322,7 @@ class NfsDriverTestCase(test.TestCase):
'size_gb': src_volume.size,
'size_b': src_volume.size * units.Gi}
img_info = imageutils.QemuImgInfo(img_out)
img_info = imageutils.QemuImgInfo(img_out, format='json')
mock_img_info = self.mock_object(image_utils, 'qemu_img_info')
mock_img_info.return_value = img_info
mock_convert_image = self.mock_object(image_utils, 'convert_image')
@ -1392,7 +1402,7 @@ class NfsDriverTestCase(test.TestCase):
'snapid': fake_snap.id,
'size_gb': src_volume.size,
'size_b': src_volume.size * units.Gi}
img_info = imageutils.QemuImgInfo(img_out)
img_info = imageutils.QemuImgInfo(img_out, format='json')
mock_img_info = self.mock_object(image_utils, 'qemu_img_info')
mock_img_info.return_value = img_info
@ -1458,7 +1468,8 @@ class NfsDriverTestCase(test.TestCase):
mock_img_utils = self.mock_object(image_utils, 'qemu_img_info')
img_out = qemu_img_info % {'volid': volume.id, 'size_gb': volume.size,
'size_b': volume.size * units.Gi}
mock_img_utils.return_value = imageutils.QemuImgInfo(img_out)
mock_img_utils.return_value = imageutils.QemuImgInfo(img_out,
format='json')
self.mock_object(drv, '_read_info_file',
return_value={'active': "volume-%s" % volume.id})
@ -1478,12 +1489,14 @@ class NfsDriverTestCase(test.TestCase):
drv = self._driver
volume = self._simple_volume()
qemu_img_output = """image: %s
file format: iso
virtual size: 1.0G (1073741824 bytes)
disk size: 173K
""" % volume['name']
mock_img_info.return_value = imageutils.QemuImgInfo(qemu_img_output)
qemu_img_output = """{
"filename": "%s",
"format": "iso",
"virtual-size": 1073741824,
"actual-size": 173000
}""" % volume['name']
mock_img_info.return_value = imageutils.QemuImgInfo(qemu_img_output,
format='json')
self.assertRaises(exception.InvalidVolume,
drv.initialize_connection,

View File

@ -940,13 +940,14 @@ class QuobyteDriverTestCase(test.TestCase):
self.TEST_QUOBYTE_VOLUME),
self.VOLUME_UUID)
qemu_img_info_output = """image: volume-%s
file format: qcow2
virtual size: 1.0G (1073741824 bytes)
disk size: 473K
""" % self.VOLUME_UUID
qemu_img_info_output = """{
"filename": "volume-%s",
"format": "qcow2",
"virtual-size": 1073741824,
"actual-size": 473000
}""" % self.VOLUME_UUID
img_info = imageutils.QemuImgInfo(qemu_img_info_output)
img_info = imageutils.QemuImgInfo(qemu_img_info_output, format='json')
image_utils.qemu_img_info = mock.Mock(return_value=img_info)
image_utils.resize_image = mock.Mock()
@ -986,13 +987,14 @@ class QuobyteDriverTestCase(test.TestCase):
size = dest_volume['size']
qemu_img_output = """image: %s
file format: raw
virtual size: 1.0G (1073741824 bytes)
disk size: 173K
backing file: %s
""" % (snap_file, src_volume['name'])
img_info = imageutils.QemuImgInfo(qemu_img_output)
qemu_img_output = """{
"filename": "%s",
"format": "raw",
"virtual-size": 1073741824,
"actual-size": 173000,
"backing-filename": "%s"
}""" % (snap_file, src_volume['name'])
img_info = imageutils.QemuImgInfo(qemu_img_output, format='json')
# mocking and testing starts here
image_utils.convert_image = mock.Mock()
@ -1042,13 +1044,14 @@ class QuobyteDriverTestCase(test.TestCase):
size = dest_volume['size']
qemu_img_output = """image: %s
file format: raw
virtual size: 1.0G (1073741824 bytes)
disk size: 173K
backing file: %s
""" % (snap_file, src_volume['name'])
img_info = imageutils.QemuImgInfo(qemu_img_output)
qemu_img_output = """{
"filename": "%s",
"format": "raw",
"virtual-size": 1073741824,
"actual-size": 173000,
"backing-filename": "%s"
}""" % (snap_file, src_volume['name'])
img_info = imageutils.QemuImgInfo(qemu_img_output, format='json')
# mocking and testing starts here
image_utils.convert_image = mock.Mock()
@ -1103,13 +1106,14 @@ class QuobyteDriverTestCase(test.TestCase):
size = dest_volume['size']
qemu_img_output = """image: %s
file format: raw
virtual size: 1.0G (1073741824 bytes)
disk size: 173K
backing file: %s
""" % (snap_file, src_volume['name'])
img_info = imageutils.QemuImgInfo(qemu_img_output)
qemu_img_output = """{
"filename": "%s",
"format": "raw",
"virtual-size": 1073741824,
"actual-size": 173000,
"backing-filename": "%s"
}""" % (snap_file, src_volume['name'])
img_info = imageutils.QemuImgInfo(qemu_img_output, format='json')
# mocking and testing starts here
image_utils.convert_image = mock.Mock()
@ -1167,13 +1171,14 @@ class QuobyteDriverTestCase(test.TestCase):
size = dest_volume['size']
qemu_img_output = """image: %s
file format: raw
virtual size: 1.0G (1073741824 bytes)
disk size: 173K
backing file: %s
""" % (snap_file, src_volume['name'])
img_info = imageutils.QemuImgInfo(qemu_img_output)
qemu_img_output = """{
"filename": "%s",
"format": "raw",
"virtual-size": 1073741824,
"actual-size": 173000,
"backing-filename": "%s"
}""" % (snap_file, src_volume['name'])
img_info = imageutils.QemuImgInfo(qemu_img_output, format='json')
# mocking and testing starts here
image_utils.convert_image = mock.Mock()
@ -1244,12 +1249,13 @@ class QuobyteDriverTestCase(test.TestCase):
drv._get_hash_str(self.TEST_QUOBYTE_VOLUME))
vol_path = os.path.join(vol_dir, volume['name'])
qemu_img_output = """image: %s
file format: raw
virtual size: 1.0G (1073741824 bytes)
disk size: 173K
""" % volume['name']
img_info = imageutils.QemuImgInfo(qemu_img_output)
qemu_img_output = """{
"filename": "%s",
"format": "raw",
"virtual-size": 1073741824,
"actual-size": 173000
}""" % volume['name']
img_info = imageutils.QemuImgInfo(qemu_img_output, format='json')
drv.get_active_image_from_info = mock.Mock(return_value=volume['name'])
image_utils.qemu_img_info = mock.Mock(return_value=img_info)
@ -1293,12 +1299,13 @@ class QuobyteDriverTestCase(test.TestCase):
mock_create_temporary_file.return_value = self.TEST_TMP_FILE
qemu_img_output = """image: %s
file format: raw
virtual size: 1.0G (1073741824 bytes)
disk size: 173K
""" % volume['name']
img_info = imageutils.QemuImgInfo(qemu_img_output)
qemu_img_output = """{
"filename": "%s",
"format": "raw",
"virtual-size": 1073741824,
"actual-size": 173000
}""" % volume['name']
img_info = imageutils.QemuImgInfo(qemu_img_output, format='json')
mock_qemu_img_info.return_value = img_info
upload_path = volume_path
@ -1345,12 +1352,13 @@ class QuobyteDriverTestCase(test.TestCase):
mock_create_temporary_file.return_value = self.TEST_TMP_FILE
qemu_img_output = """image: %s
file format: qcow2
virtual size: 1.0G (1073741824 bytes)
disk size: 173K
""" % volume['name']
img_info = imageutils.QemuImgInfo(qemu_img_output)
qemu_img_output = """{
"filename": "%s",
"format": "qcow2",
"virtual-size": 1073741824,
"actual-size": 173000
}""" % volume['name']
img_info = imageutils.QemuImgInfo(qemu_img_output, format='json')
mock_qemu_img_info.return_value = img_info
upload_path = self.TEST_TMP_FILE
@ -1400,13 +1408,14 @@ class QuobyteDriverTestCase(test.TestCase):
mock_create_temporary_file.return_value = self.TEST_TMP_FILE
qemu_img_output = """image: volume-%s.%s
file format: qcow2
virtual size: 1.0G (1073741824 bytes)
disk size: 173K
backing file: %s
""" % (self.VOLUME_UUID, self.SNAP_UUID, volume_filename)
img_info = imageutils.QemuImgInfo(qemu_img_output)
qemu_img_output = """{
"filename": "volume-%s.%s",
"format": "qcow2",
"virtual-size": 1073741824,
"actual-size": 173000,
"backing-filename": "%s"
}""" % (self.VOLUME_UUID, self.SNAP_UUID, volume_filename)
img_info = imageutils.QemuImgInfo(qemu_img_output, format='json')
mock_qemu_img_info.return_value = img_info
upload_path = self.TEST_TMP_FILE

View File

@ -21,6 +21,7 @@ from oslo_log import log as logging
from oslo_utils import excutils
from oslo_utils import fileutils
from oslo_utils import netutils
from oslo_utils import strutils
from oslo_utils import timeutils
from oslo_utils import uuidutils
import six
@ -552,7 +553,8 @@ class CreateVolumeFromSpecTask(flow_utils.CinderTask):
volume,
encryption)
if image_info.encrypted == 'yes':
# see Bug #1942682 and Change I949f07582a708 for why we do this
if strutils.bool_from_string(image_info.encrypted):
key_str = source_pass + "\n" + new_pass + "\n"
del source_pass