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
|
from __future__ import absolute_import
|
||||||
|
|
||||||
import os
|
import os
|
||||||
|
import time
|
||||||
|
|
||||||
import six
|
import six
|
||||||
|
|
||||||
from oslo_log import log as logging
|
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
|
# should have picked up the change already, so it is enough to query
|
||||||
# the actual disk device to see if its size is correct.
|
# 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)
|
volume_id = connection_properties.get('volume', None)
|
||||||
if volume_id is None:
|
if volume_id is None:
|
||||||
raise exception.BrickException(
|
raise exception.BrickException(
|
||||||
'Invalid StorPool connection data, no volume ID specified.')
|
'Invalid StorPool connection data, no volume ID specified.')
|
||||||
|
|
||||||
|
# Get the expected (new) size from the StorPool API
|
||||||
volume = self._attach.volumeName(volume_id)
|
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
|
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):
|
def volumeName(self, vid):
|
||||||
return volumeNameExt(vid)
|
return volumeNameExt(vid)
|
||||||
|
|
||||||
|
def get_fake_size(self):
|
||||||
|
return self.fakeSize
|
||||||
|
|
||||||
def execute(self, *cmd, **kwargs):
|
def execute(self, *cmd, **kwargs):
|
||||||
if cmd[0] == 'blockdev':
|
if cmd[0] == 'blockdev':
|
||||||
self.assertEqual(len(cmd), 3)
|
self.assertEqual(len(cmd), 3)
|
||||||
self.assertEqual(cmd[1], '--getsize64')
|
self.assertEqual(cmd[1], '--getsize64')
|
||||||
self.assertEqual(cmd[2], '/dev/storpool/' +
|
self.assertEqual(cmd[2], '/dev/storpool/' +
|
||||||
self.volumeName(self.fakeProp['volume']))
|
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 " +
|
raise Exception("Unrecognized command passed to " +
|
||||||
type(self).__name__ + ".execute(): " +
|
type(self).__name__ + ".execute(): " +
|
||||||
str.join(", ", map(lambda s: "'" + s + "'", cmd)))
|
str.join(", ", map(lambda s: "'" + s + "'", cmd)))
|
||||||
@ -148,5 +151,42 @@ class StorPoolConnectorTestCase(test_connector.ConnectorTestCase):
|
|||||||
self.test_connect_volume()
|
self.test_connect_volume()
|
||||||
|
|
||||||
self.fakeSize += 1024 * 1024 * 1024
|
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)
|
self.assertEqual(newSize, self.fakeSize)
|
||||||
|
Loading…
Reference in New Issue
Block a user