Merge "StorPool: wait for the device to be resized."
This commit is contained in:
commit
2a6e8d405e
@ -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
|
||||
|
@ -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
|
||||
|
||||
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)
|
||||
|
Loading…
Reference in New Issue
Block a user