Merge "Cinder consistency group returning generic error message"

This commit is contained in:
Jenkins 2016-12-21 13:34:40 +00:00 committed by Gerrit Code Review
commit 107ca25b99
7 changed files with 80 additions and 3 deletions

View File

@ -33,6 +33,7 @@ from cinder import objects
from cinder.objects import fields as c_fields
import cinder.policy
from cinder import quota
from cinder import quota_utils
from cinder.scheduler import rpcapi as scheduler_rpcapi
from cinder.volume import api as volume_api
from cinder.volume import rpcapi as volume_rpcapi
@ -405,10 +406,13 @@ class API(base.Base):
**reserve_opts)
if reservations:
CGQUOTAS.commit(context, reservations)
except Exception:
except Exception as e:
with excutils.save_and_reraise_exception():
try:
group.destroy()
if isinstance(e, exception.OverQuota):
quota_utils.process_reserve_over_quota(
context, e, resource='groups')
finally:
LOG.error(_LE("Failed to update quota for "
"consistency group %s."), group.id)

View File

@ -659,6 +659,10 @@ class GroupTypeUpdateFailed(CinderException):
message = _("Cannot update group_type %(id)s")
class GroupLimitExceeded(QuotaError):
message = _("Maximum number of groups allowed (%(allowed)d) exceeded")
class UnknownCmd(VolumeDriverException):
message = _("Unknown or unsupported command %(cmd)s")

View File

@ -35,6 +35,7 @@ from cinder.objects import base as objects_base
from cinder.objects import fields as c_fields
import cinder.policy
from cinder import quota
from cinder import quota_utils
from cinder.scheduler import rpcapi as scheduler_rpcapi
from cinder.volume import api as volume_api
from cinder.volume import rpcapi as volume_rpcapi
@ -469,10 +470,13 @@ class API(base.Base):
**reserve_opts)
if reservations:
GROUP_QUOTAS.commit(context, reservations)
except Exception:
except Exception as e:
with excutils.save_and_reraise_exception():
try:
group.destroy()
if isinstance(e, exception.OverQuota):
quota_utils.process_reserve_over_quota(
context, e, resource='groups')
finally:
LOG.error(_LE("Failed to update quota for "
"group %s."), group.id)

View File

@ -238,7 +238,8 @@ def _keystone_client(context, version=(3, 0)):
OVER_QUOTA_RESOURCE_EXCEPTIONS = {'snapshots': exception.SnapshotLimitExceeded,
'backups': exception.BackupLimitExceeded,
'volumes': exception.VolumeLimitExceeded, }
'volumes': exception.VolumeLimitExceeded,
'groups': exception.GroupLimitExceeded}
def process_reserve_over_quota(context, over_quota_exception,

View File

@ -491,6 +491,22 @@ class GroupsAPITestCase(test.TestCase):
group.id)
self.assertEqual(fields.GroupStatus.DELETED, group.status)
@mock.patch('cinder.group.api.API.create')
def test_create_group_failed_exceeded_quota(self, mock_group_create):
mock_group_create.side_effect = exception.GroupLimitExceeded(allowed=1)
name = 'group1'
body = {"group": {"group_type": fake.GROUP_TYPE_ID,
"volume_types": [fake.VOLUME_TYPE_ID],
"name": name,
"description":
"Group 1", }}
req = fakes.HTTPRequest.blank('/v3/%s/groups' % fake.PROJECT_ID,
version=GROUP_MICRO_VERSION)
ex = self.assertRaises(exception.GroupLimitExceeded,
self.controller.create,
req, body)
self.assertEqual(413, ex.code)
def test_delete_group_with_invalid_body(self):
self.group1.status = fields.GroupStatus.AVAILABLE
self.group1.save()

View File

@ -22,14 +22,19 @@ import mock
from cinder import context
from cinder import db
from cinder import exception
import cinder.group
from cinder import objects
from cinder.objects import fields
from cinder import quota
from cinder import test
from cinder.tests.unit import fake_constants as fake
from cinder.tests.unit import utils
GROUP_QUOTAS = quota.GROUP_QUOTAS
@ddt.ddt
class GroupAPITestCase(test.TestCase):
"""Test Case for group API."""
@ -168,6 +173,40 @@ class GroupAPITestCase(test.TestCase):
mock_volume_types_get.assert_called_once_with(mock.ANY,
volume_type_names)
@mock.patch.object(GROUP_QUOTAS, "reserve")
@mock.patch('cinder.objects.Group')
@mock.patch('cinder.db.group_type_get_by_name')
@mock.patch('cinder.db.volume_types_get_by_name_or_id')
@mock.patch('cinder.group.api.check_policy')
def test_create_group_failed_update_quota(self, mock_policy,
mock_volume_types_get,
mock_group_type_get, mock_group,
mock_group_quota_reserve):
mock_volume_types_get.return_value = [{'id': fake.VOLUME_TYPE_ID}]
mock_group_type_get.return_value = {'id': fake.GROUP_TYPE_ID}
fake_overs = ['groups']
fake_quotas = {'groups': 1}
fake_usages = {'groups': {'reserved': 0, 'in_use': 1}}
mock_group_quota_reserve.side_effect = exception.OverQuota(
overs=fake_overs,
quotas=fake_quotas,
usages=fake_usages)
name = "test_group"
description = "this is a test group"
grp = utils.create_group(self.ctxt, group_type_id=fake.GROUP_TYPE_ID,
volume_type_ids=[fake.VOLUME_TYPE_ID],
availability_zone='nova', host=None,
name=name, description=description,
status=fields.GroupStatus.CREATING)
mock_group.return_value = grp
self.assertRaises(exception.GroupLimitExceeded,
self.group_api.create,
self.ctxt, name, description,
"fake-grouptype-name",
[fake.VOLUME_TYPE_ID],
availability_zone='nova')
@mock.patch('cinder.volume.rpcapi.VolumeAPI.update_group')
@mock.patch('cinder.db.volume_get_all_by_generic_group')
@mock.patch('cinder.group.api.API._cast_create_group')

View File

@ -225,6 +225,15 @@ class QuotaUtilsTest(test.TestCase):
overs, usages, quotas,
exception.VolumeLimitExceeded)
def test_groups_limit_quota(self):
overs = ['groups']
usages = {'groups': {'reserved': 1, 'in_use': 9}}
quotas = {'groups': 9}
self._process_reserve_over_quota(
overs, usages, quotas,
exception.GroupLimitExceeded,
resource='groups')
def test_unknown_quota(self):
overs = ['unknown']
usages = {'volumes': {'reserved': 1, 'in_use': 9}}