StorPool: wait for the device to be resized.

Change-Id: I176ba9c4efd1361c16babc3c96e07bee0595d55d
This commit is contained in:
Peter Penchev 2019-12-04 12:10:17 +02:00
parent ffd57863f9
commit 0907c08df7
2 changed files with 62 additions and 4 deletions

View File

@ -16,6 +16,8 @@
from __future__ import absolute_import
import os
import time
import six
from oslo_log import log as logging
@ -212,11 +214,27 @@ class StorPoolConnector(base.BaseLinuxConnector):
# should have picked up the change already, so it is enough to query
# the actual disk device to see if its size is correct.
#
# TODO(pp): query the API to see if this is really the case
volume_id = connection_properties.get('volume', None)
if volume_id is None:
raise exception.BrickException(
'Invalid StorPool connection data, no volume ID specified.')
# Get the expected (new) size from the StorPool API
volume = self._attach.volumeName(volume_id)
LOG.debug('Querying the StorPool API for the size of %(vol)s',
{'vol': volume})
vdata = self._attach.api().volumeList(volume)[0]
LOG.debug('Got size %(size)d', {'size': vdata.size})
# Wait for the StorPool client to update the size of the local device
path = '/dev/storpool/' + volume
return self._get_device_size(path)
for _ in range(10):
size = self._get_device_size(path)
LOG.debug('Got local size %(size)d', {'size': size})
if size == vdata.size:
return size
time.sleep(0.1)
else:
size = self._get_device_size(path)
LOG.debug('Last attempt: local size %(size)d', {'size': size})
return size

View File

@ -79,13 +79,16 @@ class StorPoolConnectorTestCase(test_connector.ConnectorTestCase):
def volumeName(self, vid):
return volumeNameExt(vid)
def get_fake_size(self):
return self.fakeSize
def execute(self, *cmd, **kwargs):
if cmd[0] == 'blockdev':
self.assertEqual(len(cmd), 3)
self.assertEqual(cmd[1], '--getsize64')
self.assertEqual(cmd[2], '/dev/storpool/' +
self.volumeName(self.fakeProp['volume']))
return (str(self.fakeSize) + '\n', None)
return (str(self.get_fake_size()) + '\n', None)
raise Exception("Unrecognized command passed to " +
type(self).__name__ + ".execute(): " +
str.join(", ", map(lambda s: "'" + s + "'", cmd)))
@ -148,5 +151,42 @@ class StorPoolConnectorTestCase(test_connector.ConnectorTestCase):
self.test_connect_volume()
self.fakeSize += 1024 * 1024 * 1024
newSize = self.connector.extend_volume(self.fakeProp)
size_list = [self.fakeSize, self.fakeSize - 1, self.fakeSize - 2]
vdata = mock.MagicMock(spec=['size'])
vdata.size = self.fakeSize
vdata_list = [[vdata]]
def fake_volume_list(name):
self.assertEqual(
name,
self.adb.volumeName(self.fakeProp['volume'])
)
return vdata_list.pop()
api = mock.MagicMock(spec=['volumeList'])
api.volumeList = mock.MagicMock(spec=['__call__'])
with mock.patch.object(
self.adb, attribute='api', spec=['__call__']
) as fake_api, mock.patch.object(
self, attribute='get_fake_size', spec=['__call__']
) as fake_size, mock.patch('time.sleep') as fake_sleep:
fake_api.return_value = api
api.volumeList.side_effect = fake_volume_list
fake_size.side_effect = size_list.pop
newSize = self.connector.extend_volume(self.fakeProp)
self.assertEqual(fake_api.call_count, 1)
self.assertEqual(api.volumeList.call_count, 1)
self.assertListEqual(vdata_list, [])
self.assertEqual(fake_size.call_count, 3)
self.assertListEqual(size_list, [])
self.assertEqual(fake_sleep.call_count, 2)
self.assertEqual(newSize, self.fakeSize)