)]}'
{"/COMMIT_MSG":[{"author":{"_account_id":6873,"name":"Matt Riedemann","email":"mriedem.os@gmail.com","username":"mriedem"},"change_message_id":"76e827e121045bc39b7af432e42535559a050a40","unresolved":false,"context_lines":[{"line_number":19,"context_line":"/allocations that removed the last remaining allocations for a consumer."},{"line_number":20,"context_line":""},{"line_number":21,"context_line":"Change-Id: Ic2b82146d28be64b363b0b8e2e8d180b515bc0a0"},{"line_number":22,"context_line":"Closes-bug: #1779717"}],"source_content_type":"text/x-gerrit-commit-message","patch_set":1,"id":"5f7c97a3_ee3508a9","line":22,"updated":"2018-07-09 16:48:15.000000000","message":"This is the wrong bug.","commit_id":"5f886c3ba998330a99e80c82b181149a27d739a6"},{"author":{"_account_id":6873,"name":"Matt Riedemann","email":"mriedem.os@gmail.com","username":"mriedem"},"change_message_id":"7e087d5c99dfc4ead16107045b6bf5ee939c9a32","unresolved":false,"context_lines":[{"line_number":19,"context_line":"/allocations that removed the last remaining allocations for a consumer."},{"line_number":20,"context_line":""},{"line_number":21,"context_line":"Change-Id: Ic2b82146d28be64b363b0b8e2e8d180b515bc0a0"},{"line_number":22,"context_line":"Closes-bug: #1779717"}],"source_content_type":"text/x-gerrit-commit-message","patch_set":1,"id":"5f7c97a3_2e4f8035","line":22,"in_reply_to":"5f7c97a3_ee3508a9","updated":"2018-07-09 16:48:52.000000000","message":"This should be bug 1780799.","commit_id":"5f886c3ba998330a99e80c82b181149a27d739a6"},{"author":{"_account_id":14070,"name":"Eric Fried","email":"openstack@fried.cc","username":"efried"},"change_message_id":"e7dbded4a2db3a1427ae51362a437f4e55202714","unresolved":false,"context_lines":[{"line_number":6,"context_line":""},{"line_number":7,"context_line":"delete consumers which no longer have allocations"},{"line_number":8,"context_line":""},{"line_number":9,"context_line":"We made the decision to delete consumer records when those consumers no"},{"line_number":10,"context_line":"longer had any allocations referring to them (as opposed to keeping"},{"line_number":11,"context_line":"those consumer records around and incrementing the consumer generation"},{"line_number":12,"context_line":"for them)."}],"source_content_type":"text/x-gerrit-commit-message","patch_set":4,"id":"5f7c97a3_b41202b3","line":9,"range":{"start_line":9,"start_character":12,"end_line":9,"end_character":20},"updated":"2018-07-09 19:35:44.000000000","message":"#link http://eavesdrop.openstack.org/irclogs/%23openstack-placement/%23openstack-placement.2018-07-03.log.html#t2018-07-03T21:42:32","commit_id":"126e25eb2f6721a4767f1a2549a20fe3b28ffa60"}],"nova/api/openstack/placement/objects/consumer.py":[{"author":{"_account_id":11564,"name":"Chris Dent","email":"cdent@anticdent.org","username":"chdent"},"change_message_id":"e73e746d66f31afc6e4835838eebe4280872e72b","unresolved":false,"context_lines":[{"line_number":79,"context_line":"    sel \u003d sel.where(_ALLOC_TBL.c.consumer_id \u003d\u003d consumer_uuid)"},{"line_number":80,"context_line":"    sel \u003d sel.limit(1)"},{"line_number":81,"context_line":"    res \u003d ctx.session.execute(sel)"},{"line_number":82,"context_line":"    if not res:"},{"line_number":83,"context_line":"        return"},{"line_number":84,"context_line":"    # Delete the consumer since there\u0027s no allocation records"},{"line_number":85,"context_line":"    del_stmt \u003d CONSUMER_TBL.delete()"}],"source_content_type":"text/x-python","patch_set":2,"id":"5f7c97a3_29ee9ab4","line":82,"updated":"2018-07-09 17:56:06.000000000","message":"Is this backwards. We want to return if there are no results, not if there is a result?","commit_id":"0f53ee577f69f250b876412a4c4178d7303a78bc"},{"author":{"_account_id":7,"name":"Jay Pipes","email":"jaypipes@gmail.com","username":"jaypipes"},"change_message_id":"389fda6e2862b2d89586c093e034687fa5392f15","unresolved":false,"context_lines":[{"line_number":79,"context_line":"    sel \u003d sel.where(_ALLOC_TBL.c.consumer_id \u003d\u003d consumer_uuid)"},{"line_number":80,"context_line":"    sel \u003d sel.limit(1)"},{"line_number":81,"context_line":"    res \u003d ctx.session.execute(sel)"},{"line_number":82,"context_line":"    if not res:"},{"line_number":83,"context_line":"        return"},{"line_number":84,"context_line":"    # Delete the consumer since there\u0027s no allocation records"},{"line_number":85,"context_line":"    del_stmt \u003d CONSUMER_TBL.delete()"}],"source_content_type":"text/x-python","patch_set":2,"id":"5f7c97a3_496c3632","line":82,"in_reply_to":"5f7c97a3_29ee9ab4","updated":"2018-07-09 17:57:15.000000000","message":"doh, yeah...","commit_id":"0f53ee577f69f250b876412a4c4178d7303a78bc"},{"author":{"_account_id":6873,"name":"Matt Riedemann","email":"mriedem.os@gmail.com","username":"mriedem"},"change_message_id":"58e8365f58ffd9fd9f7f297c1dd22ba9e7fdb76c","unresolved":false,"context_lines":[{"line_number":66,"context_line":""},{"line_number":67,"context_line":""},{"line_number":68,"context_line":"@db_api.placement_context_manager.writer"},{"line_number":69,"context_line":"def delete_consumer_if_no_allocations(ctx, consumer_uuid):"},{"line_number":70,"context_line":"    \"\"\"Looks to see if the supplied consumer has any allocations and if not,"},{"line_number":71,"context_line":"    deletes the consumer record entirely."},{"line_number":72,"context_line":""}],"source_content_type":"text/x-python","patch_set":4,"id":"5f7c97a3_f1c3ac56","line":69,"updated":"2018-07-09 18:38:25.000000000","message":"Clearly this could be racing with another request that\u0027s PUTing allocations for the given consumer, but I\u0027m guessing that other request would eventually fail when it tries to create allocations with a consumer id that was deleted out from under it? Since the allocation create flow first ensures the consumer exists and then creates allocations using that consumer. So if we deleted in between, the allocation record insert should fail a referential constraint on the consumer record being gone, in which case the user would get a 500 and then have to retry the PUT /allocations request. Without a DLM or retry on allocation insert, I\u0027m not sure what we\u0027d do about this.","commit_id":"126e25eb2f6721a4767f1a2549a20fe3b28ffa60"},{"author":{"_account_id":7,"name":"Jay Pipes","email":"jaypipes@gmail.com","username":"jaypipes"},"change_message_id":"fdaad79265d289deefb540fa43ffcee695b8b01e","unresolved":false,"context_lines":[{"line_number":66,"context_line":""},{"line_number":67,"context_line":""},{"line_number":68,"context_line":"@db_api.placement_context_manager.writer"},{"line_number":69,"context_line":"def delete_consumer_if_no_allocations(ctx, consumer_uuid):"},{"line_number":70,"context_line":"    \"\"\"Looks to see if the supplied consumer has any allocations and if not,"},{"line_number":71,"context_line":"    deletes the consumer record entirely."},{"line_number":72,"context_line":""}],"source_content_type":"text/x-python","patch_set":4,"id":"5f7c97a3_34f8327a","line":69,"in_reply_to":"5f7c97a3_14bbb6bd","updated":"2018-07-09 19:22:11.000000000","message":"Pretty sure you\u0027re right, Eric. I was planning on going deep into all this when doing the single-trx reshaper work...","commit_id":"126e25eb2f6721a4767f1a2549a20fe3b28ffa60"},{"author":{"_account_id":7,"name":"Jay Pipes","email":"jaypipes@gmail.com","username":"jaypipes"},"change_message_id":"19634c515a72df015a9ba567dbef59de2192e49b","unresolved":false,"context_lines":[{"line_number":66,"context_line":""},{"line_number":67,"context_line":""},{"line_number":68,"context_line":"@db_api.placement_context_manager.writer"},{"line_number":69,"context_line":"def delete_consumer_if_no_allocations(ctx, consumer_uuid):"},{"line_number":70,"context_line":"    \"\"\"Looks to see if the supplied consumer has any allocations and if not,"},{"line_number":71,"context_line":"    deletes the consumer record entirely."},{"line_number":72,"context_line":""}],"source_content_type":"text/x-python","patch_set":4,"id":"5f7c97a3_f1edecb7","line":69,"in_reply_to":"5f7c97a3_f1c3ac56","updated":"2018-07-09 18:41:25.000000000","message":"So, for the case of PUT|POST /allocations, I put the call to delete_consumer_if_no_allocations() after the checks that increment consumer generations. I suppose I could put this *before* those checks and then remove the consumers that were deleted. That might provide some smallish level of security? Not really sure...","commit_id":"126e25eb2f6721a4767f1a2549a20fe3b28ffa60"},{"author":{"_account_id":14070,"name":"Eric Fried","email":"openstack@fried.cc","username":"efried"},"change_message_id":"8e15ba12b53aa2b3b2c9ab1e9dd08afdc03873dd","unresolved":false,"context_lines":[{"line_number":66,"context_line":""},{"line_number":67,"context_line":""},{"line_number":68,"context_line":"@db_api.placement_context_manager.writer"},{"line_number":69,"context_line":"def delete_consumer_if_no_allocations(ctx, consumer_uuid):"},{"line_number":70,"context_line":"    \"\"\"Looks to see if the supplied consumer has any allocations and if not,"},{"line_number":71,"context_line":"    deletes the consumer record entirely."},{"line_number":72,"context_line":""}],"source_content_type":"text/x-python","patch_set":4,"id":"5f7c97a3_14bbb6bd","line":69,"in_reply_to":"5f7c97a3_f1edecb7","updated":"2018-07-09 19:20:15.000000000","message":"Not having looked closely yet...\n\nAren\u0027t we in an atomic transaction when we use this?\n\nThe PUTter supplies a generation, which is either null or whatever it was before we started the DELETEr transaction. If the latter and the PUTter wins, the DELETEr will bounce when it hits increment. If the latter and DELETEr wins, the PUTter will bounce when it hits increment (because we were expecting generation\u003dnull).\n\nIf the PUTter supplies a generation of null and \"wins\", he\u0027ll bounce because the generation doesn\u0027t match. If the DELETEr wins, the PUTter will succeed - and that\u0027s correct because the PUTter is declaring that he expects the consumer to be absent before he starts.\n\nMaybe I\u0027m being dense, but I don\u0027t see how one transaction can get into a code path where the record exists at first and then disappears due to a separate transaction, or vice versa.","commit_id":"126e25eb2f6721a4767f1a2549a20fe3b28ffa60"},{"author":{"_account_id":6873,"name":"Matt Riedemann","email":"mriedem.os@gmail.com","username":"mriedem"},"change_message_id":"58e8365f58ffd9fd9f7f297c1dd22ba9e7fdb76c","unresolved":false,"context_lines":[{"line_number":70,"context_line":"    \"\"\"Looks to see if the supplied consumer has any allocations and if not,"},{"line_number":71,"context_line":"    deletes the consumer record entirely."},{"line_number":72,"context_line":""},{"line_number":73,"context_line":"    :param ctx: `nova.context.RequestContext` that contains an oslo_db Session"},{"line_number":74,"context_line":"    :param consumer_uuid: UUID of the consumer to check and maybe delete"},{"line_number":75,"context_line":"    \"\"\""},{"line_number":76,"context_line":"    # First, do a fast lookup to see if there are any allocation records for"}],"source_content_type":"text/x-python","patch_set":4,"id":"5f7c97a3_71d79c23","line":73,"range":{"start_line":73,"start_character":17,"end_line":73,"end_character":21},"updated":"2018-07-09 18:38:25.000000000","message":"technically this would be nova.api.openstack.placement\n\nhttps://github.com/openstack/nova/blob/master/nova/api/openstack/placement/context.py","commit_id":"126e25eb2f6721a4767f1a2549a20fe3b28ffa60"},{"author":{"_account_id":7,"name":"Jay Pipes","email":"jaypipes@gmail.com","username":"jaypipes"},"change_message_id":"19634c515a72df015a9ba567dbef59de2192e49b","unresolved":false,"context_lines":[{"line_number":70,"context_line":"    \"\"\"Looks to see if the supplied consumer has any allocations and if not,"},{"line_number":71,"context_line":"    deletes the consumer record entirely."},{"line_number":72,"context_line":""},{"line_number":73,"context_line":"    :param ctx: `nova.context.RequestContext` that contains an oslo_db Session"},{"line_number":74,"context_line":"    :param consumer_uuid: UUID of the consumer to check and maybe delete"},{"line_number":75,"context_line":"    \"\"\""},{"line_number":76,"context_line":"    # First, do a fast lookup to see if there are any allocation records for"}],"source_content_type":"text/x-python","patch_set":4,"id":"5f7c97a3_11e988a9","line":73,"range":{"start_line":73,"start_character":17,"end_line":73,"end_character":21},"in_reply_to":"5f7c97a3_71d79c23","updated":"2018-07-09 18:41:25.000000000","message":"ack, can fix in followup... was a copy pasta from below.","commit_id":"126e25eb2f6721a4767f1a2549a20fe3b28ffa60"},{"author":{"_account_id":6873,"name":"Matt Riedemann","email":"mriedem.os@gmail.com","username":"mriedem"},"change_message_id":"1970529609f1253668ecd27e1c796d622eb70bb0","unresolved":false,"context_lines":[{"line_number":63,"context_line":""},{"line_number":64,"context_line":""},{"line_number":65,"context_line":"@db_api.placement_context_manager.writer"},{"line_number":66,"context_line":"def delete_consumers_if_no_allocations(ctx, consumer_uuids):"},{"line_number":67,"context_line":"    \"\"\"Looks to see if any of the supplied consumers has any allocations and if"},{"line_number":68,"context_line":"    not, deletes the consumer record entirely."},{"line_number":69,"context_line":""}],"source_content_type":"text/x-python","patch_set":5,"id":"5f7c97a3_80ed3c25","line":66,"updated":"2018-07-09 22:24:24.000000000","message":"oops\n\nhttp://logs.openstack.org/86/581086/5/check/tempest-full/4a79185/controller/logs/screen-placement-api.txt.gz?level\u003dTRACE#_Jul_09_21_05_05_553299","commit_id":"1fe5d455497295dea4de8dedc789d17b4dbc0457"},{"author":{"_account_id":6873,"name":"Matt Riedemann","email":"mriedem.os@gmail.com","username":"mriedem"},"change_message_id":"1874165a7aa01e53d8a4da2925bf1a2edfbfdf35","unresolved":false,"context_lines":[{"line_number":67,"context_line":"    \"\"\"Looks to see if any of the supplied consumers has any allocations and if"},{"line_number":68,"context_line":"    not, deletes the consumer record entirely."},{"line_number":69,"context_line":""},{"line_number":70,"context_line":"    :param ctx: `nova.context.RequestContext` that contains an oslo_db Session"},{"line_number":71,"context_line":"    :param consumer_uuids: UUIDs of the consumers to check and maybe delete"},{"line_number":72,"context_line":"    \"\"\""},{"line_number":73,"context_line":"    # Delete consumers that are not referenced in the allocations table"}],"source_content_type":"text/x-python","patch_set":5,"id":"5f7c97a3_ba60a936","line":70,"range":{"start_line":70,"start_character":17,"end_line":70,"end_character":21},"updated":"2018-07-09 21:08:30.000000000","message":"same nit","commit_id":"1fe5d455497295dea4de8dedc789d17b4dbc0457"}],"nova/api/openstack/placement/objects/resource_provider.py":[{"author":{"_account_id":6873,"name":"Matt Riedemann","email":"mriedem.os@gmail.com","username":"mriedem"},"change_message_id":"c1e8b15c4f203b88fb52e6412db3a519f1316405","unresolved":false,"context_lines":[{"line_number":2086,"context_line":"        # that fact and do an efficient batch delete"},{"line_number":2087,"context_line":"        consumer_uuid \u003d self.objects[0].consumer.uuid"},{"line_number":2088,"context_line":"        _delete_allocations_for_consumer(self._context, consumer_uuid)"},{"line_number":2089,"context_line":""},{"line_number":2090,"context_line":"    def __repr__(self):"},{"line_number":2091,"context_line":"        strings \u003d [repr(x) for x in self.objects]"},{"line_number":2092,"context_line":"        return \"AllocationList[\" + \", \".join(strings) + \"]\""}],"source_content_type":"text/x-python","patch_set":2,"id":"5f7c97a3_6911f252","line":2089,"updated":"2018-07-09 17:26:03.000000000","message":"Shouldn\u0027t we also delete the consumer record once it\u0027s allocations are gone?","commit_id":"0f53ee577f69f250b876412a4c4178d7303a78bc"},{"author":{"_account_id":7,"name":"Jay Pipes","email":"jaypipes@gmail.com","username":"jaypipes"},"change_message_id":"65a385e9913ca8039b0e56d3372b90c525952c08","unresolved":false,"context_lines":[{"line_number":2086,"context_line":"        # that fact and do an efficient batch delete"},{"line_number":2087,"context_line":"        consumer_uuid \u003d self.objects[0].consumer.uuid"},{"line_number":2088,"context_line":"        _delete_allocations_for_consumer(self._context, consumer_uuid)"},{"line_number":2089,"context_line":""},{"line_number":2090,"context_line":"    def __repr__(self):"},{"line_number":2091,"context_line":"        strings \u003d [repr(x) for x in self.objects]"},{"line_number":2092,"context_line":"        return \"AllocationList[\" + \", \".join(strings) + \"]\""}],"source_content_type":"text/x-python","patch_set":2,"id":"5f7c97a3_49bbd6bc","line":2089,"in_reply_to":"5f7c97a3_2999ba78","updated":"2018-07-09 17:50:04.000000000","message":"@cdent this is AllocationList, not Allocation :) So, yes, each Allocation can have only one consumer, but an AllocationList can have allocations that have different consumers.","commit_id":"0f53ee577f69f250b876412a4c4178d7303a78bc"},{"author":{"_account_id":6873,"name":"Matt Riedemann","email":"mriedem.os@gmail.com","username":"mriedem"},"change_message_id":"12058885b79a81bbd2fc932ff8bc3a6d8643398a","unresolved":false,"context_lines":[{"line_number":2086,"context_line":"        # that fact and do an efficient batch delete"},{"line_number":2087,"context_line":"        consumer_uuid \u003d self.objects[0].consumer.uuid"},{"line_number":2088,"context_line":"        _delete_allocations_for_consumer(self._context, consumer_uuid)"},{"line_number":2089,"context_line":""},{"line_number":2090,"context_line":"    def __repr__(self):"},{"line_number":2091,"context_line":"        strings \u003d [repr(x) for x in self.objects]"},{"line_number":2092,"context_line":"        return \"AllocationList[\" + \", \".join(strings) + \"]\""}],"source_content_type":"text/x-python","patch_set":2,"id":"5f7c97a3_a92f0af3","line":2089,"in_reply_to":"5f7c97a3_49bbd6bc","updated":"2018-07-09 17:54:27.000000000","message":"As far as I can tell, we only get here from DELETE /allocations/{consumer_id} so we\u0027d be deleting all allocations for a single consumer here anyway. Not deleting all allocations across multiple consumers on, for example, a single resource provider.","commit_id":"0f53ee577f69f250b876412a4c4178d7303a78bc"},{"author":{"_account_id":11564,"name":"Chris Dent","email":"cdent@anticdent.org","username":"chdent"},"change_message_id":"e73e746d66f31afc6e4835838eebe4280872e72b","unresolved":false,"context_lines":[{"line_number":2086,"context_line":"        # that fact and do an efficient batch delete"},{"line_number":2087,"context_line":"        consumer_uuid \u003d self.objects[0].consumer.uuid"},{"line_number":2088,"context_line":"        _delete_allocations_for_consumer(self._context, consumer_uuid)"},{"line_number":2089,"context_line":""},{"line_number":2090,"context_line":"    def __repr__(self):"},{"line_number":2091,"context_line":"        strings \u003d [repr(x) for x in self.objects]"},{"line_number":2092,"context_line":"        return \"AllocationList[\" + \", \".join(strings) + \"]\""}],"source_content_type":"text/x-python","patch_set":2,"id":"5f7c97a3_89380e3b","line":2089,"in_reply_to":"5f7c97a3_49bbd6bc","updated":"2018-07-09 17:56:06.000000000","message":"naming is hard","commit_id":"0f53ee577f69f250b876412a4c4178d7303a78bc"},{"author":{"_account_id":7,"name":"Jay Pipes","email":"jaypipes@gmail.com","username":"jaypipes"},"change_message_id":"4fa148e21930cabdd375439d9fa340bda0e8773a","unresolved":false,"context_lines":[{"line_number":2086,"context_line":"        # that fact and do an efficient batch delete"},{"line_number":2087,"context_line":"        consumer_uuid \u003d self.objects[0].consumer.uuid"},{"line_number":2088,"context_line":"        _delete_allocations_for_consumer(self._context, consumer_uuid)"},{"line_number":2089,"context_line":""},{"line_number":2090,"context_line":"    def __repr__(self):"},{"line_number":2091,"context_line":"        strings \u003d [repr(x) for x in self.objects]"},{"line_number":2092,"context_line":"        return \"AllocationList[\" + \", \".join(strings) + \"]\""}],"source_content_type":"text/x-python","patch_set":2,"id":"5f7c97a3_a9c62a9b","line":2089,"in_reply_to":"5f7c97a3_6911f252","updated":"2018-07-09 17:35:44.000000000","message":"err... the above is dangerous. Allocations definitely cannot \"only have a single consumer\" or at least, not anymore since POST /allocations came around in 1.13 (I think that\u0027s the right microversion at least...)\n\nNot sure we even use this code path any more, but I\u0027ll double-check and add something in there for it, sure.","commit_id":"0f53ee577f69f250b876412a4c4178d7303a78bc"},{"author":{"_account_id":11564,"name":"Chris Dent","email":"cdent@anticdent.org","username":"chdent"},"change_message_id":"f2db03c3185b96074aad2d2cc41eeb871924e0e4","unresolved":false,"context_lines":[{"line_number":2086,"context_line":"        # that fact and do an efficient batch delete"},{"line_number":2087,"context_line":"        consumer_uuid \u003d self.objects[0].consumer.uuid"},{"line_number":2088,"context_line":"        _delete_allocations_for_consumer(self._context, consumer_uuid)"},{"line_number":2089,"context_line":""},{"line_number":2090,"context_line":"    def __repr__(self):"},{"line_number":2091,"context_line":"        strings \u003d [repr(x) for x in self.objects]"},{"line_number":2092,"context_line":"        return \"AllocationList[\" + \", \".join(strings) + \"]\""}],"source_content_type":"text/x-python","patch_set":2,"id":"5f7c97a3_2999ba78","line":2089,"in_reply_to":"5f7c97a3_a9c62a9b","updated":"2018-07-09 17:44:53.000000000","message":"Each individual allocation record has only one consumer, right?\n\nA POST to /allocations is a dict keyed on consumer uuid, within which is a dict keyed on resource provider. Each value associated with a consumer uuid clobbers whatever allocations previously existed for that consumer. At least that is how it used to be. Did that change?\n\nIf it hasn\u0027t changed, then in what instance can an allocation have more than one consumer? I suspect I\u0027m misunderstanding something.","commit_id":"0f53ee577f69f250b876412a4c4178d7303a78bc"},{"author":{"_account_id":14070,"name":"Eric Fried","email":"openstack@fried.cc","username":"efried"},"change_message_id":"e7dbded4a2db3a1427ae51362a437f4e55202714","unresolved":false,"context_lines":[{"line_number":1990,"context_line":"        consumers_to_check \u003d all_cons - cons_with_allocs"},{"line_number":1991,"context_line":"        for consumer_uuid in consumers_to_check:"},{"line_number":1992,"context_line":"            consumer_obj.delete_consumer_if_no_allocations("},{"line_number":1993,"context_line":"                context, consumer_uuid)"},{"line_number":1994,"context_line":""},{"line_number":1995,"context_line":"    @classmethod"},{"line_number":1996,"context_line":"    def get_all_by_resource_provider(cls, context, rp):"}],"source_content_type":"text/x-python","patch_set":4,"id":"5f7c97a3_54828ea6","line":1993,"range":{"start_line":1993,"start_character":25,"end_line":1993,"end_character":38},"updated":"2018-07-09 19:35:44.000000000","message":"Would it be more efficient, sql-wise, to send a list of consumer_uuid and have the method use a LEFT JOIN ... WHERE allocations.id IS NULL to identify the list of allocation-less consumers?\n\nFor that matter, perhaps we should just do that - not even pass in consumer_uuid - basically always delete all allocation-less consumers - and that would clean up orphans as well.","commit_id":"126e25eb2f6721a4767f1a2549a20fe3b28ffa60"}],"nova/tests/functional/api/openstack/placement/db/test_consumer.py":[{"author":{"_account_id":6873,"name":"Matt Riedemann","email":"mriedem.os@gmail.com","username":"mriedem"},"change_message_id":"58e8365f58ffd9fd9f7f297c1dd22ba9e7fdb76c","unresolved":false,"context_lines":[{"line_number":240,"context_line":""},{"line_number":241,"context_line":"        # Validate that we have consumer records for both consumers"},{"line_number":242,"context_line":"        for c_uuid in (uuids.consumer1, uuids.consumer2):"},{"line_number":243,"context_line":"            c_obj \u003d consumer_obj.Consumer.get_by_uuid(self.ctx, c_uuid)"},{"line_number":244,"context_line":"            self.assertIsNotNone(c_obj)"},{"line_number":245,"context_line":""},{"line_number":246,"context_line":"        # OK, now \"remove\" the allocation for consumer2 by setting the used"},{"line_number":247,"context_line":"        # value for both allocated resources to 0 and re-running the"}],"source_content_type":"text/x-python","patch_set":4,"id":"5f7c97a3_91e4b8e0","line":244,"range":{"start_line":243,"start_character":12,"end_line":244,"end_character":39},"updated":"2018-07-09 18:38:25.000000000","message":"nit: get_by_uuid would raise ConsumerNotFound if it weren\u0027t found, so we don\u0027t really need to assertIsNotNone here.","commit_id":"126e25eb2f6721a4767f1a2549a20fe3b28ffa60"},{"author":{"_account_id":14070,"name":"Eric Fried","email":"openstack@fried.cc","username":"efried"},"change_message_id":"e7dbded4a2db3a1427ae51362a437f4e55202714","unresolved":false,"context_lines":[{"line_number":278,"context_line":"        # of its allocations"},{"line_number":279,"context_line":"        self.assertRaises("},{"line_number":280,"context_line":"            exception.NotFound, consumer_obj.Consumer.get_by_uuid,"},{"line_number":281,"context_line":"            self.ctx, uuids.consumer1)"}],"source_content_type":"text/x-python","patch_set":4,"id":"5f7c97a3_f47abab8","line":281,"updated":"2018-07-09 19:35:44.000000000","message":"solid","commit_id":"126e25eb2f6721a4767f1a2549a20fe3b28ffa60"}]}
