Merge "Limit the checks for block device becoming available."

This commit is contained in:
Jenkins 2013-04-03 14:01:17 +00:00 committed by Gerrit Code Review
commit f7add7ea8c
3 changed files with 66 additions and 8 deletions

View File

@ -673,6 +673,30 @@ class ComputeManager(manager.SchedulerDependentManager):
network_info = network_info.legacy()
return network_info
def _await_block_device_map_created(self, context, vol_id, max_tries=30,
wait_between=1):
# TODO(yamahata): creating volume simultaneously
# reduces creation time?
# TODO(yamahata): eliminate dumb polling
# TODO(harlowja): make the max_tries configurable or dynamic?
attempts = 0
start = time.time()
while attempts < max_tries:
volume = self.volume_api.get(context, vol_id)
volume_status = volume['status']
if volume_status != 'creating':
if volume_status != 'available':
LOG.warn(_("Volume id: %s finished being created but was"
" not set as 'available'"), vol_id)
# NOTE(harlowja): return how many attempts were tried
return attempts + 1
greenthread.sleep(wait_between)
attempts += 1
# NOTE(harlowja): Should only happen if we ran out of attempts
raise exception.VolumeNotCreated(volume_id=vol_id,
seconds=int(time.time() - start),
attempts=attempts)
def _setup_block_device_mapping(self, context, instance, bdms):
"""setup volumes for block device mapping."""
block_device_mapping = []
@ -705,14 +729,7 @@ class ComputeManager(manager.SchedulerDependentManager):
bdm['snapshot_id'])
vol = self.volume_api.create(context, bdm['volume_size'],
'', '', snapshot)
# TODO(yamahata): creating volume simultaneously
# reduces creation time?
# TODO(yamahata): eliminate dumb polling
while True:
volume = self.volume_api.get(context, vol['id'])
if volume['status'] != 'creating':
break
greenthread.sleep(1)
self._await_block_device_map_created(context, vol['id'])
self.conductor_api.block_device_mapping_update(
context, bdm['id'], {'volume_id': vol['id']})
bdm['volume_id'] = vol['id']

View File

@ -244,6 +244,12 @@ class VolumeUnattached(Invalid):
message = _("Volume %(volume_id)s is not attached to anything")
class VolumeNotCreated(NovaException):
message = _("Volume %(volume_id)s did not finish being created"
" even after we waited %(seconds)s seconds or %(attempts)s"
" attempts.")
class InvalidKeypair(Invalid):
message = _("Keypair data is invalid")

View File

@ -248,6 +248,7 @@ class ComputeVolumeTestCase(BaseTestCase):
def setUp(self):
super(ComputeVolumeTestCase, self).setUp()
self.volume_id = 'fake'
self.fetched_attempts = 0
self.instance = {
'id': 'fake',
'uuid': 'fake',
@ -283,6 +284,40 @@ class ComputeVolumeTestCase(BaseTestCase):
'/dev/vdb', self.instance)
self.assertEqual(self.cinfo.get('serial'), self.volume_id)
def test_await_block_device_created_to_slow(self):
def never_get(context, vol_id):
return {
'status': 'creating',
'id': 'blah',
}
self.stubs.Set(self.compute.volume_api, 'get', never_get)
self.assertRaises(exception.VolumeNotCreated,
self.compute._await_block_device_map_created,
self.context, '1', max_tries=2, wait_between=0.1)
def test_await_block_device_created_slow(self):
c = self.compute
def slow_get(context, vol_id):
while self.fetched_attempts < 2:
self.fetched_attempts += 1
return {
'status': 'creating',
'id': 'blah',
}
return {
'status': 'available',
'id': 'blah',
}
self.stubs.Set(c.volume_api, 'get', slow_get)
attempts = c._await_block_device_map_created(self.context, '1',
max_tries=4,
wait_between=0.1)
self.assertEqual(attempts, 3)
def test_boot_volume_serial(self):
block_device_mapping = [{
'id': 1,