diff --git a/cinder/image/image_utils.py b/cinder/image/image_utils.py index 317d5747bb9..062763a622b 100644 --- a/cinder/image/image_utils.py +++ b/cinder/image/image_utils.py @@ -108,7 +108,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') @@ -122,7 +122,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'. diff --git a/cinder/tests/unit/test_image_utils.py b/cinder/tests/unit/test_image_utils.py index c368639f5dd..08e3b6974f6 100644 --- a/cinder/tests/unit/test_image_utils.py +++ b/cinder/tests/unit/test_image_utils.py @@ -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) diff --git a/cinder/tests/unit/volume/drivers/test_nfs.py b/cinder/tests/unit/volume/drivers/test_nfs.py index d6844089e55..d82db2428f2 100644 --- a/cinder/tests/unit/volume/drivers/test_nfs.py +++ b/cinder/tests/unit/volume/drivers/test_nfs.py @@ -330,51 +330,52 @@ 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" +}""" @ddt.ddt @@ -1191,7 +1192,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') @@ -1262,7 +1263,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 @@ -1328,7 +1329,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}) @@ -1348,12 +1350,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, diff --git a/cinder/tests/unit/volume/drivers/test_quobyte.py b/cinder/tests/unit/volume/drivers/test_quobyte.py index e5fe434f067..5c1020427e9 100644 --- a/cinder/tests/unit/volume/drivers/test_quobyte.py +++ b/cinder/tests/unit/volume/drivers/test_quobyte.py @@ -936,13 +936,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() @@ -975,13 +976,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() @@ -1031,13 +1033,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() @@ -1092,13 +1095,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() @@ -1156,13 +1160,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() @@ -1247,12 +1252,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 @@ -1340,12 +1347,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 @@ -1390,13 +1398,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 diff --git a/cinder/volume/flows/manager/create_volume.py b/cinder/volume/flows/manager/create_volume.py index 721c6c4e563..c79f28b05c3 100644 --- a/cinder/volume/flows/manager/create_volume.py +++ b/cinder/volume/flows/manager/create_volume.py @@ -20,6 +20,7 @@ from oslo_config import cfg from oslo_log import log as logging from oslo_utils import excutils from oslo_utils import fileutils +from oslo_utils import strutils from oslo_utils import timeutils import six import taskflow.engines @@ -551,7 +552,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