[stable/zed] [ATMOSPHERE-482]fix: Directly import converted image to RBD (#2069)
This is an automated cherry-pick of #2000
/assign ricolin
diff --git a/images/cinder/patches/cinder/0002-Directly-import-converted-image-to-RBD.patch b/images/cinder/patches/cinder/0002-Directly-import-converted-image-to-RBD.patch
new file mode 100644
index 0000000..5466393
--- /dev/null
+++ b/images/cinder/patches/cinder/0002-Directly-import-converted-image-to-RBD.patch
@@ -0,0 +1,135 @@
+From a37e5d80306b4902a65dd3e38501fdaddc7c822a Mon Sep 17 00:00:00 2001
+From: ricolin <rlin@vexxhost.com>
+Date: Wed, 30 Oct 2024 12:54:42 +0800
+Subject: [PATCH] Directly import converted image to RBD
+
+For volume encryption from Glance image case,
+once we cloned the image down, we do convert and import back to RBD.
+
+This patch allows us to avoid another tempfile write and directly
+upload image to RBD.
+
+Related-Bug: #2055517
+Change-Id: Ib5e15eeee6a02e2833d14ac34f6fdeb4a6548a67
+---
+ cinder/volume/drivers/rbd.py | 70 +++++++++++++++++++-----------------
+ 1 file changed, 37 insertions(+), 33 deletions(-)
+
+diff --git a/cinder/volume/drivers/rbd.py b/cinder/volume/drivers/rbd.py
+index 6cc86c2c5..7c7be68ae 100644
+--- a/cinder/volume/drivers/rbd.py
++++ b/cinder/volume/drivers/rbd.py
+@@ -33,7 +33,6 @@ from oslo_log import log as logging
+ from oslo_service import loopingcall
+ from oslo_utils import encodeutils
+ from oslo_utils import excutils
+-from oslo_utils import fileutils
+ from oslo_utils import units
+ try:
+ import rados
+@@ -1911,11 +1910,10 @@ class RBDDriver(driver.CloneableImageVD, driver.MigrateVD,
+ image_id: str) -> None:
+ self._copy_image_to_volume(context, volume, image_service, image_id)
+
+- def _encrypt_image(self,
+- context: context.RequestContext,
+- volume: Volume,
+- tmp_dir: str,
+- src_image_path: Any) -> None:
++ def _encrypt_image_and_upload(
++ self, context: context.RequestContext,
++ volume: Volume, tmp_dir: str, src_image_path: Any
++ ) -> None:
+ encryption = volume_utils.check_encryption_provider(
+ volume,
+ context)
+@@ -1929,25 +1927,29 @@ class RBDDriver(driver.CloneableImageVD, driver.MigrateVD,
+ cipher_spec = image_utils.decode_cipher(encryption['cipher'],
+ encryption['key_size'])
+
++ _, conf, user_id, _ = self._get_config_tuple()
++ rbd_options = ''
++ if user_id:
++ rbd_options += f':id={user_id}'
++ if conf:
++ rbd_options += f':conf={conf}'
++
++ rbd_dest = 'rbd:%(pool_name)s/%(image_name)s%(rbd_options)s' % {
++ 'pool_name': self.configuration.rbd_pool,
++ 'image_name': volume.name,
++ 'rbd_options': rbd_options
++ }
++
+ tmp_dir = volume_utils.image_conversion_dir()
+
+ with tempfile.NamedTemporaryFile(prefix='luks_',
+ dir=tmp_dir) as pass_file:
+ with open(pass_file.name, 'w') as f:
+ f.write(passphrase)
+-
+- # Convert the raw image to luks
+- dest_image_path = src_image_path + '.luks'
+- try:
+- image_utils.convert_image(src_image_path, dest_image_path,
+- 'luks', src_format='raw',
+- cipher_spec=cipher_spec,
+- passphrase_file=pass_file.name)
+-
+- # Replace the original image with the now encrypted image
+- os.rename(dest_image_path, src_image_path)
+- finally:
+- fileutils.delete_if_exists(dest_image_path)
++ image_utils.convert_image(src_image_path, rbd_dest,
++ 'luks', src_format='raw',
++ cipher_spec=cipher_spec,
++ passphrase_file=pass_file.name)
+
+ def _copy_image_to_volume(self,
+ context: context.RequestContext,
+@@ -1964,9 +1966,6 @@ class RBDDriver(driver.CloneableImageVD, driver.MigrateVD,
+ self.configuration.volume_dd_blocksize,
+ size=volume.size)
+
+- if encrypted:
+- self._encrypt_image(context, volume, tmp_dir, tmp.name)
+-
+ @utils.retry(exception.VolumeIsBusy,
+ self.configuration.rados_connection_interval,
+ self.configuration.rados_connection_retries)
+@@ -1975,17 +1974,22 @@ class RBDDriver(driver.CloneableImageVD, driver.MigrateVD,
+
+ _delete_volume(volume)
+
+- chunk_size = self.configuration.rbd_store_chunk_size * units.Mi
+- order = int(math.log(chunk_size, 2))
+- # keep using the command line import instead of librbd since it
+- # detects zeroes to preserve sparseness in the image
+- args = ['rbd', 'import',
+- '--pool', self.configuration.rbd_pool,
+- '--order', order,
+- tmp.name, volume.name,
+- '--new-format']
+- args.extend(self._ceph_args())
+- self._try_execute(*args)
++ if encrypted:
++ self._encrypt_image_and_upload(
++ context, volume, tmp_dir, tmp.name)
++ else:
++ chunk_size = self.configuration.rbd_store_chunk_size * units.Mi
++ order = int(math.log(chunk_size, 2))
++ # keep using the command line import instead of librbd since it
++ # detects zeroes to preserve sparseness in the image
++ args = ['rbd', 'import',
++ '--pool', self.configuration.rbd_pool,
++ '--order', order,
++ tmp.name, volume.name,
++ '--new-format']
++ args.extend(self._ceph_args())
++ self._try_execute(*args)
++
+ self._resize(volume)
+ # We may need to re-enable replication because we have deleted the
+ # original image and created a new one using the command line import.
+--
+2.25.1
+