)]}'
{"nova/api/openstack/compute/server_groups.py":[{"author":{"_account_id":782,"name":"John Garbutt","email":"john@johngarbutt.com","username":"johngarbutt"},"change_message_id":"c6e4467f3e72e37894bda8555889826de054e0ba","unresolved":false,"context_lines":[{"line_number":171,"context_line":"        except ValueError as e:"},{"line_number":172,"context_line":"            raise exc.HTTPBadRequest(explanation\u003de)"},{"line_number":173,"context_line":""},{"line_number":174,"context_line":"        # NOTE(melwitt): We recheck the quota after creating the"},{"line_number":175,"context_line":"        # object to handle races. Delete the object if we\u0027re over"},{"line_number":176,"context_line":"        # quota after creating the object."},{"line_number":177,"context_line":"        try:"},{"line_number":178,"context_line":"            objects.Quotas.check_deltas(context, \u0027server_groups\u0027,"},{"line_number":179,"context_line":"                                        {\u0027server_groups\u0027: 0},"},{"line_number":180,"context_line":"                                        context.project_id, context.user_id)"},{"line_number":181,"context_line":"        except nova.exception.OverQuota:"},{"line_number":182,"context_line":"            sg.destroy()"},{"line_number":183,"context_line":"            msg \u003d _(\"Quota exceeded, too many server groups.\")"},{"line_number":184,"context_line":"            raise exc.HTTPForbidden(explanation\u003dmsg)"},{"line_number":185,"context_line":""},{"line_number":186,"context_line":"        return {\u0027server_group\u0027: self._format_server_group(context, sg, req)}"},{"line_number":187,"context_line":""}],"source_content_type":"text/x-python","patch_set":6,"id":"5ff73747_5e835f57","line":184,"range":{"start_line":174,"start_character":9,"end_line":184,"end_character":52},"updated":"2017-05-03 18:03:58.000000000","message":"I don\u0027t see a test for this bit, did I just miss it?","commit_id":"2f93a301d31df7227a6f550127aa79b091380053"},{"author":{"_account_id":4690,"name":"melanie witt","display_name":"melwitt","email":"melwittt@gmail.com","username":"melwitt"},"change_message_id":"808d79f86de3d00b3fd41eb9c8db6848ae311d27","unresolved":false,"context_lines":[{"line_number":171,"context_line":"        except ValueError as e:"},{"line_number":172,"context_line":"            raise exc.HTTPBadRequest(explanation\u003de)"},{"line_number":173,"context_line":""},{"line_number":174,"context_line":"        # NOTE(melwitt): We recheck the quota after creating the"},{"line_number":175,"context_line":"        # object to handle races. Delete the object if we\u0027re over"},{"line_number":176,"context_line":"        # quota after creating the object."},{"line_number":177,"context_line":"        try:"},{"line_number":178,"context_line":"            objects.Quotas.check_deltas(context, \u0027server_groups\u0027,"},{"line_number":179,"context_line":"                                        {\u0027server_groups\u0027: 0},"},{"line_number":180,"context_line":"                                        context.project_id, context.user_id)"},{"line_number":181,"context_line":"        except nova.exception.OverQuota:"},{"line_number":182,"context_line":"            sg.destroy()"},{"line_number":183,"context_line":"            msg \u003d _(\"Quota exceeded, too many server groups.\")"},{"line_number":184,"context_line":"            raise exc.HTTPForbidden(explanation\u003dmsg)"},{"line_number":185,"context_line":""},{"line_number":186,"context_line":"        return {\u0027server_group\u0027: self._format_server_group(context, sg, req)}"},{"line_number":187,"context_line":""}],"source_content_type":"text/x-python","patch_set":6,"id":"3f044301_914c6677","line":184,"range":{"start_line":174,"start_character":9,"end_line":184,"end_character":52},"in_reply_to":"5ff73747_5e835f57","updated":"2017-05-03 23:33:36.000000000","message":"I think you\u0027re right. Looks like I missed all of the \"recheck quota\" testing on the various resources. Will add those, thanks.","commit_id":"2f93a301d31df7227a6f550127aa79b091380053"},{"author":{"_account_id":21813,"name":"Andrey Volkov","email":"m@amadev.ru","username":"avolkov"},"change_message_id":"044c11f81f7bd191f3588a7cc8ca2b16dde20504","unresolved":false,"context_lines":[{"line_number":177,"context_line":"            objects.Quotas.check_deltas(context, {\u0027server_groups\u0027: 0},"},{"line_number":178,"context_line":"                                        context.project_id, context.user_id)"},{"line_number":179,"context_line":"        except nova.exception.OverQuota:"},{"line_number":180,"context_line":"            sg.destroy()"},{"line_number":181,"context_line":"            msg \u003d _(\"Quota exceeded, too many server groups.\")"},{"line_number":182,"context_line":"            raise exc.HTTPForbidden(explanation\u003dmsg)"},{"line_number":183,"context_line":""}],"source_content_type":"text/x-python","patch_set":13,"id":"df140735_345549c7","line":180,"updated":"2017-05-31 10:55:09.000000000","message":"We introduce here ability for both requests failing\ndue race between the check_deltas and destroy, should it be mentioned in comments?","commit_id":"20e015abfe5adcd8fb45f2960cf017589e0ff170"},{"author":{"_account_id":4690,"name":"melanie witt","display_name":"melwitt","email":"melwittt@gmail.com","username":"melwitt"},"change_message_id":"bc8e1f3d218c515a504abe0ee784e35857001c5a","unresolved":false,"context_lines":[{"line_number":177,"context_line":"            objects.Quotas.check_deltas(context, {\u0027server_groups\u0027: 0},"},{"line_number":178,"context_line":"                                        context.project_id, context.user_id)"},{"line_number":179,"context_line":"        except nova.exception.OverQuota:"},{"line_number":180,"context_line":"            sg.destroy()"},{"line_number":181,"context_line":"            msg \u003d _(\"Quota exceeded, too many server groups.\")"},{"line_number":182,"context_line":"            raise exc.HTTPForbidden(explanation\u003dmsg)"},{"line_number":183,"context_line":""}],"source_content_type":"text/x-python","patch_set":13,"id":"df140735_5293fa5b","line":180,"in_reply_to":"df140735_345549c7","updated":"2017-06-01 19:45:54.000000000","message":"Yeah, that\u0027s a possibility we\u0027ve discussed on the reviews before (that it would be possible for a user to get OverQuota if they are not actually over quota if they are part of a parallel race near their quota limit) but I haven\u0027t mentioned it in code comment. I think that\u0027s a good idea though and I\u0027ll add a comment here.","commit_id":"20e015abfe5adcd8fb45f2960cf017589e0ff170"},{"author":{"_account_id":6873,"name":"Matt Riedemann","email":"mriedem.os@gmail.com","username":"mriedem"},"change_message_id":"544dd35fbf7e13b3deabeaf289cc828a28de6b3e","unresolved":false,"context_lines":[{"line_number":125,"context_line":"        except nova.exception.InstanceGroupNotFound as e:"},{"line_number":126,"context_line":"            raise webob.exc.HTTPNotFound(explanation\u003de.format_message())"},{"line_number":127,"context_line":""},{"line_number":128,"context_line":"        quotas \u003d objects.Quotas(context\u003dcontext)"},{"line_number":129,"context_line":"        project_id, user_id \u003d objects.quotas.ids_from_server_group(context, sg)"},{"line_number":130,"context_line":"        try:"},{"line_number":131,"context_line":"            # We have to add the quota back to the user that created"},{"line_number":132,"context_line":"            # the server group"},{"line_number":133,"context_line":"            quotas.reserve(project_id\u003dproject_id,"},{"line_number":134,"context_line":"                           user_id\u003duser_id, server_groups\u003d-1)"},{"line_number":135,"context_line":"        except Exception:"},{"line_number":136,"context_line":"            quotas \u003d None"},{"line_number":137,"context_line":"            LOG.exception(\"Failed to update usages deallocating server group\")"},{"line_number":138,"context_line":""},{"line_number":139,"context_line":"        try:"},{"line_number":140,"context_line":"            sg.destroy()"},{"line_number":141,"context_line":"        except nova.exception.InstanceGroupNotFound as e:"},{"line_number":142,"context_line":"            if quotas:"},{"line_number":143,"context_line":"                quotas.rollback()"},{"line_number":144,"context_line":"            raise webob.exc.HTTPNotFound(explanation\u003de.format_message())"},{"line_number":145,"context_line":""},{"line_number":146,"context_line":"        if quotas:"},{"line_number":147,"context_line":"            quotas.commit()"},{"line_number":148,"context_line":""},{"line_number":149,"context_line":"    @extensions.expected_errors(())"},{"line_number":150,"context_line":"    def index(self, req):"}],"source_content_type":"text/x-python","patch_set":14,"id":"df140735_6fd29502","side":"PARENT","line":147,"range":{"start_line":128,"start_character":8,"end_line":147,"end_character":27},"updated":"2017-06-01 19:09:53.000000000","message":"Hmm, so, if we never decrement the usage, doesn\u0027t this mess up the used_limits API?\n\nFor example, let\u0027s say I have a quota limit of 9 before this, with in_use\u003d1 because I\u0027ve got one server group. Then after this change is applied and I delete the server group, my usages is still going to show 1 and my quota limit will be 9, which would be wrong.\n\nIn other words, shouldn\u0027t we be changing the used_limits API to use the new counting system before making changes like this?\n\nhttps://github.com/openstack/nova/blob/master/nova/api/openstack/compute/used_limits.py#L42\n\nI\u0027d think we could do the new counting quotas routine on new requests, but it seems like until the used_limits API is using the new code we need to still allow deleting resources to cleanup and decrement old usages.","commit_id":"240cd92885c6dad194af0232f5afafcd3a61182e"},{"author":{"_account_id":4690,"name":"melanie witt","display_name":"melwitt","email":"melwittt@gmail.com","username":"melwitt"},"change_message_id":"8b1494485bddd173338b66dc342acc84f5eb4a35","unresolved":false,"context_lines":[{"line_number":125,"context_line":"        except nova.exception.InstanceGroupNotFound as e:"},{"line_number":126,"context_line":"            raise webob.exc.HTTPNotFound(explanation\u003de.format_message())"},{"line_number":127,"context_line":""},{"line_number":128,"context_line":"        quotas \u003d objects.Quotas(context\u003dcontext)"},{"line_number":129,"context_line":"        project_id, user_id \u003d objects.quotas.ids_from_server_group(context, sg)"},{"line_number":130,"context_line":"        try:"},{"line_number":131,"context_line":"            # We have to add the quota back to the user that created"},{"line_number":132,"context_line":"            # the server group"},{"line_number":133,"context_line":"            quotas.reserve(project_id\u003dproject_id,"},{"line_number":134,"context_line":"                           user_id\u003duser_id, server_groups\u003d-1)"},{"line_number":135,"context_line":"        except Exception:"},{"line_number":136,"context_line":"            quotas \u003d None"},{"line_number":137,"context_line":"            LOG.exception(\"Failed to update usages deallocating server group\")"},{"line_number":138,"context_line":""},{"line_number":139,"context_line":"        try:"},{"line_number":140,"context_line":"            sg.destroy()"},{"line_number":141,"context_line":"        except nova.exception.InstanceGroupNotFound as e:"},{"line_number":142,"context_line":"            if quotas:"},{"line_number":143,"context_line":"                quotas.rollback()"},{"line_number":144,"context_line":"            raise webob.exc.HTTPNotFound(explanation\u003de.format_message())"},{"line_number":145,"context_line":""},{"line_number":146,"context_line":"        if quotas:"},{"line_number":147,"context_line":"            quotas.commit()"},{"line_number":148,"context_line":""},{"line_number":149,"context_line":"    @extensions.expected_errors(())"},{"line_number":150,"context_line":"    def index(self, req):"}],"source_content_type":"text/x-python","patch_set":14,"id":"df140735_b26a56ea","side":"PARENT","line":147,"range":{"start_line":128,"start_character":8,"end_line":147,"end_character":27},"in_reply_to":"df140735_6fd29502","updated":"2017-06-01 19:56:38.000000000","message":"It doesn\u0027t mess up the used_limits API because the used_limits API calls methods like QUOTAS.get_project_quotas() to get the usages and this change is changing \u0027server_groups\u0027 to a Countable resource, so its usage will come from the _get_usages() function that counts resources and the backward compat call to quota_usage_get_all* result won\u0027t be used because an entry for \u0027server_groups\u0027 will be found in the usages (from the _get_usages() call) and so the quota_usages record won\u0027t be used [1].\n\nYou\u0027re right though that throughout this transition, what will happen is we will orphan quota_usages and reservations records in that we\u0027ll never read them again and they\u0027ll just stay as they are.\n\n[1] https://github.com/openstack/nova/blob/832cc47/nova/quota.py#L303-L315","commit_id":"240cd92885c6dad194af0232f5afafcd3a61182e"},{"author":{"_account_id":6873,"name":"Matt Riedemann","email":"mriedem.os@gmail.com","username":"mriedem"},"change_message_id":"5a9116ddd9849588b343a2ec4cf9e1eb4f09b644","unresolved":false,"context_lines":[{"line_number":125,"context_line":"        except nova.exception.InstanceGroupNotFound as e:"},{"line_number":126,"context_line":"            raise webob.exc.HTTPNotFound(explanation\u003de.format_message())"},{"line_number":127,"context_line":""},{"line_number":128,"context_line":"        quotas \u003d objects.Quotas(context\u003dcontext)"},{"line_number":129,"context_line":"        project_id, user_id \u003d objects.quotas.ids_from_server_group(context, sg)"},{"line_number":130,"context_line":"        try:"},{"line_number":131,"context_line":"            # We have to add the quota back to the user that created"},{"line_number":132,"context_line":"            # the server group"},{"line_number":133,"context_line":"            quotas.reserve(project_id\u003dproject_id,"},{"line_number":134,"context_line":"                           user_id\u003duser_id, server_groups\u003d-1)"},{"line_number":135,"context_line":"        except Exception:"},{"line_number":136,"context_line":"            quotas \u003d None"},{"line_number":137,"context_line":"            LOG.exception(\"Failed to update usages deallocating server group\")"},{"line_number":138,"context_line":""},{"line_number":139,"context_line":"        try:"},{"line_number":140,"context_line":"            sg.destroy()"},{"line_number":141,"context_line":"        except nova.exception.InstanceGroupNotFound as e:"},{"line_number":142,"context_line":"            if quotas:"},{"line_number":143,"context_line":"                quotas.rollback()"},{"line_number":144,"context_line":"            raise webob.exc.HTTPNotFound(explanation\u003de.format_message())"},{"line_number":145,"context_line":""},{"line_number":146,"context_line":"        if quotas:"},{"line_number":147,"context_line":"            quotas.commit()"},{"line_number":148,"context_line":""},{"line_number":149,"context_line":"    @extensions.expected_errors(())"},{"line_number":150,"context_line":"    def index(self, req):"}],"source_content_type":"text/x-python","patch_set":14,"id":"df140735_3e7e0daf","side":"PARENT","line":147,"range":{"start_line":128,"start_character":8,"end_line":147,"end_character":27},"in_reply_to":"df140735_b26a56ea","updated":"2017-06-01 22:23:09.000000000","message":"*whew*","commit_id":"240cd92885c6dad194af0232f5afafcd3a61182e"},{"author":{"_account_id":6873,"name":"Matt Riedemann","email":"mriedem.os@gmail.com","username":"mriedem"},"change_message_id":"d9c811c31cb7531c833b648dace01010da9730f8","unresolved":false,"context_lines":[{"line_number":154,"context_line":""},{"line_number":155,"context_line":"        try:"},{"line_number":156,"context_line":"            objects.Quotas.check_deltas(context, {\u0027server_groups\u0027: 1},"},{"line_number":157,"context_line":"                                        context.project_id, context.user_id)"},{"line_number":158,"context_line":"        except nova.exception.OverQuota:"},{"line_number":159,"context_line":"            msg \u003d _(\"Quota exceeded, too many server groups.\")"},{"line_number":160,"context_line":"            raise exc.HTTPForbidden(explanation\u003dmsg)"}],"source_content_type":"text/x-python","patch_set":14,"id":"df140735_0f7b19be","line":157,"range":{"start_line":157,"start_character":40,"end_line":157,"end_character":75},"updated":"2017-06-01 19:31:08.000000000","message":"If I\u0027m following this correctly, this is supposed to be count_args passed to count_as_dict:\n\nhttps://github.com/openstack/nova/blob/836bfd7150b0091744663bad06cb73efb5f39c76/nova/objects/quotas.py#L153\n\nhttps://github.com/openstack/nova/blob/836bfd7150b0091744663bad06cb73efb5f39c76/nova/objects/quotas.py#L186\n\nhttps://github.com/openstack/nova/blob/836bfd7150b0091744663bad06cb73efb5f39c76/nova/objects/quotas.py#L147\n\nWhich gets passed to count_as_dict in the quota engine:\n\nhttps://github.com/openstack/nova/blob/836bfd7150b0091744663bad06cb73efb5f39c76/nova/quota.py#L1608\n\nWhich passes those down to the count_as_dict function on the CountableResource, which in the case of server groups would be this:\n\nhttps://review.openstack.org/#/c/446240/14/nova/quota.py@1859\n\nSo I think I\u0027m following this correctly. It\u0027s several abstraction layers to get through so it\u0027s confusing, but I think I\u0027ve got it and it\u0027s correct here.","commit_id":"216201ef03a39b5071218ad64ac0b1c8cd308bc8"},{"author":{"_account_id":4690,"name":"melanie witt","display_name":"melwitt","email":"melwittt@gmail.com","username":"melwitt"},"change_message_id":"85d080b9824710aab75a11b7e27d168a84745334","unresolved":false,"context_lines":[{"line_number":154,"context_line":""},{"line_number":155,"context_line":"        try:"},{"line_number":156,"context_line":"            objects.Quotas.check_deltas(context, {\u0027server_groups\u0027: 1},"},{"line_number":157,"context_line":"                                        context.project_id, context.user_id)"},{"line_number":158,"context_line":"        except nova.exception.OverQuota:"},{"line_number":159,"context_line":"            msg \u003d _(\"Quota exceeded, too many server groups.\")"},{"line_number":160,"context_line":"            raise exc.HTTPForbidden(explanation\u003dmsg)"}],"source_content_type":"text/x-python","patch_set":14,"id":"df140735_3d1a976e","line":157,"range":{"start_line":157,"start_character":40,"end_line":157,"end_character":75},"in_reply_to":"df140735_0f7b19be","updated":"2017-06-01 20:12:49.000000000","message":"Yeah, you\u0027re right. Anything after \"deltas\" are the count_args and count_kwargs that get passed on through (several levels, admittedly) to the count function. Since the count functions can have varying signatures, I thought doing a pass through all the way down was the most straightforward thing.","commit_id":"216201ef03a39b5071218ad64ac0b1c8cd308bc8"},{"author":{"_account_id":6873,"name":"Matt Riedemann","email":"mriedem.os@gmail.com","username":"mriedem"},"change_message_id":"d9c811c31cb7531c833b648dace01010da9730f8","unresolved":false,"context_lines":[{"line_number":174,"context_line":"        # object to handle races. Delete the object if we\u0027re over"},{"line_number":175,"context_line":"        # quota after creating the object."},{"line_number":176,"context_line":"        try:"},{"line_number":177,"context_line":"            objects.Quotas.check_deltas(context, {\u0027server_groups\u0027: 0},"},{"line_number":178,"context_line":"                                        context.project_id, context.user_id)"},{"line_number":179,"context_line":"        except nova.exception.OverQuota:"},{"line_number":180,"context_line":"            sg.destroy()"}],"source_content_type":"text/x-python","patch_set":14,"id":"df140735_b2c936ad","line":177,"range":{"start_line":177,"start_character":67,"end_line":177,"end_character":68},"updated":"2017-06-01 19:31:08.000000000","message":"I\u0027m lost in how this 0 is being processed for the delta - can you explain? check_deltas gets the current usage count and adds the delta (0), so I\u0027m not sure how this is going to save us from a race - is this just to avoid a race to pick up the last usage available? So if limit is 10 and usage is 9, and request A gets the last usage record so usage is now 10 in that request, and request B is going at the same time and gets the last usage record so usage is 11 in that request, when request A double checks here it\u0027s going to see usage is 11 (per request B) and fail and delete the usage record it created, thus going back down to 10 for usage?","commit_id":"216201ef03a39b5071218ad64ac0b1c8cd308bc8"},{"author":{"_account_id":6873,"name":"Matt Riedemann","email":"mriedem.os@gmail.com","username":"mriedem"},"change_message_id":"5a9116ddd9849588b343a2ec4cf9e1eb4f09b644","unresolved":false,"context_lines":[{"line_number":174,"context_line":"        # object to handle races. Delete the object if we\u0027re over"},{"line_number":175,"context_line":"        # quota after creating the object."},{"line_number":176,"context_line":"        try:"},{"line_number":177,"context_line":"            objects.Quotas.check_deltas(context, {\u0027server_groups\u0027: 0},"},{"line_number":178,"context_line":"                                        context.project_id, context.user_id)"},{"line_number":179,"context_line":"        except nova.exception.OverQuota:"},{"line_number":180,"context_line":"            sg.destroy()"}],"source_content_type":"text/x-python","patch_set":14,"id":"df140735_f2056912","line":177,"range":{"start_line":177,"start_character":67,"end_line":177,"end_character":68},"in_reply_to":"df140735_9da7630c","updated":"2017-06-01 22:23:09.000000000","message":"OK I think a comment explaining it is what I\u0027m ultimately looking for. I think it\u0027s fine to return an error during a collision in the absence of having something like etags or generation IDs.","commit_id":"216201ef03a39b5071218ad64ac0b1c8cd308bc8"},{"author":{"_account_id":4690,"name":"melanie witt","display_name":"melwitt","email":"melwittt@gmail.com","username":"melwitt"},"change_message_id":"85d080b9824710aab75a11b7e27d168a84745334","unresolved":false,"context_lines":[{"line_number":174,"context_line":"        # object to handle races. Delete the object if we\u0027re over"},{"line_number":175,"context_line":"        # quota after creating the object."},{"line_number":176,"context_line":"        try:"},{"line_number":177,"context_line":"            objects.Quotas.check_deltas(context, {\u0027server_groups\u0027: 0},"},{"line_number":178,"context_line":"                                        context.project_id, context.user_id)"},{"line_number":179,"context_line":"        except nova.exception.OverQuota:"},{"line_number":180,"context_line":"            sg.destroy()"}],"source_content_type":"text/x-python","patch_set":14,"id":"df140735_7d75af63","line":177,"range":{"start_line":177,"start_character":67,"end_line":177,"end_character":68},"in_reply_to":"df140735_b257f6ca","updated":"2017-06-01 20:12:49.000000000","message":"I tested it here [1], let me know if you think that\u0027s not sufficient and we should add something else.\n\n[1] https://github.com/openstack/nova/blob/832cc47/nova/tests/unit/objects/test_quotas.py#L207-L232","commit_id":"216201ef03a39b5071218ad64ac0b1c8cd308bc8"},{"author":{"_account_id":4690,"name":"melanie witt","display_name":"melwitt","email":"melwittt@gmail.com","username":"melwitt"},"change_message_id":"85d080b9824710aab75a11b7e27d168a84745334","unresolved":false,"context_lines":[{"line_number":174,"context_line":"        # object to handle races. Delete the object if we\u0027re over"},{"line_number":175,"context_line":"        # quota after creating the object."},{"line_number":176,"context_line":"        try:"},{"line_number":177,"context_line":"            objects.Quotas.check_deltas(context, {\u0027server_groups\u0027: 0},"},{"line_number":178,"context_line":"                                        context.project_id, context.user_id)"},{"line_number":179,"context_line":"        except nova.exception.OverQuota:"},{"line_number":180,"context_line":"            sg.destroy()"}],"source_content_type":"text/x-python","patch_set":14,"id":"df140735_9da7630c","line":177,"range":{"start_line":177,"start_character":67,"end_line":177,"end_character":68},"in_reply_to":"df140735_b2c936ad","updated":"2017-06-01 20:12:49.000000000","message":"The thinking here was, if we already passed the first check, things were fine and we created an object. Now we want to check, \"now that we created an object, are we over quota?\" and we do that by checking with a delta of 0. It just means, in our current state, not trying to allocate anything new, are we over quota? If we are, destroy the object and fail the request. This means no one can ever go over their quota. BUT, there\u0027s a caveat that this opens the possibility of someone getting rejected with OverQuota even if they aren\u0027t over quota, if they raced in parallel with other users in their project, all passed the first check at the same time (let\u0027s say limit is 5 for the project, current count is 3, and 3 users try to create a new object at the same time), then all fail the second check at the same time (count will be 6), and all get their object deleted and get the OverQuota exception, even though technically 2 of the users should have been able to succeed. Andrey pointed this out and I\u0027m going to add a code comment explaining that possibility.","commit_id":"216201ef03a39b5071218ad64ac0b1c8cd308bc8"},{"author":{"_account_id":6873,"name":"Matt Riedemann","email":"mriedem.os@gmail.com","username":"mriedem"},"change_message_id":"b8ed0f6a30e711aa029e9a383ef28560ab42f2dd","unresolved":false,"context_lines":[{"line_number":174,"context_line":"        # object to handle races. Delete the object if we\u0027re over"},{"line_number":175,"context_line":"        # quota after creating the object."},{"line_number":176,"context_line":"        try:"},{"line_number":177,"context_line":"            objects.Quotas.check_deltas(context, {\u0027server_groups\u0027: 0},"},{"line_number":178,"context_line":"                                        context.project_id, context.user_id)"},{"line_number":179,"context_line":"        except nova.exception.OverQuota:"},{"line_number":180,"context_line":"            sg.destroy()"}],"source_content_type":"text/x-python","patch_set":14,"id":"df140735_b257f6ca","line":177,"range":{"start_line":177,"start_character":67,"end_line":177,"end_character":68},"in_reply_to":"df140735_b2c936ad","updated":"2017-06-01 19:32:58.000000000","message":"btw, is it possible to test this out somehow?","commit_id":"216201ef03a39b5071218ad64ac0b1c8cd308bc8"},{"author":{"_account_id":6873,"name":"Matt Riedemann","email":"mriedem.os@gmail.com","username":"mriedem"},"change_message_id":"5a12d1dfb71abe82bad474ce19aee37ba8cdc43a","unresolved":false,"context_lines":[{"line_number":174,"context_line":"            raise exc.HTTPBadRequest(explanation\u003de)"},{"line_number":175,"context_line":""},{"line_number":176,"context_line":"        # NOTE(melwitt): We recheck the quota after creating the object to"},{"line_number":177,"context_line":"        # prevent allowing quota to be exceeded during a race. Please see the"},{"line_number":178,"context_line":"        # config option help for more detail."},{"line_number":179,"context_line":"        if CONF.quota.recheck_quota:"},{"line_number":180,"context_line":"            try:"},{"line_number":181,"context_line":"                objects.Quotas.check_deltas(context, {\u0027server_groups\u0027: 0},"}],"source_content_type":"text/x-python","patch_set":15,"id":"df140735_5f20084a","line":178,"range":{"start_line":177,"start_character":63,"end_line":178,"end_character":45},"updated":"2017-06-07 11:13:18.000000000","message":"I\u0027d probably remove / replace this with something like, \"This is configurable since it can be expensive if you don\u0027t care and are loose about temporarily exceeding quota or don\u0027t expect much traffic.\"","commit_id":"f0dc3eecc901b1133fa2d6747de4809deb4af4b9"},{"author":{"_account_id":6873,"name":"Matt Riedemann","email":"mriedem.os@gmail.com","username":"mriedem"},"change_message_id":"6ad606f3964094830066d6a6ff2aaf713e7eb0ac","unresolved":false,"context_lines":[{"line_number":174,"context_line":"            raise exc.HTTPBadRequest(explanation\u003de)"},{"line_number":175,"context_line":""},{"line_number":176,"context_line":"        # NOTE(melwitt): We recheck the quota after creating the object to"},{"line_number":177,"context_line":"        # prevent allowing quota to be exceeded during a race. Please see the"},{"line_number":178,"context_line":"        # config option help for more detail."},{"line_number":179,"context_line":"        if CONF.quota.recheck_quota:"},{"line_number":180,"context_line":"            try:"},{"line_number":181,"context_line":"                objects.Quotas.check_deltas(context, {\u0027server_groups\u0027: 0},"}],"source_content_type":"text/x-python","patch_set":15,"id":"df140735_88d9b6f5","line":178,"range":{"start_line":177,"start_character":63,"end_line":178,"end_character":45},"in_reply_to":"df140735_37068f22","updated":"2017-06-07 18:09:02.000000000","message":"OK, that\u0027s what I was looking for - does this fix itself or do you exceed and blow it up. We should work that information into the config option help so people can weigh that risk if they disable this.","commit_id":"f0dc3eecc901b1133fa2d6747de4809deb4af4b9"},{"author":{"_account_id":4690,"name":"melanie witt","display_name":"melwitt","email":"melwittt@gmail.com","username":"melwitt"},"change_message_id":"704100977049cb24425046e553ba9014af62e248","unresolved":false,"context_lines":[{"line_number":174,"context_line":"            raise exc.HTTPBadRequest(explanation\u003de)"},{"line_number":175,"context_line":""},{"line_number":176,"context_line":"        # NOTE(melwitt): We recheck the quota after creating the object to"},{"line_number":177,"context_line":"        # prevent allowing quota to be exceeded during a race. Please see the"},{"line_number":178,"context_line":"        # config option help for more detail."},{"line_number":179,"context_line":"        if CONF.quota.recheck_quota:"},{"line_number":180,"context_line":"            try:"},{"line_number":181,"context_line":"                objects.Quotas.check_deltas(context, {\u0027server_groups\u0027: 0},"}],"source_content_type":"text/x-python","patch_set":15,"id":"df140735_37068f22","line":178,"range":{"start_line":177,"start_character":63,"end_line":178,"end_character":45},"in_reply_to":"df140735_5f20084a","updated":"2017-06-07 17:05:31.000000000","message":"Hm, okay. I\u0027m not sure I would consider it temporarily exceeding quota since it would be exceeded as long as the user keeps the instances. And it can be exceeded by a lot, like \u003e 50, see https://bugs.launchpad.net/nova/+bug/1301532","commit_id":"f0dc3eecc901b1133fa2d6747de4809deb4af4b9"},{"author":{"_account_id":4690,"name":"melanie witt","display_name":"melwitt","email":"melwittt@gmail.com","username":"melwitt"},"change_message_id":"3750d4d19419f229f86e084e34b11a521c834fa6","unresolved":false,"context_lines":[{"line_number":174,"context_line":"            raise exc.HTTPBadRequest(explanation\u003de)"},{"line_number":175,"context_line":""},{"line_number":176,"context_line":"        # NOTE(melwitt): We recheck the quota after creating the object to"},{"line_number":177,"context_line":"        # prevent allowing quota to be exceeded during a race. Please see the"},{"line_number":178,"context_line":"        # config option help for more detail."},{"line_number":179,"context_line":"        if CONF.quota.recheck_quota:"},{"line_number":180,"context_line":"            try:"},{"line_number":181,"context_line":"                objects.Quotas.check_deltas(context, {\u0027server_groups\u0027: 0},"}],"source_content_type":"text/x-python","patch_set":15,"id":"df140735_a39c9d5d","line":178,"range":{"start_line":177,"start_character":63,"end_line":178,"end_character":45},"in_reply_to":"df140735_88d9b6f5","updated":"2017-06-07 18:35:09.000000000","message":"So do you think it\u0027s okay to say \"Please see the config option help for details\" or put more words here? I was trying to avoid too large a paragraph here because the quota race stuff isn\u0027t really simple.","commit_id":"f0dc3eecc901b1133fa2d6747de4809deb4af4b9"},{"author":{"_account_id":6873,"name":"Matt Riedemann","email":"mriedem.os@gmail.com","username":"mriedem"},"change_message_id":"5a12d1dfb71abe82bad474ce19aee37ba8cdc43a","unresolved":false,"context_lines":[{"line_number":176,"context_line":"        # NOTE(melwitt): We recheck the quota after creating the object to"},{"line_number":177,"context_line":"        # prevent allowing quota to be exceeded during a race. Please see the"},{"line_number":178,"context_line":"        # config option help for more detail."},{"line_number":179,"context_line":"        if CONF.quota.recheck_quota:"},{"line_number":180,"context_line":"            try:"},{"line_number":181,"context_line":"                objects.Quotas.check_deltas(context, {\u0027server_groups\u0027: 0},"},{"line_number":182,"context_line":"                                            context.project_id,"}],"source_content_type":"text/x-python","patch_set":15,"id":"df140735_7a2bda2f","line":179,"range":{"start_line":179,"start_character":22,"end_line":179,"end_character":35},"updated":"2017-06-07 11:13:18.000000000","message":"You don\u0027t have any unit test for when this is False to assert we don\u0027t check_deltas again.","commit_id":"f0dc3eecc901b1133fa2d6747de4809deb4af4b9"},{"author":{"_account_id":4690,"name":"melanie witt","display_name":"melwitt","email":"melwittt@gmail.com","username":"melwitt"},"change_message_id":"704100977049cb24425046e553ba9014af62e248","unresolved":false,"context_lines":[{"line_number":176,"context_line":"        # NOTE(melwitt): We recheck the quota after creating the object to"},{"line_number":177,"context_line":"        # prevent allowing quota to be exceeded during a race. Please see the"},{"line_number":178,"context_line":"        # config option help for more detail."},{"line_number":179,"context_line":"        if CONF.quota.recheck_quota:"},{"line_number":180,"context_line":"            try:"},{"line_number":181,"context_line":"                objects.Quotas.check_deltas(context, {\u0027server_groups\u0027: 0},"},{"line_number":182,"context_line":"                                            context.project_id,"}],"source_content_type":"text/x-python","patch_set":15,"id":"df140735_3218dd73","line":179,"range":{"start_line":179,"start_character":22,"end_line":179,"end_character":35},"in_reply_to":"df140735_7a2bda2f","updated":"2017-06-07 17:05:31.000000000","message":"Good point, will add.","commit_id":"f0dc3eecc901b1133fa2d6747de4809deb4af4b9"}],"nova/conf/quota.py":[{"author":{"_account_id":6873,"name":"Matt Riedemann","email":"mriedem.os@gmail.com","username":"mriedem"},"change_message_id":"5a12d1dfb71abe82bad474ce19aee37ba8cdc43a","unresolved":false,"context_lines":[{"line_number":311,"context_line":"        help\u003d\"\"\""},{"line_number":312,"context_line":"Recheck quota after resource creation to prevent allowing quota to be exceeded."},{"line_number":313,"context_line":""},{"line_number":314,"context_line":"This defaults to True (recheck quota after resource creation) but can be set to"},{"line_number":315,"context_line":"False to avoid additional load if allowing quota to be exceeded because of"},{"line_number":316,"context_line":"racing requests is considered acceptable."},{"line_number":317,"context_line":""},{"line_number":318,"context_line":"The initial quota check is done before resources are created, so if multiple"},{"line_number":319,"context_line":"parallel requests arrive at the same time, all could pass the quota check and"}],"source_content_type":"text/x-python","patch_set":15,"id":"df140735_fae12a2c","line":316,"range":{"start_line":314,"start_character":62,"end_line":316,"end_character":41},"updated":"2017-06-07 11:13:18.000000000","message":"If I were an operator (or just myself, right now), my question would be - so what happens if this is False and someone goes over quota, does the system eventually fix that, or bar them from getting more quota after the initial overage? In other words, if Bob has a quota of 10 instances but races and gets 11, will he be barred from getting 12 or is it at that point open-ended? I think people looking at this would want some indication of what the fallout could be if they set this to False and if they are willing to accept that.","commit_id":"f0dc3eecc901b1133fa2d6747de4809deb4af4b9"},{"author":{"_account_id":4690,"name":"melanie witt","display_name":"melwitt","email":"melwittt@gmail.com","username":"melwitt"},"change_message_id":"704100977049cb24425046e553ba9014af62e248","unresolved":false,"context_lines":[{"line_number":311,"context_line":"        help\u003d\"\"\""},{"line_number":312,"context_line":"Recheck quota after resource creation to prevent allowing quota to be exceeded."},{"line_number":313,"context_line":""},{"line_number":314,"context_line":"This defaults to True (recheck quota after resource creation) but can be set to"},{"line_number":315,"context_line":"False to avoid additional load if allowing quota to be exceeded because of"},{"line_number":316,"context_line":"racing requests is considered acceptable."},{"line_number":317,"context_line":""},{"line_number":318,"context_line":"The initial quota check is done before resources are created, so if multiple"},{"line_number":319,"context_line":"parallel requests arrive at the same time, all could pass the quota check and"}],"source_content_type":"text/x-python","patch_set":15,"id":"df140735_1275d998","line":316,"range":{"start_line":314,"start_character":62,"end_line":316,"end_character":41},"in_reply_to":"df140735_fae12a2c","updated":"2017-06-07 17:05:31.000000000","message":"Okay, I\u0027ll add something.","commit_id":"f0dc3eecc901b1133fa2d6747de4809deb4af4b9"},{"author":{"_account_id":6873,"name":"Matt Riedemann","email":"mriedem.os@gmail.com","username":"mriedem"},"change_message_id":"5a12d1dfb71abe82bad474ce19aee37ba8cdc43a","unresolved":false,"context_lines":[{"line_number":319,"context_line":"parallel requests arrive at the same time, all could pass the quota check and"},{"line_number":320,"context_line":"create resources, potentially exceeding quota. When recheck_quota is True,"},{"line_number":321,"context_line":"quota will be checked a second time after resources have been created and if"},{"line_number":322,"context_line":"the resource is over quota, it will be deleted and OverQuota will be raised."},{"line_number":323,"context_line":"This makes it impossible for a user to exceed their quota with the caveat that"},{"line_number":324,"context_line":"it will be possible for a user to receive OverQuota in the event of a collision"},{"line_number":325,"context_line":"close to quota limits, even if the user has enough quota available."}],"source_content_type":"text/x-python","patch_set":15,"id":"df140735_7a73dab2","line":322,"range":{"start_line":322,"start_character":47,"end_line":322,"end_character":75},"updated":"2017-06-07 11:13:18.000000000","message":"nit: I might extend this by saying:\n\n\"and OverQuota will be raised, usually resulting in a 403 response to the REST API user.\"","commit_id":"f0dc3eecc901b1133fa2d6747de4809deb4af4b9"},{"author":{"_account_id":4690,"name":"melanie witt","display_name":"melwitt","email":"melwittt@gmail.com","username":"melwitt"},"change_message_id":"704100977049cb24425046e553ba9014af62e248","unresolved":false,"context_lines":[{"line_number":319,"context_line":"parallel requests arrive at the same time, all could pass the quota check and"},{"line_number":320,"context_line":"create resources, potentially exceeding quota. When recheck_quota is True,"},{"line_number":321,"context_line":"quota will be checked a second time after resources have been created and if"},{"line_number":322,"context_line":"the resource is over quota, it will be deleted and OverQuota will be raised."},{"line_number":323,"context_line":"This makes it impossible for a user to exceed their quota with the caveat that"},{"line_number":324,"context_line":"it will be possible for a user to receive OverQuota in the event of a collision"},{"line_number":325,"context_line":"close to quota limits, even if the user has enough quota available."}],"source_content_type":"text/x-python","patch_set":15,"id":"df140735_f2794593","line":322,"range":{"start_line":322,"start_character":47,"end_line":322,"end_character":75},"in_reply_to":"df140735_7a73dab2","updated":"2017-06-07 17:05:31.000000000","message":"K, will add.","commit_id":"f0dc3eecc901b1133fa2d6747de4809deb4af4b9"},{"author":{"_account_id":6873,"name":"Matt Riedemann","email":"mriedem.os@gmail.com","username":"mriedem"},"change_message_id":"5a12d1dfb71abe82bad474ce19aee37ba8cdc43a","unresolved":false,"context_lines":[{"line_number":321,"context_line":"quota will be checked a second time after resources have been created and if"},{"line_number":322,"context_line":"the resource is over quota, it will be deleted and OverQuota will be raised."},{"line_number":323,"context_line":"This makes it impossible for a user to exceed their quota with the caveat that"},{"line_number":324,"context_line":"it will be possible for a user to receive OverQuota in the event of a collision"},{"line_number":325,"context_line":"close to quota limits, even if the user has enough quota available."},{"line_number":326,"context_line":"\"\"\"),"},{"line_number":327,"context_line":"]"}],"source_content_type":"text/x-python","patch_set":15,"id":"df140735_1ab73e3d","line":324,"range":{"start_line":324,"start_character":34,"end_line":324,"end_character":51},"updated":"2017-06-07 11:13:18.000000000","message":"s/receive OverQuota/exceed quota/?\n\nI\u0027m trying to avoid putting too much emphasis on internal exception types which really have no meaning to the operator.","commit_id":"f0dc3eecc901b1133fa2d6747de4809deb4af4b9"},{"author":{"_account_id":4690,"name":"melanie witt","display_name":"melwitt","email":"melwittt@gmail.com","username":"melwitt"},"change_message_id":"704100977049cb24425046e553ba9014af62e248","unresolved":false,"context_lines":[{"line_number":321,"context_line":"quota will be checked a second time after resources have been created and if"},{"line_number":322,"context_line":"the resource is over quota, it will be deleted and OverQuota will be raised."},{"line_number":323,"context_line":"This makes it impossible for a user to exceed their quota with the caveat that"},{"line_number":324,"context_line":"it will be possible for a user to receive OverQuota in the event of a collision"},{"line_number":325,"context_line":"close to quota limits, even if the user has enough quota available."},{"line_number":326,"context_line":"\"\"\"),"},{"line_number":327,"context_line":"]"}],"source_content_type":"text/x-python","patch_set":15,"id":"df140735_726535e1","line":324,"range":{"start_line":324,"start_character":34,"end_line":324,"end_character":51},"in_reply_to":"df140735_1ab73e3d","updated":"2017-06-07 17:05:31.000000000","message":"Yeah, I was trying to put emphasis on the fact that their request will be rejected, so maybe replace OverQuota with 403 or some other words indicating that if they collide, they might be rejected when they actually have enough quota.","commit_id":"f0dc3eecc901b1133fa2d6747de4809deb4af4b9"}],"nova/quota.py":[{"author":{"_account_id":21813,"name":"Andrey Volkov","email":"m@amadev.ru","username":"avolkov"},"change_message_id":"044c11f81f7bd191f3588a7cc8ca2b16dde20504","unresolved":false,"context_lines":[{"line_number":1869,"context_line":"                 \u0027user\u0027: {\u0027server_groups\u0027: \u003ccount across user\u003e}}"},{"line_number":1870,"context_line":"    \"\"\""},{"line_number":1871,"context_line":"    return objects.InstanceGroupList.get_counts(context, project_id,"},{"line_number":1872,"context_line":"                                                user_id\u003duser_id)"},{"line_number":1873,"context_line":""},{"line_number":1874,"context_line":""},{"line_number":1875,"context_line":"def _security_group_rule_count_by_group(context, security_group_id):"}],"source_content_type":"text/x-python","patch_set":13,"id":"df140735_f40591c3","line":1872,"updated":"2017-05-31 10:55:09.000000000","message":"There are no indexes for project_id and user_id in instance_groups. Do you think it should be addressed in a follow-up patch?","commit_id":"20e015abfe5adcd8fb45f2960cf017589e0ff170"},{"author":{"_account_id":4690,"name":"melanie witt","display_name":"melwitt","email":"melwittt@gmail.com","username":"melwitt"},"change_message_id":"bc8e1f3d218c515a504abe0ee784e35857001c5a","unresolved":false,"context_lines":[{"line_number":1869,"context_line":"                 \u0027user\u0027: {\u0027server_groups\u0027: \u003ccount across user\u003e}}"},{"line_number":1870,"context_line":"    \"\"\""},{"line_number":1871,"context_line":"    return objects.InstanceGroupList.get_counts(context, project_id,"},{"line_number":1872,"context_line":"                                                user_id\u003duser_id)"},{"line_number":1873,"context_line":""},{"line_number":1874,"context_line":""},{"line_number":1875,"context_line":"def _security_group_rule_count_by_group(context, security_group_id):"}],"source_content_type":"text/x-python","patch_set":13,"id":"df140735_b232565d","line":1872,"in_reply_to":"df140735_f40591c3","updated":"2017-06-01 19:45:54.000000000","message":"Hm, I would think that would be out of scope for this patch, but it\u0027s something to consider. That is, I have a feeling several of the tables involved in this series aren\u0027t going to have indexes for project_id and user_id and we can look at adding migrations to add them.","commit_id":"20e015abfe5adcd8fb45f2960cf017589e0ff170"},{"author":{"_account_id":6873,"name":"Matt Riedemann","email":"mriedem.os@gmail.com","username":"mriedem"},"change_message_id":"d9c811c31cb7531c833b648dace01010da9730f8","unresolved":false,"context_lines":[{"line_number":1887,"context_line":"                      _security_group_rule_count_by_group,"},{"line_number":1888,"context_line":"                      \u0027security_group_rules\u0027),"},{"line_number":1889,"context_line":"    CountableResource(\u0027key_pairs\u0027, _keypair_get_count_by_user, \u0027key_pairs\u0027),"},{"line_number":1890,"context_line":"    ReservableResource(\u0027server_groups\u0027, \u0027_sync_server_groups\u0027,"},{"line_number":1891,"context_line":"                      \u0027server_groups\u0027),"},{"line_number":1892,"context_line":"    CountableResource(\u0027server_group_members\u0027,"},{"line_number":1893,"context_line":"                      _server_group_count_members_by_user,"}],"source_content_type":"text/x-python","patch_set":14,"id":"df140735_1217c247","side":"PARENT","line":1890,"range":{"start_line":1890,"start_character":41,"end_line":1890,"end_character":60},"updated":"2017-06-01 19:31:08.000000000","message":"I suppose we can deprecate _sync_server_groups at some point.","commit_id":"240cd92885c6dad194af0232f5afafcd3a61182e"},{"author":{"_account_id":4690,"name":"melanie witt","display_name":"melwitt","email":"melwittt@gmail.com","username":"melwitt"},"change_message_id":"85d080b9824710aab75a11b7e27d168a84745334","unresolved":false,"context_lines":[{"line_number":1887,"context_line":"                      _security_group_rule_count_by_group,"},{"line_number":1888,"context_line":"                      \u0027security_group_rules\u0027),"},{"line_number":1889,"context_line":"    CountableResource(\u0027key_pairs\u0027, _keypair_get_count_by_user, \u0027key_pairs\u0027),"},{"line_number":1890,"context_line":"    ReservableResource(\u0027server_groups\u0027, \u0027_sync_server_groups\u0027,"},{"line_number":1891,"context_line":"                      \u0027server_groups\u0027),"},{"line_number":1892,"context_line":"    CountableResource(\u0027server_group_members\u0027,"},{"line_number":1893,"context_line":"                      _server_group_count_members_by_user,"}],"source_content_type":"text/x-python","patch_set":14,"id":"df140735_9d2ac329","side":"PARENT","line":1890,"range":{"start_line":1890,"start_character":41,"end_line":1890,"end_character":60},"in_reply_to":"df140735_1217c247","updated":"2017-06-01 20:12:49.000000000","message":"Yeah. There will be various things unused in nova/db/sqlalchemy/api.py after all of this.","commit_id":"240cd92885c6dad194af0232f5afafcd3a61182e"}],"releasenotes/notes/recheck-quota-conf-043a5d6057b33282.yaml":[{"author":{"_account_id":6873,"name":"Matt Riedemann","email":"mriedem.os@gmail.com","username":"mriedem"},"change_message_id":"5a12d1dfb71abe82bad474ce19aee37ba8cdc43a","unresolved":false,"context_lines":[{"line_number":4,"context_line":"    recheck quota after resource creation to prevent allowing quota to be"},{"line_number":5,"context_line":"    exceeded as a result of racing requests. It defaults to True, which makes"},{"line_number":6,"context_line":"    it impossible for a user to exceed their quota with the caveat that it will"},{"line_number":7,"context_line":"    be possible for a user to be rejected with OverQuota in the event of a"},{"line_number":8,"context_line":"    collision close to quota limits, even if the user has enough quota"},{"line_number":9,"context_line":"    available. Operators may want to set the option to False to avoid"},{"line_number":10,"context_line":"    additional load on the system if allowing quota to be exceeded because of"}],"source_content_type":"text/x-yaml","patch_set":15,"id":"df140735_faba4a08","line":7,"range":{"start_line":7,"start_character":47,"end_line":7,"end_character":56},"updated":"2017-06-07 11:13:18.000000000","message":"I\u0027d try to work in \"resulting in a 403 error response to the REST API user\" here.","commit_id":"f0dc3eecc901b1133fa2d6747de4809deb4af4b9"},{"author":{"_account_id":4690,"name":"melanie witt","display_name":"melwitt","email":"melwittt@gmail.com","username":"melwitt"},"change_message_id":"704100977049cb24425046e553ba9014af62e248","unresolved":false,"context_lines":[{"line_number":4,"context_line":"    recheck quota after resource creation to prevent allowing quota to be"},{"line_number":5,"context_line":"    exceeded as a result of racing requests. It defaults to True, which makes"},{"line_number":6,"context_line":"    it impossible for a user to exceed their quota with the caveat that it will"},{"line_number":7,"context_line":"    be possible for a user to be rejected with OverQuota in the event of a"},{"line_number":8,"context_line":"    collision close to quota limits, even if the user has enough quota"},{"line_number":9,"context_line":"    available. Operators may want to set the option to False to avoid"},{"line_number":10,"context_line":"    additional load on the system if allowing quota to be exceeded because of"}],"source_content_type":"text/x-yaml","patch_set":15,"id":"df140735_325fbd0f","line":7,"range":{"start_line":7,"start_character":47,"end_line":7,"end_character":56},"in_reply_to":"df140735_faba4a08","updated":"2017-06-07 17:05:31.000000000","message":"K","commit_id":"f0dc3eecc901b1133fa2d6747de4809deb4af4b9"},{"author":{"_account_id":6873,"name":"Matt Riedemann","email":"mriedem.os@gmail.com","username":"mriedem"},"change_message_id":"5a12d1dfb71abe82bad474ce19aee37ba8cdc43a","unresolved":false,"context_lines":[{"line_number":2,"context_line":"  - |"},{"line_number":3,"context_line":"    A new configuration option ``[quota]/recheck_quota`` has been added to"},{"line_number":4,"context_line":"    recheck quota after resource creation to prevent allowing quota to be"},{"line_number":5,"context_line":"    exceeded as a result of racing requests. It defaults to True, which makes"},{"line_number":6,"context_line":"    it impossible for a user to exceed their quota with the caveat that it will"},{"line_number":7,"context_line":"    be possible for a user to be rejected with OverQuota in the event of a"},{"line_number":8,"context_line":"    collision close to quota limits, even if the user has enough quota"},{"line_number":9,"context_line":"    available. Operators may want to set the option to False to avoid"},{"line_number":10,"context_line":"    additional load on the system if allowing quota to be exceeded because of"},{"line_number":11,"context_line":"    racing requests is considered acceptable."}],"source_content_type":"text/x-yaml","patch_set":15,"id":"df140735_ba0852d9","line":9,"range":{"start_line":5,"start_character":45,"end_line":9,"end_character":14},"updated":"2017-06-07 11:13:18.000000000","message":"This single sentence is a bit hard to read, could we break it into two sentences? Maybe something like:\n\n\"It defaults to True, which makes it impossible for a user to exceed their quota. However, it will be possible for a user to be rejected with an over quota error resulting in a 403 response in the event of a collision close to reaching their quota limit, even if the user has enough quota available when they made the request.\"","commit_id":"f0dc3eecc901b1133fa2d6747de4809deb4af4b9"},{"author":{"_account_id":4690,"name":"melanie witt","display_name":"melwitt","email":"melwittt@gmail.com","username":"melwitt"},"change_message_id":"704100977049cb24425046e553ba9014af62e248","unresolved":false,"context_lines":[{"line_number":2,"context_line":"  - |"},{"line_number":3,"context_line":"    A new configuration option ``[quota]/recheck_quota`` has been added to"},{"line_number":4,"context_line":"    recheck quota after resource creation to prevent allowing quota to be"},{"line_number":5,"context_line":"    exceeded as a result of racing requests. It defaults to True, which makes"},{"line_number":6,"context_line":"    it impossible for a user to exceed their quota with the caveat that it will"},{"line_number":7,"context_line":"    be possible for a user to be rejected with OverQuota in the event of a"},{"line_number":8,"context_line":"    collision close to quota limits, even if the user has enough quota"},{"line_number":9,"context_line":"    available. Operators may want to set the option to False to avoid"},{"line_number":10,"context_line":"    additional load on the system if allowing quota to be exceeded because of"},{"line_number":11,"context_line":"    racing requests is considered acceptable."}],"source_content_type":"text/x-yaml","patch_set":15,"id":"df140735_d2a3e1ff","line":9,"range":{"start_line":5,"start_character":45,"end_line":9,"end_character":14},"in_reply_to":"df140735_ba0852d9","updated":"2017-06-07 17:05:31.000000000","message":"Sure","commit_id":"f0dc3eecc901b1133fa2d6747de4809deb4af4b9"}]}
