)]}'
{"/COMMIT_MSG":[{"author":{"_account_id":14070,"name":"Eric Fried","email":"openstack@fried.cc","username":"efried"},"change_message_id":"415f3de2af5069d9a86a6a57bb0c373d7b8c042e","unresolved":false,"context_lines":[{"line_number":1,"context_line":"Parent:     47edae31 (Enlighten server tags API about cells)"},{"line_number":2,"context_line":"Author:     Dan Smith \u003cdansmith@redhat.com\u003e"},{"line_number":3,"context_line":"AuthorDate: 2017-03-03 10:50:41 -0800"},{"line_number":4,"context_line":"Commit:     Dan Smith \u003cdansmith@redhat.com\u003e"}],"source_content_type":"text/x-gerrit-commit-message","patch_set":1,"id":"ba2be162_c8336f61","line":1,"updated":"2017-03-06 16:24:48.000000000","message":"blueprint?","commit_id":"2387f93f8cf419f603ea9ae342a384de3bededb7"}],"nova/api/openstack/compute/simple_tenant_usage.py":[{"author":{"_account_id":6873,"name":"Matt Riedemann","email":"mriedem.os@gmail.com","username":"mriedem"},"change_message_id":"318b70679a18d05c5dd0cce40e2c104255709b47","unresolved":false,"context_lines":[{"line_number":113,"context_line":"            with nova_context.target_cell(context, cell):"},{"line_number":114,"context_line":"                instances \u003d objects.InstanceList.get_active_by_window_joined("},{"line_number":115,"context_line":"                    context, period_start, period_stop, tenant_id,"},{"line_number":116,"context_line":"                    expected_attrs\u003d[\u0027flavor\u0027], limit\u003dlimit, marker\u003dmarker)"},{"line_number":117,"context_line":"                all_instances.extend(instances.objects)"},{"line_number":118,"context_line":"        return all_instances"},{"line_number":119,"context_line":""}],"source_content_type":"text/x-python","patch_set":5,"id":"9a30ddce_be5d5aeb","line":116,"range":{"start_line":116,"start_character":47,"end_line":116,"end_character":58},"updated":"2017-03-07 20:39:36.000000000","message":"Hmm, don\u0027t we need to honor the limit and marker somehow?\n\nFor example, if I have 10 instances in cell1 and 10 instances in cell2, and my limit is 5, then I\u0027m going to end up with 10 instances in the resulting set aren\u0027t I? Because we\u0027ll get 5 from cell1 and 5 from cell2.","commit_id":"e5bffba2aea0e0b6e15b252c00418c7ebeca5610"},{"author":{"_account_id":16907,"name":"Diana Clarke","email":"diana.joan.clarke@gmail.com","username":"diana-clarke"},"change_message_id":"80f516cd9369d8285a083ea2ae32f191ec045182","unresolved":false,"context_lines":[{"line_number":113,"context_line":"            with nova_context.target_cell(context, cell):"},{"line_number":114,"context_line":"                instances \u003d objects.InstanceList.get_active_by_window_joined("},{"line_number":115,"context_line":"                    context, period_start, period_stop, tenant_id,"},{"line_number":116,"context_line":"                    expected_attrs\u003d[\u0027flavor\u0027], limit\u003dlimit, marker\u003dmarker)"},{"line_number":117,"context_line":"                all_instances.extend(instances.objects)"},{"line_number":118,"context_line":"        return all_instances"},{"line_number":119,"context_line":""}],"source_content_type":"text/x-python","patch_set":5,"id":"9a30ddce_9e3b36eb","line":116,"range":{"start_line":116,"start_character":47,"end_line":116,"end_character":58},"in_reply_to":"9a30ddce_be5d5aeb","updated":"2017-03-07 20:54:14.000000000","message":"lol, I\u0027m glad you have your thinking cap on. good catch!","commit_id":"e5bffba2aea0e0b6e15b252c00418c7ebeca5610"},{"author":{"_account_id":6873,"name":"Matt Riedemann","email":"mriedem.os@gmail.com","username":"mriedem"},"change_message_id":"7e37f400792123a65bb9a15beaffca6b497c0e0c","unresolved":false,"context_lines":[{"line_number":113,"context_line":"            with nova_context.target_cell(context, cell):"},{"line_number":114,"context_line":"                try:"},{"line_number":115,"context_line":"                    instances \u003d ("},{"line_number":116,"context_line":"                        objects.InstanceList.get_active_by_window_joined("},{"line_number":117,"context_line":"                            context, period_start, period_stop, tenant_id,"},{"line_number":118,"context_line":"                            expected_attrs\u003d[\u0027flavor\u0027], limit\u003dlimit,"},{"line_number":119,"context_line":"                            marker\u003dmarker))"}],"source_content_type":"text/x-python","patch_set":6,"id":"9a30ddce_74f30374","line":116,"range":{"start_line":116,"start_character":45,"end_line":116,"end_character":72},"updated":"2017-03-07 21:47:06.000000000","message":"I was thinking we could ignore cell0 during this iteration but this DB API query is checking for instances where terminated_at is null or newer than period_start, which I suppose could still be the case in cell0 if the instance is in error state there but not deleted yet. Are you thinking the same or am I missing something?","commit_id":"5479b4ae17e0bdd9d7dc8b23ff65d3bc84a5736e"},{"author":{"_account_id":4393,"name":"Dan Smith","email":"dms@danplanet.com","username":"danms"},"change_message_id":"c579ab121dca154a357764839ab29fddaefc5669","unresolved":false,"context_lines":[{"line_number":113,"context_line":"            with nova_context.target_cell(context, cell):"},{"line_number":114,"context_line":"                try:"},{"line_number":115,"context_line":"                    instances \u003d ("},{"line_number":116,"context_line":"                        objects.InstanceList.get_active_by_window_joined("},{"line_number":117,"context_line":"                            context, period_start, period_stop, tenant_id,"},{"line_number":118,"context_line":"                            expected_attrs\u003d[\u0027flavor\u0027], limit\u003dlimit,"},{"line_number":119,"context_line":"                            marker\u003dmarker))"}],"source_content_type":"text/x-python","patch_set":6,"id":"9a30ddce_d7ce7182","line":116,"range":{"start_line":116,"start_character":45,"end_line":116,"end_character":72},"in_reply_to":"9a30ddce_74f30374","updated":"2017-03-07 21:55:45.000000000","message":"Yes, I intentionally didn\u0027t filter cell0 from this like I did elsewhere so that we aren\u0027t ignoring those resources.","commit_id":"5479b4ae17e0bdd9d7dc8b23ff65d3bc84a5736e"},{"author":{"_account_id":6873,"name":"Matt Riedemann","email":"mriedem.os@gmail.com","username":"mriedem"},"change_message_id":"7e37f400792123a65bb9a15beaffca6b497c0e0c","unresolved":false,"context_lines":[{"line_number":121,"context_line":"                    # NOTE(danms): We need to keep looking through the later"},{"line_number":122,"context_line":"                    # cells to find the marker"},{"line_number":123,"context_line":"                    continue"},{"line_number":124,"context_line":"                all_instances.extend(instances.objects)"},{"line_number":125,"context_line":"                marker \u003d None"},{"line_number":126,"context_line":"                if limit:"},{"line_number":127,"context_line":"                    limit -\u003d len(instances.objects)"}],"source_content_type":"text/x-python","patch_set":6,"id":"9a30ddce_9720799d","line":124,"range":{"start_line":124,"start_character":46,"end_line":124,"end_character":54},"updated":"2017-03-07 21:47:06.000000000","message":"nit: I don\u0027t think this is necessary, it isn\u0027t here:\n\nhttps://github.com/openstack/nova/blob/15.0.0/nova/compute/api.py#L2543","commit_id":"5479b4ae17e0bdd9d7dc8b23ff65d3bc84a5736e"},{"author":{"_account_id":4393,"name":"Dan Smith","email":"dms@danplanet.com","username":"danms"},"change_message_id":"72cecadf181989f403c21c5120b0c4deda3871c4","unresolved":false,"context_lines":[{"line_number":121,"context_line":"                    # NOTE(danms): We need to keep looking through the later"},{"line_number":122,"context_line":"                    # cells to find the marker"},{"line_number":123,"context_line":"                    continue"},{"line_number":124,"context_line":"                all_instances.extend(instances.objects)"},{"line_number":125,"context_line":"                marker \u003d None"},{"line_number":126,"context_line":"                if limit:"},{"line_number":127,"context_line":"                    limit -\u003d len(instances.objects)"}],"source_content_type":"text/x-python","patch_set":6,"id":"9a30ddce_b7bbbd71","line":124,"range":{"start_line":124,"start_character":46,"end_line":124,"end_character":54},"in_reply_to":"9a30ddce_9720799d","updated":"2017-03-07 22:06:04.000000000","message":"Done","commit_id":"5479b4ae17e0bdd9d7dc8b23ff65d3bc84a5736e"},{"author":{"_account_id":6873,"name":"Matt Riedemann","email":"mriedem.os@gmail.com","username":"mriedem"},"change_message_id":"7e37f400792123a65bb9a15beaffca6b497c0e0c","unresolved":false,"context_lines":[{"line_number":122,"context_line":"                    # cells to find the marker"},{"line_number":123,"context_line":"                    continue"},{"line_number":124,"context_line":"                all_instances.extend(instances.objects)"},{"line_number":125,"context_line":"                marker \u003d None"},{"line_number":126,"context_line":"                if limit:"},{"line_number":127,"context_line":"                    limit -\u003d len(instances.objects)"},{"line_number":128,"context_line":"                    if limit \u003c\u003d 0:"}],"source_content_type":"text/x-python","patch_set":6,"id":"9a30ddce_d741113b","line":125,"updated":"2017-03-07 21:47:06.000000000","message":"Want to copy the same comment as here?\n\nhttps://github.com/openstack/nova/blob/15.0.0/nova/compute/api.py#L2544","commit_id":"5479b4ae17e0bdd9d7dc8b23ff65d3bc84a5736e"},{"author":{"_account_id":4393,"name":"Dan Smith","email":"dms@danplanet.com","username":"danms"},"change_message_id":"72cecadf181989f403c21c5120b0c4deda3871c4","unresolved":false,"context_lines":[{"line_number":122,"context_line":"                    # cells to find the marker"},{"line_number":123,"context_line":"                    continue"},{"line_number":124,"context_line":"                all_instances.extend(instances.objects)"},{"line_number":125,"context_line":"                marker \u003d None"},{"line_number":126,"context_line":"                if limit:"},{"line_number":127,"context_line":"                    limit -\u003d len(instances.objects)"},{"line_number":128,"context_line":"                    if limit \u003c\u003d 0:"}],"source_content_type":"text/x-python","patch_set":6,"id":"9a30ddce_97b6b988","line":125,"in_reply_to":"9a30ddce_d741113b","updated":"2017-03-07 22:06:04.000000000","message":"Done","commit_id":"5479b4ae17e0bdd9d7dc8b23ff65d3bc84a5736e"},{"author":{"_account_id":6873,"name":"Matt Riedemann","email":"mriedem.os@gmail.com","username":"mriedem"},"change_message_id":"7e37f400792123a65bb9a15beaffca6b497c0e0c","unresolved":false,"context_lines":[{"line_number":124,"context_line":"                all_instances.extend(instances.objects)"},{"line_number":125,"context_line":"                marker \u003d None"},{"line_number":126,"context_line":"                if limit:"},{"line_number":127,"context_line":"                    limit -\u003d len(instances.objects)"},{"line_number":128,"context_line":"                    if limit \u003c\u003d 0:"},{"line_number":129,"context_line":"                        break"},{"line_number":130,"context_line":"        if marker is not None and len(all_instances) \u003d\u003d 0:"}],"source_content_type":"text/x-python","patch_set":6,"id":"9a30ddce_37498d60","line":127,"range":{"start_line":127,"start_character":42,"end_line":127,"end_character":50},"updated":"2017-03-07 21:47:06.000000000","message":"ditto","commit_id":"5479b4ae17e0bdd9d7dc8b23ff65d3bc84a5736e"},{"author":{"_account_id":4393,"name":"Dan Smith","email":"dms@danplanet.com","username":"danms"},"change_message_id":"72cecadf181989f403c21c5120b0c4deda3871c4","unresolved":false,"context_lines":[{"line_number":124,"context_line":"                all_instances.extend(instances.objects)"},{"line_number":125,"context_line":"                marker \u003d None"},{"line_number":126,"context_line":"                if limit:"},{"line_number":127,"context_line":"                    limit -\u003d len(instances.objects)"},{"line_number":128,"context_line":"                    if limit \u003c\u003d 0:"},{"line_number":129,"context_line":"                        break"},{"line_number":130,"context_line":"        if marker is not None and len(all_instances) \u003d\u003d 0:"}],"source_content_type":"text/x-python","patch_set":6,"id":"9a30ddce_d7b0318e","line":127,"range":{"start_line":127,"start_character":42,"end_line":127,"end_character":50},"in_reply_to":"9a30ddce_37498d60","updated":"2017-03-07 22:06:04.000000000","message":"Done","commit_id":"5479b4ae17e0bdd9d7dc8b23ff65d3bc84a5736e"},{"author":{"_account_id":6873,"name":"Matt Riedemann","email":"mriedem.os@gmail.com","username":"mriedem"},"change_message_id":"7e37f400792123a65bb9a15beaffca6b497c0e0c","unresolved":false,"context_lines":[{"line_number":132,"context_line":"            # mimic the db_api behavior here"},{"line_number":133,"context_line":"            raise exception.MarkerNotFound(marker\u003dmarker)"},{"line_number":134,"context_line":""},{"line_number":135,"context_line":"        return all_instances"},{"line_number":136,"context_line":""},{"line_number":137,"context_line":"    def _tenant_usages_for_period(self, context, period_start, period_stop,"},{"line_number":138,"context_line":"                                  tenant_id\u003dNone, detailed\u003dTrue, limit\u003dNone,"}],"source_content_type":"text/x-python","patch_set":6,"id":"9a30ddce_d7af51e1","line":135,"updated":"2017-03-07 21:47:06.000000000","message":"The DB API sorts by [project_id, uuid]:\n\nhttps://github.com/openstack/nova/blob/15.0.0/nova/db/sqlalchemy/api.py#L2561\n\nOnce we\u0027ve pulled the instances from all cells, do we need to do any sort of merge sorting here?\n\nI\u0027m not totally sure the sort order matters because of how _tenant_usages_for_period uses the instances to calculate the usages.\n\nIf \u0027detailed\u0027 is provided then the \u0027server_usages\u0027 list will not be sorted though...","commit_id":"5479b4ae17e0bdd9d7dc8b23ff65d3bc84a5736e"},{"author":{"_account_id":4393,"name":"Dan Smith","email":"dms@danplanet.com","username":"danms"},"change_message_id":"7d420221b5e610698ccf043d384335860aef811a","unresolved":false,"context_lines":[{"line_number":132,"context_line":"            # mimic the db_api behavior here"},{"line_number":133,"context_line":"            raise exception.MarkerNotFound(marker\u003dmarker)"},{"line_number":134,"context_line":""},{"line_number":135,"context_line":"        return all_instances"},{"line_number":136,"context_line":""},{"line_number":137,"context_line":"    def _tenant_usages_for_period(self, context, period_start, period_stop,"},{"line_number":138,"context_line":"                                  tenant_id\u003dNone, detailed\u003dTrue, limit\u003dNone,"}],"source_content_type":"text/x-python","patch_set":6,"id":"9a30ddce_af51a1da","line":135,"in_reply_to":"9a30ddce_034febbd","updated":"2017-03-07 23:50:19.000000000","message":"So just to be clear, we cannot do a completely stable cross-cell sort of any key. Doing so has the same infinite-memory requirement that get-instances does. We\u0027d have to list everything from all cells, sort them, then apply the limit. Otherwise we haven\u0027t queried enough from each to know whether we\u0027ve gotten a correct global sort. If we just sort the results we get from each cell, we end up with a very very strange moving target. Imagine cells with objects like this:\n\n cell1: A D G J\n cell2: B E H K\n cell3: C F I L\n\nThe correct sort requires us to select everything out of all cells, to arrive at:\n\n A B C D E F G H I J K L\n\nIf we have a limit of 6 and sort the results of each page, we\u0027ll get pages of:\n\n A B D E G J\n C F H I L K\n\nWhich is not any more sorted than the natural result of the independent queries (which is what is present in this patch):\n\n A D G J B E\n H K C F I L\n\nThe problem here is almost definitely worse than get-instances, since the latter only deals with current instances and simple_tenant_usage deals with potentially current and past instances. So, we can sort the pages and take the performance hit for doing that, but it won\u0027t get us a fully sorted result.\n\nGiven that the user already has to stitch periods together themselves across pages, I\u0027m not sure why sorting the result really matters, especially given that it\u0027s sorted by something non-sequential (i.e. not time, or size, or even age).\n\nAs long as the marker puts us in the same page we stopped on due to the limit (which what I have here does, AFAICT), that\u0027s the only thing that really matters.\n\nWhat am I missing?","commit_id":"5479b4ae17e0bdd9d7dc8b23ff65d3bc84a5736e"},{"author":{"_account_id":16907,"name":"Diana Clarke","email":"diana.joan.clarke@gmail.com","username":"diana-clarke"},"change_message_id":"d1091dee175fa4b14709f457b62ee1ba7915d85c","unresolved":false,"context_lines":[{"line_number":132,"context_line":"            # mimic the db_api behavior here"},{"line_number":133,"context_line":"            raise exception.MarkerNotFound(marker\u003dmarker)"},{"line_number":134,"context_line":""},{"line_number":135,"context_line":"        return all_instances"},{"line_number":136,"context_line":""},{"line_number":137,"context_line":"    def _tenant_usages_for_period(self, context, period_start, period_stop,"},{"line_number":138,"context_line":"                                  tenant_id\u003dNone, detailed\u003dTrue, limit\u003dNone,"}],"source_content_type":"text/x-python","patch_set":6,"id":"9a30ddce_e3cbb770","line":135,"in_reply_to":"9a30ddce_77306557","updated":"2017-03-07 23:21:15.000000000","message":"IIRC, sorting by project_id was a requirement that fell out of spec review. Deterministic sorting was another requirement (which is why it is also sorted by uuid). I can look more tomorrow though.\n\nSo sorry for not catching this, first pass. It was mostly a drive by review, giving you a heads up about the other simple tenant usage patch in the queue. That said, if anyone should have caught that, it should have been me. Apologies.","commit_id":"5479b4ae17e0bdd9d7dc8b23ff65d3bc84a5736e"},{"author":{"_account_id":6873,"name":"Matt Riedemann","email":"mriedem.os@gmail.com","username":"mriedem"},"change_message_id":"fab622249c9d29ddfaead2851183f188773db5a0","unresolved":false,"context_lines":[{"line_number":132,"context_line":"            # mimic the db_api behavior here"},{"line_number":133,"context_line":"            raise exception.MarkerNotFound(marker\u003dmarker)"},{"line_number":134,"context_line":""},{"line_number":135,"context_line":"        return all_instances"},{"line_number":136,"context_line":""},{"line_number":137,"context_line":"    def _tenant_usages_for_period(self, context, period_start, period_stop,"},{"line_number":138,"context_line":"                                  tenant_id\u003dNone, detailed\u003dTrue, limit\u003dNone,"}],"source_content_type":"text/x-python","patch_set":6,"id":"9a30ddce_a387ff0d","line":135,"in_reply_to":"9a30ddce_77bb05c5","updated":"2017-03-07 23:23:25.000000000","message":"\u003e Why is sorting by a uuid (both of these are) in any way useful?\n\nGood question, I have no idea why we do that in the DB API, it seems pointless. Maybe because the uuid is the marker? I think we\u0027ve said before though that having uuid as a marker is misleading since you could create a new instance and it\u0027s random uuid could mess up your sort order/marker. I think we talked about that a bit when Diana was writing the spec for adding limit/marker to this API...","commit_id":"5479b4ae17e0bdd9d7dc8b23ff65d3bc84a5736e"},{"author":{"_account_id":4393,"name":"Dan Smith","email":"dms@danplanet.com","username":"danms"},"change_message_id":"4626608a4e8d7f77fa2d4e0dc95efff9592009bd","unresolved":false,"context_lines":[{"line_number":132,"context_line":"            # mimic the db_api behavior here"},{"line_number":133,"context_line":"            raise exception.MarkerNotFound(marker\u003dmarker)"},{"line_number":134,"context_line":""},{"line_number":135,"context_line":"        return all_instances"},{"line_number":136,"context_line":""},{"line_number":137,"context_line":"    def _tenant_usages_for_period(self, context, period_start, period_stop,"},{"line_number":138,"context_line":"                                  tenant_id\u003dNone, detailed\u003dTrue, limit\u003dNone,"}],"source_content_type":"text/x-python","patch_set":6,"id":"9a30ddce_77306557","line":135,"in_reply_to":"9a30ddce_77bb05c5","updated":"2017-03-07 21:57:16.000000000","message":"And more specifically, if the user isn\u0027t asking for it to be sorted a specific way, I don\u0027t think they can or should expect it\u0027s sorted by any specific key.","commit_id":"5479b4ae17e0bdd9d7dc8b23ff65d3bc84a5736e"},{"author":{"_account_id":6873,"name":"Matt Riedemann","email":"mriedem.os@gmail.com","username":"mriedem"},"change_message_id":"75ae5b6d707bdfd47d71b1f30f0bb58e884125c0","unresolved":false,"context_lines":[{"line_number":132,"context_line":"            # mimic the db_api behavior here"},{"line_number":133,"context_line":"            raise exception.MarkerNotFound(marker\u003dmarker)"},{"line_number":134,"context_line":""},{"line_number":135,"context_line":"        return all_instances"},{"line_number":136,"context_line":""},{"line_number":137,"context_line":"    def _tenant_usages_for_period(self, context, period_start, period_stop,"},{"line_number":138,"context_line":"                                  tenant_id\u003dNone, detailed\u003dTrue, limit\u003dNone,"}],"source_content_type":"text/x-python","patch_set":6,"id":"9a30ddce_034febbd","line":135,"in_reply_to":"9a30ddce_a3037f72","updated":"2017-03-07 23:31:12.000000000","message":"FWIW there was a long discussion in the spec review for this:\n\nhttps://review.openstack.org/#/c/386771/\n\nBetween Diana, Alex, Jay and John about sort ordering here. I won\u0027t claim to have it all in my head or understand it, I\u0027m hoping they can, but it does seem like it was intentional enough that we need to maintain it across multiple cells.","commit_id":"5479b4ae17e0bdd9d7dc8b23ff65d3bc84a5736e"},{"author":{"_account_id":6873,"name":"Matt Riedemann","email":"mriedem.os@gmail.com","username":"mriedem"},"change_message_id":"4904ebcec85104f962b49e20e3593e61bbfea3e1","unresolved":false,"context_lines":[{"line_number":132,"context_line":"            # mimic the db_api behavior here"},{"line_number":133,"context_line":"            raise exception.MarkerNotFound(marker\u003dmarker)"},{"line_number":134,"context_line":""},{"line_number":135,"context_line":"        return all_instances"},{"line_number":136,"context_line":""},{"line_number":137,"context_line":"    def _tenant_usages_for_period(self, context, period_start, period_stop,"},{"line_number":138,"context_line":"                                  tenant_id\u003dNone, detailed\u003dTrue, limit\u003dNone,"}],"source_content_type":"text/x-python","patch_set":6,"id":"9a30ddce_a3037f72","line":135,"in_reply_to":"9a30ddce_a387ff0d","updated":"2017-03-07 23:26:33.000000000","message":"https://specs.openstack.org/openstack/nova-specs/specs/ocata/approved/paginate-simple-tenant-usage.html#data-model-impact\n\nSo it seems this was by design, as Diana pointed out, so I\u0027m not sure why we wouldn\u0027t continue to sort.","commit_id":"5479b4ae17e0bdd9d7dc8b23ff65d3bc84a5736e"},{"author":{"_account_id":5754,"name":"Alex Xu","email":"hejie.xu@intel.com","username":"xuhj"},"change_message_id":"360959a37a1c71ddd427228cdf338c83679fbb5c","unresolved":false,"context_lines":[{"line_number":132,"context_line":"            # mimic the db_api behavior here"},{"line_number":133,"context_line":"            raise exception.MarkerNotFound(marker\u003dmarker)"},{"line_number":134,"context_line":""},{"line_number":135,"context_line":"        return all_instances"},{"line_number":136,"context_line":""},{"line_number":137,"context_line":"    def _tenant_usages_for_period(self, context, period_start, period_stop,"},{"line_number":138,"context_line":"                                  tenant_id\u003dNone, detailed\u003dTrue, limit\u003dNone,"}],"source_content_type":"text/x-python","patch_set":6,"id":"9a30ddce_c32b0e93","line":135,"in_reply_to":"9a30ddce_af51a1da","updated":"2017-03-08 02:33:01.000000000","message":"Sorted by \u0027project_id\u0027 is for user to get same project resources closely, not spread same project resources in many different pages.\n\nSorted by \u0027uuid\u0027 is for stable sort result. That is the thing to guarantee the pagination works correctly.\n\nI\u0027m ok without sorted by \u0027project_id\u0027 with cells, since if we sort in the memory, that make the pagination meanless.\n\nFor stable sort result, \"objects.CellMappingList.get_all\" didn\u0027t have a specific sort key. But yes, it will be stable, just not guaranteed. \n\nSo talk with Dan on the IRC, he will follow a separate patch to sort the cells by specific sort key.","commit_id":"5479b4ae17e0bdd9d7dc8b23ff65d3bc84a5736e"},{"author":{"_account_id":4393,"name":"Dan Smith","email":"dms@danplanet.com","username":"danms"},"change_message_id":"c579ab121dca154a357764839ab29fddaefc5669","unresolved":false,"context_lines":[{"line_number":132,"context_line":"            # mimic the db_api behavior here"},{"line_number":133,"context_line":"            raise exception.MarkerNotFound(marker\u003dmarker)"},{"line_number":134,"context_line":""},{"line_number":135,"context_line":"        return all_instances"},{"line_number":136,"context_line":""},{"line_number":137,"context_line":"    def _tenant_usages_for_period(self, context, period_start, period_stop,"},{"line_number":138,"context_line":"                                  tenant_id\u003dNone, detailed\u003dTrue, limit\u003dNone,"}],"source_content_type":"text/x-python","patch_set":6,"id":"9a30ddce_77bb05c5","line":135,"in_reply_to":"9a30ddce_d720314c","updated":"2017-03-07 21:55:45.000000000","message":"Why is sorting by a uuid (both of these are) in any way useful?","commit_id":"5479b4ae17e0bdd9d7dc8b23ff65d3bc84a5736e"},{"author":{"_account_id":6873,"name":"Matt Riedemann","email":"mriedem.os@gmail.com","username":"mriedem"},"change_message_id":"6bcd0e201193a8a7ea784ef34a25a7a517d047ea","unresolved":false,"context_lines":[{"line_number":132,"context_line":"            # mimic the db_api behavior here"},{"line_number":133,"context_line":"            raise exception.MarkerNotFound(marker\u003dmarker)"},{"line_number":134,"context_line":""},{"line_number":135,"context_line":"        return all_instances"},{"line_number":136,"context_line":""},{"line_number":137,"context_line":"    def _tenant_usages_for_period(self, context, period_start, period_stop,"},{"line_number":138,"context_line":"                                  tenant_id\u003dNone, detailed\u003dTrue, limit\u003dNone,"}],"source_content_type":"text/x-python","patch_set":6,"id":"9a30ddce_d720314c","line":135,"in_reply_to":"9a30ddce_d7af51e1","updated":"2017-03-07 21:51:53.000000000","message":"I haven\u0027t tried it yet, but it seems we could easily sort like this:\n\n  from operator import attrgetter\n  return sorted(all_instances, key\u003dattrgetter(\u0027project_id\u0027, \u0027uuid\u0027))","commit_id":"5479b4ae17e0bdd9d7dc8b23ff65d3bc84a5736e"},{"author":{"_account_id":6873,"name":"Matt Riedemann","email":"mriedem.os@gmail.com","username":"mriedem"},"change_message_id":"f2c3fa800ba6afa3d84fa06398795cb05af9b59d","unresolved":false,"context_lines":[{"line_number":113,"context_line":"            with nova_context.target_cell(context, cell):"},{"line_number":114,"context_line":"                try:"},{"line_number":115,"context_line":"                    instances \u003d ("},{"line_number":116,"context_line":"                        objects.InstanceList.get_active_by_window_joined("},{"line_number":117,"context_line":"                            context, period_start, period_stop, tenant_id,"},{"line_number":118,"context_line":"                            expected_attrs\u003d[\u0027flavor\u0027], limit\u003dlimit,"},{"line_number":119,"context_line":"                            marker\u003dmarker))"}],"source_content_type":"text/x-python","patch_set":7,"id":"9a30ddce_0eda8f78","line":116,"updated":"2017-03-08 17:14:42.000000000","message":"Something else I thought of, but in the compute API get_all method we have to make a distinction with cells v1 being enabled:\n\nhttps://github.com/openstack/nova/blob/347808c0a8555c11be399121642d09792297d9dc/nova/compute/api.py#L2449-L2463\n\nDo we need to also consider that here? The comment there says:\n\n\"because reading from cells results in changed behavior, because of the syncing.\"\n\nI don\u0027t really follow what that means wrt cells v1.","commit_id":"15e06bbc406da4d3ee64103abefeedf47e763607"},{"author":{"_account_id":4393,"name":"Dan Smith","email":"dms@danplanet.com","username":"danms"},"change_message_id":"f286065685f8faee98f59284f21fcf36e363ba99","unresolved":false,"context_lines":[{"line_number":113,"context_line":"            with nova_context.target_cell(context, cell):"},{"line_number":114,"context_line":"                try:"},{"line_number":115,"context_line":"                    instances \u003d ("},{"line_number":116,"context_line":"                        objects.InstanceList.get_active_by_window_joined("},{"line_number":117,"context_line":"                            context, period_start, period_stop, tenant_id,"},{"line_number":118,"context_line":"                            expected_attrs\u003d[\u0027flavor\u0027], limit\u003dlimit,"},{"line_number":119,"context_line":"                            marker\u003dmarker))"}],"source_content_type":"text/x-python","patch_set":7,"id":"9a30ddce_d439e642","line":116,"in_reply_to":"9a30ddce_0eda8f78","updated":"2017-03-08 18:18:36.000000000","message":"The reason it matters for cellsv1 there is because we end up being faster than the replication in the API. Meaning, we take some action, then immediately check state. If the API goes straight to the cell DB, we\u0027ll still see the old state, because the replication hasn\u0027t happened yet. Since get_all (and get) is in the critical path for tempest tests, they fail because they expect things to go through a particular set of transitions (understandably).\n\nFor this it doesn\u0027t matter as much since it\u0027s not highly tied to state in the same way. That\u0027s why the cells job is passing on this.","commit_id":"15e06bbc406da4d3ee64103abefeedf47e763607"},{"author":{"_account_id":6873,"name":"Matt Riedemann","email":"mriedem.os@gmail.com","username":"mriedem"},"change_message_id":"8969599e06d276676cde24f153e9fb92b299a7cb","unresolved":false,"context_lines":[{"line_number":113,"context_line":"            with nova_context.target_cell(context, cell):"},{"line_number":114,"context_line":"                try:"},{"line_number":115,"context_line":"                    instances \u003d ("},{"line_number":116,"context_line":"                        objects.InstanceList.get_active_by_window_joined("},{"line_number":117,"context_line":"                            context, period_start, period_stop, tenant_id,"},{"line_number":118,"context_line":"                            expected_attrs\u003d[\u0027flavor\u0027], limit\u003dlimit,"},{"line_number":119,"context_line":"                            marker\u003dmarker))"}],"source_content_type":"text/x-python","patch_set":7,"id":"9a30ddce_036418e2","line":116,"in_reply_to":"9a30ddce_d439e642","updated":"2017-03-09 03:10:05.000000000","message":"OK that helps. And actually ^ would be awesome to have in https://github.com/openstack/nova/blob/347808c0a8555c11be399121642d09792297d9dc/nova/compute/api.py#L2449-L2463 for more detail.","commit_id":"15e06bbc406da4d3ee64103abefeedf47e763607"},{"author":{"_account_id":5754,"name":"Alex Xu","email":"hejie.xu@intel.com","username":"xuhj"},"change_message_id":"7818ca8d587eb6a6065eb3cf6f3254c4cf61c09c","unresolved":false,"context_lines":[{"line_number":117,"context_line":"                            context, period_start, period_stop, tenant_id,"},{"line_number":118,"context_line":"                            expected_attrs\u003d[\u0027flavor\u0027], limit\u003dlimit,"},{"line_number":119,"context_line":"                            marker\u003dmarker))"},{"line_number":120,"context_line":"                except exception.MarkerNotFound:"},{"line_number":121,"context_line":"                    # NOTE(danms): We need to keep looking through the later"},{"line_number":122,"context_line":"                    # cells to find the marker"},{"line_number":123,"context_line":"                    continue"},{"line_number":124,"context_line":"                all_instances.extend(instances)"},{"line_number":125,"context_line":"                # NOTE(danms): We must have found a marker if we had one,"},{"line_number":126,"context_line":"                # so make sure we don\u0027t require a marker in the next cell"}],"source_content_type":"text/x-python","patch_set":7,"id":"9a30ddce_6927a112","line":123,"range":{"start_line":120,"start_character":23,"end_line":123,"end_character":28},"updated":"2017-03-08 03:32:43.000000000","message":"We can optimize this. We can use \"ComputeAPI._get_instance_map_or_none\" to locate the cell of maker first, instead of iterate all the cells.\n\nIf we have 10 cells, and the marker in the last cell, we can save many db call.","commit_id":"15e06bbc406da4d3ee64103abefeedf47e763607"},{"author":{"_account_id":6873,"name":"Matt Riedemann","email":"mriedem.os@gmail.com","username":"mriedem"},"change_message_id":"07393889590ebf021d5b1b3394cee4b92a309ca0","unresolved":false,"context_lines":[{"line_number":117,"context_line":"                            context, period_start, period_stop, tenant_id,"},{"line_number":118,"context_line":"                            expected_attrs\u003d[\u0027flavor\u0027], limit\u003dlimit,"},{"line_number":119,"context_line":"                            marker\u003dmarker))"},{"line_number":120,"context_line":"                except exception.MarkerNotFound:"},{"line_number":121,"context_line":"                    # NOTE(danms): We need to keep looking through the later"},{"line_number":122,"context_line":"                    # cells to find the marker"},{"line_number":123,"context_line":"                    continue"},{"line_number":124,"context_line":"                all_instances.extend(instances)"},{"line_number":125,"context_line":"                # NOTE(danms): We must have found a marker if we had one,"},{"line_number":126,"context_line":"                # so make sure we don\u0027t require a marker in the next cell"}],"source_content_type":"text/x-python","patch_set":7,"id":"9a30ddce_63f5ebc9","line":123,"range":{"start_line":120,"start_character":23,"end_line":123,"end_character":28},"in_reply_to":"9a30ddce_23a933e0","updated":"2017-03-08 15:04:31.000000000","message":"Yeah, that\u0027s not too bad I guess. You still take the hit on querying all of the cell mappings, but at least you avoid the unnecessary get_active_by_window_joined queries in each cell.","commit_id":"15e06bbc406da4d3ee64103abefeedf47e763607"},{"author":{"_account_id":4393,"name":"Dan Smith","email":"dms@danplanet.com","username":"danms"},"change_message_id":"c135d5922195572dbaa1a871ccdf3e7113bdc7e6","unresolved":false,"context_lines":[{"line_number":117,"context_line":"                            context, period_start, period_stop, tenant_id,"},{"line_number":118,"context_line":"                            expected_attrs\u003d[\u0027flavor\u0027], limit\u003dlimit,"},{"line_number":119,"context_line":"                            marker\u003dmarker))"},{"line_number":120,"context_line":"                except exception.MarkerNotFound:"},{"line_number":121,"context_line":"                    # NOTE(danms): We need to keep looking through the later"},{"line_number":122,"context_line":"                    # cells to find the marker"},{"line_number":123,"context_line":"                    continue"},{"line_number":124,"context_line":"                all_instances.extend(instances)"},{"line_number":125,"context_line":"                # NOTE(danms): We must have found a marker if we had one,"},{"line_number":126,"context_line":"                # so make sure we don\u0027t require a marker in the next cell"}],"source_content_type":"text/x-python","patch_set":7,"id":"9a30ddce_83ae5f83","line":123,"range":{"start_line":120,"start_character":23,"end_line":123,"end_character":28},"in_reply_to":"9a30ddce_63f5ebc9","updated":"2017-03-08 15:08:56.000000000","message":"Yes, but querying one or all is pretty much the same hit since there won\u0027t be lots of them.\n\nIn compute api, we cache that list so it\u0027s not any more work, really. Just a little more complicated loop.","commit_id":"15e06bbc406da4d3ee64103abefeedf47e763607"},{"author":{"_account_id":4393,"name":"Dan Smith","email":"dms@danplanet.com","username":"danms"},"change_message_id":"be50bb48656de93db1abe70bc721fd8fa646c537","unresolved":false,"context_lines":[{"line_number":117,"context_line":"                            context, period_start, period_stop, tenant_id,"},{"line_number":118,"context_line":"                            expected_attrs\u003d[\u0027flavor\u0027], limit\u003dlimit,"},{"line_number":119,"context_line":"                            marker\u003dmarker))"},{"line_number":120,"context_line":"                except exception.MarkerNotFound:"},{"line_number":121,"context_line":"                    # NOTE(danms): We need to keep looking through the later"},{"line_number":122,"context_line":"                    # cells to find the marker"},{"line_number":123,"context_line":"                    continue"},{"line_number":124,"context_line":"                all_instances.extend(instances)"},{"line_number":125,"context_line":"                # NOTE(danms): We must have found a marker if we had one,"},{"line_number":126,"context_line":"                # so make sure we don\u0027t require a marker in the next cell"}],"source_content_type":"text/x-python","patch_set":7,"id":"9a30ddce_8973f5e6","line":123,"range":{"start_line":120,"start_character":23,"end_line":123,"end_character":28},"in_reply_to":"9a30ddce_6927a112","updated":"2017-03-08 03:36:15.000000000","message":"That\u0027s true, if we know that the marker is the instance uuid.\n\nThis is the pattern we have for instance list already, so how about we optimize both later in one patch? I think the same applies there right?","commit_id":"15e06bbc406da4d3ee64103abefeedf47e763607"},{"author":{"_account_id":4393,"name":"Dan Smith","email":"dms@danplanet.com","username":"danms"},"change_message_id":"a4e3efd4e73dbb19efc280cdb7efaf93baaea6c1","unresolved":false,"context_lines":[{"line_number":117,"context_line":"                            context, period_start, period_stop, tenant_id,"},{"line_number":118,"context_line":"                            expected_attrs\u003d[\u0027flavor\u0027], limit\u003dlimit,"},{"line_number":119,"context_line":"                            marker\u003dmarker))"},{"line_number":120,"context_line":"                except exception.MarkerNotFound:"},{"line_number":121,"context_line":"                    # NOTE(danms): We need to keep looking through the later"},{"line_number":122,"context_line":"                    # cells to find the marker"},{"line_number":123,"context_line":"                    continue"},{"line_number":124,"context_line":"                all_instances.extend(instances)"},{"line_number":125,"context_line":"                # NOTE(danms): We must have found a marker if we had one,"},{"line_number":126,"context_line":"                # so make sure we don\u0027t require a marker in the next cell"}],"source_content_type":"text/x-python","patch_set":7,"id":"9a30ddce_23a933e0","line":123,"range":{"start_line":120,"start_character":23,"end_line":123,"end_character":28},"in_reply_to":"9a30ddce_83357fdb","updated":"2017-03-08 14:57:37.000000000","message":"That\u0027s why this makes it a little complicated. We basically need to look up the cell, then find that cell in our ordered list of cells, and then start iterating cells from there until we run out of limit.","commit_id":"15e06bbc406da4d3ee64103abefeedf47e763607"},{"author":{"_account_id":6873,"name":"Matt Riedemann","email":"mriedem.os@gmail.com","username":"mriedem"},"change_message_id":"5665e741e266207f463863e54a8d45944a470fc4","unresolved":false,"context_lines":[{"line_number":117,"context_line":"                            context, period_start, period_stop, tenant_id,"},{"line_number":118,"context_line":"                            expected_attrs\u003d[\u0027flavor\u0027], limit\u003dlimit,"},{"line_number":119,"context_line":"                            marker\u003dmarker))"},{"line_number":120,"context_line":"                except exception.MarkerNotFound:"},{"line_number":121,"context_line":"                    # NOTE(danms): We need to keep looking through the later"},{"line_number":122,"context_line":"                    # cells to find the marker"},{"line_number":123,"context_line":"                    continue"},{"line_number":124,"context_line":"                all_instances.extend(instances)"},{"line_number":125,"context_line":"                # NOTE(danms): We must have found a marker if we had one,"},{"line_number":126,"context_line":"                # so make sure we don\u0027t require a marker in the next cell"}],"source_content_type":"text/x-python","patch_set":7,"id":"9a30ddce_e063913f","line":123,"range":{"start_line":120,"start_character":23,"end_line":123,"end_character":28},"in_reply_to":"9a30ddce_8973f5e6","updated":"2017-03-08 14:47:21.000000000","message":"\u003e That\u0027s true, if we know that the marker is the instance uuid.\n\nWe know the marker in this case is the instance uuid because of the DB API call for get_active_by_window_joined. But agree that we could handle this later separately so it doesn\u0027t clutter up this change.","commit_id":"15e06bbc406da4d3ee64103abefeedf47e763607"},{"author":{"_account_id":6873,"name":"Matt Riedemann","email":"mriedem.os@gmail.com","username":"mriedem"},"change_message_id":"7f348a4bd10b3388d07f8f3f9710515e40697b3d","unresolved":false,"context_lines":[{"line_number":117,"context_line":"                            context, period_start, period_stop, tenant_id,"},{"line_number":118,"context_line":"                            expected_attrs\u003d[\u0027flavor\u0027], limit\u003dlimit,"},{"line_number":119,"context_line":"                            marker\u003dmarker))"},{"line_number":120,"context_line":"                except exception.MarkerNotFound:"},{"line_number":121,"context_line":"                    # NOTE(danms): We need to keep looking through the later"},{"line_number":122,"context_line":"                    # cells to find the marker"},{"line_number":123,"context_line":"                    continue"},{"line_number":124,"context_line":"                all_instances.extend(instances)"},{"line_number":125,"context_line":"                # NOTE(danms): We must have found a marker if we had one,"},{"line_number":126,"context_line":"                # so make sure we don\u0027t require a marker in the next cell"}],"source_content_type":"text/x-python","patch_set":7,"id":"9a30ddce_83357fdb","line":123,"range":{"start_line":120,"start_character":23,"end_line":123,"end_character":28},"in_reply_to":"9a30ddce_e063913f","updated":"2017-03-08 14:55:25.000000000","message":"However, if we have a limit and marker and let\u0027s say the marker is the last instance in a cell4 but our limit is 20, we\u0027d still need to pull 19 more instances from the next cell in the list, right? So finding the cell to start in using the marker is fine, but how do you get the other cells that come after that to continuing querying to fill the limit?","commit_id":"15e06bbc406da4d3ee64103abefeedf47e763607"}],"nova/tests/unit/api/openstack/compute/test_simple_tenant_usage.py":[{"author":{"_account_id":4393,"name":"Dan Smith","email":"dms@danplanet.com","username":"danms"},"change_message_id":"d6aea3366a8690566c472b120b592e78ba4803f7","unresolved":false,"context_lines":[{"line_number":99,"context_line":"    return objects.InstanceList(objects\u003d["},{"line_number":100,"context_line":"        _fake_instance(START, STOP, x,"},{"line_number":101,"context_line":"                       project_id or \u0027faketenant_%s\u0027 % (x // SERVERS))"},{"line_number":102,"context_line":"        for x in range(TENANTS * SERVERS)])"},{"line_number":103,"context_line":""},{"line_number":104,"context_line":""},{"line_number":105,"context_line":"@mock.patch(\u0027nova.objects.InstanceList.get_active_by_window_joined\u0027,"}],"source_content_type":"text/x-python","patch_set":3,"id":"9a30ddce_9536be01","line":102,"updated":"2017-03-07 18:08:43.000000000","message":"It was because this just returns data, and we call it once per cell. So if we call it for cell0 and cell1, we get double the usage data in our tests. There\u0027s not a super easy way to tell what cell this is being called for inside the test. So I made it do just one cell to keep the math straight.","commit_id":"87641518a7be870958c2455bcde1ec392b504e35"},{"author":{"_account_id":7,"name":"Jay Pipes","email":"jaypipes@gmail.com","username":"jaypipes"},"change_message_id":"f7de262f2719baf5e12d4bc33229272e6fe2309c","unresolved":false,"context_lines":[{"line_number":124,"context_line":""},{"line_number":125,"context_line":"        def fake_get_cells(cls, context):"},{"line_number":126,"context_line":"            return [c for c in cells"},{"line_number":127,"context_line":"                    if c.uuid !\u003d objects.CellMapping.CELL0_UUID]"},{"line_number":128,"context_line":""},{"line_number":129,"context_line":"        self.useFixture(fixtures.MonkeyPatch("},{"line_number":130,"context_line":"            \u0027nova.objects.CellMappingList.get_all\u0027,"}],"source_content_type":"text/x-python","patch_set":3,"id":"9a30ddce_b57ca273","line":127,"updated":"2017-03-07 17:54:39.000000000","message":"I\u0027m not following why the above is filtering out cell0 but the actual code isn\u0027t?","commit_id":"87641518a7be870958c2455bcde1ec392b504e35"},{"author":{"_account_id":4393,"name":"Dan Smith","email":"dms@danplanet.com","username":"danms"},"change_message_id":"492d626e3dc4461c70cb6eb6ccb23c4de3bb6f80","unresolved":false,"context_lines":[{"line_number":124,"context_line":""},{"line_number":125,"context_line":"        def fake_get_cells(cls, context):"},{"line_number":126,"context_line":"            return [c for c in cells"},{"line_number":127,"context_line":"                    if c.uuid !\u003d objects.CellMapping.CELL0_UUID]"},{"line_number":128,"context_line":""},{"line_number":129,"context_line":"        self.useFixture(fixtures.MonkeyPatch("},{"line_number":130,"context_line":"            \u0027nova.objects.CellMappingList.get_all\u0027,"}],"source_content_type":"text/x-python","patch_set":3,"id":"9a30ddce_f5e7fa0f","line":127,"in_reply_to":"9a30ddce_b57ca273","updated":"2017-03-07 17:58:30.000000000","message":"Because I wanted to keep the single-call asserts below. This reduces to one cell, but I can\u0027t just return a fake because I need the actual mapping from the CellDatabases fixture. They\u0027re not really testing the multi-cells-ness, they\u0027re testing that we do the right thing when we do call, and I\u0027m reducing to just one cell for the sake of the test.\n\nI could avoid this and just return those like normal, but then I have to make all the mocks work for multiple calls too. I guess I\u0027ll see how onerous that is.","commit_id":"87641518a7be870958c2455bcde1ec392b504e35"},{"author":{"_account_id":7,"name":"Jay Pipes","email":"jaypipes@gmail.com","username":"jaypipes"},"change_message_id":"ff9bc1bcf54d038a23e7ada3527877296d7beb58","unresolved":false,"context_lines":[{"line_number":124,"context_line":""},{"line_number":125,"context_line":"        def fake_get_cells(cls, context):"},{"line_number":126,"context_line":"            return [c for c in cells"},{"line_number":127,"context_line":"                    if c.uuid !\u003d objects.CellMapping.CELL0_UUID]"},{"line_number":128,"context_line":""},{"line_number":129,"context_line":"        self.useFixture(fixtures.MonkeyPatch("},{"line_number":130,"context_line":"            \u0027nova.objects.CellMappingList.get_all\u0027,"}],"source_content_type":"text/x-python","patch_set":3,"id":"9a30ddce_f8c44f93","line":127,"in_reply_to":"9a30ddce_f5e7fa0f","updated":"2017-03-07 18:15:57.000000000","message":"Gotcha. Yeah, feel free to keep it as-is, just add a quick comment above it saying why we\u0027re doing that.","commit_id":"87641518a7be870958c2455bcde1ec392b504e35"},{"author":{"_account_id":6873,"name":"Matt Riedemann","email":"mriedem.os@gmail.com","username":"mriedem"},"change_message_id":"57dc37e36852735d0f6d184dfc2ba41faa78aecc","unresolved":false,"context_lines":[{"line_number":314,"context_line":""},{"line_number":315,"context_line":"    def test_next_links_index(self):"},{"line_number":316,"context_line":"        self._test_verify_index(START, STOP,"},{"line_number":317,"context_line":"                                limit\u003dSERVERS * TENANTS * self.num_cells)"},{"line_number":318,"context_line":""},{"line_number":319,"context_line":""},{"line_number":320,"context_line":"class SimpleTenantUsageLimitsTestV21(test.TestCase):"}],"source_content_type":"text/x-python","patch_set":5,"id":"9a30ddce_7e8da230","line":317,"range":{"start_line":317,"start_character":56,"end_line":317,"end_character":72},"updated":"2017-03-07 20:44:07.000000000","message":"Here is where you cheated. :)","commit_id":"e5bffba2aea0e0b6e15b252c00418c7ebeca5610"},{"author":{"_account_id":6873,"name":"Matt Riedemann","email":"mriedem.os@gmail.com","username":"mriedem"},"change_message_id":"7e37f400792123a65bb9a15beaffca6b497c0e0c","unresolved":false,"context_lines":[{"line_number":311,"context_line":"class SimpleTenantUsageTestV40(SimpleTenantUsageTestV21):"},{"line_number":312,"context_line":"    version \u003d \u00272.40\u0027"},{"line_number":313,"context_line":""},{"line_number":314,"context_line":"    def test_next_links_show(self):"},{"line_number":315,"context_line":"        self._test_verify_show(START, STOP,"},{"line_number":316,"context_line":"                               limit\u003dSERVERS * TENANTS)"},{"line_number":317,"context_line":""},{"line_number":318,"context_line":"    def test_next_links_index(self):"},{"line_number":319,"context_line":"        self._test_verify_index(START, STOP,"},{"line_number":320,"context_line":"                                limit\u003dSERVERS * TENANTS)"},{"line_number":321,"context_line":""},{"line_number":322,"context_line":""},{"line_number":323,"context_line":"class SimpleTenantUsageLimitsTestV21(test.TestCase):"}],"source_content_type":"text/x-python","patch_set":6,"id":"9a30ddce_57d0c153","line":320,"range":{"start_line":314,"start_character":0,"end_line":320,"end_character":56},"updated":"2017-03-07 21:47:06.000000000","message":"nit: didn\u0027t need to change these anymore after the rebase.","commit_id":"5479b4ae17e0bdd9d7dc8b23ff65d3bc84a5736e"}]}
