diff --git a/cinder/volume/manager.py b/cinder/volume/manager.py index 4886fa943..cd9184727 100644 --- a/cinder/volume/manager.py +++ b/cinder/volume/manager.py @@ -2166,9 +2166,24 @@ class VolumeManager(manager.CleanableManager, capabilities.get('sparse_copy_volume', False)) + src_device_path = src_attach_info['device']['path'] + converted_path = None + + # Check if we don't try to copy qcow where it's not supported + if src_attach_info['conn']['data'].get('format') == 'qcow2' and \ + src_attach_info['conn']['driver_volume_type'] == 'nfs' and \ + src_attach_info['conn']['driver_volume_type'] != \ + dest_attach_info['conn']['driver_volume_type']: + + converted_path = "%s.raw" % src_attach_info['device']['path'] + volume_utils.qemu_img_convert(src_attach_info['device']['path'], + converted_path) + + src_device_path = converted_path + try: size_in_mb = int(src_vol['size']) * units.Ki # vol size is in GB - volume_utils.copy_volume(src_attach_info['device']['path'], + volume_utils.copy_volume(src_device_path, dest_attach_info['device']['path'], size_in_mb, self.configuration.volume_dd_blocksize, @@ -2184,6 +2199,8 @@ class VolumeManager(manager.CleanableManager, remote=dest_remote, attach_encryptor=attach_encryptor) finally: + if converted_path: + utils.execute('rm', '-f', converted_path, run_as_root=True) self._detach_volume(ctxt, src_attach_info, src_vol, properties, force=True, remote=src_remote, diff --git a/cinder/volume/volume_utils.py b/cinder/volume/volume_utils.py index 52485e809..ec562bd82 100644 --- a/cinder/volume/volume_utils.py +++ b/cinder/volume/volume_utils.py @@ -546,6 +546,21 @@ def _transfer_data(src, dest, length, chunk_size): tpool.execute(dest.flush) +def qemu_img_convert(src, dest, dst_f='raw'): + + LOG.info("Volume %(src)s is QCOW2, so needs to be converted into RAW", + {'src': src}) + convert_cmd = [ + 'qemu-img', 'convert', '-O', dst_f, src, dest + ] + try: + utils.execute(*convert_cmd, run_as_root=True) + except Exception: + with excutils.save_and_reraise_exception(): + LOG.error("Unable to convert volume %(src)s into %(fmt)s format", + {'src': src, 'fmt': dst_f}) + + def _copy_volume_with_file(src, dest, size_in_m): src_handle = src if isinstance(src, six.string_types):