)]}'
{"/COMMIT_MSG":[{"author":{"_account_id":26936,"name":"Surya Seetharaman","email":"suryaseetharaman.9@gmail.com","username":"tssurya"},"change_message_id":"50ad5910071deea114038b6f11d26942c1a49b50","unresolved":false,"context_lines":[{"line_number":6,"context_line":""},{"line_number":7,"context_line":"Add get_usages_counts_for_quota to SchedulerReportClient"},{"line_number":8,"context_line":""},{"line_number":9,"context_line":"This adds a method for requesting /usages from placement for the"},{"line_number":10,"context_line":"purpose of counting quota usage for cores and ram. It is used in the"},{"line_number":11,"context_line":"next patch in the series."},{"line_number":12,"context_line":""}],"source_content_type":"text/x-gerrit-commit-message","patch_set":3,"id":"dfbec78f_c45b42f3","line":9,"range":{"start_line":9,"start_character":34,"end_line":9,"end_character":35},"updated":"2019-05-16 12:29:07.000000000","message":"nit: nix (I guess this is for ``GET /usages`` api?)","commit_id":"54408d0ce4a74395cd585d5f24b0c143b8618623"},{"author":{"_account_id":4690,"name":"melanie witt","display_name":"melwitt","email":"melwittt@gmail.com","username":"melwitt"},"change_message_id":"d4ef8f4018758f87b8a6a11bca8aa8767060c570","unresolved":false,"context_lines":[{"line_number":6,"context_line":""},{"line_number":7,"context_line":"Add get_usages_counts_for_quota to SchedulerReportClient"},{"line_number":8,"context_line":""},{"line_number":9,"context_line":"This adds a method for requesting /usages from placement for the"},{"line_number":10,"context_line":"purpose of counting quota usage for cores and ram. It is used in the"},{"line_number":11,"context_line":"next patch in the series."},{"line_number":12,"context_line":""}],"source_content_type":"text/x-gerrit-commit-message","patch_set":3,"id":"bfb3d3c7_e0cb466f","line":9,"range":{"start_line":9,"start_character":34,"end_line":9,"end_character":35},"in_reply_to":"dfbec78f_c45b42f3","updated":"2019-05-22 23:12:28.000000000","message":"Yeah, would have been more clear if I had GET here.","commit_id":"54408d0ce4a74395cd585d5f24b0c143b8618623"}],"nova/scheduler/client/report.py":[{"author":{"_account_id":4690,"name":"melanie witt","display_name":"melwitt","email":"melwittt@gmail.com","username":"melwitt"},"change_message_id":"0216d57c61e262857706fbadfb767429f51b4b89","unresolved":false,"context_lines":[{"line_number":2353,"context_line":"                                 \u0027ram\u0027: \u003ccount across project\u003e},"},{"line_number":2354,"context_line":"                    {\u0027user\u0027: {\u0027cores\u0027: \u003ccount across user\u003e,"},{"line_number":2355,"context_line":"                              \u0027ram\u0027: \u003ccount across user\u003e},"},{"line_number":2356,"context_line":"        :raises: `exception.UsagesRetrievalFailed` if a placement API call fails"},{"line_number":2357,"context_line":"        \"\"\""},{"line_number":2358,"context_line":"        total_counts \u003d {\u0027project\u0027: {}}"},{"line_number":2359,"context_line":"        # First query counts across all users of a project"}],"source_content_type":"text/x-python","patch_set":1,"id":"3fce034c_23d4f51f","line":2356,"range":{"start_line":2356,"start_character":75,"end_line":2356,"end_character":80},"updated":"2019-04-17 01:37:38.000000000","message":"\u0027tox -efast8\u0027 bit me here. I must have missed running it on this particular patch.","commit_id":"4ff50e6d24e629a194320938022b38c8b8da8e0d"},{"author":{"_account_id":6873,"name":"Matt Riedemann","email":"mriedem.os@gmail.com","username":"mriedem"},"change_message_id":"f50077dd6dc79580a9ccb5f82239466a89b4f65d","unresolved":false,"context_lines":[{"line_number":2329,"context_line":"                \u0027err_text\u0027: resp.text}"},{"line_number":2330,"context_line":"        LOG.error(msg, args)"},{"line_number":2331,"context_line":"        raise exception.UsagesRetrievalFailed(project_id\u003dproject_id,"},{"line_number":2332,"context_line":"                                              user_id\u003duser_id or \u0027N/A\u0027)"},{"line_number":2333,"context_line":""},{"line_number":2334,"context_line":"    @retrying.retry(stop_max_attempt_number\u003d4,"},{"line_number":2335,"context_line":"                    retry_on_exception\u003dlambda e: isinstance("}],"source_content_type":"text/x-python","patch_set":2,"id":"3fce034c_834fbe32","line":2332,"range":{"start_line":2332,"start_character":54,"end_line":2332,"end_character":70},"updated":"2019-04-18 18:22:51.000000000","message":"nit: could make user_id a kwarg defaulting to None so this is a bit more obvious why we need the \"or \u0027N/A\u0027\".","commit_id":"ff0582bb802ab468953ac325d0a3fd1ecc48dcdf"},{"author":{"_account_id":6873,"name":"Matt Riedemann","email":"mriedem.os@gmail.com","username":"mriedem"},"change_message_id":"f50077dd6dc79580a9ccb5f82239466a89b4f65d","unresolved":false,"context_lines":[{"line_number":2333,"context_line":""},{"line_number":2334,"context_line":"    @retrying.retry(stop_max_attempt_number\u003d4,"},{"line_number":2335,"context_line":"                    retry_on_exception\u003dlambda e: isinstance("},{"line_number":2336,"context_line":"                        e, ks_exc.ConnectFailure))"},{"line_number":2337,"context_line":"    def _get_usages(self, context, project_id, user_id\u003dNone):"},{"line_number":2338,"context_line":"        url \u003d \u0027/usages?project_id\u003d%s\u0027 % project_id"},{"line_number":2339,"context_line":"        if user_id:"}],"source_content_type":"text/x-python","patch_set":2,"id":"3fce034c_430c76ec","line":2336,"range":{"start_line":2336,"start_character":34,"end_line":2336,"end_character":48},"updated":"2019-04-18 18:22:51.000000000","message":"Looking at the @safe_connect decorator I see this is the only non-config related case that we deal with there so seems OK. Other uses of retrying.retry in here are handling specific nova exceptions so I was wondering about this one.","commit_id":"ff0582bb802ab468953ac325d0a3fd1ecc48dcdf"},{"author":{"_account_id":782,"name":"John Garbutt","email":"john@johngarbutt.com","username":"johngarbutt"},"change_message_id":"3b87add7910b6c2407c96cee523404ca938ce9fb","unresolved":false,"context_lines":[{"line_number":2341,"context_line":"        return self.get(url, version\u003dGET_USAGES_VERSION,"},{"line_number":2342,"context_line":"                        global_request_id\u003dcontext.global_id)"},{"line_number":2343,"context_line":""},{"line_number":2344,"context_line":"    def get_usages_counts_for_quota(self, context, project_id, user_id\u003dNone):"},{"line_number":2345,"context_line":"        \"\"\"Get the usages counts for the purpose of counting quota usage."},{"line_number":2346,"context_line":""},{"line_number":2347,"context_line":"        :param context: The request context"}],"source_content_type":"text/x-python","patch_set":2,"id":"3fce034c_e85ea874","line":2344,"updated":"2019-04-18 12:28:45.000000000","message":"Part of me wonders if we should pass in a list of resources... but that should be for another day.","commit_id":"ff0582bb802ab468953ac325d0a3fd1ecc48dcdf"},{"author":{"_account_id":6873,"name":"Matt Riedemann","email":"mriedem.os@gmail.com","username":"mriedem"},"change_message_id":"f50077dd6dc79580a9ccb5f82239466a89b4f65d","unresolved":false,"context_lines":[{"line_number":2359,"context_line":"        total_counts \u003d {\u0027project\u0027: {}}"},{"line_number":2360,"context_line":"        # First query counts across all users of a project"},{"line_number":2361,"context_line":"        resp \u003d self._get_usages(context, project_id)"},{"line_number":2362,"context_line":"        if resp.status_code \u003d\u003d 200:"},{"line_number":2363,"context_line":"            data \u003d resp.json()"},{"line_number":2364,"context_line":"            cores \u003d data[\u0027usages\u0027].get(orc.VCPU, 0)"},{"line_number":2365,"context_line":"            ram \u003d data[\u0027usages\u0027].get(orc.MEMORY_MB, 0)"}],"source_content_type":"text/x-python","patch_set":2,"id":"3fce034c_a3e8bae1","line":2362,"range":{"start_line":2362,"start_character":8,"end_line":2362,"end_character":35},"updated":"2019-04-18 18:22:51.000000000","message":"nit: this can just be \"if resp\" because the Response object implements __bool__ based on the status code being \u003c 400.","commit_id":"ff0582bb802ab468953ac325d0a3fd1ecc48dcdf"},{"author":{"_account_id":4690,"name":"melanie witt","display_name":"melwitt","email":"melwittt@gmail.com","username":"melwitt"},"change_message_id":"dca9eb7e2ee266e589bad7606c9fb2c345ff947c","unresolved":false,"context_lines":[{"line_number":2361,"context_line":"        resp \u003d self._get_usages(context, project_id)"},{"line_number":2362,"context_line":"        if resp.status_code \u003d\u003d 200:"},{"line_number":2363,"context_line":"            data \u003d resp.json()"},{"line_number":2364,"context_line":"            cores \u003d data[\u0027usages\u0027].get(orc.VCPU, 0)"},{"line_number":2365,"context_line":"            ram \u003d data[\u0027usages\u0027].get(orc.MEMORY_MB, 0)"},{"line_number":2366,"context_line":"            total_counts[\u0027project\u0027] \u003d {\u0027cores\u0027: cores, \u0027ram\u0027: ram}"},{"line_number":2367,"context_line":"        else:"}],"source_content_type":"text/x-python","patch_set":2,"id":"3fce034c_2807c9cc","line":2364,"range":{"start_line":2364,"start_character":49,"end_line":2364,"end_character":50},"updated":"2019-04-18 17:23:01.000000000","message":"Note to reviewers: this is done because if there\u0027s no usage for a resource class in placement, it will not include the resource class in the response. So if VCPU isn\u0027t present, we can take that to mean it\u0027s 0.","commit_id":"ff0582bb802ab468953ac325d0a3fd1ecc48dcdf"},{"author":{"_account_id":6873,"name":"Matt Riedemann","email":"mriedem.os@gmail.com","username":"mriedem"},"change_message_id":"f50077dd6dc79580a9ccb5f82239466a89b4f65d","unresolved":false,"context_lines":[{"line_number":2361,"context_line":"        resp \u003d self._get_usages(context, project_id)"},{"line_number":2362,"context_line":"        if resp.status_code \u003d\u003d 200:"},{"line_number":2363,"context_line":"            data \u003d resp.json()"},{"line_number":2364,"context_line":"            cores \u003d data[\u0027usages\u0027].get(orc.VCPU, 0)"},{"line_number":2365,"context_line":"            ram \u003d data[\u0027usages\u0027].get(orc.MEMORY_MB, 0)"},{"line_number":2366,"context_line":"            total_counts[\u0027project\u0027] \u003d {\u0027cores\u0027: cores, \u0027ram\u0027: ram}"},{"line_number":2367,"context_line":"        else:"}],"source_content_type":"text/x-python","patch_set":2,"id":"3fce034c_a3967a4b","line":2364,"range":{"start_line":2364,"start_character":49,"end_line":2364,"end_character":50},"in_reply_to":"3fce034c_23304a9f","updated":"2019-04-18 18:22:51.000000000","message":"You also don\u0027t have a test wrinkle for this default behavior.","commit_id":"ff0582bb802ab468953ac325d0a3fd1ecc48dcdf"},{"author":{"_account_id":4690,"name":"melanie witt","display_name":"melwitt","email":"melwittt@gmail.com","username":"melwitt"},"change_message_id":"46008245c002b3118a86052b6cf27057ba88729d","unresolved":false,"context_lines":[{"line_number":2361,"context_line":"        resp \u003d self._get_usages(context, project_id)"},{"line_number":2362,"context_line":"        if resp.status_code \u003d\u003d 200:"},{"line_number":2363,"context_line":"            data \u003d resp.json()"},{"line_number":2364,"context_line":"            cores \u003d data[\u0027usages\u0027].get(orc.VCPU, 0)"},{"line_number":2365,"context_line":"            ram \u003d data[\u0027usages\u0027].get(orc.MEMORY_MB, 0)"},{"line_number":2366,"context_line":"            total_counts[\u0027project\u0027] \u003d {\u0027cores\u0027: cores, \u0027ram\u0027: ram}"},{"line_number":2367,"context_line":"        else:"}],"source_content_type":"text/x-python","patch_set":2,"id":"3fce034c_23304a9f","line":2364,"range":{"start_line":2364,"start_character":49,"end_line":2364,"end_character":50},"in_reply_to":"3fce034c_2807c9cc","updated":"2019-04-18 18:19:05.000000000","message":"Bleh, I should have added a code comment to this during my respin. Will add it locally and push it with the next batch of changes needed.","commit_id":"ff0582bb802ab468953ac325d0a3fd1ecc48dcdf"},{"author":{"_account_id":6873,"name":"Matt Riedemann","email":"mriedem.os@gmail.com","username":"mriedem"},"change_message_id":"f50077dd6dc79580a9ccb5f82239466a89b4f65d","unresolved":false,"context_lines":[{"line_number":2361,"context_line":"        resp \u003d self._get_usages(context, project_id)"},{"line_number":2362,"context_line":"        if resp.status_code \u003d\u003d 200:"},{"line_number":2363,"context_line":"            data \u003d resp.json()"},{"line_number":2364,"context_line":"            cores \u003d data[\u0027usages\u0027].get(orc.VCPU, 0)"},{"line_number":2365,"context_line":"            ram \u003d data[\u0027usages\u0027].get(orc.MEMORY_MB, 0)"},{"line_number":2366,"context_line":"            total_counts[\u0027project\u0027] \u003d {\u0027cores\u0027: cores, \u0027ram\u0027: ram}"},{"line_number":2367,"context_line":"        else:"}],"source_content_type":"text/x-python","patch_set":2,"id":"3fce034c_630092ac","line":2364,"range":{"start_line":2364,"start_character":49,"end_line":2364,"end_character":50},"in_reply_to":"3fce034c_2807c9cc","updated":"2019-04-18 18:22:51.000000000","message":"If you respin or start working a follow up patch that would be a good comment for the code.","commit_id":"ff0582bb802ab468953ac325d0a3fd1ecc48dcdf"},{"author":{"_account_id":26936,"name":"Surya Seetharaman","email":"suryaseetharaman.9@gmail.com","username":"tssurya"},"change_message_id":"50ad5910071deea114038b6f11d26942c1a49b50","unresolved":false,"context_lines":[{"line_number":2331,"context_line":"        raise exception.UsagesRetrievalFailed(project_id\u003dproject_id,"},{"line_number":2332,"context_line":"                                              user_id\u003duser_id or \u0027N/A\u0027)"},{"line_number":2333,"context_line":""},{"line_number":2334,"context_line":"    @retrying.retry(stop_max_attempt_number\u003d4,"},{"line_number":2335,"context_line":"                    retry_on_exception\u003dlambda e: isinstance("},{"line_number":2336,"context_line":"                        e, ks_exc.ConnectFailure))"},{"line_number":2337,"context_line":"    def _get_usages(self, context, project_id, user_id\u003dNone):"}],"source_content_type":"text/x-python","patch_set":3,"id":"dfbec78f_917909c9","line":2334,"updated":"2019-05-16 12:29:07.000000000","message":"when I was trying the failure connect in devstack I got \n\n \u003cclass \u0027nova.exception.UsagesRetrievalFailed\u0027\u003e (HTTP 500) (Request-ID: req-7c8bfe37-6392-404a-bda9-4fb30a7fb54c)\n\nimmediately. I am not sure if its supposed to retry at least 4 times ? Or maybe I did something wrong.","commit_id":"54408d0ce4a74395cd585d5f24b0c143b8618623"},{"author":{"_account_id":26936,"name":"Surya Seetharaman","email":"suryaseetharaman.9@gmail.com","username":"tssurya"},"change_message_id":"c0f9f40ce5c5824193c7c8656212676f633752cc","unresolved":false,"context_lines":[{"line_number":2331,"context_line":"        raise exception.UsagesRetrievalFailed(project_id\u003dproject_id,"},{"line_number":2332,"context_line":"                                              user_id\u003duser_id or \u0027N/A\u0027)"},{"line_number":2333,"context_line":""},{"line_number":2334,"context_line":"    @retrying.retry(stop_max_attempt_number\u003d4,"},{"line_number":2335,"context_line":"                    retry_on_exception\u003dlambda e: isinstance("},{"line_number":2336,"context_line":"                        e, ks_exc.ConnectFailure))"},{"line_number":2337,"context_line":"    def _get_usages(self, context, project_id, user_id\u003dNone):"}],"source_content_type":"text/x-python","patch_set":3,"id":"dfbec78f_7101f505","line":2334,"in_reply_to":"dfbec78f_917909c9","updated":"2019-05-16 12:44:42.000000000","message":"hmm okay so nvm silly me, I failed to notice that it retries only for keystone failures.","commit_id":"54408d0ce4a74395cd585d5f24b0c143b8618623"},{"author":{"_account_id":26936,"name":"Surya Seetharaman","email":"suryaseetharaman.9@gmail.com","username":"tssurya"},"change_message_id":"50ad5910071deea114038b6f11d26942c1a49b50","unresolved":false,"context_lines":[{"line_number":2335,"context_line":"                    retry_on_exception\u003dlambda e: isinstance("},{"line_number":2336,"context_line":"                        e, ks_exc.ConnectFailure))"},{"line_number":2337,"context_line":"    def _get_usages(self, context, project_id, user_id\u003dNone):"},{"line_number":2338,"context_line":"        url \u003d \u0027/usages?project_id\u003d%s\u0027 % project_id"},{"line_number":2339,"context_line":"        if user_id:"},{"line_number":2340,"context_line":"            url \u003d \u0027\u0027.join([url, \u0027\u0026user_id\u003d%s\u0027 % user_id])"},{"line_number":2341,"context_line":"        return self.get(url, version\u003dGET_USAGES_VERSION,"}],"source_content_type":"text/x-python","patch_set":3,"id":"dfbec78f_f1364551","line":2338,"updated":"2019-05-16 12:29:07.000000000","message":"Overall if there are no connection failures to placement, we will be doing 4 calls to placement if user_id is specified and 2 calls to placement if user_id is not specified right ? One for the initial quota check and the other is the recheck that happens after the claim.","commit_id":"54408d0ce4a74395cd585d5f24b0c143b8618623"},{"author":{"_account_id":4690,"name":"melanie witt","display_name":"melwitt","email":"melwittt@gmail.com","username":"melwitt"},"change_message_id":"3049bb4d6aa0bd7989c97d60e71f06a611f77cc4","unresolved":false,"context_lines":[{"line_number":2335,"context_line":"                    retry_on_exception\u003dlambda e: isinstance("},{"line_number":2336,"context_line":"                        e, ks_exc.ConnectFailure))"},{"line_number":2337,"context_line":"    def _get_usages(self, context, project_id, user_id\u003dNone):"},{"line_number":2338,"context_line":"        url \u003d \u0027/usages?project_id\u003d%s\u0027 % project_id"},{"line_number":2339,"context_line":"        if user_id:"},{"line_number":2340,"context_line":"            url \u003d \u0027\u0027.join([url, \u0027\u0026user_id\u003d%s\u0027 % user_id])"},{"line_number":2341,"context_line":"        return self.get(url, version\u003dGET_USAGES_VERSION,"}],"source_content_type":"text/x-python","patch_set":3,"id":"bfb3d3c7_654bd32a","line":2338,"in_reply_to":"bfb3d3c7_005d3a79","updated":"2019-05-23 18:51:58.000000000","message":"Update: while testing the next patch in the series with additional debug log messages, I found that if there are no user-scoped quota limits in the database, a second call to placement will *not* occur.\n\nGoes to show how complicated the quotas code is... I need to re-look through the code to identify how it skips the user-scoped count if user-scoped limits are not found in the database.","commit_id":"54408d0ce4a74395cd585d5f24b0c143b8618623"},{"author":{"_account_id":782,"name":"John Garbutt","email":"john@johngarbutt.com","username":"johngarbutt"},"change_message_id":"18257a84776b288062ac10bc6378db23105da820","unresolved":false,"context_lines":[{"line_number":2335,"context_line":"                    retry_on_exception\u003dlambda e: isinstance("},{"line_number":2336,"context_line":"                        e, ks_exc.ConnectFailure))"},{"line_number":2337,"context_line":"    def _get_usages(self, context, project_id, user_id\u003dNone):"},{"line_number":2338,"context_line":"        url \u003d \u0027/usages?project_id\u003d%s\u0027 % project_id"},{"line_number":2339,"context_line":"        if user_id:"},{"line_number":2340,"context_line":"            url \u003d \u0027\u0027.join([url, \u0027\u0026user_id\u003d%s\u0027 % user_id])"},{"line_number":2341,"context_line":"        return self.get(url, version\u003dGET_USAGES_VERSION,"}],"source_content_type":"text/x-python","patch_set":3,"id":"bfb3d3c7_b5153c9e","line":2338,"in_reply_to":"bfb3d3c7_654bd32a","updated":"2019-05-28 19:29:57.000000000","message":"Shameless plug for the unified limits POC I uploaded at the end of this chain :)\n\nIt\u0027s only simpler by deprecating the complicated bits, but would love to build consensus around the approach.\n\nIt can reuse most of this though, which is all good.","commit_id":"54408d0ce4a74395cd585d5f24b0c143b8618623"},{"author":{"_account_id":4690,"name":"melanie witt","display_name":"melwitt","email":"melwittt@gmail.com","username":"melwitt"},"change_message_id":"d4ef8f4018758f87b8a6a11bca8aa8767060c570","unresolved":false,"context_lines":[{"line_number":2335,"context_line":"                    retry_on_exception\u003dlambda e: isinstance("},{"line_number":2336,"context_line":"                        e, ks_exc.ConnectFailure))"},{"line_number":2337,"context_line":"    def _get_usages(self, context, project_id, user_id\u003dNone):"},{"line_number":2338,"context_line":"        url \u003d \u0027/usages?project_id\u003d%s\u0027 % project_id"},{"line_number":2339,"context_line":"        if user_id:"},{"line_number":2340,"context_line":"            url \u003d \u0027\u0027.join([url, \u0027\u0026user_id\u003d%s\u0027 % user_id])"},{"line_number":2341,"context_line":"        return self.get(url, version\u003dGET_USAGES_VERSION,"}],"source_content_type":"text/x-python","patch_set":3,"id":"bfb3d3c7_005d3a79","line":2338,"in_reply_to":"dfbec78f_f1364551","updated":"2019-05-22 23:12:28.000000000","message":"Yes, that\u0027s right.\n\nI just had a look through the code in nova/quota.py and realized we always count once with project_id and then another time with project_id + user_id, even when there are no user-scoped quota limits found in the database. This could be optimized (as a separate change) to skip counting with user_id if no user-scoped quota limit overrides are found in the database.","commit_id":"54408d0ce4a74395cd585d5f24b0c143b8618623"},{"author":{"_account_id":26936,"name":"Surya Seetharaman","email":"suryaseetharaman.9@gmail.com","username":"tssurya"},"change_message_id":"50ad5910071deea114038b6f11d26942c1a49b50","unresolved":false,"context_lines":[{"line_number":2347,"context_line":"        :param context: The request context"},{"line_number":2348,"context_line":"        :param project_id: The project_id to count across"},{"line_number":2349,"context_line":"        :param user_id: The user_id to count across"},{"line_number":2350,"context_line":"        :returns: A dict containing the project-scoped and user-scoped counts"},{"line_number":2351,"context_line":"                  if user_id is specified. For example:"},{"line_number":2352,"context_line":"                    {\u0027project\u0027: {\u0027cores\u0027: \u003ccount across project\u003e,"},{"line_number":2353,"context_line":"                                 \u0027ram\u0027: \u003ccount across project\u003e},"}],"source_content_type":"text/x-python","patch_set":3,"id":"dfbec78f_44fc32b4","line":2350,"range":{"start_line":2350,"start_character":8,"end_line":2350,"end_character":16},"updated":"2019-05-16 12:29:07.000000000","message":"++ nice doc string, makes it easy to understand","commit_id":"54408d0ce4a74395cd585d5f24b0c143b8618623"},{"author":{"_account_id":26936,"name":"Surya Seetharaman","email":"suryaseetharaman.9@gmail.com","username":"tssurya"},"change_message_id":"50ad5910071deea114038b6f11d26942c1a49b50","unresolved":false,"context_lines":[{"line_number":2368,"context_line":"            total_counts[\u0027project\u0027] \u003d {\u0027cores\u0027: cores, \u0027ram\u0027: ram}"},{"line_number":2369,"context_line":"        else:"},{"line_number":2370,"context_line":"            self._handle_usages_error_from_placement(resp, project_id)"},{"line_number":2371,"context_line":"        # If specified, second query counts across one user in the project"},{"line_number":2372,"context_line":"        if user_id:"},{"line_number":2373,"context_line":"            resp \u003d self._get_usages(context, project_id, user_id\u003duser_id)"},{"line_number":2374,"context_line":"            if resp:"}],"source_content_type":"text/x-python","patch_set":3,"id":"dfbec78f_04f63a64","line":2371,"range":{"start_line":2371,"start_character":24,"end_line":2371,"end_character":36},"updated":"2019-05-16 12:29:07.000000000","message":"ah so this is what you meant in the mailing list by why we need to do two queries? It\u0027s because GET /usages only gives a total dict in the response and doesn\u0027t group it by the users in the project like you do for the legacy way (https://github.com/openstack/nova/blob/1e2327991df04fcc37cd006dd61d0cb9425066f3/nova/objects/instance.py#L1539).","commit_id":"54408d0ce4a74395cd585d5f24b0c143b8618623"},{"author":{"_account_id":4690,"name":"melanie witt","display_name":"melwitt","email":"melwittt@gmail.com","username":"melwitt"},"change_message_id":"d4ef8f4018758f87b8a6a11bca8aa8767060c570","unresolved":false,"context_lines":[{"line_number":2368,"context_line":"            total_counts[\u0027project\u0027] \u003d {\u0027cores\u0027: cores, \u0027ram\u0027: ram}"},{"line_number":2369,"context_line":"        else:"},{"line_number":2370,"context_line":"            self._handle_usages_error_from_placement(resp, project_id)"},{"line_number":2371,"context_line":"        # If specified, second query counts across one user in the project"},{"line_number":2372,"context_line":"        if user_id:"},{"line_number":2373,"context_line":"            resp \u003d self._get_usages(context, project_id, user_id\u003duser_id)"},{"line_number":2374,"context_line":"            if resp:"}],"source_content_type":"text/x-python","patch_set":3,"id":"bfb3d3c7_20607e32","line":2371,"range":{"start_line":2371,"start_character":24,"end_line":2371,"end_character":36},"in_reply_to":"dfbec78f_04f63a64","updated":"2019-05-22 23:12:28.000000000","message":"Correct.","commit_id":"54408d0ce4a74395cd585d5f24b0c143b8618623"}],"nova/tests/unit/scheduler/client/test_report.py":[{"author":{"_account_id":26936,"name":"Surya Seetharaman","email":"suryaseetharaman.9@gmail.com","username":"tssurya"},"change_message_id":"50ad5910071deea114038b6f11d26942c1a49b50","unresolved":false,"context_lines":[{"line_number":4078,"context_line":"    def test_get_usages_counts_for_quota_fail(self, mock_get):"},{"line_number":4079,"context_line":"        # First call with project fails"},{"line_number":4080,"context_line":"        mock_get.return_value \u003d fake_requests.FakeResponse(500, content\u003d\u0027err\u0027)"},{"line_number":4081,"context_line":"        self.assertRaises(exception.UsagesRetrievalFailed,"},{"line_number":4082,"context_line":"                          self.client.get_usages_counts_for_quota,"},{"line_number":4083,"context_line":"                          self.context, \u0027fake-project\u0027)"},{"line_number":4084,"context_line":"        mock_get.assert_called_once_with("}],"source_content_type":"text/x-python","patch_set":3,"id":"dfbec78f_582df6a5","line":4081,"updated":"2019-05-16 12:29:07.000000000","message":"nit: could have tested the error message but not a biggie.","commit_id":"54408d0ce4a74395cd585d5f24b0c143b8618623"}]}
