diff --git a/nova/api/openstack/compute/server_groups.py b/nova/api/openstack/compute/server_groups.py index 4129122..a134477 100644 --- a/nova/api/openstack/compute/server_groups.py +++ b/nova/api/openstack/compute/server_groups.py @@ -27,7 +27,6 @@ from nova.api.openstack import wsgi from nova.api import validation import nova.exception from nova.i18n import _ -from nova.i18n import _LE from nova import objects from nova.policies import server_groups as sg_policies @@ -91,29 +90,11 @@ class ServerGroupController(wsgi.Controller): sg = objects.InstanceGroup.get_by_uuid(context, id) except nova.exception.InstanceGroupNotFound as e: raise webob.exc.HTTPNotFound(explanation=e.format_message()) - - quotas = objects.Quotas(context=context) - project_id, user_id = objects.quotas.ids_from_server_group(context, sg) - try: - # We have to add the quota back to the user that created - # the server group - quotas.reserve(project_id=project_id, - user_id=user_id, server_groups=-1) - except Exception: - quotas = None - LOG.exception(_LE("Failed to update usages deallocating " - "server group")) - try: sg.destroy() except nova.exception.InstanceGroupNotFound as e: - if quotas: - quotas.rollback() raise webob.exc.HTTPNotFound(explanation=e.format_message()) - if quotas: - quotas.commit() - @extensions.expected_errors(()) def index(self, req): """Returns a list of server groups.""" @@ -137,10 +118,10 @@ class ServerGroupController(wsgi.Controller): """Creates a new server group.""" context = _authorize_context(req, 'create') - quotas = objects.Quotas(context=context) try: - quotas.reserve(project_id=context.project_id, - user_id=context.user_id, server_groups=1) + objects.Quotas.check_deltas(context, 'server_groups', + {'server_groups': 1}, + context.project_id, context.user_id) except nova.exception.OverQuota: msg = _("Quota exceeded, too many server groups.") raise exc.HTTPForbidden(explanation=msg) @@ -154,10 +135,20 @@ class ServerGroupController(wsgi.Controller): sg.policies = vals.get('policies') sg.create() except ValueError as e: - quotas.rollback() raise exc.HTTPBadRequest(explanation=e) - quotas.commit() + # NOTE(melwitt): We recheck the quota after creating the + # object to handle races. Delete the object if we're over + # quota after creating the object. + try: + objects.Quotas.check_deltas(context, 'server_groups', + {'server_groups': 0}, + context.project_id, context.user_id) + except nova.exception.OverQuota: + sg.destroy() + msg = _("Quota exceeded, too many server groups.") + raise exc.HTTPForbidden(explanation=msg) + return {'server_group': self._format_server_group(context, sg, req)}