Merge "Use the json format output of qemu-img info"

This commit is contained in:
Zuul 2022-09-21 21:53:43 +00:00 committed by Gerrit Code Review
commit acb8711dcf
5 changed files with 193 additions and 167 deletions

View File

@ -135,7 +135,7 @@ def qemu_img_info(path: str,
run_as_root: bool = True, run_as_root: bool = True,
force_share: bool = False) -> imageutils.QemuImgInfo: force_share: bool = False) -> imageutils.QemuImgInfo:
"""Return an object containing the parsed output from qemu-img info.""" """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 force_share:
if qemu_img_supports_force_share(): if qemu_img_supports_force_share():
cmd.append('--force-share') cmd.append('--force-share')
@ -149,7 +149,7 @@ def qemu_img_info(path: str,
cmd = cmd[2:] cmd = cmd[2:]
out, _err = utils.execute(*cmd, run_as_root=run_as_root, out, _err = utils.execute(*cmd, run_as_root=run_as_root,
prlimit=QEMU_IMG_LIMITS) prlimit=QEMU_IMG_LIMITS)
info = imageutils.QemuImgInfo(out) info = imageutils.QemuImgInfo(out, format='json')
# From Cinder's point of view, any 'luks' formatted images # From Cinder's point of view, any 'luks' formatted images
# should be treated as 'raw'. # should be treated as 'raw'.

View File

@ -40,7 +40,8 @@ class TestQemuImgInfo(test.TestCase):
output = image_utils.qemu_img_info(test_path) output = image_utils.qemu_img_info(test_path)
mock_exec.assert_called_once_with('env', 'LC_ALL=C', 'qemu-img', 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) prlimit=image_utils.QEMU_IMG_LIMITS)
self.assertEqual(mock_info.return_value, output) self.assertEqual(mock_info.return_value, output)
@ -57,7 +58,8 @@ class TestQemuImgInfo(test.TestCase):
force_share=False, force_share=False,
run_as_root=False) run_as_root=False)
mock_exec.assert_called_once_with('env', 'LC_ALL=C', 'qemu-img', 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) prlimit=image_utils.QEMU_IMG_LIMITS)
self.assertEqual(mock_info.return_value, output) self.assertEqual(mock_info.return_value, output)
@ -72,8 +74,8 @@ class TestQemuImgInfo(test.TestCase):
mock_os.name = 'nt' mock_os.name = 'nt'
output = image_utils.qemu_img_info(test_path) output = image_utils.qemu_img_info(test_path)
mock_exec.assert_called_once_with('qemu-img', 'info', test_path, mock_exec.assert_called_once_with('qemu-img', 'info', '--output=json',
run_as_root=True, test_path, run_as_root=True,
prlimit=image_utils.QEMU_IMG_LIMITS) prlimit=image_utils.QEMU_IMG_LIMITS)
self.assertEqual(mock_info.return_value, output) self.assertEqual(mock_info.return_value, output)

View File

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

View File

@ -941,13 +941,14 @@ class QuobyteDriverTestCase(test.TestCase):
self.TEST_QUOBYTE_VOLUME), self.TEST_QUOBYTE_VOLUME),
self.VOLUME_UUID) self.VOLUME_UUID)
qemu_img_info_output = """image: volume-%s qemu_img_info_output = """{
file format: qcow2 "filename": "volume-%s",
virtual size: 1.0G (1073741824 bytes) "format": "qcow2",
disk size: 473K "virtual-size": 1073741824,
""" % self.VOLUME_UUID "actual-size": 473000
}""" % self.VOLUME_UUID
img_info = imageutils.QemuImgInfo(qemu_img_info_output) img_info = imageutils.QemuImgInfo(qemu_img_info_output, format='json')
self.mock_object(image_utils, 'qemu_img_info', return_value=img_info) self.mock_object(image_utils, 'qemu_img_info', return_value=img_info)
self.mock_object(image_utils, 'resize_image') self.mock_object(image_utils, 'resize_image')
@ -987,13 +988,14 @@ class QuobyteDriverTestCase(test.TestCase):
size = dest_volume['size'] size = dest_volume['size']
qemu_img_output = """image: %s qemu_img_output = """{
file format: raw "filename": "%s",
virtual size: 1.0G (1073741824 bytes) "format": "raw",
disk size: 173K "virtual-size": 1073741824,
backing file: %s "actual-size": 173000,
""" % (snap_file, src_volume['name']) "backing-filename": "%s"
img_info = imageutils.QemuImgInfo(qemu_img_output) }""" % (snap_file, src_volume['name'])
img_info = imageutils.QemuImgInfo(qemu_img_output, format='json')
# mocking and testing starts here # mocking and testing starts here
mock_convert = self.mock_object(image_utils, 'convert_image') mock_convert = self.mock_object(image_utils, 'convert_image')
@ -1043,13 +1045,14 @@ class QuobyteDriverTestCase(test.TestCase):
size = dest_volume['size'] size = dest_volume['size']
qemu_img_output = """image: %s qemu_img_output = """{
file format: raw "filename": "%s",
virtual size: 1.0G (1073741824 bytes) "format": "raw",
disk size: 173K "virtual-size": 1073741824,
backing file: %s "actual-size": 173000,
""" % (snap_file, src_volume['name']) "backing-filename": "%s"
img_info = imageutils.QemuImgInfo(qemu_img_output) }""" % (snap_file, src_volume['name'])
img_info = imageutils.QemuImgInfo(qemu_img_output, format='json')
# mocking and testing starts here # mocking and testing starts here
mock_convert = self.mock_object(image_utils, 'convert_image') mock_convert = self.mock_object(image_utils, 'convert_image')
@ -1104,13 +1107,14 @@ class QuobyteDriverTestCase(test.TestCase):
size = dest_volume['size'] size = dest_volume['size']
qemu_img_output = """image: %s qemu_img_output = """{
file format: raw "filename": "%s",
virtual size: 1.0G (1073741824 bytes) "format": "raw",
disk size: 173K "virtual-size": 1073741824,
backing file: %s "actual-size": 173000,
""" % (snap_file, src_volume['name']) "backing-filename": "%s"
img_info = imageutils.QemuImgInfo(qemu_img_output) }""" % (snap_file, src_volume['name'])
img_info = imageutils.QemuImgInfo(qemu_img_output, format='json')
# mocking and testing starts here # mocking and testing starts here
mock_convert = self.mock_object(image_utils, 'convert_image') mock_convert = self.mock_object(image_utils, 'convert_image')
@ -1168,13 +1172,14 @@ class QuobyteDriverTestCase(test.TestCase):
size = dest_volume['size'] size = dest_volume['size']
qemu_img_output = """image: %s qemu_img_output = """{
file format: raw "filename": "%s",
virtual size: 1.0G (1073741824 bytes) "format": "raw",
disk size: 173K "virtual-size": 1073741824,
backing file: %s "actual-size": 173000,
""" % (snap_file, src_volume['name']) "backing-filename": "%s"
img_info = imageutils.QemuImgInfo(qemu_img_output) }""" % (snap_file, src_volume['name'])
img_info = imageutils.QemuImgInfo(qemu_img_output, format='json')
# mocking and testing starts here # mocking and testing starts here
mock_convert = self.mock_object(image_utils, 'convert_image') mock_convert = self.mock_object(image_utils, 'convert_image')
@ -1245,12 +1250,13 @@ class QuobyteDriverTestCase(test.TestCase):
drv._get_hash_str(self.TEST_QUOBYTE_VOLUME)) drv._get_hash_str(self.TEST_QUOBYTE_VOLUME))
vol_path = os.path.join(vol_dir, volume['name']) vol_path = os.path.join(vol_dir, volume['name'])
qemu_img_output = """image: %s qemu_img_output = """{
file format: raw "filename": "%s",
virtual size: 1.0G (1073741824 bytes) "format": "raw",
disk size: 173K "virtual-size": 1073741824,
""" % volume['name'] "actual-size": 173000
img_info = imageutils.QemuImgInfo(qemu_img_output) }""" % volume['name']
img_info = imageutils.QemuImgInfo(qemu_img_output, format='json')
drv.get_active_image_from_info = mock.Mock(return_value=volume['name']) drv.get_active_image_from_info = mock.Mock(return_value=volume['name'])
self.mock_object(image_utils, 'qemu_img_info', return_value=img_info) self.mock_object(image_utils, 'qemu_img_info', return_value=img_info)
@ -1294,12 +1300,13 @@ class QuobyteDriverTestCase(test.TestCase):
mock_create_temporary_file.return_value = self.TEST_TMP_FILE mock_create_temporary_file.return_value = self.TEST_TMP_FILE
qemu_img_output = """image: %s qemu_img_output = """{
file format: raw "filename": "%s",
virtual size: 1.0G (1073741824 bytes) "format": "raw",
disk size: 173K "virtual-size": 1073741824,
""" % volume['name'] "actual-size": 173000
img_info = imageutils.QemuImgInfo(qemu_img_output) }""" % volume['name']
img_info = imageutils.QemuImgInfo(qemu_img_output, format='json')
mock_qemu_img_info.return_value = img_info mock_qemu_img_info.return_value = img_info
upload_path = volume_path upload_path = volume_path
@ -1346,12 +1353,13 @@ class QuobyteDriverTestCase(test.TestCase):
mock_create_temporary_file.return_value = self.TEST_TMP_FILE mock_create_temporary_file.return_value = self.TEST_TMP_FILE
qemu_img_output = """image: %s qemu_img_output = """{
file format: qcow2 "filename": "%s",
virtual size: 1.0G (1073741824 bytes) "format": "qcow2",
disk size: 173K "virtual-size": 1073741824,
""" % volume['name'] "actual-size": 173000
img_info = imageutils.QemuImgInfo(qemu_img_output) }""" % volume['name']
img_info = imageutils.QemuImgInfo(qemu_img_output, format='json')
mock_qemu_img_info.return_value = img_info mock_qemu_img_info.return_value = img_info
upload_path = self.TEST_TMP_FILE upload_path = self.TEST_TMP_FILE
@ -1401,13 +1409,14 @@ class QuobyteDriverTestCase(test.TestCase):
mock_create_temporary_file.return_value = self.TEST_TMP_FILE mock_create_temporary_file.return_value = self.TEST_TMP_FILE
qemu_img_output = """image: volume-%s.%s qemu_img_output = """{
file format: qcow2 "filename": "volume-%s.%s",
virtual size: 1.0G (1073741824 bytes) "format": "qcow2",
disk size: 173K "virtual-size": 1073741824,
backing file: %s "actual-size": 173000,
""" % (self.VOLUME_UUID, self.SNAP_UUID, volume_filename) "backing-filename": "%s"
img_info = imageutils.QemuImgInfo(qemu_img_output) }""" % (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 mock_qemu_img_info.return_value = img_info
upload_path = self.TEST_TMP_FILE upload_path = self.TEST_TMP_FILE

View File

@ -25,6 +25,7 @@ from oslo_log import log as logging
from oslo_utils import excutils from oslo_utils import excutils
from oslo_utils import fileutils from oslo_utils import fileutils
from oslo_utils import netutils from oslo_utils import netutils
from oslo_utils import strutils
from oslo_utils import timeutils from oslo_utils import timeutils
from oslo_utils import uuidutils from oslo_utils import uuidutils
import taskflow.engines import taskflow.engines
@ -572,7 +573,8 @@ class CreateVolumeFromSpecTask(flow_utils.CinderTask):
volume, volume,
encryption) 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" key_str = source_pass + "\n" + new_pass + "\n"
del source_pass del source_pass