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

Closes-Bug: #1940540
Change-Id: Ia0353204abf849467106ee08982d1271de23101a
This commit is contained in:
Takashi Kajinami 2021-07-06 21:48:44 +09:00
parent a5e77329e0
commit c0d2e7ebd8
5 changed files with 193 additions and 167 deletions

View File

@ -128,7 +128,7 @@ def qemu_img_info(path: str,
run_as_root: bool = True,
force_share: bool = False) -> imageutils.QemuImgInfo:
"""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')
@ -142,7 +142,7 @@ def qemu_img_info(path: str,
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

@ -40,7 +40,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)
@ -57,7 +58,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)
@ -72,8 +74,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
@ -1323,7 +1333,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')
@ -1404,7 +1414,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
@ -1470,7 +1480,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})
@ -1490,12 +1501,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

@ -941,13 +941,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()
@ -987,13 +988,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()
@ -1043,13 +1045,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()
@ -1104,13 +1107,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()
@ -1168,13 +1172,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()
@ -1245,12 +1250,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)
@ -1294,12 +1300,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
@ -1346,12 +1353,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
@ -1401,13 +1409,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

@ -23,6 +23,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 taskflow.engines
@ -557,7 +558,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