RBD: Handle ImageNotFound exception in _get_usage_info correctly

Change https://review.openstack.org/#/c/486734 moved try-except
statement to the wrong place. We need to open image in Ceph inside
try-except block.

This patch also fixes race condition between volume deletion and
_get_usage_info calls.

Closed-Bug: #1765845
Change-Id: I7d3d006b023ca4b7963c4c684e4c036399d1295c
Co-Authored-By: Melanie Witt <melwittt@gmail.com>
This commit is contained in:
Ivan Kolodyazhny 2018-04-21 00:02:13 +03:00 committed by melanie witt
parent a49eb33a66
commit 3cc8cbdee7
2 changed files with 26 additions and 31 deletions

View File

@ -1968,38 +1968,33 @@ class RBDTestCase(test.TestCase):
@mock.patch('cinder.volume.drivers.rbd.RADOSClient')
@mock.patch('cinder.volume.drivers.rbd.RBDDriver.RBDProxy')
def test__get_usage_info(self, rbdproxy_mock, client_mock, volproxy_mock):
def FakeVolProxy(size):
if size == -1:
size_mock = mock.Mock(side_effect=MockImageNotFoundException)
else:
size_mock = mock.Mock(return_value=size * units.Gi)
return mock.Mock(return_value=mock.Mock(size=size_mock))
def FakeVolProxy(size_or_exc):
return mock.Mock(return_value=mock.Mock(
size=mock.Mock(side_effect=(size_or_exc,))))
volumes = ['volume-1', 'non-existent', 'non-cinder-volume']
client = client_mock.return_value.__enter__.return_value
rbdproxy_mock.return_value.list.return_value = volumes
with mock.patch.object(self.driver, 'rbd',
ImageNotFound=MockImageNotFoundException):
volproxy_mock.side_effect = [
mock.Mock(**{'__enter__': FakeVolProxy(1.0),
'__exit__': mock.Mock()}),
mock.Mock(**{'__enter__': FakeVolProxy(-1),
'__exit__': mock.Mock()}),
mock.Mock(**{'__enter__': FakeVolProxy(2.0),
'__exit__': mock.Mock()})
mock.MagicMock(**{'__enter__': FakeVolProxy(s)})
for s in (1.0 * units.Gi,
self.driver.rbd.ImageNotFound,
2.0 * units.Gi)
]
with mock.patch.object(self.driver, 'rbd') as mock_rbd:
mock_rbd.ImageNotFound = MockImageNotFoundException
total_provision = self.driver._get_usage_info()
rbdproxy_mock.return_value.list.assert_called_once_with(client.ioctx)
volproxy_mock.assert_has_calls([
mock.call(self.driver, volumes[0], read_only=True,
client=client.cluster, ioctx=client.ioctx),
mock.call(self.driver, volumes[1], read_only=True,
client=client.cluster, ioctx=client.ioctx),
])
expected_volproxy_calls = [
mock.call(self.driver, v, read_only=True,
client=client.cluster, ioctx=client.ioctx)
for v in volumes]
self.assertEqual(expected_volproxy_calls, volproxy_mock.mock_calls)
self.assertEqual(3.00, total_provision)

View File

@ -403,10 +403,10 @@ class RBDDriver(driver.CloneableImageVD, driver.MigrateVD,
total_provisioned = 0
with RADOSClient(self) as client:
for t in self.RBDProxy().list(client.ioctx):
try:
with RBDVolumeProxy(self, t, read_only=True,
client=client.cluster,
ioctx=client.ioctx) as v:
try:
size = v.size()
except self.rbd.ImageNotFound:
LOG.debug("Image %s is not found.", t)