From ae375ebb9d64f67767838d91c5d007fee93f4f63 Mon Sep 17 00:00:00 2001 From: wuyuting Date: Mon, 19 Jan 2015 06:32:34 +0800 Subject: [PATCH] Fix bug in rbd driver: the cloned volume size is wrong The cloned volume size is wrong when the size is different from source volume. This is because rbd driver doesn't resize the volume when clone has completed. Change-Id: If953441b2c24dee46bd64e6d4b8f4d3ab116f0fa Closes-Bug: #1412317 --- cinder/tests/test_rbd.py | 64 +++++++++++++++++++++++++++++------- cinder/volume/drivers/rbd.py | 7 ++++ 2 files changed, 59 insertions(+), 12 deletions(-) diff --git a/cinder/tests/test_rbd.py b/cinder/tests/test_rbd.py index 2dabe8c4a..ea7793e58 100644 --- a/cinder/tests/test_rbd.py +++ b/cinder/tests/test_rbd.py @@ -472,7 +472,7 @@ class RBDTestCase(test.TestCase): volume.parent_info.assert_called_once_with() @common_mocks - def test_create_cloned_volume(self): + def test_create_cloned_volume_same_size(self): src_name = u'volume-00000001' dst_name = u'volume-00000002' @@ -481,19 +481,59 @@ class RBDTestCase(test.TestCase): with mock.patch.object(self.driver, '_get_clone_depth') as \ mock_get_clone_depth: # Try with no flatten required - mock_get_clone_depth.return_value = 1 + with mock.patch.object(self.driver, '_resize') as mock_resize: + mock_get_clone_depth.return_value = 1 + + self.driver.create_cloned_volume({'name': dst_name, + 'size': 10}, + {'name': src_name, + 'size': 10}) + + (self.mock_rbd.Image.return_value.create_snap + .assert_called_once_with('.'.join((dst_name, + 'clone_snap')))) + (self.mock_rbd.Image.return_value.protect_snap + .assert_called_once_with('.'.join((dst_name, + 'clone_snap')))) + self.assertEqual( + 1, self.mock_rbd.RBD.return_value.clone.call_count) + self.mock_rbd.Image.return_value.close \ + .assert_called_once_with() + self.assertTrue(mock_get_clone_depth.called) + self.assertEqual( + 0, mock_resize.call_count) - self.driver.create_cloned_volume({'name': dst_name}, - {'name': src_name}) + @common_mocks + def test_create_cloned_volume_different_size(self): + src_name = u'volume-00000001' + dst_name = u'volume-00000002' - (self.mock_rbd.Image.return_value.create_snap - .assert_called_once_with('.'.join((dst_name, 'clone_snap')))) - (self.mock_rbd.Image.return_value.protect_snap - .assert_called_once_with('.'.join((dst_name, 'clone_snap')))) - self.assertEqual( - 1, self.mock_rbd.RBD.return_value.clone.call_count) - self.mock_rbd.Image.return_value.close.assert_called_once_with() - self.assertTrue(mock_get_clone_depth.called) + self.cfg.rbd_max_clone_depth = 2 + + with mock.patch.object(self.driver, '_get_clone_depth') as \ + mock_get_clone_depth: + # Try with no flatten required + with mock.patch.object(self.driver, '_resize') as mock_resize: + mock_get_clone_depth.return_value = 1 + + self.driver.create_cloned_volume({'name': dst_name, + 'size': 20}, + {'name': src_name, + 'size': 10}) + + (self.mock_rbd.Image.return_value.create_snap + .assert_called_once_with('.'.join((dst_name, + 'clone_snap')))) + (self.mock_rbd.Image.return_value.protect_snap + .assert_called_once_with('.'.join((dst_name, + 'clone_snap')))) + self.assertEqual( + 1, self.mock_rbd.RBD.return_value.clone.call_count) + self.mock_rbd.Image.return_value.close \ + .assert_called_once_with() + self.assertTrue(mock_get_clone_depth.called) + self.assertEqual( + 1, mock_resize.call_count) @common_mocks def test_create_cloned_volume_w_flatten(self): diff --git a/cinder/volume/drivers/rbd.py b/cinder/volume/drivers/rbd.py index 6a9e16837..7a79a8547 100644 --- a/cinder/volume/drivers/rbd.py +++ b/cinder/volume/drivers/rbd.py @@ -482,6 +482,13 @@ class RBDDriver(driver.VolumeDriver): finally: src_volume.close() + if volume['size'] != src_vref['size']: + LOG.debug("resize volume '%(dst_vol)s' from %(src_size)d to " + "%(dst_size)d" % + {'dst_vol': volume['name'], 'src_size': src_vref['size'], + 'dst_size': volume['size']}) + self._resize(volume) + LOG.debug("clone created successfully") def create_volume(self, volume): -- 2.45.2