)]}'
{"nova/api/openstack/placement/handlers/allocation.py":[{"author":{"_account_id":14070,"name":"Eric Fried","email":"openstack@fried.cc","username":"efried"},"change_message_id":"620ff417a114a507fcc4d720ca5b405ad809ea56","unresolved":false,"context_lines":[{"line_number":278,"context_line":"    # information, so use the fake missing project/user sentinel and always"},{"line_number":279,"context_line":"    # create a consumers table record. If we move minimum microversion past"},{"line_number":280,"context_line":"    # 1.8, we can remove this conditional."},{"line_number":281,"context_line":"    if project_id is None:"},{"line_number":282,"context_line":"        project_id \u003d rp_obj.CONSUMER_MISSING_SENTINEL"},{"line_number":283,"context_line":"        user_id \u003d rp_obj.CONSUMER_MISSING_SENTINEL"},{"line_number":284,"context_line":""},{"line_number":285,"context_line":"    consumer \u003d _ensure_consumer(context, consumer_uuid, project_id, user_id)"},{"line_number":286,"context_line":""}],"source_content_type":"text/x-python","patch_set":9,"id":"5f7c97a3_cc7c6fed","line":283,"range":{"start_line":281,"start_character":0,"end_line":283,"end_character":50},"updated":"2018-05-07 22:03:46.000000000","message":"I know they\u0027re interdependent, but I would feel better if this was two separate conditions, one for project and one for user.","commit_id":"afb9262f715df4a898844ac1b4a7c2cb1be0ca1d"},{"author":{"_account_id":11564,"name":"Chris Dent","email":"cdent@anticdent.org","username":"chdent"},"change_message_id":"96f973d75128274794b93151dfd0b692b09744a1","unresolved":false,"context_lines":[{"line_number":195,"context_line":"    return response"},{"line_number":196,"context_line":""},{"line_number":197,"context_line":""},{"line_number":198,"context_line":"def _ensure_consumer(ctx, consumer_uuid, project_id, user_id):"},{"line_number":199,"context_line":"    \"\"\"Ensures there are records in the consumers, projects and users table for"},{"line_number":200,"context_line":"    the supplied external identifiers."},{"line_number":201,"context_line":""}],"source_content_type":"text/x-python","patch_set":11,"id":"5f7c97a3_1138ffec","line":198,"updated":"2018-05-10 13:58:36.000000000","message":"I\u0027d much prefer not see this in the handler file. Up to now, generally speaking we\u0027ve had very limited interactions with the db and objects in the hanlder files. We\u0027ve used the objects (and their file) as the place where much of that happens.\n\nI agree the object file is overworked, but there\u0027s a third option: some other files. It\u0027s important that the handler files be short so that the association between (RESTy) resources and handlers are clear. Having this in here muddies that and encourages long monolithic files, which we don\u0027t want.\n\nThere\u0027s some very tangentially related stuff on this in https://docs.openstack.org/nova/latest/contributor/placement.html#testing","commit_id":"bd54e6b182578e5f81f2b3b9c86131129af52ca1"},{"author":{"_account_id":7,"name":"Jay Pipes","email":"jaypipes@gmail.com","username":"jaypipes"},"change_message_id":"f34b881435189d8e79b21d248ee10a81ef465253","unresolved":false,"context_lines":[{"line_number":195,"context_line":"    return response"},{"line_number":196,"context_line":""},{"line_number":197,"context_line":""},{"line_number":198,"context_line":"def _ensure_consumer(ctx, consumer_uuid, project_id, user_id):"},{"line_number":199,"context_line":"    \"\"\"Ensures there are records in the consumers, projects and users table for"},{"line_number":200,"context_line":"    the supplied external identifiers."},{"line_number":201,"context_line":""}],"source_content_type":"text/x-python","patch_set":11,"id":"5f7c97a3_feb2d193","line":198,"in_reply_to":"5f7c97a3_1138ffec","updated":"2018-05-11 18:52:14.000000000","message":"I put this into the util module.","commit_id":"bd54e6b182578e5f81f2b3b9c86131129af52ca1"},{"author":{"_account_id":7,"name":"Jay Pipes","email":"jaypipes@gmail.com","username":"jaypipes"},"change_message_id":"bb75e32f6f30bdf201836c1213bf4d7498bc0564","unresolved":false,"context_lines":[{"line_number":195,"context_line":"    return response"},{"line_number":196,"context_line":""},{"line_number":197,"context_line":""},{"line_number":198,"context_line":"def _ensure_consumer(ctx, consumer_uuid, project_id, user_id):"},{"line_number":199,"context_line":"    \"\"\"Ensures there are records in the consumers, projects and users table for"},{"line_number":200,"context_line":"    the supplied external identifiers."},{"line_number":201,"context_line":""}],"source_content_type":"text/x-python","patch_set":11,"id":"5f7c97a3_041bdbcf","line":198,"in_reply_to":"5f7c97a3_1138ffec","updated":"2018-05-10 14:18:56.000000000","message":"It\u0027s not (just) that the object *file* is overworked. It\u0027s that the objects themselves are overworked and infested with the (seemingly constantly changing) API microversion logic. If it\u0027s past this version, do this, before this version, do that, etc.\n\nMy goal is to have the objects be plain old data objects and not contain any attributes that are not germane to the object themselves (like the enforce_consumer_generation attribute in Ed\u0027s previously-proposed patch series).\n\nLogic whose conditionals derives from our API microversions should be in the handlers, IMHO, where the conditions for that logic originate.","commit_id":"bd54e6b182578e5f81f2b3b9c86131129af52ca1"},{"author":{"_account_id":11564,"name":"Chris Dent","email":"cdent@anticdent.org","username":"chdent"},"change_message_id":"96f973d75128274794b93151dfd0b692b09744a1","unresolved":false,"context_lines":[{"line_number":269,"context_line":"    # NOTE(jaypipes): Before 1.8, we didn\u0027t require user or project"},{"line_number":270,"context_line":"    # information, so use the fake missing project/user sentinel and always"},{"line_number":271,"context_line":"    # create a consumers table record. If we move minimum microversion past"},{"line_number":272,"context_line":"    # 1.8, we can remove this conditional."},{"line_number":273,"context_line":"    if project_id is None:"},{"line_number":274,"context_line":"        project_id \u003d CONF.placement.incomplete_consumer_project_id"},{"line_number":275,"context_line":"        user_id \u003d CONF.placement.incomplete_consumer_user_id"}],"source_content_type":"text/x-python","patch_set":11,"id":"5f7c97a3_9123afbd","line":272,"updated":"2018-05-10 13:58:36.000000000","message":"Not sure the \"If we move\" sentence is required. We want to encourage that we never raise the minimum microversion.","commit_id":"bd54e6b182578e5f81f2b3b9c86131129af52ca1"},{"author":{"_account_id":11564,"name":"Chris Dent","email":"cdent@anticdent.org","username":"chdent"},"change_message_id":"910fadadffb52d785a84de980a7cf24a6a04af02","unresolved":false,"context_lines":[{"line_number":269,"context_line":"    # NOTE(jaypipes): Before 1.8, we didn\u0027t require user or project"},{"line_number":270,"context_line":"    # information, so use the fake missing project/user sentinel and always"},{"line_number":271,"context_line":"    # create a consumers table record. If we move minimum microversion past"},{"line_number":272,"context_line":"    # 1.8, we can remove this conditional."},{"line_number":273,"context_line":"    if project_id is None:"},{"line_number":274,"context_line":"        project_id \u003d CONF.placement.incomplete_consumer_project_id"},{"line_number":275,"context_line":"        user_id \u003d CONF.placement.incomplete_consumer_user_id"}],"source_content_type":"text/x-python","patch_set":11,"id":"5f7c97a3_e76101ab","line":272,"in_reply_to":"5f7c97a3_04bf5bb0","updated":"2018-05-10 14:39:29.000000000","message":"Since we\u0027ve gone to all the trouble to support microversions at all, we should go ahead and provide the functionality that microversions provide. In the context of Nova, the interop guarantees that microversions in placement provide are not all that relevant, but outside that context they are.\n\nSo I\u0027ll carry on holding this little torch.","commit_id":"bd54e6b182578e5f81f2b3b9c86131129af52ca1"},{"author":{"_account_id":7,"name":"Jay Pipes","email":"jaypipes@gmail.com","username":"jaypipes"},"change_message_id":"32121b7ebdfe461fee3859eb6a682e4782ca7d8d","unresolved":false,"context_lines":[{"line_number":269,"context_line":"    # NOTE(jaypipes): Before 1.8, we didn\u0027t require user or project"},{"line_number":270,"context_line":"    # information, so use the fake missing project/user sentinel and always"},{"line_number":271,"context_line":"    # create a consumers table record. If we move minimum microversion past"},{"line_number":272,"context_line":"    # 1.8, we can remove this conditional."},{"line_number":273,"context_line":"    if project_id is None:"},{"line_number":274,"context_line":"        project_id \u003d CONF.placement.incomplete_consumer_project_id"},{"line_number":275,"context_line":"        user_id \u003d CONF.placement.incomplete_consumer_user_id"}],"source_content_type":"text/x-python","patch_set":11,"id":"5f7c97a3_96d2bcff","line":272,"in_reply_to":"5f7c97a3_569c2469","updated":"2018-05-10 19:06:41.000000000","message":"@mordred: sure, I hear that. it\u0027s annoying as all get-out to have to keep old, crufty code and structs around ad infinitum, though.\n\nAnd that cruft and inconsistency in our APIs is one of the things that I\u0027ve heard numerous people complain about.\n\nJust sayin.","commit_id":"bd54e6b182578e5f81f2b3b9c86131129af52ca1"},{"author":{"_account_id":7,"name":"Jay Pipes","email":"jaypipes@gmail.com","username":"jaypipes"},"change_message_id":"bb75e32f6f30bdf201836c1213bf4d7498bc0564","unresolved":false,"context_lines":[{"line_number":269,"context_line":"    # NOTE(jaypipes): Before 1.8, we didn\u0027t require user or project"},{"line_number":270,"context_line":"    # information, so use the fake missing project/user sentinel and always"},{"line_number":271,"context_line":"    # create a consumers table record. If we move minimum microversion past"},{"line_number":272,"context_line":"    # 1.8, we can remove this conditional."},{"line_number":273,"context_line":"    if project_id is None:"},{"line_number":274,"context_line":"        project_id \u003d CONF.placement.incomplete_consumer_project_id"},{"line_number":275,"context_line":"        user_id \u003d CONF.placement.incomplete_consumer_user_id"}],"source_content_type":"text/x-python","patch_set":11,"id":"5f7c97a3_04bf5bb0","line":272,"in_reply_to":"5f7c97a3_9123afbd","updated":"2018-05-10 14:18:56.000000000","message":"I disagree with you about never raising the minimum microversion.","commit_id":"bd54e6b182578e5f81f2b3b9c86131129af52ca1"},{"author":{"_account_id":11564,"name":"Chris Dent","email":"cdent@anticdent.org","username":"chdent"},"change_message_id":"127b81be536db465f3bd6318f2ae3bc9250736df","unresolved":false,"context_lines":[{"line_number":269,"context_line":"    # NOTE(jaypipes): Before 1.8, we didn\u0027t require user or project"},{"line_number":270,"context_line":"    # information, so use the fake missing project/user sentinel and always"},{"line_number":271,"context_line":"    # create a consumers table record. If we move minimum microversion past"},{"line_number":272,"context_line":"    # 1.8, we can remove this conditional."},{"line_number":273,"context_line":"    if project_id is None:"},{"line_number":274,"context_line":"        project_id \u003d CONF.placement.incomplete_consumer_project_id"},{"line_number":275,"context_line":"        user_id \u003d CONF.placement.incomplete_consumer_user_id"}],"source_content_type":"text/x-python","patch_set":11,"id":"5f7c97a3_f32c6303","line":272,"in_reply_to":"5f7c97a3_937c0f20","updated":"2018-05-10 17:29:31.000000000","message":"\u003e I\u0027m not really sure what the above means. If you mean that your\n \u003e interpretation of the purpose of microversions is to allow users to\n \u003e continue to call old versions of an API ad infinitum, I\u0027m afraid I\n \u003e have to object to that.\n\nYou are welcome to object, and agreeable people can disagree, but there are plenty of people who think that is _exactly_ the value of microversions. I reckon a primary promulgator of this idea is Monty.\n\nThat position is one of several reasons why I have objected to microversions in the past: they can result in a lack of an evolutionary balance between \"users\" and \"developers\". The justification is that we (the \"developers\") are willingly taking on a burden to allow others some ease.\n\nIf we were to desire to raise the minimum, then that ought to be considered something like a major version break, but we haven\u0027t got non-micro versions in placement, so we\u0027re in a weird state.\n\nSo to be differently concise: if we\u0027re going to do microversions, let\u0027s do them, including all their warts (of which there are many).","commit_id":"bd54e6b182578e5f81f2b3b9c86131129af52ca1"},{"author":{"_account_id":7,"name":"Jay Pipes","email":"jaypipes@gmail.com","username":"jaypipes"},"change_message_id":"d380cf5631a821e75e5bca03ec951fc2c3015268","unresolved":false,"context_lines":[{"line_number":269,"context_line":"    # NOTE(jaypipes): Before 1.8, we didn\u0027t require user or project"},{"line_number":270,"context_line":"    # information, so use the fake missing project/user sentinel and always"},{"line_number":271,"context_line":"    # create a consumers table record. If we move minimum microversion past"},{"line_number":272,"context_line":"    # 1.8, we can remove this conditional."},{"line_number":273,"context_line":"    if project_id is None:"},{"line_number":274,"context_line":"        project_id \u003d CONF.placement.incomplete_consumer_project_id"},{"line_number":275,"context_line":"        user_id \u003d CONF.placement.incomplete_consumer_user_id"}],"source_content_type":"text/x-python","patch_set":11,"id":"5f7c97a3_937c0f20","line":272,"in_reply_to":"5f7c97a3_e76101ab","updated":"2018-05-10 17:18:50.000000000","message":"I\u0027m not really sure what the above means. If you mean that your interpretation of the purpose of microversions is to allow users to continue to call old versions of an API ad infinitum, I\u0027m afraid I have to object to that.\n\nThe purpose of microversions was to allow a *controlled evolution* of the API when changes or cleanups to the API were needed (in addition to providing a signaling mechanism to consumers that the API had changed).\n\nUpping the minimum supported microversion is simply a statement by the API authors that the API has evolved past some old structure and if users want to use the API in its current supported form, they should up the microversion they send as acceptable and get with the program.","commit_id":"bd54e6b182578e5f81f2b3b9c86131129af52ca1"},{"author":{"_account_id":2,"name":"Monty Taylor","email":"mordred@inaugust.com","username":"mordred"},"change_message_id":"722a191325fba1c62e6178b7c91abdbda158e0ee","unresolved":false,"context_lines":[{"line_number":269,"context_line":"    # NOTE(jaypipes): Before 1.8, we didn\u0027t require user or project"},{"line_number":270,"context_line":"    # information, so use the fake missing project/user sentinel and always"},{"line_number":271,"context_line":"    # create a consumers table record. If we move minimum microversion past"},{"line_number":272,"context_line":"    # 1.8, we can remove this conditional."},{"line_number":273,"context_line":"    if project_id is None:"},{"line_number":274,"context_line":"        project_id \u003d CONF.placement.incomplete_consumer_project_id"},{"line_number":275,"context_line":"        user_id \u003d CONF.placement.incomplete_consumer_user_id"}],"source_content_type":"text/x-python","patch_set":11,"id":"5f7c97a3_569c2469","line":272,"in_reply_to":"5f7c97a3_f32c6303","updated":"2018-05-10 19:02:04.000000000","message":"From an end-user perspective, bumping the min microversion is functionally equivalent to bumping a major version. The beauty of microversions is that they empower the USER to adopt new functionality or breaking changes on their terms and timelines.\n\nWith OpenStack we do not have the luxury of a single deployment. That means tools and frameworks MUST support all of the versions. We could point our fingers at a deployer and say \"your cloud is too old\" - but that doesn\u0027t come across to end-users. To the end user, they\u0027ll experience \"I did pip install ansible and then tried to use os_server and it didn\u0027t work ... man OpenStack sucks\"\n\nWith microversions we seem to have found a happy medium. As a service developer new things can be added or new cleaner ways of doing things can be added. The neutron port_id for a fixed address could be added to the server record so the end-user doesn\u0027t have to perform an in-memory join across two services and 4 resources in their own code in order to be able to safely attach a floating ip ... but it can be put behind a microversion so that if someone has written code which would be confused by new substructures in the server record they won\u0027t get broken.\n\nAs a user, I don\u0027t have to care about a new microversion until I care. Then I only have to care about it on a case-by-case basis. For instance, I can check if \"get-me-a-network\" microversion exists and if so use it, but otherwise can do it the 10 API call method. get-me-a-network itself can be exposed in libraries and frameworks.\n\nFor supporting the ability to use tools across clouds - this is **awesome**.\n\nIt\u0027s not a magic wand though - and it doesn\u0027t change the fundamental nature of removing api calls.\n\n  \"Upping the minimum supported microversion is simply a statement by the API authors that the API has evolved past some old structure and if users want to use the API in its current supported form, they should up the microversion they send as acceptable and get with the program.\"\n\nThat would be true if we were all working on the same installation of a service, or if any given user were only ever reasonably expected to consume one installation of a service. What bumping a min ACTUALLY does is shift the burden of support from the service authors to the library and framework authors where it has to be repeated for every language and framework.\n\nSo yes - there is a mechanism and it can be used. But let\u0027s be really clear -  doing so will not clean anything up or make anything go away, it\u0027ll just shift the mess to somewhere else. Exercise it if you must - but it is a MASSIVE sledgehammer so **PLEASE** for the love of all that is holy have a **REALLY** good reason.\n\nAnd actually, as a request from someone who deals with api version differences on the daily - **PLEASE** just cut a new major version when you do. It\u0027ll be much easier on consumers.","commit_id":"bd54e6b182578e5f81f2b3b9c86131129af52ca1"},{"author":{"_account_id":11564,"name":"Chris Dent","email":"cdent@anticdent.org","username":"chdent"},"change_message_id":"96f973d75128274794b93151dfd0b692b09744a1","unresolved":false,"context_lines":[{"line_number":272,"context_line":"    # 1.8, we can remove this conditional."},{"line_number":273,"context_line":"    if project_id is None:"},{"line_number":274,"context_line":"        project_id \u003d CONF.placement.incomplete_consumer_project_id"},{"line_number":275,"context_line":"        user_id \u003d CONF.placement.incomplete_consumer_user_id"},{"line_number":276,"context_line":""},{"line_number":277,"context_line":"    consumer \u003d _ensure_consumer(context, consumer_uuid, project_id, user_id)"},{"line_number":278,"context_line":""}],"source_content_type":"text/x-python","patch_set":11,"id":"5f7c97a3_4430f3e8","line":275,"updated":"2018-05-10 13:58:36.000000000","message":"Consider moving this in to _ensure_consumer so that when that gets moved to some other file, only that file needs to import icky CONF?","commit_id":"bd54e6b182578e5f81f2b3b9c86131129af52ca1"},{"author":{"_account_id":7,"name":"Jay Pipes","email":"jaypipes@gmail.com","username":"jaypipes"},"change_message_id":"f34b881435189d8e79b21d248ee10a81ef465253","unresolved":false,"context_lines":[{"line_number":272,"context_line":"    # 1.8, we can remove this conditional."},{"line_number":273,"context_line":"    if project_id is None:"},{"line_number":274,"context_line":"        project_id \u003d CONF.placement.incomplete_consumer_project_id"},{"line_number":275,"context_line":"        user_id \u003d CONF.placement.incomplete_consumer_user_id"},{"line_number":276,"context_line":""},{"line_number":277,"context_line":"    consumer \u003d _ensure_consumer(context, consumer_uuid, project_id, user_id)"},{"line_number":278,"context_line":""}],"source_content_type":"text/x-python","patch_set":11,"id":"5f7c97a3_3eb5a97e","line":275,"in_reply_to":"5f7c97a3_4430f3e8","updated":"2018-05-11 18:52:14.000000000","message":"Done","commit_id":"bd54e6b182578e5f81f2b3b9c86131129af52ca1"},{"author":{"_account_id":7,"name":"Jay Pipes","email":"jaypipes@gmail.com","username":"jaypipes"},"change_message_id":"bb75e32f6f30bdf201836c1213bf4d7498bc0564","unresolved":false,"context_lines":[{"line_number":272,"context_line":"    # 1.8, we can remove this conditional."},{"line_number":273,"context_line":"    if project_id is None:"},{"line_number":274,"context_line":"        project_id \u003d CONF.placement.incomplete_consumer_project_id"},{"line_number":275,"context_line":"        user_id \u003d CONF.placement.incomplete_consumer_user_id"},{"line_number":276,"context_line":""},{"line_number":277,"context_line":"    consumer \u003d _ensure_consumer(context, consumer_uuid, project_id, user_id)"},{"line_number":278,"context_line":""}],"source_content_type":"text/x-python","patch_set":11,"id":"5f7c97a3_444313b0","line":275,"in_reply_to":"5f7c97a3_4430f3e8","updated":"2018-05-10 14:18:56.000000000","message":"ack, can do.","commit_id":"bd54e6b182578e5f81f2b3b9c86131129af52ca1"},{"author":{"_account_id":11564,"name":"Chris Dent","email":"cdent@anticdent.org","username":"chdent"},"change_message_id":"96f973d75128274794b93151dfd0b692b09744a1","unresolved":false,"context_lines":[{"line_number":280,"context_line":"        allocation \u003d rp_obj.Allocation("},{"line_number":281,"context_line":"            resource_provider\u003dresource_provider,"},{"line_number":282,"context_line":"            consumer_id\u003dconsumer_uuid,"},{"line_number":283,"context_line":"            consumer\u003dconsumer,"},{"line_number":284,"context_line":"            resource_class\u003dresource_class,"},{"line_number":285,"context_line":"            used\u003dresources[resource_class])"},{"line_number":286,"context_line":"        allocations.append(allocation)"}],"source_content_type":"text/x-python","patch_set":11,"id":"5f7c97a3_1121dfb0","line":283,"updated":"2018-05-10 13:58:36.000000000","message":"If we have a consumer object, why do we also need a consumer_id?","commit_id":"bd54e6b182578e5f81f2b3b9c86131129af52ca1"},{"author":{"_account_id":7,"name":"Jay Pipes","email":"jaypipes@gmail.com","username":"jaypipes"},"change_message_id":"bb75e32f6f30bdf201836c1213bf4d7498bc0564","unresolved":false,"context_lines":[{"line_number":280,"context_line":"        allocation \u003d rp_obj.Allocation("},{"line_number":281,"context_line":"            resource_provider\u003dresource_provider,"},{"line_number":282,"context_line":"            consumer_id\u003dconsumer_uuid,"},{"line_number":283,"context_line":"            consumer\u003dconsumer,"},{"line_number":284,"context_line":"            resource_class\u003dresource_class,"},{"line_number":285,"context_line":"            used\u003dresources[resource_class])"},{"line_number":286,"context_line":"        allocations.append(allocation)"}],"source_content_type":"text/x-python","patch_set":11,"id":"5f7c97a3_e42c9f03","line":283,"in_reply_to":"5f7c97a3_1121dfb0","updated":"2018-05-10 14:18:56.000000000","message":"we don\u0027t any more. this patch series has gone through a number of iterations. an earlier revision was not creating consumers table records when the project/user was missing. The consumer_id column was used when those consumer records were not found in the backend database.\n\nNow that consumer records are always created and guaranteed to be available, I can remove the consumer_id field from the Allocation object.","commit_id":"bd54e6b182578e5f81f2b3b9c86131129af52ca1"},{"author":{"_account_id":7,"name":"Jay Pipes","email":"jaypipes@gmail.com","username":"jaypipes"},"change_message_id":"f34b881435189d8e79b21d248ee10a81ef465253","unresolved":false,"context_lines":[{"line_number":280,"context_line":"        allocation \u003d rp_obj.Allocation("},{"line_number":281,"context_line":"            resource_provider\u003dresource_provider,"},{"line_number":282,"context_line":"            consumer_id\u003dconsumer_uuid,"},{"line_number":283,"context_line":"            consumer\u003dconsumer,"},{"line_number":284,"context_line":"            resource_class\u003dresource_class,"},{"line_number":285,"context_line":"            used\u003dresources[resource_class])"},{"line_number":286,"context_line":"        allocations.append(allocation)"}],"source_content_type":"text/x-python","patch_set":11,"id":"5f7c97a3_5ebae56d","line":283,"in_reply_to":"5f7c97a3_e42c9f03","updated":"2018-05-11 18:52:14.000000000","message":"Done","commit_id":"bd54e6b182578e5f81f2b3b9c86131129af52ca1"},{"author":{"_account_id":4393,"name":"Dan Smith","email":"dms@danplanet.com","username":"danms"},"change_message_id":"5c307f93dcafc5c02fdfdcda6fae1e4c8dca941f","unresolved":false,"context_lines":[{"line_number":27,"context_line":"from nova.api.openstack.placement import wsgi_wrapper"},{"line_number":28,"context_line":"from nova.i18n import _"},{"line_number":29,"context_line":""},{"line_number":30,"context_line":""},{"line_number":31,"context_line":"LOG \u003d logging.getLogger(__name__)"},{"line_number":32,"context_line":""},{"line_number":33,"context_line":""}],"source_content_type":"text/x-python","patch_set":13,"id":"5f7c97a3_e7615d13","side":"PARENT","line":30,"updated":"2018-05-18 16:03:26.000000000","message":"Random whitespace damage","commit_id":"52f0d2ecc5dd0507bf3e348ec9bd06c48de761b0"},{"author":{"_account_id":7,"name":"Jay Pipes","email":"jaypipes@gmail.com","username":"jaypipes"},"change_message_id":"33892f86fed4f2e44b2be800b72f848a90bcd9dd","unresolved":false,"context_lines":[{"line_number":27,"context_line":"from nova.api.openstack.placement import wsgi_wrapper"},{"line_number":28,"context_line":"from nova.i18n import _"},{"line_number":29,"context_line":""},{"line_number":30,"context_line":""},{"line_number":31,"context_line":"LOG \u003d logging.getLogger(__name__)"},{"line_number":32,"context_line":""},{"line_number":33,"context_line":""}],"source_content_type":"text/x-python","patch_set":13,"id":"5f7c97a3_2b4f0035","side":"PARENT","line":30,"in_reply_to":"5f7c97a3_e7615d13","updated":"2018-05-21 17:32:54.000000000","message":"Done","commit_id":"52f0d2ecc5dd0507bf3e348ec9bd06c48de761b0"},{"author":{"_account_id":4393,"name":"Dan Smith","email":"dms@danplanet.com","username":"danms"},"change_message_id":"5c307f93dcafc5c02fdfdcda6fae1e4c8dca941f","unresolved":false,"context_lines":[{"line_number":61,"context_line":"        result[\u0027resource_provider_generation\u0027] \u003d resource_provider.generation"},{"line_number":62,"context_line":"    else:"},{"line_number":63,"context_line":"        if allocations and want_version and want_version.matches((1, 12)):"},{"line_number":64,"context_line":"            project_id \u003d allocations[0].consumer.project.external_id"},{"line_number":65,"context_line":"            user_id \u003d allocations[0].consumer.user.external_id"},{"line_number":66,"context_line":""},{"line_number":67,"context_line":"            result[\u0027project_id\u0027] \u003d project_id"}],"source_content_type":"text/x-python","patch_set":13,"id":"5f7c97a3_07081826","line":64,"updated":"2018-05-18 16:03:26.000000000","message":"This is just a suggestion, but what about a @property on consumer for project_id and user_id? I think it makes sense to reference consumer here, but maybe the property could sugar this up a bit so it looks like:\n\n result[\u0027project_id\u0027] \u003d allocations[0].consumer.project_id\n\nand consumer gets:\n\n @property\n def project_id(self):\n     return self.project.external_id\n\nand so forth? Maybe that would help with the appearance of it being so heavy, drilling through all the objects?","commit_id":"624c8ada83ba920d361217d2be4498c534a9180e"},{"author":{"_account_id":7,"name":"Jay Pipes","email":"jaypipes@gmail.com","username":"jaypipes"},"change_message_id":"33892f86fed4f2e44b2be800b72f848a90bcd9dd","unresolved":false,"context_lines":[{"line_number":61,"context_line":"        result[\u0027resource_provider_generation\u0027] \u003d resource_provider.generation"},{"line_number":62,"context_line":"    else:"},{"line_number":63,"context_line":"        if allocations and want_version and want_version.matches((1, 12)):"},{"line_number":64,"context_line":"            project_id \u003d allocations[0].consumer.project.external_id"},{"line_number":65,"context_line":"            user_id \u003d allocations[0].consumer.user.external_id"},{"line_number":66,"context_line":""},{"line_number":67,"context_line":"            result[\u0027project_id\u0027] \u003d project_id"}],"source_content_type":"text/x-python","patch_set":13,"id":"5f7c97a3_0b1b241b","line":64,"in_reply_to":"5f7c97a3_07081826","updated":"2018-05-21 17:32:54.000000000","message":"Yeah, I considered that, but ended up actually preferring the longer format because it was explicit that the thing we were emitting was the *external* ID of the project, whereas a property called Consumer.project_id kinda gives the impression that it\u0027s an internal identifier for the project? If you feel strongly about it, though, I can certainly add the @property sugar.","commit_id":"624c8ada83ba920d361217d2be4498c534a9180e"},{"author":{"_account_id":14070,"name":"Eric Fried","email":"openstack@fried.cc","username":"efried"},"change_message_id":"25e58796f48189dfe7855d94981999f2f7de6503","unresolved":false,"context_lines":[{"line_number":63,"context_line":"        result[\u0027resource_provider_generation\u0027] \u003d resource_provider.generation"},{"line_number":64,"context_line":"    else:"},{"line_number":65,"context_line":"        if allocations and want_version and want_version.matches((1, 12)):"},{"line_number":66,"context_line":"            project_id \u003d allocations[0].consumer.project.external_id"},{"line_number":67,"context_line":"            user_id \u003d allocations[0].consumer.user.external_id"},{"line_number":68,"context_line":""},{"line_number":69,"context_line":"            result[\u0027project_id\u0027] \u003d project_id"}],"source_content_type":"text/x-python","patch_set":23,"id":"5f7c97a3_3b9cb2be","line":66,"updated":"2018-06-12 21:42:46.000000000","message":"I liked the comment that explained why it\u0027s okay to peel these out of the first allocation.","commit_id":"d6517e58536696d7fa903872dba5b83da2fb0def"},{"author":{"_account_id":6873,"name":"Matt Riedemann","email":"mriedem.os@gmail.com","username":"mriedem"},"change_message_id":"9dff7f096a3da005e0f7a84ebb7ad710b3b075bf","unresolved":false,"context_lines":[{"line_number":63,"context_line":"        result[\u0027resource_provider_generation\u0027] \u003d resource_provider.generation"},{"line_number":64,"context_line":"    else:"},{"line_number":65,"context_line":"        if allocations and want_version and want_version.matches((1, 12)):"},{"line_number":66,"context_line":"            project_id \u003d allocations[0].consumer.project.external_id"},{"line_number":67,"context_line":"            user_id \u003d allocations[0].consumer.user.external_id"},{"line_number":68,"context_line":""},{"line_number":69,"context_line":"            result[\u0027project_id\u0027] \u003d project_id"}],"source_content_type":"text/x-python","patch_set":23,"id":"5f7c97a3_910d9890","line":66,"in_reply_to":"5f7c97a3_3b9cb2be","updated":"2018-06-13 13:29:22.000000000","message":"agree that was useful","commit_id":"d6517e58536696d7fa903872dba5b83da2fb0def"},{"author":{"_account_id":7,"name":"Jay Pipes","email":"jaypipes@gmail.com","username":"jaypipes"},"change_message_id":"7404eaa06234ccaa310b02c2068a501188777681","unresolved":false,"context_lines":[{"line_number":63,"context_line":"        result[\u0027resource_provider_generation\u0027] \u003d resource_provider.generation"},{"line_number":64,"context_line":"    else:"},{"line_number":65,"context_line":"        if allocations and want_version and want_version.matches((1, 12)):"},{"line_number":66,"context_line":"            project_id \u003d allocations[0].consumer.project.external_id"},{"line_number":67,"context_line":"            user_id \u003d allocations[0].consumer.user.external_id"},{"line_number":68,"context_line":""},{"line_number":69,"context_line":"            result[\u0027project_id\u0027] \u003d project_id"}],"source_content_type":"text/x-python","patch_set":23,"id":"5f7c97a3_1742d83b","line":66,"in_reply_to":"5f7c97a3_910d9890","updated":"2018-06-13 14:38:15.000000000","message":"Done","commit_id":"d6517e58536696d7fa903872dba5b83da2fb0def"}],"nova/api/openstack/placement/objects/consumer.py":[{"author":{"_account_id":11564,"name":"Chris Dent","email":"cdent@anticdent.org","username":"chdent"},"change_message_id":"1a8601952bf7264f469411d2e108584a4bb03c2d","unresolved":false,"context_lines":[{"line_number":22,"context_line":"from nova.db.sqlalchemy import api_models as models"},{"line_number":23,"context_line":""},{"line_number":24,"context_line":"CONSUMER_TBL \u003d models.Consumer.__table__"},{"line_number":25,"context_line":"_ALLOC_TBL \u003d models.Allocation.__table__"},{"line_number":26,"context_line":""},{"line_number":27,"context_line":""},{"line_number":28,"context_line":"@db_api.api_context_manager.writer"}],"source_content_type":"text/x-python","patch_set":18,"id":"5f7c97a3_178626bc","line":25,"updated":"2018-06-04 17:56:34.000000000","message":"Not that it really matters, but the disjunct between private and not private here is a bit jarring. I guess CONSUMER is the odd one out, comparing with the next file.","commit_id":"f12875ac3a5f64c1d33a4a1803e052ad9c980c80"},{"author":{"_account_id":7,"name":"Jay Pipes","email":"jaypipes@gmail.com","username":"jaypipes"},"change_message_id":"b703d24cf31009659261a5fd413633ace94ef819","unresolved":false,"context_lines":[{"line_number":22,"context_line":"from nova.db.sqlalchemy import api_models as models"},{"line_number":23,"context_line":""},{"line_number":24,"context_line":"CONSUMER_TBL \u003d models.Consumer.__table__"},{"line_number":25,"context_line":"_ALLOC_TBL \u003d models.Allocation.__table__"},{"line_number":26,"context_line":""},{"line_number":27,"context_line":""},{"line_number":28,"context_line":"@db_api.api_context_manager.writer"}],"source_content_type":"text/x-python","patch_set":18,"id":"5f7c97a3_b2be60d2","line":25,"in_reply_to":"5f7c97a3_178626bc","updated":"2018-06-04 18:10:02.000000000","message":"ack. I reference the CONSUMER_TBL object from the functional test file which is why I made it \"public\" here. But yes, I hear you. It is a bit jarring.","commit_id":"f12875ac3a5f64c1d33a4a1803e052ad9c980c80"},{"author":{"_account_id":14070,"name":"Eric Fried","email":"openstack@fried.cc","username":"efried"},"change_message_id":"25e58796f48189dfe7855d94981999f2f7de6503","unresolved":false,"context_lines":[{"line_number":45,"context_line":"    # allocations.consumer_id doesn\u0027t exist in the consumers table. Use the"},{"line_number":46,"context_line":"    # incomplete consumer project and user ID."},{"line_number":47,"context_line":"    alloc_to_consumer \u003d sa.outerjoin("},{"line_number":48,"context_line":"        _ALLOC_TBL, CONSUMER_TBL,"},{"line_number":49,"context_line":"        _ALLOC_TBL.c.consumer_id \u003d\u003d CONSUMER_TBL.c.uuid)"},{"line_number":50,"context_line":"    cols \u003d ["},{"line_number":51,"context_line":"        _ALLOC_TBL.c.consumer_id,"},{"line_number":52,"context_line":"        incomplete_proj_id,"},{"line_number":53,"context_line":"        incomplete_user_id,"},{"line_number":54,"context_line":"    ]"}],"source_content_type":"text/x-python","patch_set":23,"id":"5f7c97a3_bb98c2bf","line":51,"range":{"start_line":48,"start_character":0,"end_line":51,"end_character":33},"updated":"2018-06-12 21:42:46.000000000","message":"I like this cleanup, but to be clear, it\u0027s not related to this patch functionally, right?","commit_id":"d6517e58536696d7fa903872dba5b83da2fb0def"}],"nova/api/openstack/placement/objects/resource_provider.py":[{"author":{"_account_id":14070,"name":"Eric Fried","email":"openstack@fried.cc","username":"efried"},"change_message_id":"f27b9b0c2200e69d49809c55fb51d9b3e75a2c91","unresolved":false,"context_lines":[{"line_number":1732,"context_line":"    fields \u003d {"},{"line_number":1733,"context_line":"        \u0027id\u0027: fields.IntegerField(),"},{"line_number":1734,"context_line":"        \u0027resource_provider\u0027: fields.ObjectField(\u0027ResourceProvider\u0027),"},{"line_number":1735,"context_line":"        \u0027consumer_id\u0027: fields.UUIDField(),"},{"line_number":1736,"context_line":"        # TODO(jaypipes): Make this field non-nullable when we remove support"},{"line_number":1737,"context_line":"        # for microversions \u003c\u003d1.7 which did not require a user/project and only"},{"line_number":1738,"context_line":"        # supplied a consumer UUID"}],"source_content_type":"text/x-python","patch_set":2,"id":"9f6a8fd7_808cea35","line":1735,"range":{"start_line":1735,"start_character":8,"end_line":1735,"end_character":42},"updated":"2018-05-01 15:48:23.000000000","message":"TODO(jaypipes): Remove this field when we remove support for microversions \u003c\u003d1.7 (because `consumer` will always be present, so this is redundant).","commit_id":"4f2b060b5c23ad2daa138b405730516299bd96c5"},{"author":{"_account_id":7,"name":"Jay Pipes","email":"jaypipes@gmail.com","username":"jaypipes"},"change_message_id":"14a628e5bac6650736f182f519e0fff414bc9161","unresolved":false,"context_lines":[{"line_number":1732,"context_line":"    fields \u003d {"},{"line_number":1733,"context_line":"        \u0027id\u0027: fields.IntegerField(),"},{"line_number":1734,"context_line":"        \u0027resource_provider\u0027: fields.ObjectField(\u0027ResourceProvider\u0027),"},{"line_number":1735,"context_line":"        \u0027consumer_id\u0027: fields.UUIDField(),"},{"line_number":1736,"context_line":"        # TODO(jaypipes): Make this field non-nullable when we remove support"},{"line_number":1737,"context_line":"        # for microversions \u003c\u003d1.7 which did not require a user/project and only"},{"line_number":1738,"context_line":"        # supplied a consumer UUID"}],"source_content_type":"text/x-python","patch_set":2,"id":"9f6a8fd7_40a1f245","line":1735,"range":{"start_line":1735,"start_character":8,"end_line":1735,"end_character":42},"in_reply_to":"9f6a8fd7_808cea35","updated":"2018-05-01 16:01:14.000000000","message":"Done","commit_id":"4f2b060b5c23ad2daa138b405730516299bd96c5"},{"author":{"_account_id":14070,"name":"Eric Fried","email":"openstack@fried.cc","username":"efried"},"change_message_id":"78cfef6e5be8e54ccf78778c031435aab327c0aa","unresolved":false,"context_lines":[{"line_number":1746,"context_line":"        \u0027user_id\u0027: fields.StringField(nullable\u003dTrue),"},{"line_number":1747,"context_line":"    }"},{"line_number":1748,"context_line":""},{"line_number":1749,"context_line":"    def ensure_consumer_project_user(self, ctx):"},{"line_number":1750,"context_line":"        \"\"\"Examines the project_id, user_id of the object along with the"},{"line_number":1751,"context_line":"        supplied consumer_id and ensures that if project_id and user_id"},{"line_number":1752,"context_line":"        are set that there are records in the consumers, projects, and"},{"line_number":1753,"context_line":"        users table for these entities."},{"line_number":1754,"context_line":""},{"line_number":1755,"context_line":"        :param ctx: `nova.context.RequestContext` object that has the oslo.db"},{"line_number":1756,"context_line":"                    Session object in it"},{"line_number":1757,"context_line":"        \"\"\""},{"line_number":1758,"context_line":"        # If project_id and user_id are not set then silently"},{"line_number":1759,"context_line":"        # move on. This allows microversion \u003c1.8 to continue to work. Since"},{"line_number":1760,"context_line":"        # then the fields are required and the enforcement is at the HTTP"},{"line_number":1761,"context_line":"        # API layer."},{"line_number":1762,"context_line":"        if not (\u0027project_id\u0027 in self and"},{"line_number":1763,"context_line":"                self.project_id is not None and"},{"line_number":1764,"context_line":"                \u0027user_id\u0027 in self and"},{"line_number":1765,"context_line":"                self.user_id is not None):"},{"line_number":1766,"context_line":"            return"},{"line_number":1767,"context_line":"        # Grab the project internal ID if it exists in the projects table"},{"line_number":1768,"context_line":"        pid \u003d _ensure_project(ctx, self.project_id)"},{"line_number":1769,"context_line":"        # Grab the user internal ID if it exists in the users table"},{"line_number":1770,"context_line":"        uid \u003d _ensure_user(ctx, self.user_id)"},{"line_number":1771,"context_line":""},{"line_number":1772,"context_line":"        # Add the consumer if it doesn\u0027t already exist"},{"line_number":1773,"context_line":"        sel_stmt \u003d sa.select([_CONSUMER_TBL.c.uuid]).where("},{"line_number":1774,"context_line":"            _CONSUMER_TBL.c.uuid \u003d\u003d self.consumer_id)"},{"line_number":1775,"context_line":"        result \u003d ctx.session.execute(sel_stmt).fetchall()"},{"line_number":1776,"context_line":"        if not result:"},{"line_number":1777,"context_line":"            try:"},{"line_number":1778,"context_line":"                ctx.session.execute(_CONSUMER_TBL.insert().values("},{"line_number":1779,"context_line":"                    uuid\u003dself.consumer_id,"},{"line_number":1780,"context_line":"                    project_id\u003dpid,"},{"line_number":1781,"context_line":"                    user_id\u003duid))"},{"line_number":1782,"context_line":"            except db_exc.DBDuplicateEntry:"},{"line_number":1783,"context_line":"                # We assume at this time that a consumer project/user can\u0027t"},{"line_number":1784,"context_line":"                # change, so if we get here, we raced and should just pass"},{"line_number":1785,"context_line":"                # if the consumer already exists."},{"line_number":1786,"context_line":"                pass"},{"line_number":1787,"context_line":""},{"line_number":1788,"context_line":""},{"line_number":1789,"context_line":"@db_api.api_context_manager.writer"}],"source_content_type":"text/x-python","patch_set":2,"id":"9f6a8fd7_255bb087","line":1786,"range":{"start_line":1749,"start_character":0,"end_line":1786,"end_character":20},"updated":"2018-05-01 15:33:41.000000000","message":"This can go now, right?","commit_id":"4f2b060b5c23ad2daa138b405730516299bd96c5"},{"author":{"_account_id":7,"name":"Jay Pipes","email":"jaypipes@gmail.com","username":"jaypipes"},"change_message_id":"0deec00c7188b0f4fe1ace8003e95b6248e17593","unresolved":false,"context_lines":[{"line_number":1746,"context_line":"        \u0027user_id\u0027: fields.StringField(nullable\u003dTrue),"},{"line_number":1747,"context_line":"    }"},{"line_number":1748,"context_line":""},{"line_number":1749,"context_line":"    def ensure_consumer_project_user(self, ctx):"},{"line_number":1750,"context_line":"        \"\"\"Examines the project_id, user_id of the object along with the"},{"line_number":1751,"context_line":"        supplied consumer_id and ensures that if project_id and user_id"},{"line_number":1752,"context_line":"        are set that there are records in the consumers, projects, and"},{"line_number":1753,"context_line":"        users table for these entities."},{"line_number":1754,"context_line":""},{"line_number":1755,"context_line":"        :param ctx: `nova.context.RequestContext` object that has the oslo.db"},{"line_number":1756,"context_line":"                    Session object in it"},{"line_number":1757,"context_line":"        \"\"\""},{"line_number":1758,"context_line":"        # If project_id and user_id are not set then silently"},{"line_number":1759,"context_line":"        # move on. This allows microversion \u003c1.8 to continue to work. Since"},{"line_number":1760,"context_line":"        # then the fields are required and the enforcement is at the HTTP"},{"line_number":1761,"context_line":"        # API layer."},{"line_number":1762,"context_line":"        if not (\u0027project_id\u0027 in self and"},{"line_number":1763,"context_line":"                self.project_id is not None and"},{"line_number":1764,"context_line":"                \u0027user_id\u0027 in self and"},{"line_number":1765,"context_line":"                self.user_id is not None):"},{"line_number":1766,"context_line":"            return"},{"line_number":1767,"context_line":"        # Grab the project internal ID if it exists in the projects table"},{"line_number":1768,"context_line":"        pid \u003d _ensure_project(ctx, self.project_id)"},{"line_number":1769,"context_line":"        # Grab the user internal ID if it exists in the users table"},{"line_number":1770,"context_line":"        uid \u003d _ensure_user(ctx, self.user_id)"},{"line_number":1771,"context_line":""},{"line_number":1772,"context_line":"        # Add the consumer if it doesn\u0027t already exist"},{"line_number":1773,"context_line":"        sel_stmt \u003d sa.select([_CONSUMER_TBL.c.uuid]).where("},{"line_number":1774,"context_line":"            _CONSUMER_TBL.c.uuid \u003d\u003d self.consumer_id)"},{"line_number":1775,"context_line":"        result \u003d ctx.session.execute(sel_stmt).fetchall()"},{"line_number":1776,"context_line":"        if not result:"},{"line_number":1777,"context_line":"            try:"},{"line_number":1778,"context_line":"                ctx.session.execute(_CONSUMER_TBL.insert().values("},{"line_number":1779,"context_line":"                    uuid\u003dself.consumer_id,"},{"line_number":1780,"context_line":"                    project_id\u003dpid,"},{"line_number":1781,"context_line":"                    user_id\u003duid))"},{"line_number":1782,"context_line":"            except db_exc.DBDuplicateEntry:"},{"line_number":1783,"context_line":"                # We assume at this time that a consumer project/user can\u0027t"},{"line_number":1784,"context_line":"                # change, so if we get here, we raced and should just pass"},{"line_number":1785,"context_line":"                # if the consumer already exists."},{"line_number":1786,"context_line":"                pass"},{"line_number":1787,"context_line":""},{"line_number":1788,"context_line":""},{"line_number":1789,"context_line":"@db_api.api_context_manager.writer"}],"source_content_type":"text/x-python","patch_set":2,"id":"9f6a8fd7_602d1645","line":1786,"range":{"start_line":1749,"start_character":0,"end_line":1786,"end_character":20},"in_reply_to":"9f6a8fd7_255bb087","updated":"2018-05-01 15:48:05.000000000","message":"It is removed in the following patch when the project_id and user_id fields are removed from the Allocation object entirely.","commit_id":"4f2b060b5c23ad2daa138b405730516299bd96c5"},{"author":{"_account_id":7,"name":"Jay Pipes","email":"jaypipes@gmail.com","username":"jaypipes"},"change_message_id":"14a628e5bac6650736f182f519e0fff414bc9161","unresolved":false,"context_lines":[{"line_number":1746,"context_line":"        \u0027user_id\u0027: fields.StringField(nullable\u003dTrue),"},{"line_number":1747,"context_line":"    }"},{"line_number":1748,"context_line":""},{"line_number":1749,"context_line":"    def ensure_consumer_project_user(self, ctx):"},{"line_number":1750,"context_line":"        \"\"\"Examines the project_id, user_id of the object along with the"},{"line_number":1751,"context_line":"        supplied consumer_id and ensures that if project_id and user_id"},{"line_number":1752,"context_line":"        are set that there are records in the consumers, projects, and"},{"line_number":1753,"context_line":"        users table for these entities."},{"line_number":1754,"context_line":""},{"line_number":1755,"context_line":"        :param ctx: `nova.context.RequestContext` object that has the oslo.db"},{"line_number":1756,"context_line":"                    Session object in it"},{"line_number":1757,"context_line":"        \"\"\""},{"line_number":1758,"context_line":"        # If project_id and user_id are not set then silently"},{"line_number":1759,"context_line":"        # move on. This allows microversion \u003c1.8 to continue to work. Since"},{"line_number":1760,"context_line":"        # then the fields are required and the enforcement is at the HTTP"},{"line_number":1761,"context_line":"        # API layer."},{"line_number":1762,"context_line":"        if not (\u0027project_id\u0027 in self and"},{"line_number":1763,"context_line":"                self.project_id is not None and"},{"line_number":1764,"context_line":"                \u0027user_id\u0027 in self and"},{"line_number":1765,"context_line":"                self.user_id is not None):"},{"line_number":1766,"context_line":"            return"},{"line_number":1767,"context_line":"        # Grab the project internal ID if it exists in the projects table"},{"line_number":1768,"context_line":"        pid \u003d _ensure_project(ctx, self.project_id)"},{"line_number":1769,"context_line":"        # Grab the user internal ID if it exists in the users table"},{"line_number":1770,"context_line":"        uid \u003d _ensure_user(ctx, self.user_id)"},{"line_number":1771,"context_line":""},{"line_number":1772,"context_line":"        # Add the consumer if it doesn\u0027t already exist"},{"line_number":1773,"context_line":"        sel_stmt \u003d sa.select([_CONSUMER_TBL.c.uuid]).where("},{"line_number":1774,"context_line":"            _CONSUMER_TBL.c.uuid \u003d\u003d self.consumer_id)"},{"line_number":1775,"context_line":"        result \u003d ctx.session.execute(sel_stmt).fetchall()"},{"line_number":1776,"context_line":"        if not result:"},{"line_number":1777,"context_line":"            try:"},{"line_number":1778,"context_line":"                ctx.session.execute(_CONSUMER_TBL.insert().values("},{"line_number":1779,"context_line":"                    uuid\u003dself.consumer_id,"},{"line_number":1780,"context_line":"                    project_id\u003dpid,"},{"line_number":1781,"context_line":"                    user_id\u003duid))"},{"line_number":1782,"context_line":"            except db_exc.DBDuplicateEntry:"},{"line_number":1783,"context_line":"                # We assume at this time that a consumer project/user can\u0027t"},{"line_number":1784,"context_line":"                # change, so if we get here, we raced and should just pass"},{"line_number":1785,"context_line":"                # if the consumer already exists."},{"line_number":1786,"context_line":"                pass"},{"line_number":1787,"context_line":""},{"line_number":1788,"context_line":""},{"line_number":1789,"context_line":"@db_api.api_context_manager.writer"}],"source_content_type":"text/x-python","patch_set":2,"id":"9f6a8fd7_e075a6cd","line":1786,"range":{"start_line":1749,"start_character":0,"end_line":1786,"end_character":20},"in_reply_to":"9f6a8fd7_602d1645","updated":"2018-05-01 16:01:14.000000000","message":"Done","commit_id":"4f2b060b5c23ad2daa138b405730516299bd96c5"},{"author":{"_account_id":14070,"name":"Eric Fried","email":"openstack@fried.cc","username":"efried"},"change_message_id":"f27b9b0c2200e69d49809c55fb51d9b3e75a2c91","unresolved":false,"context_lines":[{"line_number":1956,"context_line":"    return res_providers"},{"line_number":1957,"context_line":""},{"line_number":1958,"context_line":""},{"line_number":1959,"context_line":"def _ensure_lookup_table_entry(ctx, tbl, external_id):"},{"line_number":1960,"context_line":"    \"\"\"Ensures the supplied external ID exists in the specified lookup table"},{"line_number":1961,"context_line":"    and if not, adds it. Returns the internal ID."},{"line_number":1962,"context_line":""},{"line_number":1963,"context_line":"    :param ctx: `nova.context.RequestContext` object that has the oslo.db"},{"line_number":1964,"context_line":"                Session object in it"},{"line_number":1965,"context_line":"    :param tbl: The lookup table"},{"line_number":1966,"context_line":"    :param external_id: The external project or user identifier"},{"line_number":1967,"context_line":"    :type external_id: string"},{"line_number":1968,"context_line":"    \"\"\""},{"line_number":1969,"context_line":"    # Grab the project internal ID if it exists in the projects table"},{"line_number":1970,"context_line":"    sel \u003d sa.select([tbl.c.id]).where("},{"line_number":1971,"context_line":"        tbl.c.external_id \u003d\u003d external_id"},{"line_number":1972,"context_line":"    )"},{"line_number":1973,"context_line":"    res \u003d ctx.session.execute(sel).fetchall()"},{"line_number":1974,"context_line":"    if not res:"},{"line_number":1975,"context_line":"        try:"},{"line_number":1976,"context_line":"            ins_stmt \u003d tbl.insert().values(external_id\u003dexternal_id)"},{"line_number":1977,"context_line":"            res \u003d ctx.session.execute(ins_stmt)"},{"line_number":1978,"context_line":"            return res.inserted_primary_key[0]"},{"line_number":1979,"context_line":"        except db_exc.DBDuplicateEntry:"},{"line_number":1980,"context_line":"            # Another thread added it just before us, so just read the"},{"line_number":1981,"context_line":"            # internal ID that that thread created..."},{"line_number":1982,"context_line":"            res \u003d ctx.session.execute(sel).fetchall()"},{"line_number":1983,"context_line":""},{"line_number":1984,"context_line":"    return res[0][0]"},{"line_number":1985,"context_line":""},{"line_number":1986,"context_line":""},{"line_number":1987,"context_line":"def _ensure_project(ctx, external_id):"},{"line_number":1988,"context_line":"    \"\"\"Ensures the supplied external project ID exists in the projects lookup"},{"line_number":1989,"context_line":"    table and if not, adds it. Returns the internal project ID."},{"line_number":1990,"context_line":""},{"line_number":1991,"context_line":"    :param ctx: `nova.context.RequestContext` object that has the oslo.db"},{"line_number":1992,"context_line":"                Session object in it"},{"line_number":1993,"context_line":"    :param external_id: The external project identifier"},{"line_number":1994,"context_line":"    :type external_id: string"},{"line_number":1995,"context_line":"    \"\"\""},{"line_number":1996,"context_line":"    return _ensure_lookup_table_entry(ctx, _PROJECT_TBL, external_id)"},{"line_number":1997,"context_line":""},{"line_number":1998,"context_line":""},{"line_number":1999,"context_line":"def _ensure_user(ctx, external_id):"},{"line_number":2000,"context_line":"    \"\"\"Ensures the supplied external user ID exists in the users lookup table"},{"line_number":2001,"context_line":"    and if not, adds it. Returns the internal user ID."},{"line_number":2002,"context_line":""},{"line_number":2003,"context_line":"    :param ctx: `nova.context.RequestContext` object that has the oslo.db"},{"line_number":2004,"context_line":"                Session object in it"},{"line_number":2005,"context_line":"    :param external_id: The external user identifier"},{"line_number":2006,"context_line":"    :type external_id: string"},{"line_number":2007,"context_line":"    \"\"\""},{"line_number":2008,"context_line":"    return _ensure_lookup_table_entry(ctx, _USER_TBL, external_id)"},{"line_number":2009,"context_line":""},{"line_number":2010,"context_line":""},{"line_number":2011,"context_line":"@db_api.api_context_manager.reader"}],"source_content_type":"text/x-python","patch_set":2,"id":"9f6a8fd7_008f7a2e","line":2008,"range":{"start_line":1959,"start_character":0,"end_line":2008,"end_character":66},"updated":"2018-05-01 15:48:23.000000000","message":"And these.  I see they were removed in the subsequent patch, but they should be removed here.","commit_id":"4f2b060b5c23ad2daa138b405730516299bd96c5"},{"author":{"_account_id":7,"name":"Jay Pipes","email":"jaypipes@gmail.com","username":"jaypipes"},"change_message_id":"14a628e5bac6650736f182f519e0fff414bc9161","unresolved":false,"context_lines":[{"line_number":1956,"context_line":"    return res_providers"},{"line_number":1957,"context_line":""},{"line_number":1958,"context_line":""},{"line_number":1959,"context_line":"def _ensure_lookup_table_entry(ctx, tbl, external_id):"},{"line_number":1960,"context_line":"    \"\"\"Ensures the supplied external ID exists in the specified lookup table"},{"line_number":1961,"context_line":"    and if not, adds it. Returns the internal ID."},{"line_number":1962,"context_line":""},{"line_number":1963,"context_line":"    :param ctx: `nova.context.RequestContext` object that has the oslo.db"},{"line_number":1964,"context_line":"                Session object in it"},{"line_number":1965,"context_line":"    :param tbl: The lookup table"},{"line_number":1966,"context_line":"    :param external_id: The external project or user identifier"},{"line_number":1967,"context_line":"    :type external_id: string"},{"line_number":1968,"context_line":"    \"\"\""},{"line_number":1969,"context_line":"    # Grab the project internal ID if it exists in the projects table"},{"line_number":1970,"context_line":"    sel \u003d sa.select([tbl.c.id]).where("},{"line_number":1971,"context_line":"        tbl.c.external_id \u003d\u003d external_id"},{"line_number":1972,"context_line":"    )"},{"line_number":1973,"context_line":"    res \u003d ctx.session.execute(sel).fetchall()"},{"line_number":1974,"context_line":"    if not res:"},{"line_number":1975,"context_line":"        try:"},{"line_number":1976,"context_line":"            ins_stmt \u003d tbl.insert().values(external_id\u003dexternal_id)"},{"line_number":1977,"context_line":"            res \u003d ctx.session.execute(ins_stmt)"},{"line_number":1978,"context_line":"            return res.inserted_primary_key[0]"},{"line_number":1979,"context_line":"        except db_exc.DBDuplicateEntry:"},{"line_number":1980,"context_line":"            # Another thread added it just before us, so just read the"},{"line_number":1981,"context_line":"            # internal ID that that thread created..."},{"line_number":1982,"context_line":"            res \u003d ctx.session.execute(sel).fetchall()"},{"line_number":1983,"context_line":""},{"line_number":1984,"context_line":"    return res[0][0]"},{"line_number":1985,"context_line":""},{"line_number":1986,"context_line":""},{"line_number":1987,"context_line":"def _ensure_project(ctx, external_id):"},{"line_number":1988,"context_line":"    \"\"\"Ensures the supplied external project ID exists in the projects lookup"},{"line_number":1989,"context_line":"    table and if not, adds it. Returns the internal project ID."},{"line_number":1990,"context_line":""},{"line_number":1991,"context_line":"    :param ctx: `nova.context.RequestContext` object that has the oslo.db"},{"line_number":1992,"context_line":"                Session object in it"},{"line_number":1993,"context_line":"    :param external_id: The external project identifier"},{"line_number":1994,"context_line":"    :type external_id: string"},{"line_number":1995,"context_line":"    \"\"\""},{"line_number":1996,"context_line":"    return _ensure_lookup_table_entry(ctx, _PROJECT_TBL, external_id)"},{"line_number":1997,"context_line":""},{"line_number":1998,"context_line":""},{"line_number":1999,"context_line":"def _ensure_user(ctx, external_id):"},{"line_number":2000,"context_line":"    \"\"\"Ensures the supplied external user ID exists in the users lookup table"},{"line_number":2001,"context_line":"    and if not, adds it. Returns the internal user ID."},{"line_number":2002,"context_line":""},{"line_number":2003,"context_line":"    :param ctx: `nova.context.RequestContext` object that has the oslo.db"},{"line_number":2004,"context_line":"                Session object in it"},{"line_number":2005,"context_line":"    :param external_id: The external user identifier"},{"line_number":2006,"context_line":"    :type external_id: string"},{"line_number":2007,"context_line":"    \"\"\""},{"line_number":2008,"context_line":"    return _ensure_lookup_table_entry(ctx, _USER_TBL, external_id)"},{"line_number":2009,"context_line":""},{"line_number":2010,"context_line":""},{"line_number":2011,"context_line":"@db_api.api_context_manager.reader"}],"source_content_type":"text/x-python","patch_set":2,"id":"9f6a8fd7_a07faea9","line":2008,"range":{"start_line":1959,"start_character":0,"end_line":2008,"end_character":66},"in_reply_to":"9f6a8fd7_008f7a2e","updated":"2018-05-01 16:01:14.000000000","message":"Done","commit_id":"4f2b060b5c23ad2daa138b405730516299bd96c5"},{"author":{"_account_id":14070,"name":"Eric Fried","email":"openstack@fried.cc","username":"efried"},"change_message_id":"42cd2112cd87afa0d83a77f94e9cee7f307063cd","unresolved":false,"context_lines":[{"line_number":1863,"context_line":"        # microversions \u003c\u003d1.7 (because `consumer` will always be present, so"},{"line_number":1864,"context_line":"        # this is redundant)."},{"line_number":1865,"context_line":"        \u0027consumer_id\u0027: fields.UUIDField(),"},{"line_number":1866,"context_line":"        # TODO(jaypipes): Make this field non-nullable when we remove support"},{"line_number":1867,"context_line":"        # for microversions \u003c\u003d1.7 which did not require a user/project and only"},{"line_number":1868,"context_line":"        # supplied a consumer UUID"},{"line_number":1869,"context_line":"        \u0027consumer\u0027: fields.ObjectField(\u0027Consumer\u0027, nullable\u003dTrue),"},{"line_number":1870,"context_line":"        \u0027resource_class\u0027: rc_fields.ResourceClassField(),"},{"line_number":1871,"context_line":"        \u0027used\u0027: fields.IntegerField(),"},{"line_number":1872,"context_line":"        # The following two fields are allowed to be set to None to"}],"source_content_type":"text/x-python","patch_set":6,"id":"5f7c97a3_ec77eb39","line":1869,"range":{"start_line":1866,"start_character":0,"end_line":1869,"end_character":66},"updated":"2018-05-07 21:50:59.000000000","message":"So this is weird - we\u0027re adding this field as nullable and then changing it to non-nullable in the next change in the series (having not removed support for \u003c\u003d1.7, as the TODO says).  Can we maybe squash these two commits together?","commit_id":"d358cf909065a740651b0a5641a100ec4066a371"},{"author":{"_account_id":7,"name":"Jay Pipes","email":"jaypipes@gmail.com","username":"jaypipes"},"change_message_id":"6d719c9ad3d5503f6073c805bce61b0457fd3fa5","unresolved":false,"context_lines":[{"line_number":1863,"context_line":"        # microversions \u003c\u003d1.7 (because `consumer` will always be present, so"},{"line_number":1864,"context_line":"        # this is redundant)."},{"line_number":1865,"context_line":"        \u0027consumer_id\u0027: fields.UUIDField(),"},{"line_number":1866,"context_line":"        # TODO(jaypipes): Make this field non-nullable when we remove support"},{"line_number":1867,"context_line":"        # for microversions \u003c\u003d1.7 which did not require a user/project and only"},{"line_number":1868,"context_line":"        # supplied a consumer UUID"},{"line_number":1869,"context_line":"        \u0027consumer\u0027: fields.ObjectField(\u0027Consumer\u0027, nullable\u003dTrue),"},{"line_number":1870,"context_line":"        \u0027resource_class\u0027: rc_fields.ResourceClassField(),"},{"line_number":1871,"context_line":"        \u0027used\u0027: fields.IntegerField(),"},{"line_number":1872,"context_line":"        # The following two fields are allowed to be set to None to"}],"source_content_type":"text/x-python","patch_set":6,"id":"5f7c97a3_8cb517d0","line":1869,"range":{"start_line":1866,"start_character":0,"end_line":1869,"end_character":66},"in_reply_to":"5f7c97a3_ec77eb39","updated":"2018-05-07 21:54:23.000000000","message":"ack. squashed.","commit_id":"d358cf909065a740651b0a5641a100ec4066a371"},{"author":{"_account_id":11564,"name":"Chris Dent","email":"cdent@anticdent.org","username":"chdent"},"change_message_id":"96f973d75128274794b93151dfd0b692b09744a1","unresolved":false,"context_lines":[{"line_number":1863,"context_line":"        \u0027resource_provider\u0027: fields.ObjectField(\u0027ResourceProvider\u0027),"},{"line_number":1864,"context_line":"        # TODO(jaypipes): Remove this field when we remove support for"},{"line_number":1865,"context_line":"        # microversions \u003c\u003d1.7 (because `consumer` will always be present, so"},{"line_number":1866,"context_line":"        # this is redundant)."},{"line_number":1867,"context_line":"        \u0027consumer_id\u0027: fields.UUIDField(),"},{"line_number":1868,"context_line":"        \u0027consumer\u0027: fields.ObjectField(\u0027Consumer\u0027, nullable\u003dFalse),"},{"line_number":1869,"context_line":"        \u0027resource_class\u0027: rc_fields.ResourceClassField(),"}],"source_content_type":"text/x-python","patch_set":11,"id":"5f7c97a3_24b61740","line":1866,"updated":"2018-05-10 13:58:36.000000000","message":"Why not just change it to a property now, one that looks at the consumer object? We\u0027ve not versioning objects so since (I think) in the callers (and in the migration) you\u0027re requiring that we have a consumer object, it would work?\n\nAlso this isn\u0027t really a TODO because we won\u0027t remove support for lower microversions.","commit_id":"bd54e6b182578e5f81f2b3b9c86131129af52ca1"},{"author":{"_account_id":7,"name":"Jay Pipes","email":"jaypipes@gmail.com","username":"jaypipes"},"change_message_id":"bb75e32f6f30bdf201836c1213bf4d7498bc0564","unresolved":false,"context_lines":[{"line_number":1863,"context_line":"        \u0027resource_provider\u0027: fields.ObjectField(\u0027ResourceProvider\u0027),"},{"line_number":1864,"context_line":"        # TODO(jaypipes): Remove this field when we remove support for"},{"line_number":1865,"context_line":"        # microversions \u003c\u003d1.7 (because `consumer` will always be present, so"},{"line_number":1866,"context_line":"        # this is redundant)."},{"line_number":1867,"context_line":"        \u0027consumer_id\u0027: fields.UUIDField(),"},{"line_number":1868,"context_line":"        \u0027consumer\u0027: fields.ObjectField(\u0027Consumer\u0027, nullable\u003dFalse),"},{"line_number":1869,"context_line":"        \u0027resource_class\u0027: rc_fields.ResourceClassField(),"}],"source_content_type":"text/x-python","patch_set":11,"id":"5f7c97a3_8454cb54","line":1866,"in_reply_to":"5f7c97a3_24b61740","updated":"2018-05-10 14:18:56.000000000","message":"see note in the handler file... this is due to an earlier revision. I can remove.","commit_id":"bd54e6b182578e5f81f2b3b9c86131129af52ca1"},{"author":{"_account_id":7,"name":"Jay Pipes","email":"jaypipes@gmail.com","username":"jaypipes"},"change_message_id":"f34b881435189d8e79b21d248ee10a81ef465253","unresolved":false,"context_lines":[{"line_number":1863,"context_line":"        \u0027resource_provider\u0027: fields.ObjectField(\u0027ResourceProvider\u0027),"},{"line_number":1864,"context_line":"        # TODO(jaypipes): Remove this field when we remove support for"},{"line_number":1865,"context_line":"        # microversions \u003c\u003d1.7 (because `consumer` will always be present, so"},{"line_number":1866,"context_line":"        # this is redundant)."},{"line_number":1867,"context_line":"        \u0027consumer_id\u0027: fields.UUIDField(),"},{"line_number":1868,"context_line":"        \u0027consumer\u0027: fields.ObjectField(\u0027Consumer\u0027, nullable\u003dFalse),"},{"line_number":1869,"context_line":"        \u0027resource_class\u0027: rc_fields.ResourceClassField(),"}],"source_content_type":"text/x-python","patch_set":11,"id":"5f7c97a3_1eb0ed89","line":1866,"in_reply_to":"5f7c97a3_8454cb54","updated":"2018-05-11 18:52:14.000000000","message":"Done","commit_id":"bd54e6b182578e5f81f2b3b9c86131129af52ca1"},{"author":{"_account_id":25625,"name":"Tetsuro Nakamura","email":"tetsuro.nakamura.bc@hco.ntt.co.jp","username":"tetsuro0907"},"change_message_id":"4fa62e50d3102a1170c7cf87ab22e76bba67bd7e","unresolved":false,"context_lines":[{"line_number":2155,"context_line":"        # First delete any existing allocations for any consumers. This"},{"line_number":2156,"context_line":"        # provides a clean slate for the consumers mentioned in the list of"},{"line_number":2157,"context_line":"        # allocations being manipulated."},{"line_number":2158,"context_line":"        consumer_ids \u003d set(alloc.consumer.uuid for alloc in allocs)"},{"line_number":2159,"context_line":"        for consumer_id in consumer_ids:"},{"line_number":2160,"context_line":"            _delete_allocations_for_consumer(context, consumer_id)"},{"line_number":2161,"context_line":""}],"source_content_type":"text/x-python","patch_set":14,"id":"5f7c97a3_efdc6175","line":2158,"range":{"start_line":2158,"start_character":8,"end_line":2158,"end_character":20},"updated":"2018-05-29 05:18:45.000000000","message":"nit: I would feel better using \"consumer_uuid\" as much as possible.","commit_id":"94719b02402e420fc81495baab54bf47047ef1c1"},{"author":{"_account_id":6873,"name":"Matt Riedemann","email":"mriedem.os@gmail.com","username":"mriedem"},"change_message_id":"9dff7f096a3da005e0f7a84ebb7ad710b3b075bf","unresolved":false,"context_lines":[{"line_number":1539,"context_line":"    fields \u003d {"},{"line_number":1540,"context_line":"        \u0027id\u0027: fields.IntegerField(),"},{"line_number":1541,"context_line":"        \u0027resource_provider\u0027: fields.ObjectField(\u0027ResourceProvider\u0027),"},{"line_number":1542,"context_line":"        \u0027consumer\u0027: fields.ObjectField(\u0027Consumer\u0027, nullable\u003dFalse),"},{"line_number":1543,"context_line":"        \u0027resource_class\u0027: rc_fields.ResourceClassField(),"},{"line_number":1544,"context_line":"        \u0027used\u0027: fields.IntegerField(),"},{"line_number":1545,"context_line":"    }"}],"source_content_type":"text/x-python","patch_set":23,"id":"5f7c97a3_b1c77412","line":1542,"updated":"2018-06-13 13:29:22.000000000","message":"And this is OK because we don\u0027t have versions on these things, they are just strongly typed data bags.","commit_id":"d6517e58536696d7fa903872dba5b83da2fb0def"},{"author":{"_account_id":14070,"name":"Eric Fried","email":"openstack@fried.cc","username":"efried"},"change_message_id":"25e58796f48189dfe7855d94981999f2f7de6503","unresolved":false,"context_lines":[{"line_number":1735,"context_line":"        users.c.id.label(\"user_id\"),"},{"line_number":1736,"context_line":"        users.c.external_id.label(\"user_external_id\"),"},{"line_number":1737,"context_line":"    ]"},{"line_number":1738,"context_line":"    # TODO(jaypipes): change this join to be on ID not UUID"},{"line_number":1739,"context_line":"    consumers_join \u003d sa.join("},{"line_number":1740,"context_line":"        allocs, consumers, allocs.c.consumer_id \u003d\u003d consumers.c.uuid)"},{"line_number":1741,"context_line":"    projects_join \u003d sa.join("}],"source_content_type":"text/x-python","patch_set":23,"id":"5f7c97a3_bbf9a2c8","line":1738,"range":{"start_line":1738,"start_character":22,"end_line":1738,"end_character":59},"updated":"2018-06-12 21:42:46.000000000","message":"But we can\u0027t do that unless we add the consumer internal ID to the allocations table, right?","commit_id":"d6517e58536696d7fa903872dba5b83da2fb0def"},{"author":{"_account_id":7,"name":"Jay Pipes","email":"jaypipes@gmail.com","username":"jaypipes"},"change_message_id":"e082b35682a5abc806209433cfd1d852265567e0","unresolved":false,"context_lines":[{"line_number":1735,"context_line":"        users.c.id.label(\"user_id\"),"},{"line_number":1736,"context_line":"        users.c.external_id.label(\"user_external_id\"),"},{"line_number":1737,"context_line":"    ]"},{"line_number":1738,"context_line":"    # TODO(jaypipes): change this join to be on ID not UUID"},{"line_number":1739,"context_line":"    consumers_join \u003d sa.join("},{"line_number":1740,"context_line":"        allocs, consumers, allocs.c.consumer_id \u003d\u003d consumers.c.uuid)"},{"line_number":1741,"context_line":"    projects_join \u003d sa.join("}],"source_content_type":"text/x-python","patch_set":23,"id":"5f7c97a3_b4e9a21a","line":1738,"range":{"start_line":1738,"start_character":22,"end_line":1738,"end_character":59},"in_reply_to":"5f7c97a3_bbf9a2c8","updated":"2018-06-13 13:33:59.000000000","message":"yes.","commit_id":"d6517e58536696d7fa903872dba5b83da2fb0def"},{"author":{"_account_id":14070,"name":"Eric Fried","email":"openstack@fried.cc","username":"efried"},"change_message_id":"25e58796f48189dfe7855d94981999f2f7de6503","unresolved":false,"context_lines":[{"line_number":1912,"context_line":"        db_allocs \u003d _get_allocations_by_consumer_uuid(context, consumer_id)"},{"line_number":1913,"context_line":""},{"line_number":1914,"context_line":"        # Build up the Consumer object (it\u0027s the same for all allocations since"},{"line_number":1915,"context_line":"        # we looked up by consumer ID..."},{"line_number":1916,"context_line":"        consumer \u003d None"},{"line_number":1917,"context_line":"        if len(db_allocs) \u003e 0:"},{"line_number":1918,"context_line":"            db_first \u003d db_allocs[0]"}],"source_content_type":"text/x-python","patch_set":23,"id":"5f7c97a3_bbd0c220","line":1915,"updated":"2018-06-12 21:42:46.000000000","message":")","commit_id":"d6517e58536696d7fa903872dba5b83da2fb0def"},{"author":{"_account_id":7,"name":"Jay Pipes","email":"jaypipes@gmail.com","username":"jaypipes"},"change_message_id":"7404eaa06234ccaa310b02c2068a501188777681","unresolved":false,"context_lines":[{"line_number":1912,"context_line":"        db_allocs \u003d _get_allocations_by_consumer_uuid(context, consumer_id)"},{"line_number":1913,"context_line":""},{"line_number":1914,"context_line":"        # Build up the Consumer object (it\u0027s the same for all allocations since"},{"line_number":1915,"context_line":"        # we looked up by consumer ID..."},{"line_number":1916,"context_line":"        consumer \u003d None"},{"line_number":1917,"context_line":"        if len(db_allocs) \u003e 0:"},{"line_number":1918,"context_line":"            db_first \u003d db_allocs[0]"}],"source_content_type":"text/x-python","patch_set":23,"id":"5f7c97a3_945906fe","line":1915,"in_reply_to":"5f7c97a3_bbd0c220","updated":"2018-06-13 14:38:15.000000000","message":"Done","commit_id":"d6517e58536696d7fa903872dba5b83da2fb0def"},{"author":{"_account_id":6873,"name":"Matt Riedemann","email":"mriedem.os@gmail.com","username":"mriedem"},"change_message_id":"9dff7f096a3da005e0f7a84ebb7ad710b3b075bf","unresolved":false,"context_lines":[{"line_number":1914,"context_line":"        # Build up the Consumer object (it\u0027s the same for all allocations since"},{"line_number":1915,"context_line":"        # we looked up by consumer ID..."},{"line_number":1916,"context_line":"        consumer \u003d None"},{"line_number":1917,"context_line":"        if len(db_allocs) \u003e 0:"},{"line_number":1918,"context_line":"            db_first \u003d db_allocs[0]"},{"line_number":1919,"context_line":"            consumer \u003d consumer_obj.Consumer("},{"line_number":1920,"context_line":"                context, id\u003ddb_first[\u0027consumer_id\u0027],"}],"source_content_type":"text/x-python","patch_set":23,"id":"5f7c97a3_b14c549e","line":1917,"updated":"2018-06-13 13:29:22.000000000","message":"And if this is False, it means someone hasn\u0027t run the online data migration for these allocations yet, correct? In that case, should we trigger an \u0027ensure_consumer\u0027 routine here otherwise we\u0027re going to get an error below.","commit_id":"d6517e58536696d7fa903872dba5b83da2fb0def"},{"author":{"_account_id":6873,"name":"Matt Riedemann","email":"mriedem.os@gmail.com","username":"mriedem"},"change_message_id":"bb690f57ce8539f63ae48443a354f54b5caa6927","unresolved":false,"context_lines":[{"line_number":1914,"context_line":"        # Build up the Consumer object (it\u0027s the same for all allocations since"},{"line_number":1915,"context_line":"        # we looked up by consumer ID..."},{"line_number":1916,"context_line":"        consumer \u003d None"},{"line_number":1917,"context_line":"        if len(db_allocs) \u003e 0:"},{"line_number":1918,"context_line":"            db_first \u003d db_allocs[0]"},{"line_number":1919,"context_line":"            consumer \u003d consumer_obj.Consumer("},{"line_number":1920,"context_line":"                context, id\u003ddb_first[\u0027consumer_id\u0027],"}],"source_content_type":"text/x-python","patch_set":23,"id":"5f7c97a3_947d866e","line":1917,"in_reply_to":"5f7c97a3_b14c549e","updated":"2018-06-13 13:31:00.000000000","message":"Oh wait, if this is False, it means db_allocs is empty which means objs below will also be empty, so not an issue.","commit_id":"d6517e58536696d7fa903872dba5b83da2fb0def"},{"author":{"_account_id":7,"name":"Jay Pipes","email":"jaypipes@gmail.com","username":"jaypipes"},"change_message_id":"e082b35682a5abc806209433cfd1d852265567e0","unresolved":false,"context_lines":[{"line_number":1914,"context_line":"        # Build up the Consumer object (it\u0027s the same for all allocations since"},{"line_number":1915,"context_line":"        # we looked up by consumer ID..."},{"line_number":1916,"context_line":"        consumer \u003d None"},{"line_number":1917,"context_line":"        if len(db_allocs) \u003e 0:"},{"line_number":1918,"context_line":"            db_first \u003d db_allocs[0]"},{"line_number":1919,"context_line":"            consumer \u003d consumer_obj.Consumer("},{"line_number":1920,"context_line":"                context, id\u003ddb_first[\u0027consumer_id\u0027],"}],"source_content_type":"text/x-python","patch_set":23,"id":"5f7c97a3_14b73623","line":1917,"in_reply_to":"5f7c97a3_b14c549e","updated":"2018-06-13 13:33:59.000000000","message":"Yes, you are correct. Originally I had the code able to tolerate missing consumers, but then we went the direction of ensuring the consumer information exists always. This is just leftover from that previous worldview. I\u0027ll fix it up.","commit_id":"d6517e58536696d7fa903872dba5b83da2fb0def"},{"author":{"_account_id":6873,"name":"Matt Riedemann","email":"mriedem.os@gmail.com","username":"mriedem"},"change_message_id":"9dff7f096a3da005e0f7a84ebb7ad710b3b075bf","unresolved":false,"context_lines":[{"line_number":1945,"context_line":"                    generation\u003drec[\u0027resource_provider_generation\u0027]),"},{"line_number":1946,"context_line":"                resource_class\u003d_RC_CACHE.string_from_id("},{"line_number":1947,"context_line":"                    rec[\u0027resource_class_id\u0027]),"},{"line_number":1948,"context_line":"                consumer\u003dconsumer,"},{"line_number":1949,"context_line":"                used\u003drec[\u0027used\u0027])"},{"line_number":1950,"context_line":"            for rec in db_allocs"},{"line_number":1951,"context_line":"        ]"}],"source_content_type":"text/x-python","patch_set":23,"id":"5f7c97a3_b131b40d","line":1948,"updated":"2018-06-13 13:29:22.000000000","message":"Technically this could be None, right? And since Allocation.consumer.nullable\u003dFalse, this would blow up if you hadn\u0027t run the online data migrations, right?","commit_id":"d6517e58536696d7fa903872dba5b83da2fb0def"},{"author":{"_account_id":6873,"name":"Matt Riedemann","email":"mriedem.os@gmail.com","username":"mriedem"},"change_message_id":"bb690f57ce8539f63ae48443a354f54b5caa6927","unresolved":false,"context_lines":[{"line_number":1945,"context_line":"                    generation\u003drec[\u0027resource_provider_generation\u0027]),"},{"line_number":1946,"context_line":"                resource_class\u003d_RC_CACHE.string_from_id("},{"line_number":1947,"context_line":"                    rec[\u0027resource_class_id\u0027]),"},{"line_number":1948,"context_line":"                consumer\u003dconsumer,"},{"line_number":1949,"context_line":"                used\u003drec[\u0027used\u0027])"},{"line_number":1950,"context_line":"            for rec in db_allocs"},{"line_number":1951,"context_line":"        ]"}],"source_content_type":"text/x-python","patch_set":23,"id":"5f7c97a3_54936ea3","line":1948,"in_reply_to":"5f7c97a3_b131b40d","updated":"2018-06-13 13:31:00.000000000","message":"Nevermind, figured out the flaw in my logic above.","commit_id":"d6517e58536696d7fa903872dba5b83da2fb0def"},{"author":{"_account_id":7,"name":"Jay Pipes","email":"jaypipes@gmail.com","username":"jaypipes"},"change_message_id":"e082b35682a5abc806209433cfd1d852265567e0","unresolved":false,"context_lines":[{"line_number":1945,"context_line":"                    generation\u003drec[\u0027resource_provider_generation\u0027]),"},{"line_number":1946,"context_line":"                resource_class\u003d_RC_CACHE.string_from_id("},{"line_number":1947,"context_line":"                    rec[\u0027resource_class_id\u0027]),"},{"line_number":1948,"context_line":"                consumer\u003dconsumer,"},{"line_number":1949,"context_line":"                used\u003drec[\u0027used\u0027])"},{"line_number":1950,"context_line":"            for rec in db_allocs"},{"line_number":1951,"context_line":"        ]"}],"source_content_type":"text/x-python","patch_set":23,"id":"5f7c97a3_b43762b0","line":1948,"in_reply_to":"5f7c97a3_b131b40d","updated":"2018-06-13 13:33:59.000000000","message":"yep.","commit_id":"d6517e58536696d7fa903872dba5b83da2fb0def"},{"author":{"_account_id":6873,"name":"Matt Riedemann","email":"mriedem.os@gmail.com","username":"mriedem"},"change_message_id":"af63b19e4fc7ba6b45252232ce060275d996af79","unresolved":false,"context_lines":[{"line_number":1786,"context_line":"    return [dict(r) for r in ctx.session.execute(sel)]"},{"line_number":1787,"context_line":""},{"line_number":1788,"context_line":""},{"line_number":1789,"context_line":"@db_api.api_context_manager.writer.independent"},{"line_number":1790,"context_line":"def _check_incomplete_consumers(ctx):"},{"line_number":1791,"context_line":"    # TODO(jaypipes): Remove in Stein after a blocker migration is added."},{"line_number":1792,"context_line":"    while True:"}],"source_content_type":"text/x-python","patch_set":24,"id":"5f7c97a3_80b21c05","line":1789,"range":{"start_line":1789,"start_character":35,"end_line":1789,"end_character":46},"updated":"2018-06-13 16:10:26.000000000","message":"never seen this before","commit_id":"b76f66102d6f32ce80df8f12fe2c6708504c023b"},{"author":{"_account_id":6873,"name":"Matt Riedemann","email":"mriedem.os@gmail.com","username":"mriedem"},"change_message_id":"af63b19e4fc7ba6b45252232ce060275d996af79","unresolved":false,"context_lines":[{"line_number":1787,"context_line":""},{"line_number":1788,"context_line":""},{"line_number":1789,"context_line":"@db_api.api_context_manager.writer.independent"},{"line_number":1790,"context_line":"def _check_incomplete_consumers(ctx):"},{"line_number":1791,"context_line":"    # TODO(jaypipes): Remove in Stein after a blocker migration is added."},{"line_number":1792,"context_line":"    while True:"},{"line_number":1793,"context_line":"        rows, _ \u003d consumer_obj.create_incomplete_consumers(ctx, 1000)"}],"source_content_type":"text/x-python","patch_set":24,"id":"5f7c97a3_a0839802","line":1790,"updated":"2018-06-13 16:10:26.000000000","message":"This isn\u0027t what I was expecting. I was expecting that we\u0027d just migrate the single set of allocations for a given missing consumer when we call GET /allocations/{consumer_id}.","commit_id":"b76f66102d6f32ce80df8f12fe2c6708504c023b"},{"author":{"_account_id":6873,"name":"Matt Riedemann","email":"mriedem.os@gmail.com","username":"mriedem"},"change_message_id":"af63b19e4fc7ba6b45252232ce060275d996af79","unresolved":false,"context_lines":[{"line_number":1790,"context_line":"def _check_incomplete_consumers(ctx):"},{"line_number":1791,"context_line":"    # TODO(jaypipes): Remove in Stein after a blocker migration is added."},{"line_number":1792,"context_line":"    while True:"},{"line_number":1793,"context_line":"        rows, _ \u003d consumer_obj.create_incomplete_consumers(ctx, 1000)"},{"line_number":1794,"context_line":"        if rows \u003d\u003d 0:"},{"line_number":1795,"context_line":"            break"},{"line_number":1796,"context_line":"        LOG.info(\"Online data migration to fix incomplete consumers \""}],"source_content_type":"text/x-python","patch_set":24,"id":"5f7c97a3_80953c34","line":1793,"range":{"start_line":1793,"start_character":64,"end_line":1793,"end_character":68},"updated":"2018-06-13 16:10:26.000000000","message":"We might not hit the allocations / consumers that we cared about since we\u0027re not doing a targeted migration, so we could still hit None failures below when the allocations don\u0027t have consumers.","commit_id":"b76f66102d6f32ce80df8f12fe2c6708504c023b"},{"author":{"_account_id":6873,"name":"Matt Riedemann","email":"mriedem.os@gmail.com","username":"mriedem"},"change_message_id":"e82117d7355c965cfb30771d60aee9e42471932a","unresolved":false,"context_lines":[{"line_number":1801,"context_line":"    sel \u003d sel.where("},{"line_number":1802,"context_line":"        sa.and_("},{"line_number":1803,"context_line":"            _ALLOC_TBL.c.resource_provider_id \u003d\u003d rp_id,"},{"line_number":1804,"context_line":"            consumer_obj.CONSUMER_TBL.c.id.is_(None)))"},{"line_number":1805,"context_line":"    missing \u003d ctx.session.execute(sel).fetchall()"},{"line_number":1806,"context_line":"    if missing:"},{"line_number":1807,"context_line":"        # Do a single INSERT for all missing consumer relationships for the"}],"source_content_type":"text/x-python","patch_set":25,"id":"5f7c97a3_0e4cf63c","line":1804,"range":{"start_line":1804,"start_character":43,"end_line":1804,"end_character":52},"updated":"2018-06-13 21:56:55.000000000","message":"hmm, I thought there was a null() sqla thing we can use...\n\nhttps://github.com/openstack/nova/blob/343c2bee234568855fd9e6ba075a05c2e70f3388/nova/db/sqlalchemy/migrate_repo/versions/267_instance_uuid_non_nullable.py#L48\n\nAlthough maybe this works similarly, I know there are several ways to skin a cat with sqla.","commit_id":"ed8ca10bbb1c2f76a52b2801904382fa435941b9"},{"author":{"_account_id":6873,"name":"Matt Riedemann","email":"mriedem.os@gmail.com","username":"mriedem"},"change_message_id":"e82117d7355c965cfb30771d60aee9e42471932a","unresolved":false,"context_lines":[{"line_number":1825,"context_line":"            target_cols, sel)"},{"line_number":1826,"context_line":"        res \u003d ctx.session.execute(ins_stmt)"},{"line_number":1827,"context_line":"        if res.rowcount \u003e 0:"},{"line_number":1828,"context_line":"            LOG.info(\"Online data migration to fix incomplete consumers \""},{"line_number":1829,"context_line":"                     \"has not been run. Migrated %d incomplete consumer \""},{"line_number":1830,"context_line":"                     \"records on the fly.\", res.rowcount)"},{"line_number":1831,"context_line":""}],"source_content_type":"text/x-python","patch_set":25,"id":"5f7c97a3_0efab6b8","line":1828,"range":{"start_line":1828,"start_character":62,"end_line":1828,"end_character":71},"updated":"2018-06-13 21:56:55.000000000","message":"nit: add something about the provider in here, like:\n\n\"incomplete consumers for provider %s has been run.\"","commit_id":"ed8ca10bbb1c2f76a52b2801904382fa435941b9"},{"author":{"_account_id":6873,"name":"Matt Riedemann","email":"mriedem.os@gmail.com","username":"mriedem"},"change_message_id":"449de4208e14d39624a15d85222b8ee83695f3ef","unresolved":false,"context_lines":[{"line_number":1825,"context_line":"            target_cols, sel)"},{"line_number":1826,"context_line":"        res \u003d ctx.session.execute(ins_stmt)"},{"line_number":1827,"context_line":"        if res.rowcount \u003e 0:"},{"line_number":1828,"context_line":"            LOG.info(\"Online data migration to fix incomplete consumers \""},{"line_number":1829,"context_line":"                     \"has not been run. Migrated %d incomplete consumer \""},{"line_number":1830,"context_line":"                     \"records on the fly.\", res.rowcount)"},{"line_number":1831,"context_line":""}],"source_content_type":"text/x-python","patch_set":25,"id":"5f7c97a3_4e68ae1f","line":1828,"range":{"start_line":1828,"start_character":62,"end_line":1828,"end_character":71},"in_reply_to":"5f7c97a3_0efab6b8","updated":"2018-06-13 22:19:26.000000000","message":"Done","commit_id":"ed8ca10bbb1c2f76a52b2801904382fa435941b9"},{"author":{"_account_id":6873,"name":"Matt Riedemann","email":"mriedem.os@gmail.com","username":"mriedem"},"change_message_id":"e82117d7355c965cfb30771d60aee9e42471932a","unresolved":false,"context_lines":[{"line_number":1826,"context_line":"        res \u003d ctx.session.execute(ins_stmt)"},{"line_number":1827,"context_line":"        if res.rowcount \u003e 0:"},{"line_number":1828,"context_line":"            LOG.info(\"Online data migration to fix incomplete consumers \""},{"line_number":1829,"context_line":"                     \"has not been run. Migrated %d incomplete consumer \""},{"line_number":1830,"context_line":"                     \"records on the fly.\", res.rowcount)"},{"line_number":1831,"context_line":""},{"line_number":1832,"context_line":""}],"source_content_type":"text/x-python","patch_set":25,"id":"5f7c97a3_ae2e2240","line":1829,"range":{"start_line":1829,"start_character":26,"end_line":1829,"end_character":29},"updated":"2018-06-13 21:56:55.000000000","message":"nix","commit_id":"ed8ca10bbb1c2f76a52b2801904382fa435941b9"},{"author":{"_account_id":6873,"name":"Matt Riedemann","email":"mriedem.os@gmail.com","username":"mriedem"},"change_message_id":"449de4208e14d39624a15d85222b8ee83695f3ef","unresolved":false,"context_lines":[{"line_number":1826,"context_line":"        res \u003d ctx.session.execute(ins_stmt)"},{"line_number":1827,"context_line":"        if res.rowcount \u003e 0:"},{"line_number":1828,"context_line":"            LOG.info(\"Online data migration to fix incomplete consumers \""},{"line_number":1829,"context_line":"                     \"has not been run. Migrated %d incomplete consumer \""},{"line_number":1830,"context_line":"                     \"records on the fly.\", res.rowcount)"},{"line_number":1831,"context_line":""},{"line_number":1832,"context_line":""}],"source_content_type":"text/x-python","patch_set":25,"id":"5f7c97a3_ee72da11","line":1829,"range":{"start_line":1829,"start_character":26,"end_line":1829,"end_character":29},"in_reply_to":"5f7c97a3_ae2e2240","updated":"2018-06-13 22:19:26.000000000","message":"Done","commit_id":"ed8ca10bbb1c2f76a52b2801904382fa435941b9"},{"author":{"_account_id":6873,"name":"Matt Riedemann","email":"mriedem.os@gmail.com","username":"mriedem"},"change_message_id":"e82117d7355c965cfb30771d60aee9e42471932a","unresolved":false,"context_lines":[{"line_number":1856,"context_line":"            user_id\u003dincomplete_user_id)"},{"line_number":1857,"context_line":"        res \u003d ctx.session.execute(ins_stmt)"},{"line_number":1858,"context_line":"        if res.rowcount \u003e 0:"},{"line_number":1859,"context_line":"            LOG.info(\"Online data migration to fix incomplete consumers \""},{"line_number":1860,"context_line":"                     \"has not been run. Migrated %d incomplete consumer \""},{"line_number":1861,"context_line":"                     \"records on the fly.\", res.rowcount)"},{"line_number":1862,"context_line":""}],"source_content_type":"text/x-python","patch_set":25,"id":"5f7c97a3_ee173aed","line":1859,"updated":"2018-06-13 21:56:55.000000000","message":"nit: throw the consumer_id in here somewhere","commit_id":"ed8ca10bbb1c2f76a52b2801904382fa435941b9"},{"author":{"_account_id":6873,"name":"Matt Riedemann","email":"mriedem.os@gmail.com","username":"mriedem"},"change_message_id":"449de4208e14d39624a15d85222b8ee83695f3ef","unresolved":false,"context_lines":[{"line_number":1856,"context_line":"            user_id\u003dincomplete_user_id)"},{"line_number":1857,"context_line":"        res \u003d ctx.session.execute(ins_stmt)"},{"line_number":1858,"context_line":"        if res.rowcount \u003e 0:"},{"line_number":1859,"context_line":"            LOG.info(\"Online data migration to fix incomplete consumers \""},{"line_number":1860,"context_line":"                     \"has not been run. Migrated %d incomplete consumer \""},{"line_number":1861,"context_line":"                     \"records on the fly.\", res.rowcount)"},{"line_number":1862,"context_line":""}],"source_content_type":"text/x-python","patch_set":25,"id":"5f7c97a3_0e6e362b","line":1859,"in_reply_to":"5f7c97a3_ee173aed","updated":"2018-06-13 22:19:26.000000000","message":"Done","commit_id":"ed8ca10bbb1c2f76a52b2801904382fa435941b9"},{"author":{"_account_id":6873,"name":"Matt Riedemann","email":"mriedem.os@gmail.com","username":"mriedem"},"change_message_id":"e82117d7355c965cfb30771d60aee9e42471932a","unresolved":false,"context_lines":[{"line_number":1857,"context_line":"        res \u003d ctx.session.execute(ins_stmt)"},{"line_number":1858,"context_line":"        if res.rowcount \u003e 0:"},{"line_number":1859,"context_line":"            LOG.info(\"Online data migration to fix incomplete consumers \""},{"line_number":1860,"context_line":"                     \"has not been run. Migrated %d incomplete consumer \""},{"line_number":1861,"context_line":"                     \"records on the fly.\", res.rowcount)"},{"line_number":1862,"context_line":""},{"line_number":1863,"context_line":""}],"source_content_type":"text/x-python","patch_set":25,"id":"5f7c97a3_2e221253","line":1860,"range":{"start_line":1860,"start_character":26,"end_line":1860,"end_character":29},"updated":"2018-06-13 21:56:55.000000000","message":"nix","commit_id":"ed8ca10bbb1c2f76a52b2801904382fa435941b9"},{"author":{"_account_id":6873,"name":"Matt Riedemann","email":"mriedem.os@gmail.com","username":"mriedem"},"change_message_id":"449de4208e14d39624a15d85222b8ee83695f3ef","unresolved":false,"context_lines":[{"line_number":1857,"context_line":"        res \u003d ctx.session.execute(ins_stmt)"},{"line_number":1858,"context_line":"        if res.rowcount \u003e 0:"},{"line_number":1859,"context_line":"            LOG.info(\"Online data migration to fix incomplete consumers \""},{"line_number":1860,"context_line":"                     \"has not been run. Migrated %d incomplete consumer \""},{"line_number":1861,"context_line":"                     \"records on the fly.\", res.rowcount)"},{"line_number":1862,"context_line":""},{"line_number":1863,"context_line":""}],"source_content_type":"text/x-python","patch_set":25,"id":"5f7c97a3_ae62a23c","line":1860,"range":{"start_line":1860,"start_character":26,"end_line":1860,"end_character":29},"in_reply_to":"5f7c97a3_2e221253","updated":"2018-06-13 22:19:26.000000000","message":"Done","commit_id":"ed8ca10bbb1c2f76a52b2801904382fa435941b9"},{"author":{"_account_id":14070,"name":"Eric Fried","email":"openstack@fried.cc","username":"efried"},"change_message_id":"cadc9c2806f9b8348c2734c2bc5dcef98bb719c2","unresolved":false,"context_lines":[{"line_number":1792,"context_line":"    \"\"\"Creates consumer record if consumer relationship between allocations -\u003e"},{"line_number":1793,"context_line":"    consumers table is missing for any allocation on the supplied provider"},{"line_number":1794,"context_line":"    internal ID, using the \"incomplete consumer\" project and user CONF options."},{"line_number":1795,"context_line":"    \"\"\""},{"line_number":1796,"context_line":"    alloc_to_consumer \u003d sa.outerjoin("},{"line_number":1797,"context_line":"        _ALLOC_TBL, consumer_obj.CONSUMER_TBL,"},{"line_number":1798,"context_line":"        _ALLOC_TBL.c.consumer_id \u003d\u003d consumer_obj.CONSUMER_TBL.c.uuid)"}],"source_content_type":"text/x-python","patch_set":26,"id":"5f7c97a3_c1afa3dd","line":1795,"updated":"2018-06-14 12:55:05.000000000","message":"Note to self:\n\n SELECT allocation.consumer_id\n   FROM allocation LEFT JOIN consumer\n   ON allocation.consumer_id \u003d\u003d consumer.uuid\n   WHERE allocation.resource_provider_id \u003d\u003d $rp_id\n     AND consumer.id IS NULL\n\nwhich I would have written (worsely) as:\n\n SELECT consumer_id FROM allocation\n   WHERE consumer_id NOT IN (SELECT uuid FROM consumer)\n\nI.e. give me all the consumer IDs that are in the allocation table, but not in the consumer table.","commit_id":"f449650109a0512924de98318aafb874d61d5a2e"},{"author":{"_account_id":7,"name":"Jay Pipes","email":"jaypipes@gmail.com","username":"jaypipes"},"change_message_id":"f175e007c53dafeb8fa43c8389677aa4627785d0","unresolved":false,"context_lines":[{"line_number":1792,"context_line":"    \"\"\"Creates consumer record if consumer relationship between allocations -\u003e"},{"line_number":1793,"context_line":"    consumers table is missing for any allocation on the supplied provider"},{"line_number":1794,"context_line":"    internal ID, using the \"incomplete consumer\" project and user CONF options."},{"line_number":1795,"context_line":"    \"\"\""},{"line_number":1796,"context_line":"    alloc_to_consumer \u003d sa.outerjoin("},{"line_number":1797,"context_line":"        _ALLOC_TBL, consumer_obj.CONSUMER_TBL,"},{"line_number":1798,"context_line":"        _ALLOC_TBL.c.consumer_id \u003d\u003d consumer_obj.CONSUMER_TBL.c.uuid)"}],"source_content_type":"text/x-python","patch_set":26,"id":"5f7c97a3_41b153df","line":1795,"in_reply_to":"5f7c97a3_c1afa3dd","updated":"2018-06-14 12:59:07.000000000","message":"correct.","commit_id":"f449650109a0512924de98318aafb874d61d5a2e"},{"author":{"_account_id":14070,"name":"Eric Fried","email":"openstack@fried.cc","username":"efried"},"change_message_id":"cadc9c2806f9b8348c2734c2bc5dcef98bb719c2","unresolved":false,"context_lines":[{"line_number":1802,"context_line":"        sa.and_("},{"line_number":1803,"context_line":"            _ALLOC_TBL.c.resource_provider_id \u003d\u003d rp_id,"},{"line_number":1804,"context_line":"            consumer_obj.CONSUMER_TBL.c.id.is_(None)))"},{"line_number":1805,"context_line":"    missing \u003d ctx.session.execute(sel).fetchall()"},{"line_number":1806,"context_line":"    if missing:"},{"line_number":1807,"context_line":"        # Do a single INSERT for all missing consumer relationships for the"},{"line_number":1808,"context_line":"        # provider"},{"line_number":1809,"context_line":"        incomplete_proj_id \u003d project_obj.ensure_incomplete_project(ctx)"}],"source_content_type":"text/x-python","patch_set":26,"id":"5f7c97a3_016fdb91","line":1806,"range":{"start_line":1805,"start_character":4,"end_line":1806,"end_character":15},"updated":"2018-06-14 12:55:05.000000000","message":"How come we\u0027re bothering with this?  Just so we can avoid calling ensure_incomplete_* if there\u0027s no work to do?\n\n(Slightly related: Maybe it\u0027s worth caching incomplete_proj/user_id globally so ensure_incomplete_* only runs once per process.)","commit_id":"f449650109a0512924de98318aafb874d61d5a2e"},{"author":{"_account_id":7,"name":"Jay Pipes","email":"jaypipes@gmail.com","username":"jaypipes"},"change_message_id":"f175e007c53dafeb8fa43c8389677aa4627785d0","unresolved":false,"context_lines":[{"line_number":1802,"context_line":"        sa.and_("},{"line_number":1803,"context_line":"            _ALLOC_TBL.c.resource_provider_id \u003d\u003d rp_id,"},{"line_number":1804,"context_line":"            consumer_obj.CONSUMER_TBL.c.id.is_(None)))"},{"line_number":1805,"context_line":"    missing \u003d ctx.session.execute(sel).fetchall()"},{"line_number":1806,"context_line":"    if missing:"},{"line_number":1807,"context_line":"        # Do a single INSERT for all missing consumer relationships for the"},{"line_number":1808,"context_line":"        # provider"},{"line_number":1809,"context_line":"        incomplete_proj_id \u003d project_obj.ensure_incomplete_project(ctx)"}],"source_content_type":"text/x-python","patch_set":26,"id":"5f7c97a3_81e0cbcd","line":1806,"range":{"start_line":1805,"start_character":4,"end_line":1806,"end_character":15},"in_reply_to":"5f7c97a3_016fdb91","updated":"2018-06-14 12:59:07.000000000","message":"that\u0027s precisely why I placed this in here, yes.","commit_id":"f449650109a0512924de98318aafb874d61d5a2e"},{"author":{"_account_id":14070,"name":"Eric Fried","email":"openstack@fried.cc","username":"efried"},"change_message_id":"cadc9c2806f9b8348c2734c2bc5dcef98bb719c2","unresolved":false,"context_lines":[{"line_number":1815,"context_line":"            incomplete_user_id,"},{"line_number":1816,"context_line":"        ]"},{"line_number":1817,"context_line":"        sel \u003d sa.select(cols)"},{"line_number":1818,"context_line":"        sel \u003d sel.select_from(alloc_to_consumer)"},{"line_number":1819,"context_line":"        sel \u003d sel.where("},{"line_number":1820,"context_line":"            sa.and_("},{"line_number":1821,"context_line":"                _ALLOC_TBL.c.resource_provider_id \u003d\u003d rp_id,"},{"line_number":1822,"context_line":"                consumer_obj.CONSUMER_TBL.c.id.is_(None)))"},{"line_number":1823,"context_line":"        target_cols \u003d [\u0027uuid\u0027, \u0027project_id\u0027, \u0027user_id\u0027]"},{"line_number":1824,"context_line":"        ins_stmt \u003d consumer_obj.CONSUMER_TBL.insert().from_select("},{"line_number":1825,"context_line":"            target_cols, sel)"}],"source_content_type":"text/x-python","patch_set":26,"id":"5f7c97a3_21c8d7a5","line":1822,"range":{"start_line":1818,"start_character":1,"end_line":1822,"end_character":58},"updated":"2018-06-14 12:55:05.000000000","message":"This could have been factored out / reused from above rather than copied (unless you have to call the statement builder methods in a certain order, which doesn\u0027t seem to be the case).","commit_id":"f449650109a0512924de98318aafb874d61d5a2e"},{"author":{"_account_id":7,"name":"Jay Pipes","email":"jaypipes@gmail.com","username":"jaypipes"},"change_message_id":"f175e007c53dafeb8fa43c8389677aa4627785d0","unresolved":false,"context_lines":[{"line_number":1815,"context_line":"            incomplete_user_id,"},{"line_number":1816,"context_line":"        ]"},{"line_number":1817,"context_line":"        sel \u003d sa.select(cols)"},{"line_number":1818,"context_line":"        sel \u003d sel.select_from(alloc_to_consumer)"},{"line_number":1819,"context_line":"        sel \u003d sel.where("},{"line_number":1820,"context_line":"            sa.and_("},{"line_number":1821,"context_line":"                _ALLOC_TBL.c.resource_provider_id \u003d\u003d rp_id,"},{"line_number":1822,"context_line":"                consumer_obj.CONSUMER_TBL.c.id.is_(None)))"},{"line_number":1823,"context_line":"        target_cols \u003d [\u0027uuid\u0027, \u0027project_id\u0027, \u0027user_id\u0027]"},{"line_number":1824,"context_line":"        ins_stmt \u003d consumer_obj.CONSUMER_TBL.insert().from_select("},{"line_number":1825,"context_line":"            target_cols, sel)"}],"source_content_type":"text/x-python","patch_set":26,"id":"5f7c97a3_21e3f7d9","line":1822,"range":{"start_line":1818,"start_character":1,"end_line":1822,"end_character":58},"in_reply_to":"5f7c97a3_21c8d7a5","updated":"2018-06-14 12:59:07.000000000","message":"ack. I can DRY it up later.","commit_id":"f449650109a0512924de98318aafb874d61d5a2e"},{"author":{"_account_id":14070,"name":"Eric Fried","email":"openstack@fried.cc","username":"efried"},"change_message_id":"cadc9c2806f9b8348c2734c2bc5dcef98bb719c2","unresolved":false,"context_lines":[{"line_number":1832,"context_line":""},{"line_number":1833,"context_line":""},{"line_number":1834,"context_line":"@db_api.api_context_manager.writer.independent"},{"line_number":1835,"context_line":"def _create_incomplete_consumer(ctx, consumer_id):"},{"line_number":1836,"context_line":"    # TODO(jaypipes): Remove in Stein after a blocker migration is added."},{"line_number":1837,"context_line":"    \"\"\"Creates consumer record if consumer relationship between allocations -\u003e"},{"line_number":1838,"context_line":"    consumers table is missing for the supplied consumer UUID, using the"}],"source_content_type":"text/x-python","patch_set":26,"id":"5f7c97a3_e1e65f16","line":1835,"range":{"start_line":1835,"start_character":4,"end_line":1835,"end_character":31},"updated":"2018-06-14 12:55:05.000000000","message":"We could make this more efficient (and like a third of the code) if we could assume consumer_id exists in the allocation table...","commit_id":"f449650109a0512924de98318aafb874d61d5a2e"},{"author":{"_account_id":14070,"name":"Eric Fried","email":"openstack@fried.cc","username":"efried"},"change_message_id":"ede244f9f840e3faa59b43045b52c63399e236cc","unresolved":false,"context_lines":[{"line_number":1832,"context_line":""},{"line_number":1833,"context_line":""},{"line_number":1834,"context_line":"@db_api.api_context_manager.writer.independent"},{"line_number":1835,"context_line":"def _create_incomplete_consumer(ctx, consumer_id):"},{"line_number":1836,"context_line":"    # TODO(jaypipes): Remove in Stein after a blocker migration is added."},{"line_number":1837,"context_line":"    \"\"\"Creates consumer record if consumer relationship between allocations -\u003e"},{"line_number":1838,"context_line":"    consumers table is missing for the supplied consumer UUID, using the"}],"source_content_type":"text/x-python","patch_set":26,"id":"5f7c97a3_8d731a4e","line":1835,"range":{"start_line":1835,"start_character":4,"end_line":1835,"end_character":31},"in_reply_to":"5f7c97a3_6106cf88","updated":"2018-06-14 15:24:43.000000000","message":"Assuming consumer_id exists:\n\nIf we were caching in ensure_incomplete_*, it would just be:\n\n @db_api.api_context_manager.writer.independent\n def _create_incomplete_consumer(ctx, consumer_id):\n     ins_stmt \u003d consumer_obj.CONSUMER_TBL.insert().values(\n         uuid\u003dconsumer_id,\n         project_id\u003dproject_obj.ensure_incomplete_project(ctx),\n         user_id\u003duser_obj.ensure_incomplete_user(ctx))\n     res \u003d ctx.session.execute(ins_stmt)\n     LOG.info(...)\n\nIf not caching, we could still reduce to\n\n SELECT COUNT(*) FROM consumer WHERE uuid \u003d $consumer_id\n missing \u003d rowcount \u003d\u003d 0","commit_id":"f449650109a0512924de98318aafb874d61d5a2e"},{"author":{"_account_id":7,"name":"Jay Pipes","email":"jaypipes@gmail.com","username":"jaypipes"},"change_message_id":"f175e007c53dafeb8fa43c8389677aa4627785d0","unresolved":false,"context_lines":[{"line_number":1832,"context_line":""},{"line_number":1833,"context_line":""},{"line_number":1834,"context_line":"@db_api.api_context_manager.writer.independent"},{"line_number":1835,"context_line":"def _create_incomplete_consumer(ctx, consumer_id):"},{"line_number":1836,"context_line":"    # TODO(jaypipes): Remove in Stein after a blocker migration is added."},{"line_number":1837,"context_line":"    \"\"\"Creates consumer record if consumer relationship between allocations -\u003e"},{"line_number":1838,"context_line":"    consumers table is missing for the supplied consumer UUID, using the"}],"source_content_type":"text/x-python","patch_set":26,"id":"5f7c97a3_6106cf88","line":1835,"range":{"start_line":1835,"start_character":4,"end_line":1835,"end_character":31},"in_reply_to":"5f7c97a3_e1e65f16","updated":"2018-06-14 12:59:07.000000000","message":"how so?","commit_id":"f449650109a0512924de98318aafb874d61d5a2e"},{"author":{"_account_id":14070,"name":"Eric Fried","email":"openstack@fried.cc","username":"efried"},"change_message_id":"ede244f9f840e3faa59b43045b52c63399e236cc","unresolved":false,"context_lines":[{"line_number":1859,"context_line":"        if res.rowcount \u003e 0:"},{"line_number":1860,"context_line":"            LOG.info(\"Online data migration to fix incomplete consumers \""},{"line_number":1861,"context_line":"                     \"for consumer %s has been run. Migrated %d incomplete \""},{"line_number":1862,"context_line":"                     \"consumer records on the fly.\", consumer_id, res.rowcount)"},{"line_number":1863,"context_line":""},{"line_number":1864,"context_line":""},{"line_number":1865,"context_line":"@base.VersionedObjectRegistry.register_if(False)"}],"source_content_type":"text/x-python","patch_set":26,"id":"5f7c97a3_0d95ca31","line":1862,"range":{"start_line":1862,"start_character":66,"end_line":1862,"end_character":78},"updated":"2018-06-14 15:24:43.000000000","message":"This should always be 1, right?","commit_id":"f449650109a0512924de98318aafb874d61d5a2e"},{"author":{"_account_id":14070,"name":"Eric Fried","email":"openstack@fried.cc","username":"efried"},"change_message_id":"cadc9c2806f9b8348c2734c2bc5dcef98bb719c2","unresolved":false,"context_lines":[{"line_number":1986,"context_line":"    @classmethod"},{"line_number":1987,"context_line":"    def get_all_by_consumer_id(cls, context, consumer_id):"},{"line_number":1988,"context_line":"        _ensure_rc_cache(context)"},{"line_number":1989,"context_line":"        _create_incomplete_consumer(context, consumer_id)"},{"line_number":1990,"context_line":"        db_allocs \u003d _get_allocations_by_consumer_uuid(context, consumer_id)"},{"line_number":1991,"context_line":""},{"line_number":1992,"context_line":"        if db_allocs:"}],"source_content_type":"text/x-python","patch_set":26,"id":"5f7c97a3_81bf6bce","line":1989,"range":{"start_line":1989,"start_character":8,"end_line":1989,"end_character":57},"updated":"2018-06-14 12:55:05.000000000","message":"...which we could do by moving this...","commit_id":"f449650109a0512924de98318aafb874d61d5a2e"},{"author":{"_account_id":14070,"name":"Eric Fried","email":"openstack@fried.cc","username":"efried"},"change_message_id":"cadc9c2806f9b8348c2734c2bc5dcef98bb719c2","unresolved":false,"context_lines":[{"line_number":1989,"context_line":"        _create_incomplete_consumer(context, consumer_id)"},{"line_number":1990,"context_line":"        db_allocs \u003d _get_allocations_by_consumer_uuid(context, consumer_id)"},{"line_number":1991,"context_line":""},{"line_number":1992,"context_line":"        if db_allocs:"},{"line_number":1993,"context_line":"            # Build up the Consumer object (it\u0027s the same for all allocations"},{"line_number":1994,"context_line":"            # since we looked up by consumer ID)"},{"line_number":1995,"context_line":"            db_first \u003d db_allocs[0]"}],"source_content_type":"text/x-python","patch_set":26,"id":"5f7c97a3_21b21707","line":1992,"range":{"start_line":1992,"start_character":8,"end_line":1992,"end_character":21},"updated":"2018-06-14 12:55:05.000000000","message":"...inside of here.","commit_id":"f449650109a0512924de98318aafb874d61d5a2e"}],"nova/tests/functional/api/openstack/placement/db/test_base.py":[{"author":{"_account_id":14070,"name":"Eric Fried","email":"openstack@fried.cc","username":"efried"},"change_message_id":"25e58796f48189dfe7855d94981999f2f7de6503","unresolved":false,"context_lines":[{"line_number":118,"context_line":"                resource_provider\u003drp, **inv_dict)"},{"line_number":119,"context_line":"        inv_list \u003d rp_obj.InventoryList(objects\u003d[disk_inv])"},{"line_number":120,"context_line":"        rp.set_inventory(inv_list)"},{"line_number":121,"context_line":"        alloc \u003d rp_obj.Allocation("},{"line_number":122,"context_line":"            self.ctx, resource_provider\u003drp,"},{"line_number":123,"context_line":"            project_id\u003dself.ctx.project_id, user_id\u003dself.ctx.user_id,"},{"line_number":124,"context_line":"            **alloc_dict)"},{"line_number":125,"context_line":"        consumer_id \u003d alloc_dict[\u0027consumer_id\u0027]"},{"line_number":126,"context_line":"        try:"},{"line_number":127,"context_line":"            c \u003d consumer_obj.Consumer.get_by_uuid(self.ctx, consumer_id)"}],"source_content_type":"text/x-python","patch_set":23,"id":"5f7c97a3_1b99b66b","line":124,"range":{"start_line":121,"start_character":0,"end_line":124,"end_character":25},"updated":"2018-06-12 21:42:46.000000000","message":"Unused.  Is it invoking some magic I\u0027m missing?","commit_id":"d6517e58536696d7fa903872dba5b83da2fb0def"},{"author":{"_account_id":7,"name":"Jay Pipes","email":"jaypipes@gmail.com","username":"jaypipes"},"change_message_id":"7404eaa06234ccaa310b02c2068a501188777681","unresolved":false,"context_lines":[{"line_number":118,"context_line":"                resource_provider\u003drp, **inv_dict)"},{"line_number":119,"context_line":"        inv_list \u003d rp_obj.InventoryList(objects\u003d[disk_inv])"},{"line_number":120,"context_line":"        rp.set_inventory(inv_list)"},{"line_number":121,"context_line":"        alloc \u003d rp_obj.Allocation("},{"line_number":122,"context_line":"            self.ctx, resource_provider\u003drp,"},{"line_number":123,"context_line":"            project_id\u003dself.ctx.project_id, user_id\u003dself.ctx.user_id,"},{"line_number":124,"context_line":"            **alloc_dict)"},{"line_number":125,"context_line":"        consumer_id \u003d alloc_dict[\u0027consumer_id\u0027]"},{"line_number":126,"context_line":"        try:"},{"line_number":127,"context_line":"            c \u003d consumer_obj.Consumer.get_by_uuid(self.ctx, consumer_id)"}],"source_content_type":"text/x-python","patch_set":23,"id":"5f7c97a3_1a143d40","line":124,"range":{"start_line":121,"start_character":0,"end_line":124,"end_character":25},"in_reply_to":"5f7c97a3_1b99b66b","updated":"2018-06-13 14:38:15.000000000","message":"Done","commit_id":"d6517e58536696d7fa903872dba5b83da2fb0def"}],"nova/tests/functional/api/openstack/placement/db/test_consumer.py":[{"author":{"_account_id":25625,"name":"Tetsuro Nakamura","email":"tetsuro.nakamura.bc@hco.ntt.co.jp","username":"tetsuro0907"},"change_message_id":"4fa62e50d3102a1170c7cf87ab22e76bba67bd7e","unresolved":false,"context_lines":[{"line_number":50,"context_line":"        self.assertEqual(1, c.id)"},{"line_number":51,"context_line":"        # Project ID \u003d\u003d 1 is fake-project created in setup"},{"line_number":52,"context_line":"        self.assertEqual(2, c.project.id)"},{"line_number":53,"context_line":"        # User ID \u003d\u003d 1 is fake-user created in setup"},{"line_number":54,"context_line":"        self.assertEqual(2, c.user.id)"},{"line_number":55,"context_line":"        self.assertRaises(exception.ConsumerExists, c.create)"},{"line_number":56,"context_line":""}],"source_content_type":"text/x-python","patch_set":14,"id":"5f7c97a3_af50a9d6","line":53,"range":{"start_line":53,"start_character":8,"end_line":53,"end_character":52},"updated":"2018-05-29 05:18:45.000000000","message":"An alternative is to use bare DB in the same way in the following test case?","commit_id":"94719b02402e420fc81495baab54bf47047ef1c1"},{"author":{"_account_id":6873,"name":"Matt Riedemann","email":"mriedem.os@gmail.com","username":"mriedem"},"change_message_id":"e82117d7355c965cfb30771d60aee9e42471932a","unresolved":false,"context_lines":[{"line_number":183,"context_line":"        rp1 \u003d rp_obj.ResourceProvider(self.ctx, id\u003d1)"},{"line_number":184,"context_line":"        rp_obj.AllocationList.get_all_by_resource_provider(self.ctx, rp1)"},{"line_number":185,"context_line":""},{"line_number":186,"context_line":"        # get_all_by_consumer_id() should have auto-completed the still missing"},{"line_number":187,"context_line":"        # consumer record and _check_incomplete_consumers() should assert"},{"line_number":188,"context_line":"        # correctly that there are no more incomplete consumer records."},{"line_number":189,"context_line":"        self._check_incomplete_consumers(self.ctx)"}],"source_content_type":"text/x-python","patch_set":25,"id":"5f7c97a3_eeec1af5","line":186,"range":{"start_line":186,"start_character":10,"end_line":186,"end_character":32},"updated":"2018-06-13 21:56:55.000000000","message":"get_all_by_resource_provider since that was the last one to run?","commit_id":"ed8ca10bbb1c2f76a52b2801904382fa435941b9"},{"author":{"_account_id":6873,"name":"Matt Riedemann","email":"mriedem.os@gmail.com","username":"mriedem"},"change_message_id":"449de4208e14d39624a15d85222b8ee83695f3ef","unresolved":false,"context_lines":[{"line_number":183,"context_line":"        rp1 \u003d rp_obj.ResourceProvider(self.ctx, id\u003d1)"},{"line_number":184,"context_line":"        rp_obj.AllocationList.get_all_by_resource_provider(self.ctx, rp1)"},{"line_number":185,"context_line":""},{"line_number":186,"context_line":"        # get_all_by_consumer_id() should have auto-completed the still missing"},{"line_number":187,"context_line":"        # consumer record and _check_incomplete_consumers() should assert"},{"line_number":188,"context_line":"        # correctly that there are no more incomplete consumer records."},{"line_number":189,"context_line":"        self._check_incomplete_consumers(self.ctx)"}],"source_content_type":"text/x-python","patch_set":25,"id":"5f7c97a3_0edcf6de","line":186,"range":{"start_line":186,"start_character":10,"end_line":186,"end_character":32},"in_reply_to":"5f7c97a3_eeec1af5","updated":"2018-06-13 22:19:26.000000000","message":"Done","commit_id":"ed8ca10bbb1c2f76a52b2801904382fa435941b9"},{"author":{"_account_id":14070,"name":"Eric Fried","email":"openstack@fried.cc","username":"efried"},"change_message_id":"cadc9c2806f9b8348c2734c2bc5dcef98bb719c2","unresolved":false,"context_lines":[{"line_number":163,"context_line":"        # After that happens, there should still be a single allocation record"},{"line_number":164,"context_line":"        # that is missing a relation to the consumers table. We call the"},{"line_number":165,"context_line":"        # AllocationList.get_all_by_resource_provider() method and verify that"},{"line_number":166,"context_line":"        # method cleans up the remaining incomplete consumers relationship."},{"line_number":167,"context_line":"        res \u003d consumer_obj.create_incomplete_consumers(self.ctx, 1)"},{"line_number":168,"context_line":"        self.assertEqual((1, 1), res)"},{"line_number":169,"context_line":""}],"source_content_type":"text/x-python","patch_set":26,"id":"5f7c97a3_c195633e","line":166,"updated":"2018-06-14 12:55:05.000000000","message":"++ nice","commit_id":"f449650109a0512924de98318aafb874d61d5a2e"}],"nova/tests/functional/api/openstack/placement/db/test_resource_provider.py":[{"author":{"_account_id":14070,"name":"Eric Fried","email":"openstack@fried.cc","username":"efried"},"change_message_id":"78cfef6e5be8e54ccf78778c031435aab327c0aa","unresolved":false,"context_lines":[{"line_number":1783,"context_line":"        self._check_create_allocations(inventory_kwargs,"},{"line_number":1784,"context_line":"                                       bad_used, good_used)"},{"line_number":1785,"context_line":""},{"line_number":1786,"context_line":"    def test_create_all_with_project_user(self):"},{"line_number":1787,"context_line":"        consumer_uuid \u003d uuidsentinel.consumer"},{"line_number":1788,"context_line":"        rp_class \u003d fields.ResourceClass.DISK_GB"},{"line_number":1789,"context_line":"        rp \u003d self._make_rp_and_inventory(resource_class\u003drp_class,"}],"source_content_type":"text/x-python","patch_set":2,"id":"9f6a8fd7_c5f75459","side":"PARENT","line":1786,"range":{"start_line":1786,"start_character":8,"end_line":1786,"end_character":41},"updated":"2018-05-01 15:33:41.000000000","message":"Why is this going away?  It seems like a valid test.","commit_id":"7205826c99a5d825b8479c57c5f3361fad67235c"},{"author":{"_account_id":7,"name":"Jay Pipes","email":"jaypipes@gmail.com","username":"jaypipes"},"change_message_id":"0deec00c7188b0f4fe1ace8003e95b6248e17593","unresolved":false,"context_lines":[{"line_number":1783,"context_line":"        self._check_create_allocations(inventory_kwargs,"},{"line_number":1784,"context_line":"                                       bad_used, good_used)"},{"line_number":1785,"context_line":""},{"line_number":1786,"context_line":"    def test_create_all_with_project_user(self):"},{"line_number":1787,"context_line":"        consumer_uuid \u003d uuidsentinel.consumer"},{"line_number":1788,"context_line":"        rp_class \u003d fields.ResourceClass.DISK_GB"},{"line_number":1789,"context_line":"        rp \u003d self._make_rp_and_inventory(resource_class\u003drp_class,"}],"source_content_type":"text/x-python","patch_set":2,"id":"9f6a8fd7_60bbd6e4","side":"PARENT","line":1786,"range":{"start_line":1786,"start_character":8,"end_line":1786,"end_character":41},"in_reply_to":"9f6a8fd7_c5f75459","updated":"2018-05-01 15:48:05.000000000","message":"Because we no longer do the whole \"look up a consumer/project/user and create a record when project/user is present\" stuff in the object layer. It\u0027s done in the API layer.\n\nI suppose I could add the db-direct verification calls into a custom test that basically ran the gabbits in allocations-post.yaml and verified that consumer/project/user information was created. But the project_id and user_id fields in the response in that gabbit wouldn\u0027t be populated if the \"ensure consumer\" code wasn\u0027t working properly.","commit_id":"7205826c99a5d825b8479c57c5f3361fad67235c"}],"nova/tests/unit/api/openstack/placement/objects/test_resource_provider.py":[{"author":{"_account_id":11564,"name":"Chris Dent","email":"cdent@anticdent.org","username":"chdent"},"change_message_id":"1a8601952bf7264f469411d2e108584a4bb03c2d","unresolved":false,"context_lines":[{"line_number":355,"context_line":"        self.assertIsNone(inv_list.find(\u0027HOUSE\u0027))"},{"line_number":356,"context_line":""},{"line_number":357,"context_line":""},{"line_number":358,"context_line":"# TODO(jaypipes): These are not unit tests. Remove them"},{"line_number":359,"context_line":"class TestAllocation(test_objects._LocalTest):"},{"line_number":360,"context_line":"    USES_DB \u003d True"},{"line_number":361,"context_line":""}],"source_content_type":"text/x-python","patch_set":18,"id":"5f7c97a3_527b4c7a","line":358,"updated":"2018-06-04 17:56:34.000000000","message":"++\n\nWe\u0027ve probably got sufficient functional cover that we can outright delete these and not worry about moving them. If people agree, I can go ahead and a) confirm that, b) do it. And if we get that merged pronto this patch could be a bit tidier.","commit_id":"f12875ac3a5f64c1d33a4a1803e052ad9c980c80"},{"author":{"_account_id":11564,"name":"Chris Dent","email":"cdent@anticdent.org","username":"chdent"},"change_message_id":"9c47e4408bfa3e63db078ece4293ca524bb21b5e","unresolved":false,"context_lines":[],"source_content_type":"","patch_set":21,"id":"5f7c97a3_97ddba42","updated":"2018-06-11 20:59:54.000000000","message":"See https://review.openstack.org/#/c/572280/ (and its surrounding stack) which removes/moves the need for some of these changes.","commit_id":"dede0e498e9ebe734c2fd96414186a340bb1f638"}]}
