Make RBD imagebackend flatten method idempotent
If glance and nova are both configured with RBD backend, but glance
does not return location information from the API, nova will fail to
clone the image from glance pool and will download it from the API.
In this case, image will be already flat, and subsequent flatten call
will fail.
This commit makes flatten call idempotent, so that it ignores already
flat images by catching ImageUnacceptable when requesting parent info
from ceph.
Closes-Bug: 1860990
Change-Id: Ia6c184c31a980e4728b7309b2afaec4d9f494ac3
(cherry picked from commit 65825ebfbd
)
This commit is contained in:
parent
8363905a6a
commit
03d59e2893
|
@ -1577,11 +1577,28 @@ class RbdTestCase(_ImageTestCase, test.NoDBTestCase):
|
|||
["server1:1899", "server2:1920"]),
|
||||
model)
|
||||
|
||||
@mock.patch.object(rbd_utils.RBDDriver, 'parent_info')
|
||||
@mock.patch.object(rbd_utils.RBDDriver, 'flatten')
|
||||
def test_flatten(self, mock_flatten):
|
||||
def test_flatten(self, mock_flatten, mock_parent_info):
|
||||
image = self.image_class(self.INSTANCE, self.NAME)
|
||||
image.flatten()
|
||||
mock_flatten.assert_called_once_with(image.rbd_name, pool=self.POOL)
|
||||
mock_parent_info.assert_called_once_with(
|
||||
image.rbd_name, pool=self.POOL)
|
||||
|
||||
@mock.patch.object(imagebackend, 'LOG')
|
||||
@mock.patch.object(rbd_utils.RBDDriver, 'parent_info')
|
||||
@mock.patch.object(rbd_utils.RBDDriver, 'flatten')
|
||||
def test_flatten_already_flat(
|
||||
self, mock_flatten, mock_parent_info, mock_log):
|
||||
mock_parent_info.side_effect = exception.ImageUnacceptable(
|
||||
image_id=1, reason='foo')
|
||||
image = self.image_class(self.INSTANCE, self.NAME)
|
||||
image.flatten()
|
||||
mock_log.debug.assert_called_once()
|
||||
mock_flatten.assert_not_called()
|
||||
mock_parent_info.assert_called_once_with(
|
||||
image.rbd_name, pool=self.POOL)
|
||||
|
||||
def test_import_file(self):
|
||||
image = self.image_class(self.INSTANCE, self.NAME)
|
||||
|
|
|
@ -980,7 +980,17 @@ class Rbd(Image):
|
|||
reason=reason)
|
||||
|
||||
def flatten(self):
|
||||
self.driver.flatten(self.rbd_name, pool=self.driver.pool)
|
||||
# NOTE(vdrok): only flatten images if they are not already flattened,
|
||||
# meaning that parent info is present
|
||||
try:
|
||||
self.driver.parent_info(self.rbd_name, pool=self.driver.pool)
|
||||
except exception.ImageUnacceptable:
|
||||
LOG.debug(
|
||||
"Image %(img)s from pool %(pool)s has no parent info, "
|
||||
"consider it already flat", {
|
||||
'img': self.rbd_name, 'pool': self.driver.pool})
|
||||
else:
|
||||
self.driver.flatten(self.rbd_name, pool=self.driver.pool)
|
||||
|
||||
def get_model(self, connection):
|
||||
secret = None
|
||||
|
|
Loading…
Reference in New Issue