From c92c15b59ae21fdd3bf4f4db2a5aef45615a6266 Mon Sep 17 00:00:00 2001 From: Takashi Kajinami Date: Wed, 7 Oct 2020 09:55:32 +0900 Subject: [PATCH] RBD: Run flatten in a different thread when cloning a volume The current implementation of create_cloned_volume calls flatten directly, and this makes whole thread of cinder-volume blocked by that flatten call. This causes heartbeat timeout in RabbitMQ when cloning a volume with rbd backend. This patch makes sure that flatten is executed in a different thread, to allow heatbeat thread to run while flattening a rbd image. Closes-Bug: #1898918 Change-Id: I9f28260008117abcebfc96dbe69bf892f5cd14fe (cherry picked from commit bafe440b9418a1e3acd00456872d4d97a9c64c61) (cherry picked from commit f1521d82d941e711f6ef248a7eb81f096de8135f) (cherry picked from commit 223b3c7b0f614fc4a5e0e8e9612f10bb0de0ba55) --- cinder/tests/unit/volume/drivers/test_rbd.py | 11 +++++++++-- cinder/volume/drivers/rbd.py | 12 ++++++------ releasenotes/notes/bug-1898918-b24a93d7d5aff238.yaml | 7 +++++++ 3 files changed, 22 insertions(+), 8 deletions(-) create mode 100644 releasenotes/notes/bug-1898918-b24a93d7d5aff238.yaml diff --git a/cinder/tests/unit/volume/drivers/test_rbd.py b/cinder/tests/unit/volume/drivers/test_rbd.py index c60f434438e..e1ba497b2f0 100644 --- a/cinder/tests/unit/volume/drivers/test_rbd.py +++ b/cinder/tests/unit/volume/drivers/test_rbd.py @@ -1168,6 +1168,9 @@ class RBDTestCase(test.TestCase): def test_create_cloned_volume_w_flatten(self, mock_enable_repl): self.cfg.rbd_max_clone_depth = 1 + client = self.mock_client.return_value + client.__enter__.return_value = client + with mock.patch.object(self.driver, '_get_clone_info') as \ mock_get_clone_info: mock_get_clone_info.return_value = ( @@ -1197,9 +1200,13 @@ class RBDTestCase(test.TestCase): .assert_called_once_with('.'.join( (self.volume_b.name, 'clone_snap')))) - # We expect the driver to close both volumes, so 2 is expected + self.mock_proxy.assert_called_once_with( + self.driver, self.volume_b.name, + client=client, ioctx=client.ioctx) + + # Source volume is closed by direct call of close() self.assertEqual( - 2, self.mock_rbd.Image.return_value.close.call_count) + 1, self.mock_rbd.Image.return_value.close.call_count) self.assertTrue(mock_get_clone_depth.called) mock_enable_repl.assert_not_called() diff --git a/cinder/volume/drivers/rbd.py b/cinder/volume/drivers/rbd.py index 10140879651..f06162d686f 100644 --- a/cinder/volume/drivers/rbd.py +++ b/cinder/volume/drivers/rbd.py @@ -716,11 +716,13 @@ class RBDDriver(driver.CloneableImageVD, driver.MigrateVD, LOG.info("maximum clone depth (%d) has been reached - " "flattening dest volume", self.configuration.rbd_max_clone_depth) - dest_volume = self.rbd.Image(client.ioctx, dest_name) + + # Flatten destination volume try: - # Flatten destination volume - LOG.debug("flattening dest volume %s", dest_name) - dest_volume.flatten() + with RBDVolumeProxy(self, dest_name, client=client, + ioctx=client.ioctx) as dest_volume: + LOG.debug("flattening dest volume %s", dest_name) + dest_volume.flatten() except Exception as e: msg = (_("Failed to flatten volume %(volume)s with " "error: %(error)s.") % @@ -729,8 +731,6 @@ class RBDDriver(driver.CloneableImageVD, driver.MigrateVD, LOG.exception(msg) src_volume.close() raise exception.VolumeBackendAPIException(data=msg) - finally: - dest_volume.close() try: # remove temporary snap diff --git a/releasenotes/notes/bug-1898918-b24a93d7d5aff238.yaml b/releasenotes/notes/bug-1898918-b24a93d7d5aff238.yaml new file mode 100644 index 00000000000..2a81a3f1817 --- /dev/null +++ b/releasenotes/notes/bug-1898918-b24a93d7d5aff238.yaml @@ -0,0 +1,7 @@ +--- +fixes: + - | + RBD driver `Bug #1898918 + `_: Fix thread block caused + by the flatten operation during cloning a volume. Now the flatten operation + is executed in a different thread.