)]}'
{"oslo_limit/limit.py":[{"author":{"_account_id":5046,"name":"Lance Bragstad","email":"lbragstad@redhat.com","username":"ldbragst"},"change_message_id":"e4becc459fe76cd6b4c9c12dec609de7dce48ccf","unresolved":false,"context_lines":[{"line_number":131,"context_line":"    return _SDK_CONNECTION"},{"line_number":132,"context_line":""},{"line_number":133,"context_line":""},{"line_number":134,"context_line":"class _EnforcerUtils(object):"},{"line_number":135,"context_line":"    def __init__(self, keystone_connection):"},{"line_number":136,"context_line":"        self.connection \u003d keystone_connection"},{"line_number":137,"context_line":""}],"source_content_type":"text/x-python","patch_set":4,"id":"3fa7e38b_24d57543","line":134,"updated":"2019-11-22 14:06:20.000000000","message":"Is there a reason to not have these methods available in the Enforcer object?","commit_id":"921c448389cb2e844fb34abd8db7f7a984ca3fa8"},{"author":{"_account_id":782,"name":"John Garbutt","email":"john@johngarbutt.com","username":"johngarbutt"},"change_message_id":"056a08d900b54e1fcac261a53b295f2c95dc651c","unresolved":false,"context_lines":[{"line_number":131,"context_line":"    return _SDK_CONNECTION"},{"line_number":132,"context_line":""},{"line_number":133,"context_line":""},{"line_number":134,"context_line":"class _EnforcerUtils(object):"},{"line_number":135,"context_line":"    def __init__(self, keystone_connection):"},{"line_number":136,"context_line":"        self.connection \u003d keystone_connection"},{"line_number":137,"context_line":""}],"source_content_type":"text/x-python","patch_set":4,"id":"3fa7e38b_84730980","line":134,"in_reply_to":"3fa7e38b_24d57543","updated":"2019-11-22 14:47:09.000000000","message":"I just like to avoid inheritence, unless its really needed.","commit_id":"921c448389cb2e844fb34abd8db7f7a984ca3fa8"},{"author":{"_account_id":6928,"name":"Ben Nemec","email":"openstack@nemebean.com","username":"bnemec"},"change_message_id":"3e2145dbbdd5cd7ac8bd6ed8b8892233fdd39438","unresolved":false,"context_lines":[{"line_number":108,"context_line":"                       Specify a quantity of zero to check current usage."},{"line_number":109,"context_line":"        :type deltas: dictionary"},{"line_number":110,"context_line":""},{"line_number":111,"context_line":"        :raises exception.ClaimExceedsLimit"},{"line_number":112,"context_line":"        \"\"\""},{"line_number":113,"context_line":"        if not project_id or not isinstance(project_id, six.string_types):"},{"line_number":114,"context_line":"            msg \u003d \u0027project_id must be a non-empty string.\u0027"}],"source_content_type":"text/x-python","patch_set":5,"id":"3fa7e38b_1418a073","line":111,"updated":"2019-11-22 20:50:51.000000000","message":"Nit: Missing trailing :","commit_id":"dd70d1a331efcbc0eaf44134739d0ace8fa94b50"},{"author":{"_account_id":6928,"name":"Ben Nemec","email":"openstack@nemebean.com","username":"bnemec"},"change_message_id":"3e2145dbbdd5cd7ac8bd6ed8b8892233fdd39438","unresolved":false,"context_lines":[{"line_number":135,"context_line":"        self._utils \u003d _EnforcerUtils()"},{"line_number":136,"context_line":""},{"line_number":137,"context_line":"    def enforce(self, project_id, deltas):"},{"line_number":138,"context_line":"        resources_to_check \u003d list([name for name, value in deltas.items()])"},{"line_number":139,"context_line":"        # Always check the limits in the same order, for predictable errors"},{"line_number":140,"context_line":"        resources_to_check.sort()"},{"line_number":141,"context_line":""}],"source_content_type":"text/x-python","patch_set":5,"id":"3fa7e38b_94525011","line":138,"range":{"start_line":138,"start_character":29,"end_line":138,"end_character":75},"updated":"2019-11-22 20:50:51.000000000","message":"Isn\u0027t this just deltas.keys()?","commit_id":"dd70d1a331efcbc0eaf44134739d0ace8fa94b50"},{"author":{"_account_id":782,"name":"John Garbutt","email":"john@johngarbutt.com","username":"johngarbutt"},"change_message_id":"8c286b411d8d596bffcb0b84bc27bb916b4db9c2","unresolved":false,"context_lines":[{"line_number":135,"context_line":"        self._utils \u003d _EnforcerUtils()"},{"line_number":136,"context_line":""},{"line_number":137,"context_line":"    def enforce(self, project_id, deltas):"},{"line_number":138,"context_line":"        resources_to_check \u003d list([name for name, value in deltas.items()])"},{"line_number":139,"context_line":"        # Always check the limits in the same order, for predictable errors"},{"line_number":140,"context_line":"        resources_to_check.sort()"},{"line_number":141,"context_line":""}],"source_content_type":"text/x-python","patch_set":5,"id":"3fa7e38b_31036344","line":138,"range":{"start_line":138,"start_character":29,"end_line":138,"end_character":75},"in_reply_to":"3fa7e38b_94525011","updated":"2019-11-25 10:21:02.000000000","message":"heh, yes. thank you.","commit_id":"dd70d1a331efcbc0eaf44134739d0ace8fa94b50"},{"author":{"_account_id":6928,"name":"Ben Nemec","email":"openstack@nemebean.com","username":"bnemec"},"change_message_id":"3e2145dbbdd5cd7ac8bd6ed8b8892233fdd39438","unresolved":false,"context_lines":[{"line_number":182,"context_line":"        :param current_usage: dict of resource name and current usage"},{"line_number":183,"context_line":"        :param deltas: dict of resource name and proposed additional usage"},{"line_number":184,"context_line":""},{"line_number":185,"context_line":"        :raises exception.ClaimExceedsLimit if no limit is found"},{"line_number":186,"context_line":"        \"\"\""},{"line_number":187,"context_line":"        overs \u003d []"},{"line_number":188,"context_line":"        for resource_name, limit in limits:"}],"source_content_type":"text/x-python","patch_set":5,"id":"3fa7e38b_346efc63","line":185,"range":{"start_line":185,"start_character":44,"end_line":185,"end_character":64},"updated":"2019-11-22 20:50:51.000000000","message":"I think by the time we get here the limit has already been found, right?\n\nAlso missing the trailing :.","commit_id":"dd70d1a331efcbc0eaf44134739d0ace8fa94b50"},{"author":{"_account_id":782,"name":"John Garbutt","email":"john@johngarbutt.com","username":"johngarbutt"},"change_message_id":"8c286b411d8d596bffcb0b84bc27bb916b4db9c2","unresolved":false,"context_lines":[{"line_number":182,"context_line":"        :param current_usage: dict of resource name and current usage"},{"line_number":183,"context_line":"        :param deltas: dict of resource name and proposed additional usage"},{"line_number":184,"context_line":""},{"line_number":185,"context_line":"        :raises exception.ClaimExceedsLimit if no limit is found"},{"line_number":186,"context_line":"        \"\"\""},{"line_number":187,"context_line":"        overs \u003d []"},{"line_number":188,"context_line":"        for resource_name, limit in limits:"}],"source_content_type":"text/x-python","patch_set":5,"id":"3fa7e38b_51713fdd","line":185,"range":{"start_line":185,"start_character":44,"end_line":185,"end_character":64},"in_reply_to":"3fa7e38b_346efc63","updated":"2019-11-25 10:21:02.000000000","message":"oops, yes.","commit_id":"dd70d1a331efcbc0eaf44134739d0ace8fa94b50"},{"author":{"_account_id":6928,"name":"Ben Nemec","email":"openstack@nemebean.com","username":"bnemec"},"change_message_id":"3e2145dbbdd5cd7ac8bd6ed8b8892233fdd39438","unresolved":false,"context_lines":[{"line_number":198,"context_line":""},{"line_number":199,"context_line":"        if len(overs) \u003e 0:"},{"line_number":200,"context_line":"            LOG.debug(\"hit limits for project %s\", overs)"},{"line_number":201,"context_line":"            usage, delta, limit, resource \u003d overs[0]"},{"line_number":202,"context_line":"            raise exception.ClaimExceedsLimit(usage, delta, limit, resource)"},{"line_number":203,"context_line":""},{"line_number":204,"context_line":"    def get_project_limits(self, project_id, resource_names):"}],"source_content_type":"text/x-python","patch_set":5,"id":"3fa7e38b_14c5005c","line":201,"updated":"2019-11-22 20:50:51.000000000","message":"Is there no reasonable way we could include all of the over-limit resources in the exception? That\u0027s the thing the user will see, right? The way this works now the only way for them to find out all of the exceeded limits (as opposed to just the first) would be to have access to the service debug logs.\n\nIf I need to go request more quota it would be nice to know all of the quotas that need to be changed at once, rather than playing whack-a-mole or trying to calculate it manually.","commit_id":"dd70d1a331efcbc0eaf44134739d0ace8fa94b50"},{"author":{"_account_id":782,"name":"John Garbutt","email":"john@johngarbutt.com","username":"johngarbutt"},"change_message_id":"8c286b411d8d596bffcb0b84bc27bb916b4db9c2","unresolved":false,"context_lines":[{"line_number":198,"context_line":""},{"line_number":199,"context_line":"        if len(overs) \u003e 0:"},{"line_number":200,"context_line":"            LOG.debug(\"hit limits for project %s\", overs)"},{"line_number":201,"context_line":"            usage, delta, limit, resource \u003d overs[0]"},{"line_number":202,"context_line":"            raise exception.ClaimExceedsLimit(usage, delta, limit, resource)"},{"line_number":203,"context_line":""},{"line_number":204,"context_line":"    def get_project_limits(self, project_id, resource_names):"}],"source_content_type":"text/x-python","patch_set":5,"id":"3fa7e38b_118987c5","line":201,"in_reply_to":"3fa7e38b_14c5005c","updated":"2019-11-25 10:21:02.000000000","message":"I had the same thoughts, I will have a look","commit_id":"dd70d1a331efcbc0eaf44134739d0ace8fa94b50"},{"author":{"_account_id":6928,"name":"Ben Nemec","email":"openstack@nemebean.com","username":"bnemec"},"change_message_id":"3e2145dbbdd5cd7ac8bd6ed8b8892233fdd39438","unresolved":false,"context_lines":[{"line_number":209,"context_line":"        :param resource_names: list of resource_name strings"},{"line_number":210,"context_line":"        :return: list of (resource_name,limit) pairs"},{"line_number":211,"context_line":""},{"line_number":212,"context_line":"        :raises exception.ClaimExceedsLimit if no limit is found"},{"line_number":213,"context_line":"        \"\"\""},{"line_number":214,"context_line":"        # Using a list to preserver the resource_name order"},{"line_number":215,"context_line":"        project_limits \u003d []"}],"source_content_type":"text/x-python","patch_set":5,"id":"3fa7e38b_b4fe6c67","line":212,"range":{"start_line":212,"start_character":26,"end_line":212,"end_character":43},"updated":"2019-11-22 20:50:51.000000000","message":"Seems like LimitNotFound was a more specific exception, but I suppose this means consumers have to watch for only one exception class instead of two.","commit_id":"dd70d1a331efcbc0eaf44134739d0ace8fa94b50"},{"author":{"_account_id":782,"name":"John Garbutt","email":"john@johngarbutt.com","username":"johngarbutt"},"change_message_id":"8c286b411d8d596bffcb0b84bc27bb916b4db9c2","unresolved":false,"context_lines":[{"line_number":209,"context_line":"        :param resource_names: list of resource_name strings"},{"line_number":210,"context_line":"        :return: list of (resource_name,limit) pairs"},{"line_number":211,"context_line":""},{"line_number":212,"context_line":"        :raises exception.ClaimExceedsLimit if no limit is found"},{"line_number":213,"context_line":"        \"\"\""},{"line_number":214,"context_line":"        # Using a list to preserver the resource_name order"},{"line_number":215,"context_line":"        project_limits \u003d []"}],"source_content_type":"text/x-python","patch_set":5,"id":"3fa7e38b_d1652f1e","line":212,"range":{"start_line":212,"start_character":26,"end_line":212,"end_character":43},"in_reply_to":"3fa7e38b_b4fe6c67","updated":"2019-11-25 10:21:02.000000000","message":"yeah, its about ensuring the client doesn\u0027t need to decide what to do for that exception, we make sure the always \"do the right thing\", or at least, always do the same thing.","commit_id":"dd70d1a331efcbc0eaf44134739d0ace8fa94b50"},{"author":{"_account_id":4690,"name":"melanie witt","display_name":"melwitt","email":"melwittt@gmail.com","username":"melwitt"},"change_message_id":"33451e5d42ac86869131a6cbf65809851c8fe2dc","unresolved":false,"context_lines":[{"line_number":228,"context_line":"        missing_limits \u003d []"},{"line_number":229,"context_line":"        for resource_name in resource_names:"},{"line_number":230,"context_line":"            try:"},{"line_number":231,"context_line":"                limit \u003d self._get_limit(project_id, resource_name)"},{"line_number":232,"context_line":"                project_limits.append((resource_name, limit))"},{"line_number":233,"context_line":"            except _LimitNotFound:"},{"line_number":234,"context_line":"                missing_limits.append(resource_name)"}],"source_content_type":"text/x-python","patch_set":9,"id":"3fa7e38b_a27115ae","line":231,"updated":"2019-11-27 19:35:27.000000000","message":"Is it possible to get all limits for a project in a single REST call? If so, I think we should just grab all limits for a project one time. If not, I think it would be worth parallelizing this call. There will easily be 2+ limits involved in a single server create request, for example (VCPU, MEMORY_MB, VGPU or CUSTOM_RESOURCE_CLASS_A or PCPU or DISK_GB etc).","commit_id":"40ef2764a5b8483103ce4d7b8d390b4e5d643d79"},{"author":{"_account_id":6928,"name":"Ben Nemec","email":"openstack@nemebean.com","username":"bnemec"},"change_message_id":"2264ba7972a31ab6c2f5bdd6e0871daa80a46aec","unresolved":false,"context_lines":[{"line_number":228,"context_line":"        missing_limits \u003d []"},{"line_number":229,"context_line":"        for resource_name in resource_names:"},{"line_number":230,"context_line":"            try:"},{"line_number":231,"context_line":"                limit \u003d self._get_limit(project_id, resource_name)"},{"line_number":232,"context_line":"                project_limits.append((resource_name, limit))"},{"line_number":233,"context_line":"            except _LimitNotFound:"},{"line_number":234,"context_line":"                missing_limits.append(resource_name)"}],"source_content_type":"text/x-python","patch_set":9,"id":"3fa7e38b_c2d3f136","line":231,"in_reply_to":"3fa7e38b_a23275bf","updated":"2019-11-27 19:56:45.000000000","message":"There\u0027s some related discussion in https://review.opendev.org/#/c/695724/3/oslo_limit/limit.py\n\nIt\u0027s likely some optimization is in order here, but as it shouldn\u0027t affect the public API I\u0027m inclined to go with this as an initial implementation and make it more efficient as a followup if/when we verify that the API does what is needed.","commit_id":"40ef2764a5b8483103ce4d7b8d390b4e5d643d79"},{"author":{"_account_id":4690,"name":"melanie witt","display_name":"melwitt","email":"melwittt@gmail.com","username":"melwitt"},"change_message_id":"1998a15abb13f13d8c4277069ad6a02d79c1c264","unresolved":false,"context_lines":[{"line_number":228,"context_line":"        missing_limits \u003d []"},{"line_number":229,"context_line":"        for resource_name in resource_names:"},{"line_number":230,"context_line":"            try:"},{"line_number":231,"context_line":"                limit \u003d self._get_limit(project_id, resource_name)"},{"line_number":232,"context_line":"                project_limits.append((resource_name, limit))"},{"line_number":233,"context_line":"            except _LimitNotFound:"},{"line_number":234,"context_line":"                missing_limits.append(resource_name)"}],"source_content_type":"text/x-python","patch_set":9,"id":"3fa7e38b_a23275bf","line":231,"in_reply_to":"3fa7e38b_a27115ae","updated":"2019-11-27 19:44:18.000000000","message":"To be clear, in the former case (grab all limits for a project in one call) I meant, grab them all and then filter client-side by resource_names to enforce only the relevant limits. Similar to how we call placement for usages -- we do one call that grabs all usages for a project or project user and then access each resource class inside the response client-side.","commit_id":"40ef2764a5b8483103ce4d7b8d390b4e5d643d79"}],"oslo_limit/tests/test_limit.py":[{"author":{"_account_id":6928,"name":"Ben Nemec","email":"openstack@nemebean.com","username":"bnemec"},"change_message_id":"2264ba7972a31ab6c2f5bdd6e0871daa80a46aec","unresolved":false,"context_lines":[{"line_number":235,"context_line":"        self.mock_conn.limits.side_effect \u003d [a_iterator, empty_iterator,"},{"line_number":236,"context_line":"                                             empty_iterator, empty_iterator]"},{"line_number":237,"context_line":""},{"line_number":238,"context_line":"        # b has a limit, but c and d doesn\u0027t, a isn\u0027t ever checked"},{"line_number":239,"context_line":"        b \u003d registered_limit.RegisteredLimit()"},{"line_number":240,"context_line":"        b.resource_name \u003d \"b\""},{"line_number":241,"context_line":"        b.default_limit \u003d 2"}],"source_content_type":"text/x-python","patch_set":9,"id":"3fa7e38b_02c26954","line":238,"range":{"start_line":238,"start_character":37,"end_line":238,"end_character":44},"updated":"2019-11-27 19:56:45.000000000","message":"Femto-nit: *don\u0027t","commit_id":"40ef2764a5b8483103ce4d7b8d390b4e5d643d79"}]}
