Raise descriptive error for over volume quota

If you attempt to create a new instance booting from an image and you
were over your quota on cinder, the nova manager would see that as an
invalid block device. This raises a more descriptive error message in
the logs.

Closes-bug: #1013417
Change-Id: Ie50b97c31580da7fc38c6891d1f3646b91f8aa10
This commit is contained in:
Mike Perez 2014-02-04 15:00:10 -08:00
parent 8604b7c0d7
commit 4711ff3adf
4 changed files with 65 additions and 0 deletions

View File

@ -1733,6 +1733,12 @@ class ComputeManager(manager.Manager):
block_device_info['swap'])
return block_device_info
except exception.OverQuota:
msg = ('Failed to create block device for instance due to being '
'over volume resource quota')
LOG.debug(msg, instance=instance)
raise exception.InvalidBDM()
except Exception:
LOG.exception(_('Instance failed block device setup'),
instance=instance)

View File

@ -1035,6 +1035,27 @@ class ComputeVolumeTestCase(BaseTestCase):
self.compute.volume_snapshot_delete, self.context,
self.instance_object, 'fake_id', 'fake_id2', {})
@mock.patch.object(cinder.API, 'create',
side_effect=exception.OverQuota(overs='volumes'))
def test_prep_block_device_over_quota_failure(self, mock_create):
instance = self._create_fake_instance()
bdms = [
block_device.BlockDeviceDict({
'boot_index': 0,
'guest_format': None,
'connection_info': None,
'device_type': u'disk',
'source_type': 'image',
'destination_type': 'volume',
'volume_size': 1,
'image_id': 1,
'device_name': '/dev/vdb',
})]
self.assertRaises(exception.InvalidBDM,
compute_manager.ComputeManager()._prep_block_device,
self.context, instance, bdms)
mock_create.assert_called_once()
class ComputeTestCase(BaseTestCase):
def test_wrap_instance_fault(self):
@ -1513,6 +1534,30 @@ class ComputeTestCase(BaseTestCase):
self._assert_state({'vm_state': vm_states.ERROR,
'task_state': None})
@mock.patch('nova.compute.manager.ComputeManager._prep_block_device',
side_effect=exception.OverQuota(overs='volumes'))
def test_setup_block_device_over_quota_fail(self, mock_prep_block_dev):
"""block device mapping over quota failure test.
Make sure when we're over volume quota according to Cinder client, the
appropriate exception is raised and the instances to ERROR state, keep
the task state.
"""
instance = self._create_fake_instance()
self.assertRaises(exception.OverQuota, self.compute.run_instance,
self.context, instance=instance, request_spec={},
filter_properties={}, requested_networks=[],
injected_files=None, admin_password=None,
is_first_time=True, node=None,
legacy_bdm_in_spec=False)
#check state is failed even after the periodic poll
self._assert_state({'vm_state': vm_states.ERROR,
'task_state': None})
self.compute.periodic_tasks(context.get_admin_context())
self._assert_state({'vm_state': vm_states.ERROR,
'task_state': None})
mock_prep_block_dev.assert_called_once()
def test_run_instance_spawn_fail(self):
"""spawn failure test.

View File

@ -14,6 +14,7 @@
# under the License.
from cinderclient import exceptions as cinder_exception
import mock
from nova import context
from nova import exception
@ -84,6 +85,17 @@ class CinderApiTestCase(test.NoDBTestCase):
self.assertRaises(exception.InvalidInput,
self.api.create, self.ctx, 1, '', '')
@mock.patch('nova.volume.cinder.cinderclient')
def test_create_over_quota_failed(self, mock_cinderclient):
mock_cinderclient.return_value.volumes.create.side_effect = (
cinder_exception.OverLimit(413))
self.assertRaises(exception.OverQuota, self.api.create, self.ctx,
1, '', '')
mock_cinderclient.return_value.volumes.create.assert_called_once_with(
1, user_id=None, imageRef=None, availability_zone=None,
volume_type=None, display_description='', snapshot_id=None,
display_name='', project_id=None, metadata=None)
def test_get_all(self):
cinder.cinderclient(self.ctx).AndReturn(self.cinderclient)
cinder._untranslate_volume_summary_view(self.ctx,

View File

@ -301,6 +301,8 @@ class API(object):
try:
item = cinderclient(context).volumes.create(size, **kwargs)
return _untranslate_volume_summary_view(context, item)
except cinder_exception.OverLimit:
raise exception.OverQuota(overs='volumes')
except cinder_exception.BadRequest as e:
raise exception.InvalidInput(reason=unicode(e))