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:
parent
8604b7c0d7
commit
4711ff3adf
|
@ -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)
|
||||
|
|
|
@ -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.
|
||||
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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))
|
||||
|
||||
|
|
Loading…
Reference in New Issue