)]}'
{"/COMMIT_MSG":[{"author":{"_account_id":11564,"name":"Chris Dent","email":"cdent@anticdent.org","username":"chdent"},"change_message_id":"897e08e4e27df5b9b28795bb677b0466c33f9436","unresolved":false,"context_lines":[{"line_number":13,"context_line":"a resources$S."},{"line_number":14,"context_line":""},{"line_number":15,"context_line":"If this is provided,  all of the resource providers satisfying the"},{"line_number":16,"context_line":"specified request group must be rooted at one of the resource providers"},{"line_number":17,"context_line":"satisfying the request group."},{"line_number":18,"context_line":""},{"line_number":19,"context_line":"The same_subtree query parameter can be repeated and each repeat group"}],"source_content_type":"text/x-gerrit-commit-message","patch_set":1,"id":"9fb8cfa7_ce182ad4","line":16,"range":{"start_line":16,"start_character":32,"end_line":16,"end_character":41},"updated":"2019-07-01 15:58:44.000000000","message":"This suggests that one of the providers is root/anchor, but the more accurate statement is that at least one of the providers is an ancestor of the rest, yes?","commit_id":"a3720fbe3fee1602420ee4043a5aa0362c537f9b"}],"api-ref/source/parameters.yaml":[{"author":{"_account_id":14070,"name":"Eric Fried","email":"openstack@fried.cc","username":"efried"},"change_message_id":"39aa82bb81f7c1442878d1349e0274aaff12f3c4","unresolved":false,"context_lines":[{"line_number":197,"context_line":"    A comma-separated list of request group suffix strings ($S). Each must"},{"line_number":198,"context_line":"    exactly match a suffix on a granular group somewhere else in the request."},{"line_number":199,"context_line":"    Importantly, the identified request groups need not have a resources[$S]."},{"line_number":200,"context_line":"    If this is provided, at least one of the resource providers satisfying the"},{"line_number":201,"context_line":"    specified request group must be an ancestor of the rest."},{"line_number":202,"context_line":"    The ``same_subtree`` query parameter can be repeated and each repeat group"},{"line_number":203,"context_line":"    is treated independently."}],"source_content_type":"text/x-yaml","patch_set":8,"id":"7faddb67_5f2ec943","line":200,"range":{"start_line":200,"start_character":75,"end_line":200,"end_character":78},"updated":"2019-07-09 18:13:48.000000000","message":"\"a\" or \"one of the ... groups\"","commit_id":"8395e3f099022d8506ed5e6624582ec03e46c3b9"}],"placement/errors.py":[{"author":{"_account_id":14070,"name":"Eric Fried","email":"openstack@fried.cc","username":"efried"},"change_message_id":"623ee1565dda3413d120df8603aa0a32a35e95cb","unresolved":false,"context_lines":[{"line_number":49,"context_line":"ILLEGAL_DUPLICATE_QUERYPARAM \u003d \u0027placement.query.duplicate_key\u0027"},{"line_number":50,"context_line":"# Failure of a post-schema value check"},{"line_number":51,"context_line":"QUERYPARAM_BAD_VALUE \u003d \u0027placement.query.bad_value\u0027"},{"line_number":52,"context_line":"QUERYPARAM_MISSING_VALUE \u003d \u0027placement.query.missing_value\u0027"}],"source_content_type":"text/x-python","patch_set":8,"id":"7faddb67_165a76f2","line":52,"updated":"2019-07-09 21:49:54.000000000","message":"Whoops, this (and the prior two) need to be added to [1]. I opened a story about it [2].\n\n[1] https://developer.openstack.org/api-ref/placement/#errors\n[2] https://storyboard.openstack.org/#!/story/2006194","commit_id":"8395e3f099022d8506ed5e6624582ec03e46c3b9"}],"placement/handlers/allocation_candidate.py":[{"author":{"_account_id":11564,"name":"Chris Dent","email":"cdent@anticdent.org","username":"chdent"},"change_message_id":"897e08e4e27df5b9b28795bb677b0466c33f9436","unresolved":false,"context_lines":[{"line_number":256,"context_line":"    context.can(policies.LIST)"},{"line_number":257,"context_line":"    want_version \u003d req.environ[microversion.MICROVERSION_ENVIRON]"},{"line_number":258,"context_line":"    get_schema \u003d schema.GET_SCHEMA_1_10"},{"line_number":259,"context_line":"    if want_version.matches((1, 36)):"},{"line_number":260,"context_line":"        get_schema \u003d schema.GET_SCHEMA_1_36"},{"line_number":261,"context_line":"    elif want_version.matches((1, 35)):"},{"line_number":262,"context_line":"        get_schema \u003d schema.GET_SCHEMA_1_35"}],"source_content_type":"text/x-python","patch_set":1,"id":"9fb8cfa7_2e29c6e4","line":259,"updated":"2019-07-01 15:58:44.000000000","message":"This is starting to get annoying, but we can worry about that some other time.","commit_id":"a3720fbe3fee1602420ee4043a5aa0362c537f9b"}],"placement/lib.py":[{"author":{"_account_id":14070,"name":"Eric Fried","email":"openstack@fried.cc","username":"efried"},"change_message_id":"72da04b3442651b0dc6f7efd19d4dcfd78f73c86","unresolved":false,"context_lines":[{"line_number":14,"context_line":"\"\"\"Symbols intended to be imported by both placement code and placement API"},{"line_number":15,"context_line":"consumers.  When placement is separated out, this module should be part of a"},{"line_number":16,"context_line":"common library that both placement and its consumers can require.\"\"\""},{"line_number":17,"context_line":"from functools import reduce"},{"line_number":18,"context_line":"import re"},{"line_number":19,"context_line":""},{"line_number":20,"context_line":"import webob"}],"source_content_type":"text/x-python","patch_set":1,"id":"9fb8cfa7_b863bc41","line":17,"range":{"start_line":17,"start_character":0,"end_line":17,"end_character":28},"updated":"2019-07-01 14:50:29.000000000","message":"import only modules","commit_id":"a3720fbe3fee1602420ee4043a5aa0362c537f9b"},{"author":{"_account_id":14070,"name":"Eric Fried","email":"openstack@fried.cc","username":"efried"},"change_message_id":"72da04b3442651b0dc6f7efd19d4dcfd78f73c86","unresolved":false,"context_lines":[{"line_number":50,"context_line":"# In newer microversion we no longer check for orphaned member_of"},{"line_number":51,"context_line":"# and required because \"providers providing no inventory to this"},{"line_number":52,"context_line":"# request\" are now legit with `same_subtree` queryparam accompanied."},{"line_number":53,"context_line":"RESOURCELESS_PROVIDERS_VERSION \u003d (1, 36)"},{"line_number":54,"context_line":""},{"line_number":55,"context_line":""},{"line_number":56,"context_line":"class RequestGroup(object):"}],"source_content_type":"text/x-python","patch_set":1,"id":"9fb8cfa7_b300bf02","line":53,"range":{"start_line":53,"start_character":0,"end_line":53,"end_character":30},"updated":"2019-07-01 14:50:29.000000000","message":"This should be called SAME_SUBTREE_VERSION, since we need to smash resourceless into it, and same_subtree is the main feature.","commit_id":"a3720fbe3fee1602420ee4043a5aa0362c537f9b"},{"author":{"_account_id":14070,"name":"Eric Fried","email":"openstack@fried.cc","username":"efried"},"change_message_id":"72da04b3442651b0dc6f7efd19d4dcfd78f73c86","unresolved":false,"context_lines":[{"line_number":133,"context_line":"        return ret"},{"line_number":134,"context_line":""},{"line_number":135,"context_line":"    @staticmethod"},{"line_number":136,"context_line":"    def _check_for_same_subtree(by_suffix, same_subtrees):"},{"line_number":137,"context_line":"        resourceless_suffixes \u003d set("},{"line_number":138,"context_line":"            suffix for suffix, grp in by_suffix.items() if not grp.resources)"},{"line_number":139,"context_line":"        # Check not all the groups are resourceless"}],"source_content_type":"text/x-python","patch_set":1,"id":"9fb8cfa7_b3851f5c","line":136,"updated":"2019-07-01 14:50:29.000000000","message":"nit: This is all maybe better organized as\n\n def _check_groups(want_version, ...):\n     if want_version(SAME_SUBTREE):\n         resourceless \u003d ...\n         _check_for_one_resources(resourceless, ...)\n         _check_same_subtree(resourceless, ...)\n     else:\n         _check_for_orphans(...)\n\n def _check_for_orphans...\n def _check_for_one_resources...\n def _check_same_subtree...","commit_id":"a3720fbe3fee1602420ee4043a5aa0362c537f9b"},{"author":{"_account_id":14070,"name":"Eric Fried","email":"openstack@fried.cc","username":"efried"},"change_message_id":"72da04b3442651b0dc6f7efd19d4dcfd78f73c86","unresolved":false,"context_lines":[{"line_number":142,"context_line":"                   \u0027parameter.\u0027)"},{"line_number":143,"context_line":"            raise webob.exc.HTTPBadRequest(msg)"},{"line_number":144,"context_line":"        if same_subtrees:"},{"line_number":145,"context_line":"            all_subtree_suffixes \u003d reduce((lambda x, y: x | y), same_subtrees)"},{"line_number":146,"context_line":"        else:"},{"line_number":147,"context_line":"            if resourceless_suffixes:"},{"line_number":148,"context_line":"                msg \u003d (\"resourceless group should be specified in \""}],"source_content_type":"text/x-python","patch_set":1,"id":"9fb8cfa7_d899d01e","line":145,"range":{"start_line":145,"start_character":42,"end_line":145,"end_character":62},"updated":"2019-07-01 14:50:29.000000000","message":"parens redundant","commit_id":"a3720fbe3fee1602420ee4043a5aa0362c537f9b"},{"author":{"_account_id":14070,"name":"Eric Fried","email":"openstack@fried.cc","username":"efried"},"change_message_id":"0682c9270689d4949137b7728689bad7a635a1a5","unresolved":false,"context_lines":[{"line_number":142,"context_line":"                   \u0027parameter.\u0027)"},{"line_number":143,"context_line":"            raise webob.exc.HTTPBadRequest(msg)"},{"line_number":144,"context_line":"        if same_subtrees:"},{"line_number":145,"context_line":"            all_subtree_suffixes \u003d reduce((lambda x, y: x | y), same_subtrees)"},{"line_number":146,"context_line":"        else:"},{"line_number":147,"context_line":"            if resourceless_suffixes:"},{"line_number":148,"context_line":"                msg \u003d (\"resourceless group should be specified in \""}],"source_content_type":"text/x-python","patch_set":1,"id":"9fb8cfa7_a915b09d","line":145,"range":{"start_line":145,"start_character":42,"end_line":145,"end_character":62},"in_reply_to":"9fb8cfa7_493d14b9","updated":"2019-07-01 16:14:10.000000000","message":"yes, works the same, agree more readable.","commit_id":"a3720fbe3fee1602420ee4043a5aa0362c537f9b"},{"author":{"_account_id":11564,"name":"Chris Dent","email":"cdent@anticdent.org","username":"chdent"},"change_message_id":"897e08e4e27df5b9b28795bb677b0466c33f9436","unresolved":false,"context_lines":[{"line_number":142,"context_line":"                   \u0027parameter.\u0027)"},{"line_number":143,"context_line":"            raise webob.exc.HTTPBadRequest(msg)"},{"line_number":144,"context_line":"        if same_subtrees:"},{"line_number":145,"context_line":"            all_subtree_suffixes \u003d reduce((lambda x, y: x | y), same_subtrees)"},{"line_number":146,"context_line":"        else:"},{"line_number":147,"context_line":"            if resourceless_suffixes:"},{"line_number":148,"context_line":"                msg \u003d (\"resourceless group should be specified in \""}],"source_content_type":"text/x-python","patch_set":1,"id":"9fb8cfa7_493d14b9","line":145,"range":{"start_line":145,"start_character":42,"end_line":145,"end_character":62},"in_reply_to":"9fb8cfa7_d899d01e","updated":"2019-07-01 15:58:44.000000000","message":"This would also work, wouldn\u0027t it:\n\n    all_subtree_suffixes \u003d set().union(*same_subtrees)\n\nand perhaps be a bit more readable. It took me some brain cpu cycles to negotiate the reduce and the lambda.","commit_id":"a3720fbe3fee1602420ee4043a5aa0362c537f9b"},{"author":{"_account_id":14070,"name":"Eric Fried","email":"openstack@fried.cc","username":"efried"},"change_message_id":"72da04b3442651b0dc6f7efd19d4dcfd78f73c86","unresolved":false,"context_lines":[{"line_number":147,"context_line":"            if resourceless_suffixes:"},{"line_number":148,"context_line":"                msg \u003d (\"resourceless group should be specified in \""},{"line_number":149,"context_line":"                       \"`same_subtree`\")"},{"line_number":150,"context_line":"                raise webob.exc.HTTPBadRequest(msg)"},{"line_number":151,"context_line":"            all_subtree_suffixes \u003d set()"},{"line_number":152,"context_line":"        # Check resourceless group is in same_subtree"},{"line_number":153,"context_line":"        for suffix in resourceless_suffixes:"}],"source_content_type":"text/x-python","patch_set":1,"id":"9fb8cfa7_18a4484a","line":150,"range":{"start_line":150,"start_character":32,"end_line":150,"end_character":46},"updated":"2019-07-01 14:50:29.000000000","message":"let\u0027s add error codes for all these new 400s.","commit_id":"a3720fbe3fee1602420ee4043a5aa0362c537f9b"},{"author":{"_account_id":14070,"name":"Eric Fried","email":"openstack@fried.cc","username":"efried"},"change_message_id":"72da04b3442651b0dc6f7efd19d4dcfd78f73c86","unresolved":false,"context_lines":[{"line_number":150,"context_line":"                raise webob.exc.HTTPBadRequest(msg)"},{"line_number":151,"context_line":"            all_subtree_suffixes \u003d set()"},{"line_number":152,"context_line":"        # Check resourceless group is in same_subtree"},{"line_number":153,"context_line":"        for suffix in resourceless_suffixes:"},{"line_number":154,"context_line":"            if suffix not in all_subtree_suffixes:"},{"line_number":155,"context_line":"                msg \u003d (\"resourceless group %(suffix)s should be specified in\""},{"line_number":156,"context_line":"                       \"`same_subtree` query param\") % {\u0027suffix\u0027: suffix}"},{"line_number":157,"context_line":"                raise webob.exc.HTTPBadRequest(msg)"}],"source_content_type":"text/x-python","patch_set":1,"id":"9fb8cfa7_333dafc3","line":154,"range":{"start_line":153,"start_character":0,"end_line":154,"end_character":50},"updated":"2019-07-01 14:50:29.000000000","message":"could accumulate these so we can produce a message with all the orphaned resourceless suffixes at once (instead of just the first one we come across).","commit_id":"a3720fbe3fee1602420ee4043a5aa0362c537f9b"},{"author":{"_account_id":14070,"name":"Eric Fried","email":"openstack@fried.cc","username":"efried"},"change_message_id":"72da04b3442651b0dc6f7efd19d4dcfd78f73c86","unresolved":false,"context_lines":[{"line_number":152,"context_line":"        # Check resourceless group is in same_subtree"},{"line_number":153,"context_line":"        for suffix in resourceless_suffixes:"},{"line_number":154,"context_line":"            if suffix not in all_subtree_suffixes:"},{"line_number":155,"context_line":"                msg \u003d (\"resourceless group %(suffix)s should be specified in\""},{"line_number":156,"context_line":"                       \"`same_subtree` query param\") % {\u0027suffix\u0027: suffix}"},{"line_number":157,"context_line":"                raise webob.exc.HTTPBadRequest(msg)"},{"line_number":158,"context_line":"        # Check values in same_subtree are real suffixes"}],"source_content_type":"text/x-python","patch_set":1,"id":"9fb8cfa7_78b5447d","line":155,"range":{"start_line":155,"start_character":75,"end_line":155,"end_character":77},"updated":"2019-07-01 14:50:29.000000000","message":"space","commit_id":"a3720fbe3fee1602420ee4043a5aa0362c537f9b"},{"author":{"_account_id":14070,"name":"Eric Fried","email":"openstack@fried.cc","username":"efried"},"change_message_id":"72da04b3442651b0dc6f7efd19d4dcfd78f73c86","unresolved":false,"context_lines":[{"line_number":157,"context_line":"                raise webob.exc.HTTPBadRequest(msg)"},{"line_number":158,"context_line":"        # Check values in same_subtree are real suffixes"},{"line_number":159,"context_line":"        for suffix in all_subtree_suffixes:"},{"line_number":160,"context_line":"            if suffix not in by_suffix:"},{"line_number":161,"context_line":"                msg \u003d (\"Invalid query string parameters: in `same_subtree` \""},{"line_number":162,"context_line":"                       \"parameter %(suffix)s is not in the given suffixes. \""},{"line_number":163,"context_line":"                       \"Forgot underscore?\") % {\u0027suffix\u0027: suffix}"}],"source_content_type":"text/x-python","patch_set":1,"id":"9fb8cfa7_d37a1386","line":160,"range":{"start_line":160,"start_character":15,"end_line":160,"end_character":21},"updated":"2019-07-01 14:50:29.000000000","message":"nts: make sure (via schema?) that we can\u0027t send the empty suffix in here (e.g. same_subtree\u003d_FOO,,_BAR)\n\n[Later] Nope, empty suffix appears to be allowed as currently written; need to add an explicit check for that (probably below, where we\u0027re parsing).","commit_id":"a3720fbe3fee1602420ee4043a5aa0362c537f9b"},{"author":{"_account_id":11564,"name":"Chris Dent","email":"cdent@anticdent.org","username":"chdent"},"change_message_id":"897e08e4e27df5b9b28795bb677b0466c33f9436","unresolved":false,"context_lines":[{"line_number":160,"context_line":"            if suffix not in by_suffix:"},{"line_number":161,"context_line":"                msg \u003d (\"Invalid query string parameters: in `same_subtree` \""},{"line_number":162,"context_line":"                       \"parameter %(suffix)s is not in the given suffixes. \""},{"line_number":163,"context_line":"                       \"Forgot underscore?\") % {\u0027suffix\u0027: suffix}"},{"line_number":164,"context_line":"                raise webob.exc.HTTPBadRequest(msg)"},{"line_number":165,"context_line":""},{"line_number":166,"context_line":"    @staticmethod"}],"source_content_type":"text/x-python","patch_set":1,"id":"9fb8cfa7_e9740838","line":163,"range":{"start_line":163,"start_character":24,"end_line":163,"end_character":42},"updated":"2019-07-01 15:58:44.000000000","message":"I\u0027m uneasy about this. If we know that the common error is to forget the underscore then why are we requiring it?\n\nThe reason we are requiring it is because the suffix (including the _) is a name that\u0027s carried through the client\u0027s full processing of its inventory and queries, so it\u0027s not that likely to be dropped (except in manual requests).\n\nIf you want the message to be helpful, consider listing the known suffixes or the pattern for acceptable suffixes.","commit_id":"a3720fbe3fee1602420ee4043a5aa0362c537f9b"},{"author":{"_account_id":14070,"name":"Eric Fried","email":"openstack@fried.cc","username":"efried"},"change_message_id":"0682c9270689d4949137b7728689bad7a635a1a5","unresolved":false,"context_lines":[{"line_number":160,"context_line":"            if suffix not in by_suffix:"},{"line_number":161,"context_line":"                msg \u003d (\"Invalid query string parameters: in `same_subtree` \""},{"line_number":162,"context_line":"                       \"parameter %(suffix)s is not in the given suffixes. \""},{"line_number":163,"context_line":"                       \"Forgot underscore?\") % {\u0027suffix\u0027: suffix}"},{"line_number":164,"context_line":"                raise webob.exc.HTTPBadRequest(msg)"},{"line_number":165,"context_line":""},{"line_number":166,"context_line":"    @staticmethod"}],"source_content_type":"text/x-python","patch_set":1,"id":"9fb8cfa7_49699422","line":163,"range":{"start_line":163,"start_character":24,"end_line":163,"end_character":42},"in_reply_to":"9fb8cfa7_e9740838","updated":"2019-07-01 16:14:10.000000000","message":"Personally I\u0027m fine with this. The only way we *get* this error is manually, and (other than straight up typos) that\u0027s going to be the most common one, and hard to notice with the human eye even if we dump the known suffixes.\n\nWe could home in by seeing if the erroneous suffix is a substring of any of the valid ones. But that\u0027s way overkill.\n\nAnyway, I\u0027m fine with whatever this message ends up being, including what it is now.","commit_id":"a3720fbe3fee1602420ee4043a5aa0362c537f9b"},{"author":{"_account_id":14070,"name":"Eric Fried","email":"openstack@fried.cc","username":"efried"},"change_message_id":"72da04b3442651b0dc6f7efd19d4dcfd78f73c86","unresolved":false,"context_lines":[{"line_number":398,"context_line":"        same_subtrees \u003d []"},{"line_number":399,"context_line":"        if same_subtree:"},{"line_number":400,"context_line":"            for val in same_subtree:"},{"line_number":401,"context_line":"                suffixes \u003d set(substr.strip() for substr in val.split(\u0027,\u0027))"},{"line_number":402,"context_line":"                same_subtrees.append(suffixes)"},{"line_number":403,"context_line":""},{"line_number":404,"context_line":"        return cls("}],"source_content_type":"text/x-python","patch_set":1,"id":"9fb8cfa7_53ab83d4","line":401,"updated":"2019-07-01 14:50:29.000000000","message":"okay, this allows duplicates (which, meh, is probably fine) and the empty string (which isn\u0027t -- see above).","commit_id":"a3720fbe3fee1602420ee4043a5aa0362c537f9b"},{"author":{"_account_id":11564,"name":"Chris Dent","email":"cdent@anticdent.org","username":"chdent"},"change_message_id":"897e08e4e27df5b9b28795bb677b0466c33f9436","unresolved":false,"context_lines":[{"line_number":398,"context_line":"        same_subtrees \u003d []"},{"line_number":399,"context_line":"        if same_subtree:"},{"line_number":400,"context_line":"            for val in same_subtree:"},{"line_number":401,"context_line":"                suffixes \u003d set(substr.strip() for substr in val.split(\u0027,\u0027))"},{"line_number":402,"context_line":"                same_subtrees.append(suffixes)"},{"line_number":403,"context_line":""},{"line_number":404,"context_line":"        return cls("}],"source_content_type":"text/x-python","patch_set":1,"id":"9fb8cfa7_496674ef","line":401,"in_reply_to":"9fb8cfa7_53ab83d4","updated":"2019-07-01 15:58:44.000000000","message":"yeah, dupes probably fine, we squish en, but yes, empty string should error","commit_id":"a3720fbe3fee1602420ee4043a5aa0362c537f9b"},{"author":{"_account_id":11564,"name":"Chris Dent","email":"cdent@anticdent.org","username":"chdent"},"change_message_id":"9fb6ffea935788a5c7a309646a90f0cf6e37b1f8","unresolved":false,"context_lines":[{"line_number":137,"context_line":"            msg \u003d (\u0027There must be at least one resources or resources[$S] \u0027"},{"line_number":138,"context_line":"                   \u0027parameter.\u0027)"},{"line_number":139,"context_line":"            raise webob.exc.HTTPBadRequest("},{"line_number":140,"context_line":"                msg, comment\u003derrors.QUERYPARAM_BAD_VALUE)"},{"line_number":141,"context_line":""},{"line_number":142,"context_line":"    @staticmethod"},{"line_number":143,"context_line":"    def _check_resourceless_suffix(subtree_suffixes, resourceless_suffixes):"}],"source_content_type":"text/x-python","patch_set":2,"id":"9fb8cfa7_dfe3d133","line":140,"updated":"2019-07-03 11:44:09.000000000","message":"I think what Eric was trying to suggest when he said to make new error codes for these was to create new specific error codes for each kind of error, so we can distinguish different bad query params from others.","commit_id":"8810d5e5d2840c31191bb2f48f7bc57f1682a77e"},{"author":{"_account_id":14070,"name":"Eric Fried","email":"openstack@fried.cc","username":"efried"},"change_message_id":"c16b08c7254561508678cd37ddbeece7adfdd929","unresolved":false,"context_lines":[{"line_number":137,"context_line":"            msg \u003d (\u0027There must be at least one resources or resources[$S] \u0027"},{"line_number":138,"context_line":"                   \u0027parameter.\u0027)"},{"line_number":139,"context_line":"            raise webob.exc.HTTPBadRequest("},{"line_number":140,"context_line":"                msg, comment\u003derrors.QUERYPARAM_BAD_VALUE)"},{"line_number":141,"context_line":""},{"line_number":142,"context_line":"    @staticmethod"},{"line_number":143,"context_line":"    def _check_resourceless_suffix(subtree_suffixes, resourceless_suffixes):"}],"source_content_type":"text/x-python","patch_set":2,"id":"7faddb67_f52042b3","line":140,"in_reply_to":"9fb8cfa7_dfe3d133","updated":"2019-07-03 22:39:15.000000000","message":"Seems like we\u0027ve had this, ahem, discussion before. I thought we had decided we *don\u0027t* need a separate error code for every path.\n\nThat said, I agree this should be a different error code: in this case it\u0027s not a bad value per se; it\u0027s a missing key that\u0027s semantically (rather than syntactically) mandatory. (Not going to suggest what it should be called.)","commit_id":"8810d5e5d2840c31191bb2f48f7bc57f1682a77e"},{"author":{"_account_id":14070,"name":"Eric Fried","email":"openstack@fried.cc","username":"efried"},"change_message_id":"c16b08c7254561508678cd37ddbeece7adfdd929","unresolved":false,"context_lines":[{"line_number":145,"context_line":"                        if suffix not in subtree_suffixes]"},{"line_number":146,"context_line":"        if bad_suffixes:"},{"line_number":147,"context_line":"            msg \u003d (\"resourceless suffixed group request should be specified \""},{"line_number":148,"context_line":"                   \"in `same_subtree` query param: bad group - %(suffixes)s\""},{"line_number":149,"context_line":"                   ) % {\u0027suffixes\u0027: bad_suffixes}"},{"line_number":150,"context_line":"            raise webob.exc.HTTPBadRequest("},{"line_number":151,"context_line":"                msg, comment\u003derrors.QUERYPARAM_BAD_VALUE)"}],"source_content_type":"text/x-python","patch_set":2,"id":"7faddb67_60fece06","line":148,"range":{"start_line":148,"start_character":55,"end_line":148,"end_character":60},"updated":"2019-07-03 22:39:15.000000000","message":"group(s)","commit_id":"8810d5e5d2840c31191bb2f48f7bc57f1682a77e"},{"author":{"_account_id":14070,"name":"Eric Fried","email":"openstack@fried.cc","username":"efried"},"change_message_id":"c16b08c7254561508678cd37ddbeece7adfdd929","unresolved":false,"context_lines":[{"line_number":314,"context_line":"            cls._check_for_one_resources(by_suffix, resourceless_suffixes)"},{"line_number":315,"context_line":"            cls._check_resourceless_suffix("},{"line_number":316,"context_line":"                subtree_suffixes, resourceless_suffixes)"},{"line_number":317,"context_line":"            cls._check_actual_suffix(subtree_suffixes, by_suffix)"},{"line_number":318,"context_line":"        else:"},{"line_number":319,"context_line":"            cls._check_for_orphans(by_suffix)"},{"line_number":320,"context_line":""}],"source_content_type":"text/x-python","patch_set":2,"id":"7faddb67_402632ba","line":317,"updated":"2019-07-03 22:39:15.000000000","message":"clean ++","commit_id":"8810d5e5d2840c31191bb2f48f7bc57f1682a77e"},{"author":{"_account_id":14070,"name":"Eric Fried","email":"openstack@fried.cc","username":"efried"},"change_message_id":"c16b08c7254561508678cd37ddbeece7adfdd929","unresolved":false,"context_lines":[{"line_number":407,"context_line":"                suffixes \u003d set(substr.strip() for substr in val.split(\u0027,\u0027))"},{"line_number":408,"context_line":"                if \u0027\u0027 in suffixes:"},{"line_number":409,"context_line":"                    raise webob.exc.HTTPBadRequest("},{"line_number":410,"context_line":"                        \u0027Empty string (unsuffixed group) is can not specified \u0027"},{"line_number":411,"context_line":"                        \u0027in `same_subtree` \u0027,"},{"line_number":412,"context_line":"                        comment\u003derrors.QUERYPARAM_BAD_VALUE)"},{"line_number":413,"context_line":"                same_subtrees.append(suffixes)"}],"source_content_type":"text/x-python","patch_set":2,"id":"7faddb67_c031c2ee","line":410,"range":{"start_line":410,"start_character":57,"end_line":410,"end_character":67},"updated":"2019-07-03 22:39:15.000000000","message":"can not be","commit_id":"8810d5e5d2840c31191bb2f48f7bc57f1682a77e"},{"author":{"_account_id":14070,"name":"Eric Fried","email":"openstack@fried.cc","username":"efried"},"change_message_id":"c16b08c7254561508678cd37ddbeece7adfdd929","unresolved":false,"context_lines":[{"line_number":409,"context_line":"                    raise webob.exc.HTTPBadRequest("},{"line_number":410,"context_line":"                        \u0027Empty string (unsuffixed group) is can not specified \u0027"},{"line_number":411,"context_line":"                        \u0027in `same_subtree` \u0027,"},{"line_number":412,"context_line":"                        comment\u003derrors.QUERYPARAM_BAD_VALUE)"},{"line_number":413,"context_line":"                same_subtrees.append(suffixes)"},{"line_number":414,"context_line":""},{"line_number":415,"context_line":"        return cls("}],"source_content_type":"text/x-python","patch_set":2,"id":"7faddb67_604c8e76","line":412,"range":{"start_line":412,"start_character":39,"end_line":412,"end_character":59},"updated":"2019-07-03 22:39:15.000000000","message":"see, QUERYPARAM_BAD_VALUE is totally appropriate here.","commit_id":"8810d5e5d2840c31191bb2f48f7bc57f1682a77e"},{"author":{"_account_id":9708,"name":"Balazs Gibizer","display_name":"gibi","email":"gibizer@gmail.com","username":"gibi"},"change_message_id":"7d045957ed7123c1ac11eee8627bce0d05b8393c","unresolved":false,"context_lines":[{"line_number":144,"context_line":"        bad_suffixes \u003d [suffix for suffix in resourceless_suffixes"},{"line_number":145,"context_line":"                        if suffix not in subtree_suffixes]"},{"line_number":146,"context_line":"        if bad_suffixes:"},{"line_number":147,"context_line":"            msg \u003d (\"resourceless suffixed group request should be specified \""},{"line_number":148,"context_line":"                   \"in `same_subtree` query param: bad group(s) - \""},{"line_number":149,"context_line":"                   \"%(suffixes)s\") % {\u0027suffixes\u0027: bad_suffixes}"},{"line_number":150,"context_line":"            raise webob.exc.HTTPBadRequest("}],"source_content_type":"text/x-python","patch_set":7,"id":"7faddb67_6dbf77fb","line":147,"updated":"2019-07-08 16:01:27.000000000","message":"There is inconsistency about capitalizing the error message and adding a dot at the end. L137 capitalized and dotted, L147 and L158 are not capitalized and not dotted. But all of them end up in the same exception.","commit_id":"118415f62c8f66bd70d70661d7e6bd5c334bf1b6"},{"author":{"_account_id":25625,"name":"Tetsuro Nakamura","email":"tetsuro.nakamura.bc@hco.ntt.co.jp","username":"tetsuro0907"},"change_message_id":"c3a42d708d31dbfd7c529a5b2e2024a7f96eabce","unresolved":false,"context_lines":[{"line_number":144,"context_line":"        bad_suffixes \u003d [suffix for suffix in resourceless_suffixes"},{"line_number":145,"context_line":"                        if suffix not in subtree_suffixes]"},{"line_number":146,"context_line":"        if bad_suffixes:"},{"line_number":147,"context_line":"            msg \u003d (\"resourceless suffixed group request should be specified \""},{"line_number":148,"context_line":"                   \"in `same_subtree` query param: bad group(s) - \""},{"line_number":149,"context_line":"                   \"%(suffixes)s\") % {\u0027suffixes\u0027: bad_suffixes}"},{"line_number":150,"context_line":"            raise webob.exc.HTTPBadRequest("}],"source_content_type":"text/x-python","patch_set":7,"id":"7faddb67_6214564f","line":147,"in_reply_to":"7faddb67_6dbf77fb","updated":"2019-07-09 07:23:26.000000000","message":"Done","commit_id":"118415f62c8f66bd70d70661d7e6bd5c334bf1b6"},{"author":{"_account_id":9708,"name":"Balazs Gibizer","display_name":"gibi","email":"gibizer@gmail.com","username":"gibi"},"change_message_id":"7d045957ed7123c1ac11eee8627bce0d05b8393c","unresolved":false,"context_lines":[{"line_number":232,"context_line":"        If a trait in the required parameter is prefixed with ``!`` this"},{"line_number":233,"context_line":"        indicates that that trait must not be present on the resource"},{"line_number":234,"context_line":"        providers in the group. That is, the trait is forbidden. Forbidden"},{"line_number":235,"context_line":"        traits are only processed  if ``allow_forbidden`` is True. This allows"},{"line_number":236,"context_line":"        the caller to control processing based on microversion handling."},{"line_number":237,"context_line":""},{"line_number":238,"context_line":"        The return is a dict, keyed by the suffix of these RequestGroup"},{"line_number":239,"context_line":"        instances (or the empty string for the unidentified group)."}],"source_content_type":"text/x-python","patch_set":7,"id":"7faddb67_32dd5e14","line":236,"range":{"start_line":235,"start_character":35,"end_line":236,"end_character":72},"updated":"2019-07-08 16:01:27.000000000","message":"unrelated but there is no ``allow_forbidden`` param any more but the microversion check is moved into this function.","commit_id":"118415f62c8f66bd70d70661d7e6bd5c334bf1b6"},{"author":{"_account_id":25625,"name":"Tetsuro Nakamura","email":"tetsuro.nakamura.bc@hco.ntt.co.jp","username":"tetsuro0907"},"change_message_id":"acae72cc7be3d419170f095a88fdf258fa341f91","unresolved":false,"context_lines":[{"line_number":232,"context_line":"        If a trait in the required parameter is prefixed with ``!`` this"},{"line_number":233,"context_line":"        indicates that that trait must not be present on the resource"},{"line_number":234,"context_line":"        providers in the group. That is, the trait is forbidden. Forbidden"},{"line_number":235,"context_line":"        traits are only processed  if ``allow_forbidden`` is True. This allows"},{"line_number":236,"context_line":"        the caller to control processing based on microversion handling."},{"line_number":237,"context_line":""},{"line_number":238,"context_line":"        The return is a dict, keyed by the suffix of these RequestGroup"},{"line_number":239,"context_line":"        instances (or the empty string for the unidentified group)."}],"source_content_type":"text/x-python","patch_set":7,"id":"7faddb67_88173352","line":236,"range":{"start_line":235,"start_character":35,"end_line":236,"end_character":72},"in_reply_to":"7faddb67_32dd5e14","updated":"2019-07-09 07:54:16.000000000","message":"https://review.opendev.org/#/c/669810/","commit_id":"118415f62c8f66bd70d70661d7e6bd5c334bf1b6"},{"author":{"_account_id":9708,"name":"Balazs Gibizer","display_name":"gibi","email":"gibizer@gmail.com","username":"gibi"},"change_message_id":"7d045957ed7123c1ac11eee8627bce0d05b8393c","unresolved":false,"context_lines":[{"line_number":291,"context_line":"               ),"},{"line_number":292,"context_line":"        }"},{"line_number":293,"context_line":""},{"line_number":294,"context_line":"        :param req: webob.Request object"},{"line_number":295,"context_line":"        :return: A dict, keyed by suffix, of RequestGroup instances."},{"line_number":296,"context_line":"        :raises `webob.exc.HTTPBadRequest` if any value is malformed, or if a"},{"line_number":297,"context_line":"                trait list is given without corresponding resources."}],"source_content_type":"text/x-python","patch_set":7,"id":"7faddb67_b2d06ef9","line":294,"updated":"2019-07-08 16:01:27.000000000","message":"rqparams doc is missing","commit_id":"118415f62c8f66bd70d70661d7e6bd5c334bf1b6"},{"author":{"_account_id":25625,"name":"Tetsuro Nakamura","email":"tetsuro.nakamura.bc@hco.ntt.co.jp","username":"tetsuro0907"},"change_message_id":"c3a42d708d31dbfd7c529a5b2e2024a7f96eabce","unresolved":false,"context_lines":[{"line_number":291,"context_line":"               ),"},{"line_number":292,"context_line":"        }"},{"line_number":293,"context_line":""},{"line_number":294,"context_line":"        :param req: webob.Request object"},{"line_number":295,"context_line":"        :return: A dict, keyed by suffix, of RequestGroup instances."},{"line_number":296,"context_line":"        :raises `webob.exc.HTTPBadRequest` if any value is malformed, or if a"},{"line_number":297,"context_line":"                trait list is given without corresponding resources."}],"source_content_type":"text/x-python","patch_set":7,"id":"7faddb67_3df443cf","line":294,"in_reply_to":"7faddb67_b2d06ef9","updated":"2019-07-09 07:23:26.000000000","message":"Done","commit_id":"118415f62c8f66bd70d70661d7e6bd5c334bf1b6"},{"author":{"_account_id":9708,"name":"Balazs Gibizer","display_name":"gibi","email":"gibizer@gmail.com","username":"gibi"},"change_message_id":"7d045957ed7123c1ac11eee8627bce0d05b8393c","unresolved":false,"context_lines":[{"line_number":293,"context_line":""},{"line_number":294,"context_line":"        :param req: webob.Request object"},{"line_number":295,"context_line":"        :return: A dict, keyed by suffix, of RequestGroup instances."},{"line_number":296,"context_line":"        :raises `webob.exc.HTTPBadRequest` if any value is malformed, or if a"},{"line_number":297,"context_line":"                trait list is given without corresponding resources."},{"line_number":298,"context_line":"        \"\"\""},{"line_number":299,"context_line":"        want_version \u003d req.environ[microversion.MICROVERSION_ENVIRON]"},{"line_number":300,"context_line":"        # Control whether we handle forbidden traits."}],"source_content_type":"text/x-python","patch_set":7,"id":"7faddb67_d2cdea5d","line":297,"range":{"start_line":296,"start_character":73,"end_line":297,"end_character":68},"updated":"2019-07-08 16:01:27.000000000","message":"I think this is not true any more if the traits are in a group that mentioned in a same_subtree param.","commit_id":"118415f62c8f66bd70d70661d7e6bd5c334bf1b6"},{"author":{"_account_id":25625,"name":"Tetsuro Nakamura","email":"tetsuro.nakamura.bc@hco.ntt.co.jp","username":"tetsuro0907"},"change_message_id":"c3a42d708d31dbfd7c529a5b2e2024a7f96eabce","unresolved":false,"context_lines":[{"line_number":293,"context_line":""},{"line_number":294,"context_line":"        :param req: webob.Request object"},{"line_number":295,"context_line":"        :return: A dict, keyed by suffix, of RequestGroup instances."},{"line_number":296,"context_line":"        :raises `webob.exc.HTTPBadRequest` if any value is malformed, or if a"},{"line_number":297,"context_line":"                trait list is given without corresponding resources."},{"line_number":298,"context_line":"        \"\"\""},{"line_number":299,"context_line":"        want_version \u003d req.environ[microversion.MICROVERSION_ENVIRON]"},{"line_number":300,"context_line":"        # Control whether we handle forbidden traits."}],"source_content_type":"text/x-python","patch_set":7,"id":"7faddb67_1de70715","line":297,"range":{"start_line":296,"start_character":73,"end_line":297,"end_character":68},"in_reply_to":"7faddb67_d2cdea5d","updated":"2019-07-09 07:23:26.000000000","message":"Done","commit_id":"118415f62c8f66bd70d70661d7e6bd5c334bf1b6"},{"author":{"_account_id":9708,"name":"Balazs Gibizer","display_name":"gibi","email":"gibizer@gmail.com","username":"gibi"},"change_message_id":"7d045957ed7123c1ac11eee8627bce0d05b8393c","unresolved":false,"context_lines":[{"line_number":310,"context_line":"                suffix for suffix, grp in by_suffix.items()"},{"line_number":311,"context_line":"                if not grp.resources)"},{"line_number":312,"context_line":"            subtree_suffixes \u003d (set().union(*rqparams.same_subtrees)"},{"line_number":313,"context_line":"                                if rqparams.same_subtrees else set())"},{"line_number":314,"context_line":"            cls._check_for_one_resources(by_suffix, resourceless_suffixes)"},{"line_number":315,"context_line":"            cls._check_resourceless_suffix("},{"line_number":316,"context_line":"                subtree_suffixes, resourceless_suffixes)"}],"source_content_type":"text/x-python","patch_set":7,"id":"7faddb67_ad69efbe","line":313,"range":{"start_line":313,"start_character":32,"end_line":313,"end_character":68},"updated":"2019-07-08 16:01:27.000000000","message":"Do we really need this? As far as I see same_subtrees cannot be null, it can either an empty list or a non empty list. And set().union() can be called with empty args list.\n\n\u003e\u003e\u003e set().union()\nset([])","commit_id":"118415f62c8f66bd70d70661d7e6bd5c334bf1b6"},{"author":{"_account_id":25625,"name":"Tetsuro Nakamura","email":"tetsuro.nakamura.bc@hco.ntt.co.jp","username":"tetsuro0907"},"change_message_id":"c3a42d708d31dbfd7c529a5b2e2024a7f96eabce","unresolved":false,"context_lines":[{"line_number":310,"context_line":"                suffix for suffix, grp in by_suffix.items()"},{"line_number":311,"context_line":"                if not grp.resources)"},{"line_number":312,"context_line":"            subtree_suffixes \u003d (set().union(*rqparams.same_subtrees)"},{"line_number":313,"context_line":"                                if rqparams.same_subtrees else set())"},{"line_number":314,"context_line":"            cls._check_for_one_resources(by_suffix, resourceless_suffixes)"},{"line_number":315,"context_line":"            cls._check_resourceless_suffix("},{"line_number":316,"context_line":"                subtree_suffixes, resourceless_suffixes)"}],"source_content_type":"text/x-python","patch_set":7,"id":"7faddb67_9dbc57dd","line":313,"range":{"start_line":313,"start_character":32,"end_line":313,"end_character":68},"in_reply_to":"7faddb67_ad69efbe","updated":"2019-07-09 07:23:26.000000000","message":"Indeed. Done.","commit_id":"118415f62c8f66bd70d70661d7e6bd5c334bf1b6"},{"author":{"_account_id":9708,"name":"Balazs Gibizer","display_name":"gibi","email":"gibizer@gmail.com","username":"gibi"},"change_message_id":"7d045957ed7123c1ac11eee8627bce0d05b8393c","unresolved":false,"context_lines":[{"line_number":354,"context_line":"        :param anchor_forbidden_traits: Set of trait names which the anchor of"},{"line_number":355,"context_line":"                each returned allocation candidate must NOT possess, regardless"},{"line_number":356,"context_line":"                of any RequestGroup filters."},{"line_number":357,"context_line":"        :param same_subtrees: A list of comma-separated lists of request group"},{"line_number":358,"context_line":"                suffix strings. If provided, all of the resource providers"},{"line_number":359,"context_line":"                satisfying the specified request groups must be rooted at one"},{"line_number":360,"context_line":"                of the resource providers satisfying the request groups."},{"line_number":361,"context_line":"        \"\"\""}],"source_content_type":"text/x-python","patch_set":7,"id":"7faddb67_cdf54bcd","line":358,"range":{"start_line":357,"start_character":29,"end_line":358,"end_character":31},"updated":"2019-07-08 16:01:27.000000000","message":"I don\u0027t see what is coma-separated:\n\nA list of list of request group suffix strings. Where each list of request group suffix strings represents the suffixes from one same_subtree query param.","commit_id":"118415f62c8f66bd70d70661d7e6bd5c334bf1b6"},{"author":{"_account_id":25625,"name":"Tetsuro Nakamura","email":"tetsuro.nakamura.bc@hco.ntt.co.jp","username":"tetsuro0907"},"change_message_id":"c3a42d708d31dbfd7c529a5b2e2024a7f96eabce","unresolved":false,"context_lines":[{"line_number":354,"context_line":"        :param anchor_forbidden_traits: Set of trait names which the anchor of"},{"line_number":355,"context_line":"                each returned allocation candidate must NOT possess, regardless"},{"line_number":356,"context_line":"                of any RequestGroup filters."},{"line_number":357,"context_line":"        :param same_subtrees: A list of comma-separated lists of request group"},{"line_number":358,"context_line":"                suffix strings. If provided, all of the resource providers"},{"line_number":359,"context_line":"                satisfying the specified request groups must be rooted at one"},{"line_number":360,"context_line":"                of the resource providers satisfying the request groups."},{"line_number":361,"context_line":"        \"\"\""}],"source_content_type":"text/x-python","patch_set":7,"id":"7faddb67_5de7bfe5","line":358,"range":{"start_line":357,"start_character":29,"end_line":358,"end_character":31},"in_reply_to":"7faddb67_cdf54bcd","updated":"2019-07-09 07:23:26.000000000","message":"Done","commit_id":"118415f62c8f66bd70d70661d7e6bd5c334bf1b6"},{"author":{"_account_id":9708,"name":"Balazs Gibizer","display_name":"gibi","email":"gibizer@gmail.com","username":"gibi"},"change_message_id":"7d045957ed7123c1ac11eee8627bce0d05b8393c","unresolved":false,"context_lines":[{"line_number":400,"context_line":"                    comment\u003derrors.QUERYPARAM_BAD_VALUE)"},{"line_number":401,"context_line":""},{"line_number":402,"context_line":"        same_subtree \u003d req.GET.getall(\u0027same_subtree\u0027)"},{"line_number":403,"context_line":"        # A list of comma-separated sets of request group suffix strings."},{"line_number":404,"context_line":"        same_subtrees \u003d []"},{"line_number":405,"context_line":"        if same_subtree:"},{"line_number":406,"context_line":"            for val in same_subtree:"}],"source_content_type":"text/x-python","patch_set":7,"id":"7faddb67_1272a2e6","line":403,"range":{"start_line":403,"start_character":20,"end_line":403,"end_character":40},"updated":"2019-07-08 16:01:27.000000000","message":"what is a coma-separated set? As far as I understand same_subtrees is a list of set of suffixes strings. Where each set of suffixes are coming from a single `same_subtree` query param.","commit_id":"118415f62c8f66bd70d70661d7e6bd5c334bf1b6"},{"author":{"_account_id":25625,"name":"Tetsuro Nakamura","email":"tetsuro.nakamura.bc@hco.ntt.co.jp","username":"tetsuro0907"},"change_message_id":"c3a42d708d31dbfd7c529a5b2e2024a7f96eabce","unresolved":false,"context_lines":[{"line_number":400,"context_line":"                    comment\u003derrors.QUERYPARAM_BAD_VALUE)"},{"line_number":401,"context_line":""},{"line_number":402,"context_line":"        same_subtree \u003d req.GET.getall(\u0027same_subtree\u0027)"},{"line_number":403,"context_line":"        # A list of comma-separated sets of request group suffix strings."},{"line_number":404,"context_line":"        same_subtrees \u003d []"},{"line_number":405,"context_line":"        if same_subtree:"},{"line_number":406,"context_line":"            for val in same_subtree:"}],"source_content_type":"text/x-python","patch_set":7,"id":"7faddb67_5db6dffc","line":403,"range":{"start_line":403,"start_character":20,"end_line":403,"end_character":40},"in_reply_to":"7faddb67_1272a2e6","updated":"2019-07-09 07:23:26.000000000","message":"Done","commit_id":"118415f62c8f66bd70d70661d7e6bd5c334bf1b6"},{"author":{"_account_id":9708,"name":"Balazs Gibizer","display_name":"gibi","email":"gibizer@gmail.com","username":"gibi"},"change_message_id":"7d045957ed7123c1ac11eee8627bce0d05b8393c","unresolved":false,"context_lines":[{"line_number":407,"context_line":"                suffixes \u003d set(substr.strip() for substr in val.split(\u0027,\u0027))"},{"line_number":408,"context_line":"                if \u0027\u0027 in suffixes:"},{"line_number":409,"context_line":"                    raise webob.exc.HTTPBadRequest("},{"line_number":410,"context_line":"                        \u0027Empty string (unsuffixed group) is can not be \u0027"},{"line_number":411,"context_line":"                        \u0027specified in `same_subtree` \u0027,"},{"line_number":412,"context_line":"                        comment\u003derrors.QUERYPARAM_BAD_VALUE)"},{"line_number":413,"context_line":"                same_subtrees.append(suffixes)"}],"source_content_type":"text/x-python","patch_set":7,"id":"7faddb67_52c33aee","line":410,"range":{"start_line":410,"start_character":57,"end_line":410,"end_character":70},"updated":"2019-07-08 16:01:27.000000000","message":"either \u0027is\u0027 or \u0027can not be\u0027","commit_id":"118415f62c8f66bd70d70661d7e6bd5c334bf1b6"},{"author":{"_account_id":25625,"name":"Tetsuro Nakamura","email":"tetsuro.nakamura.bc@hco.ntt.co.jp","username":"tetsuro0907"},"change_message_id":"c3a42d708d31dbfd7c529a5b2e2024a7f96eabce","unresolved":false,"context_lines":[{"line_number":407,"context_line":"                suffixes \u003d set(substr.strip() for substr in val.split(\u0027,\u0027))"},{"line_number":408,"context_line":"                if \u0027\u0027 in suffixes:"},{"line_number":409,"context_line":"                    raise webob.exc.HTTPBadRequest("},{"line_number":410,"context_line":"                        \u0027Empty string (unsuffixed group) is can not be \u0027"},{"line_number":411,"context_line":"                        \u0027specified in `same_subtree` \u0027,"},{"line_number":412,"context_line":"                        comment\u003derrors.QUERYPARAM_BAD_VALUE)"},{"line_number":413,"context_line":"                same_subtrees.append(suffixes)"}],"source_content_type":"text/x-python","patch_set":7,"id":"7faddb67_fda78ba6","line":410,"range":{"start_line":410,"start_character":57,"end_line":410,"end_character":70},"in_reply_to":"7faddb67_52c33aee","updated":"2019-07-09 07:23:26.000000000","message":"Done (Fixed the test as well)","commit_id":"118415f62c8f66bd70d70661d7e6bd5c334bf1b6"}],"placement/microversion.py":[{"author":{"_account_id":11564,"name":"Chris Dent","email":"cdent@anticdent.org","username":"chdent"},"change_message_id":"9fb6ffea935788a5c7a309646a90f0cf6e37b1f8","unresolved":false,"context_lines":[{"line_number":87,"context_line":"             # resource providers satisfied which request group suffix."},{"line_number":88,"context_line":"    \u00271.35\u0027,  # Add a `root_required` queryparam on `GET /allocation_candidates`"},{"line_number":89,"context_line":"    \u00271.36\u0027,  # Add a `same_subtree` parameter on GET /allocation_candidates"},{"line_number":90,"context_line":"             # allowing resourceless requests for groups in `same_subtree`."},{"line_number":91,"context_line":"]"},{"line_number":92,"context_line":""},{"line_number":93,"context_line":""}],"source_content_type":"text/x-python","patch_set":2,"id":"9fb8cfa7_bf785d8f","line":90,"range":{"start_line":90,"start_character":15,"end_line":90,"end_character":23},"updated":"2019-07-03 11:44:09.000000000","message":"and allow\n\nis probably a bit more clear","commit_id":"8810d5e5d2840c31191bb2f48f7bc57f1682a77e"}],"placement/objects/allocation_candidate.py":[{"author":{"_account_id":14070,"name":"Eric Fried","email":"openstack@fried.cc","username":"efried"},"change_message_id":"72da04b3442651b0dc6f7efd19d4dcfd78f73c86","unresolved":false,"context_lines":[{"line_number":801,"context_line":"        #   [areq__B, areq_1_B, ..., areq_42_B],  return."},{"line_number":802,"context_line":"        #   ...,"},{"line_number":803,"context_line":"        # ]"},{"line_number":804,"context_line":"        suffix_list \u003d areq_lists_by_suffix.keys()"},{"line_number":805,"context_line":"        for areq_list in itertools.product("},{"line_number":806,"context_line":"                *list(areq_lists_by_suffix.values())):"},{"line_number":807,"context_line":"            # At this point, each AllocationRequest in areq_list is still"}],"source_content_type":"text/x-python","patch_set":1,"id":"9fb8cfa7_13df4b66","line":804,"range":{"start_line":804,"start_character":8,"end_line":804,"end_character":49},"updated":"2019-07-01 14:50:29.000000000","message":"I think this needs to be\n\n suffix_list \u003d list(areq_lists_by_suffix)\n\n(or set(...)?)\n\nOtherwise in py3 you\u0027re creating an iterator, which you\u0027ll exhaust the first time through ...\n\n[Later] Hmph. I tried it and it works fine. Never mind \u003cshrug\u003e","commit_id":"a3720fbe3fee1602420ee4043a5aa0362c537f9b"},{"author":{"_account_id":25625,"name":"Tetsuro Nakamura","email":"tetsuro.nakamura.bc@hco.ntt.co.jp","username":"tetsuro0907"},"change_message_id":"983b21775c1390882a60777cee2e42cb623becb7","unresolved":false,"context_lines":[{"line_number":813,"context_line":"                continue"},{"line_number":814,"context_line":"            if not _satisfies_same_subtree("},{"line_number":815,"context_line":"                    areq_list, suffix_list, rw_ctx.same_subtrees,"},{"line_number":816,"context_line":"                    parent_uuid_by_rp_uuid):"},{"line_number":817,"context_line":"                continue"},{"line_number":818,"context_line":"            # Now we go from this (where \u0027arr\u0027 is AllocationRequestResource):"},{"line_number":819,"context_line":"            # [ areq__B(arrX, arrY, arrZ),"}],"source_content_type":"text/x-python","patch_set":1,"id":"9fb8cfa7_b5998c6d","line":816,"updated":"2019-07-01 07:45:14.000000000","message":"We create AllocationRequest for resourceless groups as well as resourceful groups because here we\u0027d like to execute the subtree filter using AllocationRequest in the `areq_list` seamlessly being unaware of which is resourceless (or resourceful).","commit_id":"a3720fbe3fee1602420ee4043a5aa0362c537f9b"},{"author":{"_account_id":14070,"name":"Eric Fried","email":"openstack@fried.cc","username":"efried"},"change_message_id":"72da04b3442651b0dc6f7efd19d4dcfd78f73c86","unresolved":false,"context_lines":[{"line_number":813,"context_line":"                continue"},{"line_number":814,"context_line":"            if not _satisfies_same_subtree("},{"line_number":815,"context_line":"                    areq_list, suffix_list, rw_ctx.same_subtrees,"},{"line_number":816,"context_line":"                    parent_uuid_by_rp_uuid):"},{"line_number":817,"context_line":"                continue"},{"line_number":818,"context_line":"            # Now we go from this (where \u0027arr\u0027 is AllocationRequestResource):"},{"line_number":819,"context_line":"            # [ areq__B(arrX, arrY, arrZ),"}],"source_content_type":"text/x-python","patch_set":1,"id":"9fb8cfa7_18ec48b9","line":816,"in_reply_to":"9fb8cfa7_b5998c6d","updated":"2019-07-01 14:50:29.000000000","message":"Yeah, that makes sense.","commit_id":"a3720fbe3fee1602420ee4043a5aa0362c537f9b"},{"author":{"_account_id":14070,"name":"Eric Fried","email":"openstack@fried.cc","username":"efried"},"change_message_id":"72da04b3442651b0dc6f7efd19d4dcfd78f73c86","unresolved":false,"context_lines":[{"line_number":827,"context_line":"            # RequestGroup led to which piece of the final AllocationRequest."},{"line_number":828,"context_line":"            # We needed that to be present for the previous filter; we need it"},{"line_number":829,"context_line":"            # to be *absent* for the next one (and for the final output)."},{"line_number":830,"context_line":"            areq \u003d _consolidate_allocation_requests(areq_list)"},{"line_number":831,"context_line":"            # Since we sourced this AllocationRequest from multiple"},{"line_number":832,"context_line":"            # *independent* queries, it\u0027s possible that the combined result"},{"line_number":833,"context_line":"            # now exceeds capacity where amounts of the same RP+RC were"}],"source_content_type":"text/x-python","patch_set":1,"id":"9fb8cfa7_d36453bb","line":830,"range":{"start_line":830,"start_character":19,"end_line":830,"end_character":51},"updated":"2019-07-01 14:50:29.000000000","message":"ack\n\nWhen I was looking at this over the weekend, I was thinking to do the subtree filter *after* _consolidate_allocation_requests... which was how I discovered [1]. But doing it before makes at least as much sense logically; and processing-wise it\u0027s more efficient because we skip the (fairly expensive) consolidation if the check fails.\n\n++\n\n[1] https://storyboard.openstack.org/#!/story/2006068","commit_id":"a3720fbe3fee1602420ee4043a5aa0362c537f9b"},{"author":{"_account_id":14070,"name":"Eric Fried","email":"openstack@fried.cc","username":"efried"},"change_message_id":"72da04b3442651b0dc6f7efd19d4dcfd78f73c86","unresolved":false,"context_lines":[{"line_number":915,"context_line":""},{"line_number":916,"context_line":""},{"line_number":917,"context_line":"def _satisfies_same_subtree("},{"line_number":918,"context_line":"        areqs, suffixes, same_subtrees, parent_uuid_by_rp_uuid):"},{"line_number":919,"context_line":"    \"\"\"Applies same_subtree policy to a list of AllocationRequest."},{"line_number":920,"context_line":""},{"line_number":921,"context_line":"    :param areqs: A list containing one AllocationRequest for each input"}],"source_content_type":"text/x-python","patch_set":1,"id":"9fb8cfa7_73b3270b","line":918,"range":{"start_line":918,"start_character":15,"end_line":918,"end_character":23},"updated":"2019-07-01 14:50:29.000000000","message":"doc this","commit_id":"a3720fbe3fee1602420ee4043a5aa0362c537f9b"},{"author":{"_account_id":14070,"name":"Eric Fried","email":"openstack@fried.cc","username":"efried"},"change_message_id":"72da04b3442651b0dc6f7efd19d4dcfd78f73c86","unresolved":false,"context_lines":[{"line_number":921,"context_line":"    :param areqs: A list containing one AllocationRequest for each input"},{"line_number":922,"context_line":"            RequestGroup."},{"line_number":923,"context_line":"    :param same_subtrees:  A list of comma-separated lists of request group"},{"line_number":924,"context_line":"                suffix strings. If provided, all of the resource providers"},{"line_number":925,"context_line":"                satisfying the specified request groups must be rooted at one"},{"line_number":926,"context_line":"                of the resource providers satisfying the request groups."},{"line_number":927,"context_line":"    :param parent_uuid_by_rp_uuid: A dict of parent uuids keyed by rp uuids."},{"line_number":928,"context_line":"    :return: True if areqs satisfies same_subtree policy; False otherwise."},{"line_number":929,"context_line":"    \"\"\""}],"source_content_type":"text/x-python","patch_set":1,"id":"9fb8cfa7_f36ab77e","line":926,"range":{"start_line":924,"start_character":0,"end_line":926,"end_character":72},"updated":"2019-07-01 14:50:29.000000000","message":"nit: dedent these to the \"two indents on continuation\" style (like you used for areqs above)","commit_id":"a3720fbe3fee1602420ee4043a5aa0362c537f9b"},{"author":{"_account_id":14070,"name":"Eric Fried","email":"openstack@fried.cc","username":"efried"},"change_message_id":"72da04b3442651b0dc6f7efd19d4dcfd78f73c86","unresolved":false,"context_lines":[{"line_number":927,"context_line":"    :param parent_uuid_by_rp_uuid: A dict of parent uuids keyed by rp uuids."},{"line_number":928,"context_line":"    :return: True if areqs satisfies same_subtree policy; False otherwise."},{"line_number":929,"context_line":"    \"\"\""},{"line_number":930,"context_line":"    if not same_subtrees:"},{"line_number":931,"context_line":"        return True"},{"line_number":932,"context_line":"    areq_by_suffix \u003d dict(zip(suffixes, areqs))"},{"line_number":933,"context_line":"    for same_subtree in same_subtrees:"},{"line_number":934,"context_line":"        rp_uuids \u003d set("}],"source_content_type":"text/x-python","patch_set":1,"id":"9fb8cfa7_53e38305","line":931,"range":{"start_line":930,"start_character":0,"end_line":931,"end_character":19},"updated":"2019-07-01 14:50:29.000000000","message":"Could do this at the caller (this same thing came up elsewhere recently [1]) but this is probably better, as it favors a more readable flow in _merge_candidates.\n\n[1] https://review.opendev.org/#/c/637955/28/nova/cmd/manage.py@1768","commit_id":"a3720fbe3fee1602420ee4043a5aa0362c537f9b"},{"author":{"_account_id":14070,"name":"Eric Fried","email":"openstack@fried.cc","username":"efried"},"change_message_id":"72da04b3442651b0dc6f7efd19d4dcfd78f73c86","unresolved":false,"context_lines":[{"line_number":929,"context_line":"    \"\"\""},{"line_number":930,"context_line":"    if not same_subtrees:"},{"line_number":931,"context_line":"        return True"},{"line_number":932,"context_line":"    areq_by_suffix \u003d dict(zip(suffixes, areqs))"},{"line_number":933,"context_line":"    for same_subtree in same_subtrees:"},{"line_number":934,"context_line":"        rp_uuids \u003d set("},{"line_number":935,"context_line":"            areq_by_suffix[suffix].resource_requests[0].resource_provider.uuid"}],"source_content_type":"text/x-python","patch_set":1,"id":"9fb8cfa7_b3075f82","line":932,"range":{"start_line":932,"start_character":4,"end_line":932,"end_character":47},"updated":"2019-07-01 14:50:29.000000000","message":"nts: /me wondered why we needed suffixes here, rather than pulling the suffixes from areqs. That would be doable, but the suffixes live in AllocationRequestResources. At this stage, all arr in one areq happen to have the same suffix - but relying on that would be a pretty tight coupling to the calling context.\n\nThat said, we *are* relying on the order of `suffixes` being the same as the order of `areqs`, suffix-wise, and I\u0027m not sure that\u0027s any better.\n\nNote that there\u0027s discussion in [1] about the possibility of putting the suffixes in the AllocationRequest also/instead. If we did that, it would *definitely* make me feel better to pull them from there rather than passing in this `suffixes` thing.\n\n[1] https://review.opendev.org/#/c/668307/1/placement/objects/allocation_candidate.py@214","commit_id":"a3720fbe3fee1602420ee4043a5aa0362c537f9b"},{"author":{"_account_id":14070,"name":"Eric Fried","email":"openstack@fried.cc","username":"efried"},"change_message_id":"72da04b3442651b0dc6f7efd19d4dcfd78f73c86","unresolved":false,"context_lines":[{"line_number":932,"context_line":"    areq_by_suffix \u003d dict(zip(suffixes, areqs))"},{"line_number":933,"context_line":"    for same_subtree in same_subtrees:"},{"line_number":934,"context_line":"        rp_uuids \u003d set("},{"line_number":935,"context_line":"            areq_by_suffix[suffix].resource_requests[0].resource_provider.uuid"},{"line_number":936,"context_line":"            for suffix in same_subtree)"},{"line_number":937,"context_line":"        if not _check_same_subtree(rp_uuids, parent_uuid_by_rp_uuid):"},{"line_number":938,"context_line":"            return False"}],"source_content_type":"text/x-python","patch_set":1,"id":"9fb8cfa7_d318d3d3","line":935,"range":{"start_line":935,"start_character":35,"end_line":935,"end_character":55},"updated":"2019-07-01 14:50:29.000000000","message":"Oh, see, here we\u0027re relying on the first resource request anyway. So yeah, can we get rid of `suffixes`?","commit_id":"a3720fbe3fee1602420ee4043a5aa0362c537f9b"},{"author":{"_account_id":14070,"name":"Eric Fried","email":"openstack@fried.cc","username":"efried"},"change_message_id":"72da04b3442651b0dc6f7efd19d4dcfd78f73c86","unresolved":false,"context_lines":[{"line_number":951,"context_line":"        ancestors_by_uuid[rp_uuid] \u003d _get_ancestors_by_one_uuid("},{"line_number":952,"context_line":"            rp_uuid, parent_uuid_by_rp_uuid)"},{"line_number":953,"context_line":"    for rp_uuid in ancestors_by_uuid:"},{"line_number":954,"context_line":"        poped_value \u003d ancestors_by_uuid.pop(rp_uuid)"},{"line_number":955,"context_line":"        common_ancestors \u003d reduce((lambda x, y: x \u0026 y),"},{"line_number":956,"context_line":"                                  list(ancestors_by_uuid.values()))"},{"line_number":957,"context_line":"        if rp_uuid in common_ancestors:"}],"source_content_type":"text/x-python","patch_set":1,"id":"9fb8cfa7_f31e37b9","line":954,"range":{"start_line":954,"start_character":8,"end_line":954,"end_character":13},"updated":"2019-07-01 14:50:29.000000000","message":"popped? (is \u0027pop\u0027 a python token or an English verb? bah)","commit_id":"a3720fbe3fee1602420ee4043a5aa0362c537f9b"},{"author":{"_account_id":11564,"name":"Chris Dent","email":"cdent@anticdent.org","username":"chdent"},"change_message_id":"897e08e4e27df5b9b28795bb677b0466c33f9436","unresolved":false,"context_lines":[{"line_number":951,"context_line":"        ancestors_by_uuid[rp_uuid] \u003d _get_ancestors_by_one_uuid("},{"line_number":952,"context_line":"            rp_uuid, parent_uuid_by_rp_uuid)"},{"line_number":953,"context_line":"    for rp_uuid in ancestors_by_uuid:"},{"line_number":954,"context_line":"        poped_value \u003d ancestors_by_uuid.pop(rp_uuid)"},{"line_number":955,"context_line":"        common_ancestors \u003d reduce((lambda x, y: x \u0026 y),"},{"line_number":956,"context_line":"                                  list(ancestors_by_uuid.values()))"},{"line_number":957,"context_line":"        if rp_uuid in common_ancestors:"}],"source_content_type":"text/x-python","patch_set":1,"id":"9fb8cfa7_09df1c66","line":954,"range":{"start_line":954,"start_character":8,"end_line":954,"end_character":13},"in_reply_to":"9fb8cfa7_f31e37b9","updated":"2019-07-01 15:58:44.000000000","message":"popped is more correct, but it would be better, since the value is used below at line 959 to use a variable name that says what the thing is. next_ancestor?","commit_id":"a3720fbe3fee1602420ee4043a5aa0362c537f9b"},{"author":{"_account_id":11564,"name":"Chris Dent","email":"cdent@anticdent.org","username":"chdent"},"change_message_id":"897e08e4e27df5b9b28795bb677b0466c33f9436","unresolved":false,"context_lines":[{"line_number":952,"context_line":"            rp_uuid, parent_uuid_by_rp_uuid)"},{"line_number":953,"context_line":"    for rp_uuid in ancestors_by_uuid:"},{"line_number":954,"context_line":"        poped_value \u003d ancestors_by_uuid.pop(rp_uuid)"},{"line_number":955,"context_line":"        common_ancestors \u003d reduce((lambda x, y: x \u0026 y),"},{"line_number":956,"context_line":"                                  list(ancestors_by_uuid.values()))"},{"line_number":957,"context_line":"        if rp_uuid in common_ancestors:"},{"line_number":958,"context_line":"            return True"}],"source_content_type":"text/x-python","patch_set":1,"id":"9fb8cfa7_e9ff28a8","line":955,"updated":"2019-07-01 15:58:44.000000000","message":"What about:\n\n    a_b_u \u003d list(ancestors_by_uuid.values())\n    common_ancestors \u003d a_b_u[0].intersection(*a_b_u[1:])\n\nor something close to that. Feels less iterative and more pythonic.","commit_id":"a3720fbe3fee1602420ee4043a5aa0362c537f9b"},{"author":{"_account_id":14070,"name":"Eric Fried","email":"openstack@fried.cc","username":"efried"},"change_message_id":"0682c9270689d4949137b7728689bad7a635a1a5","unresolved":false,"context_lines":[{"line_number":952,"context_line":"            rp_uuid, parent_uuid_by_rp_uuid)"},{"line_number":953,"context_line":"    for rp_uuid in ancestors_by_uuid:"},{"line_number":954,"context_line":"        poped_value \u003d ancestors_by_uuid.pop(rp_uuid)"},{"line_number":955,"context_line":"        common_ancestors \u003d reduce((lambda x, y: x \u0026 y),"},{"line_number":956,"context_line":"                                  list(ancestors_by_uuid.values()))"},{"line_number":957,"context_line":"        if rp_uuid in common_ancestors:"},{"line_number":958,"context_line":"            return True"}],"source_content_type":"text/x-python","patch_set":1,"id":"9fb8cfa7_09dddcdb","line":955,"in_reply_to":"9fb8cfa7_e9ff28a8","updated":"2019-07-01 16:14:10.000000000","message":"In this case I prefer the reduce(), unless you can come up with some other way we can avoid creating the list in memory.\n\n(IRL I guess it\u0027ll be a very small list, but still...)\n\nI suppose\n\n common_ancestors \u003d set(rp_uuids).intersection(ancestors_by_uuid.values())\n\nwould work.","commit_id":"a3720fbe3fee1602420ee4043a5aa0362c537f9b"},{"author":{"_account_id":14070,"name":"Eric Fried","email":"openstack@fried.cc","username":"efried"},"change_message_id":"72da04b3442651b0dc6f7efd19d4dcfd78f73c86","unresolved":false,"context_lines":[{"line_number":952,"context_line":"            rp_uuid, parent_uuid_by_rp_uuid)"},{"line_number":953,"context_line":"    for rp_uuid in ancestors_by_uuid:"},{"line_number":954,"context_line":"        poped_value \u003d ancestors_by_uuid.pop(rp_uuid)"},{"line_number":955,"context_line":"        common_ancestors \u003d reduce((lambda x, y: x \u0026 y),"},{"line_number":956,"context_line":"                                  list(ancestors_by_uuid.values()))"},{"line_number":957,"context_line":"        if rp_uuid in common_ancestors:"},{"line_number":958,"context_line":"            return True"},{"line_number":959,"context_line":"        ancestors_by_uuid[rp_uuid] \u003d poped_value"}],"source_content_type":"text/x-python","patch_set":1,"id":"9fb8cfa7_33dccfe2","line":956,"range":{"start_line":955,"start_character":8,"end_line":956,"end_character":67},"updated":"2019-07-01 14:50:29.000000000","message":"If the filter is going to pass, this has to reduce to exactly one value *and* that value must exist in rp_uuids -- right?\n\nIn which case we can make this method more efficient and simpler as:\n\n # I think if you do this with (), it produces a generator in py3, so...\n ancestor_sets \u003d (_get_ancestors_by_one_uuid(\n    rp_uuid, parent_uuid_by_rp_uuid) for rp_uuid in rp_uuids)\n # ...this will iterate over the generator and we only had to do one pass\n common_ancestors \u003d reduce(lambda x, y: x \u0026 y, ancestor_sets)\n if len(common_ancestors) !\u003d 1: return False\n return common_ancestors[0] in rp_uuids","commit_id":"a3720fbe3fee1602420ee4043a5aa0362c537f9b"},{"author":{"_account_id":25625,"name":"Tetsuro Nakamura","email":"tetsuro.nakamura.bc@hco.ntt.co.jp","username":"tetsuro0907"},"change_message_id":"8a561b548492cca161ff22da88f6420f4bd1c9d9","unresolved":false,"context_lines":[{"line_number":952,"context_line":"            rp_uuid, parent_uuid_by_rp_uuid)"},{"line_number":953,"context_line":"    for rp_uuid in ancestors_by_uuid:"},{"line_number":954,"context_line":"        poped_value \u003d ancestors_by_uuid.pop(rp_uuid)"},{"line_number":955,"context_line":"        common_ancestors \u003d reduce((lambda x, y: x \u0026 y),"},{"line_number":956,"context_line":"                                  list(ancestors_by_uuid.values()))"},{"line_number":957,"context_line":"        if rp_uuid in common_ancestors:"},{"line_number":958,"context_line":"            return True"},{"line_number":959,"context_line":"        ancestors_by_uuid[rp_uuid] \u003d poped_value"}],"source_content_type":"text/x-python","patch_set":1,"id":"9fb8cfa7_a58e2776","line":956,"range":{"start_line":955,"start_character":8,"end_line":956,"end_character":67},"in_reply_to":"9fb8cfa7_33dccfe2","updated":"2019-07-02 12:42:21.000000000","message":"I\u0027m not sure I\u0027m catching up here. I will add a unit test that allows you to try that refactoring.","commit_id":"a3720fbe3fee1602420ee4043a5aa0362c537f9b"},{"author":{"_account_id":11564,"name":"Chris Dent","email":"cdent@anticdent.org","username":"chdent"},"change_message_id":"9fb6ffea935788a5c7a309646a90f0cf6e37b1f8","unresolved":false,"context_lines":[{"line_number":806,"context_line":""},{"line_number":807,"context_line":"        # ToDo(tetsuro): This suffix_list is used in _satisfies_same_subtree()"},{"line_number":808,"context_line":"        # and we\u0027d like to remove this adding suffix field to each"},{"line_number":809,"context_line":"        # AllocationRequest"},{"line_number":810,"context_line":"        suffix_list \u003d areq_lists_by_suffix.keys()"},{"line_number":811,"context_line":"        for areq_list in itertools.product("},{"line_number":812,"context_line":"                *list(areq_lists_by_suffix.values())):"}],"source_content_type":"text/x-python","patch_set":2,"id":"9fb8cfa7_7f72e5af","line":809,"updated":"2019-07-03 11:44:09.000000000","message":"The \u0027mappings\u0027 attribute I\u0027ve added to AllocationRequest in https://review.opendev.org/#/c/668724/ may be of some use here.","commit_id":"8810d5e5d2840c31191bb2f48f7bc57f1682a77e"},{"author":{"_account_id":11564,"name":"Chris Dent","email":"cdent@anticdent.org","username":"chdent"},"change_message_id":"ae041abbc906256f45d4388449f696a69c7810f6","unresolved":false,"context_lines":[{"line_number":427,"context_line":"    :param suffix: The suffix of the RequestGroup these resources are"},{"line_number":428,"context_line":"                   satisfying."},{"line_number":429,"context_line":"    \"\"\""},{"line_number":430,"context_line":"    mappings \u003d collections.defaultdict(set)"},{"line_number":431,"context_line":"    if not requested_resources:"},{"line_number":432,"context_line":"        # This is a resourceless request for a suffixed group that is being"},{"line_number":433,"context_line":"        # specified in the `same_subtree` queryparam. In this case, we return"}],"source_content_type":"text/x-python","patch_set":4,"id":"7faddb67_3ae31b08","line":430,"updated":"2019-07-04 12:53:31.000000000","message":"You don\u0027t need to do the defaultdict (I probably changed it while you were working on this). See line 453 below for the alternative.","commit_id":"0efe0300fa420dfd83de0cee4f903d0af2013ecb"},{"author":{"_account_id":25625,"name":"Tetsuro Nakamura","email":"tetsuro.nakamura.bc@hco.ntt.co.jp","username":"tetsuro0907"},"change_message_id":"0a29e24e3debc366ad2e4fc549e5369339c488af","unresolved":false,"context_lines":[{"line_number":427,"context_line":"    :param suffix: The suffix of the RequestGroup these resources are"},{"line_number":428,"context_line":"                   satisfying."},{"line_number":429,"context_line":"    \"\"\""},{"line_number":430,"context_line":"    mappings \u003d collections.defaultdict(set)"},{"line_number":431,"context_line":"    if not requested_resources:"},{"line_number":432,"context_line":"        # This is a resourceless request for a suffixed group that is being"},{"line_number":433,"context_line":"        # specified in the `same_subtree` queryparam. In this case, we return"}],"source_content_type":"text/x-python","patch_set":4,"id":"7faddb67_fe5330e1","line":430,"in_reply_to":"7faddb67_3ae31b08","updated":"2019-07-05 01:03:01.000000000","message":"Nice","commit_id":"0efe0300fa420dfd83de0cee4f903d0af2013ecb"},{"author":{"_account_id":9708,"name":"Balazs Gibizer","display_name":"gibi","email":"gibizer@gmail.com","username":"gibi"},"change_message_id":"7d045957ed7123c1ac11eee8627bce0d05b8393c","unresolved":false,"context_lines":[{"line_number":416,"context_line":"    return alloc_requests, list(summaries.values())"},{"line_number":417,"context_line":""},{"line_number":418,"context_line":""},{"line_number":419,"context_line":"def _allocation_request_for_provider(ctx, requested_resources, provider,"},{"line_number":420,"context_line":"                                     suffix):"},{"line_number":421,"context_line":"    \"\"\"Returns an AllocationRequest object containing AllocationRequestResource"},{"line_number":422,"context_line":"    objects for each resource class in the supplied requested resources dict."}],"source_content_type":"text/x-python","patch_set":7,"id":"7faddb67_0de28304","side":"PARENT","line":419,"updated":"2019-07-08 16:01:27.000000000","message":"This unused-param-removal seems to be unrelated to this patch.","commit_id":"d1005782f5f2c6dfbeaf32fecc821c90770108ff"},{"author":{"_account_id":9708,"name":"Balazs Gibizer","display_name":"gibi","email":"gibizer@gmail.com","username":"gibi"},"change_message_id":"7d045957ed7123c1ac11eee8627bce0d05b8393c","unresolved":false,"context_lines":[{"line_number":735,"context_line":"    For that merged list of alloc_reqs, a corresponding provider_summaries is"},{"line_number":736,"context_line":"    produced."},{"line_number":737,"context_line":""},{"line_number":738,"context_line":"    :param candidates: A dict, keyed by integer suffix or \u0027\u0027, of tuples of"},{"line_number":739,"context_line":"            (allocation_requests, provider_summaries) to be merged."},{"line_number":740,"context_line":"    :param rw_ctx: RequestWideSearchContext."},{"line_number":741,"context_line":"    :return: A tuple of (allocation_requests, provider_summaries)."}],"source_content_type":"text/x-python","patch_set":7,"id":"7faddb67_cdcc6b8b","line":738,"range":{"start_line":738,"start_character":31,"end_line":738,"end_character":54},"updated":"2019-07-08 16:01:27.000000000","message":"unrelated: suffix could be a string","commit_id":"118415f62c8f66bd70d70661d7e6bd5c334bf1b6"},{"author":{"_account_id":25625,"name":"Tetsuro Nakamura","email":"tetsuro.nakamura.bc@hco.ntt.co.jp","username":"tetsuro0907"},"change_message_id":"acae72cc7be3d419170f095a88fdf258fa341f91","unresolved":false,"context_lines":[{"line_number":735,"context_line":"    For that merged list of alloc_reqs, a corresponding provider_summaries is"},{"line_number":736,"context_line":"    produced."},{"line_number":737,"context_line":""},{"line_number":738,"context_line":"    :param candidates: A dict, keyed by integer suffix or \u0027\u0027, of tuples of"},{"line_number":739,"context_line":"            (allocation_requests, provider_summaries) to be merged."},{"line_number":740,"context_line":"    :param rw_ctx: RequestWideSearchContext."},{"line_number":741,"context_line":"    :return: A tuple of (allocation_requests, provider_summaries)."}],"source_content_type":"text/x-python","patch_set":7,"id":"7faddb67_c81d2b74","line":738,"range":{"start_line":738,"start_character":31,"end_line":738,"end_character":54},"in_reply_to":"7faddb67_cdcc6b8b","updated":"2019-07-09 07:54:16.000000000","message":"https://review.opendev.org/#/c/669810/","commit_id":"118415f62c8f66bd70d70661d7e6bd5c334bf1b6"},{"author":{"_account_id":9708,"name":"Balazs Gibizer","display_name":"gibi","email":"gibizer@gmail.com","username":"gibi"},"change_message_id":"7d045957ed7123c1ac11eee8627bce0d05b8393c","unresolved":false,"context_lines":[{"line_number":919,"context_line":""},{"line_number":920,"context_line":"    :param areqs: A list containing one AllocationRequest for each input"},{"line_number":921,"context_line":"            RequestGroup."},{"line_number":922,"context_line":"    :param same_subtrees: A list of comma-separated lists of request group"},{"line_number":923,"context_line":"            suffix strings. If provided, all of the resource providers"},{"line_number":924,"context_line":"            satisfying the specified request groups must be rooted at one of"},{"line_number":925,"context_line":"            the resource providers satisfying the request groups."}],"source_content_type":"text/x-python","patch_set":7,"id":"7faddb67_adb1ef91","line":922,"range":{"start_line":922,"start_character":26,"end_line":922,"end_character":74},"updated":"2019-07-08 16:01:27.000000000","message":"OK it is uses consistently. Still I think the terminology \u0027coma-separated list\u0027 is not specific enough to make it clear to the reader. \n\nIf we really want a sort term here instead of an extra sentence I proposed in other files then maybe: A list of same_subtree-groupped lists of request group suffix strings.","commit_id":"118415f62c8f66bd70d70661d7e6bd5c334bf1b6"},{"author":{"_account_id":25625,"name":"Tetsuro Nakamura","email":"tetsuro.nakamura.bc@hco.ntt.co.jp","username":"tetsuro0907"},"change_message_id":"c3a42d708d31dbfd7c529a5b2e2024a7f96eabce","unresolved":false,"context_lines":[{"line_number":919,"context_line":""},{"line_number":920,"context_line":"    :param areqs: A list containing one AllocationRequest for each input"},{"line_number":921,"context_line":"            RequestGroup."},{"line_number":922,"context_line":"    :param same_subtrees: A list of comma-separated lists of request group"},{"line_number":923,"context_line":"            suffix strings. If provided, all of the resource providers"},{"line_number":924,"context_line":"            satisfying the specified request groups must be rooted at one of"},{"line_number":925,"context_line":"            the resource providers satisfying the request groups."}],"source_content_type":"text/x-python","patch_set":7,"id":"7faddb67_9d069786","line":922,"range":{"start_line":922,"start_character":26,"end_line":922,"end_character":74},"in_reply_to":"7faddb67_adb1ef91","updated":"2019-07-09 07:23:26.000000000","message":"Done","commit_id":"118415f62c8f66bd70d70661d7e6bd5c334bf1b6"},{"author":{"_account_id":9708,"name":"Balazs Gibizer","display_name":"gibi","email":"gibizer@gmail.com","username":"gibi"},"change_message_id":"7d045957ed7123c1ac11eee8627bce0d05b8393c","unresolved":false,"context_lines":[{"line_number":926,"context_line":"    :param parent_uuid_by_rp_uuid: A dict of parent uuids keyed by rp uuids."},{"line_number":927,"context_line":"    :return: True if areqs satisfies same_subtree policy; False otherwise."},{"line_number":928,"context_line":"    \"\"\""},{"line_number":929,"context_line":"    if not same_subtrees:"},{"line_number":930,"context_line":"        return True"},{"line_number":931,"context_line":"    for same_subtree in same_subtrees:"},{"line_number":932,"context_line":"        rp_uuids \u003d set().union(*(areq.mappings.get(suffix) for areq in areqs"}],"source_content_type":"text/x-python","patch_set":7,"id":"7faddb67_8da8b31f","line":929,"range":{"start_line":929,"start_character":4,"end_line":929,"end_character":25},"updated":"2019-07-08 16:01:27.000000000","message":"As far as I see same_subtree cannot be null, it can only be empty list or non empty list. So the if does not optimize away anything from the for loop.","commit_id":"118415f62c8f66bd70d70661d7e6bd5c334bf1b6"},{"author":{"_account_id":25625,"name":"Tetsuro Nakamura","email":"tetsuro.nakamura.bc@hco.ntt.co.jp","username":"tetsuro0907"},"change_message_id":"c3a42d708d31dbfd7c529a5b2e2024a7f96eabce","unresolved":false,"context_lines":[{"line_number":926,"context_line":"    :param parent_uuid_by_rp_uuid: A dict of parent uuids keyed by rp uuids."},{"line_number":927,"context_line":"    :return: True if areqs satisfies same_subtree policy; False otherwise."},{"line_number":928,"context_line":"    \"\"\""},{"line_number":929,"context_line":"    if not same_subtrees:"},{"line_number":930,"context_line":"        return True"},{"line_number":931,"context_line":"    for same_subtree in same_subtrees:"},{"line_number":932,"context_line":"        rp_uuids \u003d set().union(*(areq.mappings.get(suffix) for areq in areqs"}],"source_content_type":"text/x-python","patch_set":7,"id":"7faddb67_bd091396","line":929,"range":{"start_line":929,"start_character":4,"end_line":929,"end_character":25},"in_reply_to":"7faddb67_8da8b31f","updated":"2019-07-09 07:23:26.000000000","message":"Right. Done.","commit_id":"118415f62c8f66bd70d70661d7e6bd5c334bf1b6"},{"author":{"_account_id":9708,"name":"Balazs Gibizer","display_name":"gibi","email":"gibizer@gmail.com","username":"gibi"},"change_message_id":"7d045957ed7123c1ac11eee8627bce0d05b8393c","unresolved":false,"context_lines":[{"line_number":929,"context_line":"    if not same_subtrees:"},{"line_number":930,"context_line":"        return True"},{"line_number":931,"context_line":"    for same_subtree in same_subtrees:"},{"line_number":932,"context_line":"        rp_uuids \u003d set().union(*(areq.mappings.get(suffix) for areq in areqs"},{"line_number":933,"context_line":"                               for suffix in same_subtree"},{"line_number":934,"context_line":"                               if areq.mappings.get(suffix)))"},{"line_number":935,"context_line":"        if not _check_same_subtree(rp_uuids, parent_uuid_by_rp_uuid):"}],"source_content_type":"text/x-python","patch_set":7,"id":"7faddb67_df5972fe","line":932,"updated":"2019-07-08 16:01:27.000000000","message":"This double comprehension warrant for a comment explaining the goal of it.\n\n# Collect each RP uuid that satisfy on or more groups in a single same_subtree constraint.","commit_id":"118415f62c8f66bd70d70661d7e6bd5c334bf1b6"},{"author":{"_account_id":25625,"name":"Tetsuro Nakamura","email":"tetsuro.nakamura.bc@hco.ntt.co.jp","username":"tetsuro0907"},"change_message_id":"c3a42d708d31dbfd7c529a5b2e2024a7f96eabce","unresolved":false,"context_lines":[{"line_number":929,"context_line":"    if not same_subtrees:"},{"line_number":930,"context_line":"        return True"},{"line_number":931,"context_line":"    for same_subtree in same_subtrees:"},{"line_number":932,"context_line":"        rp_uuids \u003d set().union(*(areq.mappings.get(suffix) for areq in areqs"},{"line_number":933,"context_line":"                               for suffix in same_subtree"},{"line_number":934,"context_line":"                               if areq.mappings.get(suffix)))"},{"line_number":935,"context_line":"        if not _check_same_subtree(rp_uuids, parent_uuid_by_rp_uuid):"}],"source_content_type":"text/x-python","patch_set":7,"id":"7faddb67_bd98331b","line":932,"in_reply_to":"7faddb67_df5972fe","updated":"2019-07-09 07:23:26.000000000","message":"Done","commit_id":"118415f62c8f66bd70d70661d7e6bd5c334bf1b6"},{"author":{"_account_id":9708,"name":"Balazs Gibizer","display_name":"gibi","email":"gibizer@gmail.com","username":"gibi"},"change_message_id":"7d045957ed7123c1ac11eee8627bce0d05b8393c","unresolved":false,"context_lines":[{"line_number":931,"context_line":"    for same_subtree in same_subtrees:"},{"line_number":932,"context_line":"        rp_uuids \u003d set().union(*(areq.mappings.get(suffix) for areq in areqs"},{"line_number":933,"context_line":"                               for suffix in same_subtree"},{"line_number":934,"context_line":"                               if areq.mappings.get(suffix)))"},{"line_number":935,"context_line":"        if not _check_same_subtree(rp_uuids, parent_uuid_by_rp_uuid):"},{"line_number":936,"context_line":"            return False"},{"line_number":937,"context_line":"    return True"}],"source_content_type":"text/x-python","patch_set":7,"id":"7faddb67_ff9d4e59","line":934,"range":{"start_line":934,"start_character":34,"end_line":934,"end_character":59},"updated":"2019-07-08 16:01:27.000000000","message":"How can the mapping be empty for a suffix? At L442 there is a comment that mappings is filled even for resourceless groups (if I understand correctly)","commit_id":"118415f62c8f66bd70d70661d7e6bd5c334bf1b6"},{"author":{"_account_id":25625,"name":"Tetsuro Nakamura","email":"tetsuro.nakamura.bc@hco.ntt.co.jp","username":"tetsuro0907"},"change_message_id":"c3a42d708d31dbfd7c529a5b2e2024a7f96eabce","unresolved":false,"context_lines":[{"line_number":931,"context_line":"    for same_subtree in same_subtrees:"},{"line_number":932,"context_line":"        rp_uuids \u003d set().union(*(areq.mappings.get(suffix) for areq in areqs"},{"line_number":933,"context_line":"                               for suffix in same_subtree"},{"line_number":934,"context_line":"                               if areq.mappings.get(suffix)))"},{"line_number":935,"context_line":"        if not _check_same_subtree(rp_uuids, parent_uuid_by_rp_uuid):"},{"line_number":936,"context_line":"            return False"},{"line_number":937,"context_line":"    return True"}],"source_content_type":"text/x-python","patch_set":7,"id":"7faddb67_5dea5f75","line":934,"range":{"start_line":934,"start_character":34,"end_line":934,"end_character":59},"in_reply_to":"7faddb67_ff9d4e59","updated":"2019-07-09 07:23:26.000000000","message":"This is called *before* _consolidate_allocation_requests(), so at this point each areq comes from a single suffix, so we need to iterate over all the areqs to find the areq that has the suffix.\nThis would be more readable if we call this method, _satisfies_same_subtree(), *after* _consolidate_allocation_requests(), but I wanted as small size of candidates to go through the  _consolidate_allocation_requests() as possible.","commit_id":"118415f62c8f66bd70d70661d7e6bd5c334bf1b6"},{"author":{"_account_id":9708,"name":"Balazs Gibizer","display_name":"gibi","email":"gibizer@gmail.com","username":"gibi"},"change_message_id":"7d045957ed7123c1ac11eee8627bce0d05b8393c","unresolved":false,"context_lines":[{"line_number":938,"context_line":""},{"line_number":939,"context_line":""},{"line_number":940,"context_line":"def _check_same_subtree(rp_uuids, parent_uuid_by_rp_uuid):"},{"line_number":941,"context_line":"    \"\"\"Returns True if given rp uuids are all in one same subtree."},{"line_number":942,"context_line":""},{"line_number":943,"context_line":"    Note: The rps are in one same subtree means all the providers are"},{"line_number":944,"context_line":"          rooted at one of the providers"}],"source_content_type":"text/x-python","patch_set":7,"id":"7faddb67_dfd092cc","line":941,"range":{"start_line":941,"start_character":53,"end_line":941,"end_character":57},"updated":"2019-07-08 16:01:27.000000000","message":"I\u0027m not native speaker so I might be mistaken here but it feels that \"all in one subtree\" would be enough or \"all in the same subtree\" would be enough.","commit_id":"118415f62c8f66bd70d70661d7e6bd5c334bf1b6"},{"author":{"_account_id":25625,"name":"Tetsuro Nakamura","email":"tetsuro.nakamura.bc@hco.ntt.co.jp","username":"tetsuro0907"},"change_message_id":"c3a42d708d31dbfd7c529a5b2e2024a7f96eabce","unresolved":false,"context_lines":[{"line_number":938,"context_line":""},{"line_number":939,"context_line":""},{"line_number":940,"context_line":"def _check_same_subtree(rp_uuids, parent_uuid_by_rp_uuid):"},{"line_number":941,"context_line":"    \"\"\"Returns True if given rp uuids are all in one same subtree."},{"line_number":942,"context_line":""},{"line_number":943,"context_line":"    Note: The rps are in one same subtree means all the providers are"},{"line_number":944,"context_line":"          rooted at one of the providers"}],"source_content_type":"text/x-python","patch_set":7,"id":"7faddb67_1db2a795","line":941,"range":{"start_line":941,"start_character":53,"end_line":941,"end_character":57},"in_reply_to":"7faddb67_dfd092cc","updated":"2019-07-09 07:23:26.000000000","message":"Done","commit_id":"118415f62c8f66bd70d70661d7e6bd5c334bf1b6"},{"author":{"_account_id":9708,"name":"Balazs Gibizer","display_name":"gibi","email":"gibizer@gmail.com","username":"gibi"},"change_message_id":"7d045957ed7123c1ac11eee8627bce0d05b8393c","unresolved":false,"context_lines":[{"line_number":940,"context_line":"def _check_same_subtree(rp_uuids, parent_uuid_by_rp_uuid):"},{"line_number":941,"context_line":"    \"\"\"Returns True if given rp uuids are all in one same subtree."},{"line_number":942,"context_line":""},{"line_number":943,"context_line":"    Note: The rps are in one same subtree means all the providers are"},{"line_number":944,"context_line":"          rooted at one of the providers"},{"line_number":945,"context_line":"    \"\"\""},{"line_number":946,"context_line":"    if len(rp_uuids) \u003d\u003d 1:"}],"source_content_type":"text/x-python","patch_set":7,"id":"7faddb67_7f8f1ecc","line":943,"range":{"start_line":943,"start_character":25,"end_line":943,"end_character":33},"updated":"2019-07-08 16:01:27.000000000","message":"ditto","commit_id":"118415f62c8f66bd70d70661d7e6bd5c334bf1b6"},{"author":{"_account_id":25625,"name":"Tetsuro Nakamura","email":"tetsuro.nakamura.bc@hco.ntt.co.jp","username":"tetsuro0907"},"change_message_id":"c3a42d708d31dbfd7c529a5b2e2024a7f96eabce","unresolved":false,"context_lines":[{"line_number":940,"context_line":"def _check_same_subtree(rp_uuids, parent_uuid_by_rp_uuid):"},{"line_number":941,"context_line":"    \"\"\"Returns True if given rp uuids are all in one same subtree."},{"line_number":942,"context_line":""},{"line_number":943,"context_line":"    Note: The rps are in one same subtree means all the providers are"},{"line_number":944,"context_line":"          rooted at one of the providers"},{"line_number":945,"context_line":"    \"\"\""},{"line_number":946,"context_line":"    if len(rp_uuids) \u003d\u003d 1:"}],"source_content_type":"text/x-python","patch_set":7,"id":"7faddb67_3dad2331","line":943,"range":{"start_line":943,"start_character":25,"end_line":943,"end_character":33},"in_reply_to":"7faddb67_7f8f1ecc","updated":"2019-07-09 07:23:26.000000000","message":"Done","commit_id":"118415f62c8f66bd70d70661d7e6bd5c334bf1b6"},{"author":{"_account_id":9708,"name":"Balazs Gibizer","display_name":"gibi","email":"gibizer@gmail.com","username":"gibi"},"change_message_id":"7d045957ed7123c1ac11eee8627bce0d05b8393c","unresolved":false,"context_lines":[{"line_number":950,"context_line":"    for rp_uuid in rp_uuids:"},{"line_number":951,"context_line":"        ancestors_by_uuid[rp_uuid] \u003d _get_ancestors_by_one_uuid("},{"line_number":952,"context_line":"            rp_uuid, parent_uuid_by_rp_uuid)"},{"line_number":953,"context_line":"    for rp_uuid in ancestors_by_uuid:"},{"line_number":954,"context_line":"        own_ancestors \u003d ancestors_by_uuid.pop(rp_uuid)"},{"line_number":955,"context_line":"        common_ancestors \u003d set.intersection(*ancestors_by_uuid.values())"},{"line_number":956,"context_line":"        if rp_uuid in common_ancestors:"}],"source_content_type":"text/x-python","patch_set":7,"id":"7faddb67_a25fb93f","line":953,"range":{"start_line":953,"start_character":19,"end_line":953,"end_character":36},"updated":"2019-07-08 16:01:27.000000000","message":"I think rp_uuids here would make the intention more clearer.","commit_id":"118415f62c8f66bd70d70661d7e6bd5c334bf1b6"},{"author":{"_account_id":9708,"name":"Balazs Gibizer","display_name":"gibi","email":"gibizer@gmail.com","username":"gibi"},"change_message_id":"7d045957ed7123c1ac11eee8627bce0d05b8393c","unresolved":false,"context_lines":[{"line_number":951,"context_line":"        ancestors_by_uuid[rp_uuid] \u003d _get_ancestors_by_one_uuid("},{"line_number":952,"context_line":"            rp_uuid, parent_uuid_by_rp_uuid)"},{"line_number":953,"context_line":"    for rp_uuid in ancestors_by_uuid:"},{"line_number":954,"context_line":"        own_ancestors \u003d ancestors_by_uuid.pop(rp_uuid)"},{"line_number":955,"context_line":"        common_ancestors \u003d set.intersection(*ancestors_by_uuid.values())"},{"line_number":956,"context_line":"        if rp_uuid in common_ancestors:"},{"line_number":957,"context_line":"            return True"}],"source_content_type":"text/x-python","patch_set":7,"id":"7faddb67_42360506","line":954,"range":{"start_line":954,"start_character":24,"end_line":954,"end_character":54},"updated":"2019-07-08 16:01:27.000000000","message":"Is it safe to modify the collection we are iterating on?","commit_id":"118415f62c8f66bd70d70661d7e6bd5c334bf1b6"},{"author":{"_account_id":9708,"name":"Balazs Gibizer","display_name":"gibi","email":"gibizer@gmail.com","username":"gibi"},"change_message_id":"7d045957ed7123c1ac11eee8627bce0d05b8393c","unresolved":false,"context_lines":[{"line_number":952,"context_line":"            rp_uuid, parent_uuid_by_rp_uuid)"},{"line_number":953,"context_line":"    for rp_uuid in ancestors_by_uuid:"},{"line_number":954,"context_line":"        own_ancestors \u003d ancestors_by_uuid.pop(rp_uuid)"},{"line_number":955,"context_line":"        common_ancestors \u003d set.intersection(*ancestors_by_uuid.values())"},{"line_number":956,"context_line":"        if rp_uuid in common_ancestors:"},{"line_number":957,"context_line":"            return True"},{"line_number":958,"context_line":"        ancestors_by_uuid[rp_uuid] \u003d own_ancestors"}],"source_content_type":"text/x-python","patch_set":7,"id":"7faddb67_822b9d92","line":955,"range":{"start_line":955,"start_character":8,"end_line":955,"end_character":72},"updated":"2019-07-08 16:01:27.000000000","message":"Do we need to calculate this at every iteration?","commit_id":"118415f62c8f66bd70d70661d7e6bd5c334bf1b6"},{"author":{"_account_id":9708,"name":"Balazs Gibizer","display_name":"gibi","email":"gibizer@gmail.com","username":"gibi"},"change_message_id":"7d045957ed7123c1ac11eee8627bce0d05b8393c","unresolved":false,"context_lines":[{"line_number":950,"context_line":"    for rp_uuid in rp_uuids:"},{"line_number":951,"context_line":"        ancestors_by_uuid[rp_uuid] \u003d _get_ancestors_by_one_uuid("},{"line_number":952,"context_line":"            rp_uuid, parent_uuid_by_rp_uuid)"},{"line_number":953,"context_line":"    for rp_uuid in ancestors_by_uuid:"},{"line_number":954,"context_line":"        own_ancestors \u003d ancestors_by_uuid.pop(rp_uuid)"},{"line_number":955,"context_line":"        common_ancestors \u003d set.intersection(*ancestors_by_uuid.values())"},{"line_number":956,"context_line":"        if rp_uuid in common_ancestors:"},{"line_number":957,"context_line":"            return True"},{"line_number":958,"context_line":"        ancestors_by_uuid[rp_uuid] \u003d own_ancestors"},{"line_number":959,"context_line":"    return False"},{"line_number":960,"context_line":""},{"line_number":961,"context_line":""},{"line_number":962,"context_line":"def _get_ancestors_by_one_uuid("}],"source_content_type":"text/x-python","patch_set":7,"id":"7faddb67_f5ba4ddc","line":959,"range":{"start_line":953,"start_character":0,"end_line":959,"end_character":16},"updated":"2019-07-08 16:01:27.000000000","message":"I think this can be made simpler:\n\n  # these are the common ancestors of each rp_uuid in question\n  common_ancestors \u003d set.intersection(*ancestors_by_uuid.values())\n  # if any of the rp_uuid is in the common_ancestors set, then \n  # we know that, that rp_uuid is the root of the other rp_uuids \n  # in this same_subtree constraint.\n  return len(common_ancestors.intersection(rp_uuids)) !\u003d 0\n\nI changed this locally and the tests are still green to me.","commit_id":"118415f62c8f66bd70d70661d7e6bd5c334bf1b6"},{"author":{"_account_id":25625,"name":"Tetsuro Nakamura","email":"tetsuro.nakamura.bc@hco.ntt.co.jp","username":"tetsuro0907"},"change_message_id":"c3a42d708d31dbfd7c529a5b2e2024a7f96eabce","unresolved":false,"context_lines":[{"line_number":950,"context_line":"    for rp_uuid in rp_uuids:"},{"line_number":951,"context_line":"        ancestors_by_uuid[rp_uuid] \u003d _get_ancestors_by_one_uuid("},{"line_number":952,"context_line":"            rp_uuid, parent_uuid_by_rp_uuid)"},{"line_number":953,"context_line":"    for rp_uuid in ancestors_by_uuid:"},{"line_number":954,"context_line":"        own_ancestors \u003d ancestors_by_uuid.pop(rp_uuid)"},{"line_number":955,"context_line":"        common_ancestors \u003d set.intersection(*ancestors_by_uuid.values())"},{"line_number":956,"context_line":"        if rp_uuid in common_ancestors:"},{"line_number":957,"context_line":"            return True"},{"line_number":958,"context_line":"        ancestors_by_uuid[rp_uuid] \u003d own_ancestors"},{"line_number":959,"context_line":"    return False"},{"line_number":960,"context_line":""},{"line_number":961,"context_line":""},{"line_number":962,"context_line":"def _get_ancestors_by_one_uuid("}],"source_content_type":"text/x-python","patch_set":7,"id":"7faddb67_68f3d70b","line":959,"range":{"start_line":953,"start_character":0,"end_line":959,"end_character":16},"in_reply_to":"7faddb67_f5ba4ddc","updated":"2019-07-09 07:23:26.000000000","message":"Ahhhhhhh this may be what eric also had proposed to me before. Yes, now I got it. This is cool. Done.","commit_id":"118415f62c8f66bd70d70661d7e6bd5c334bf1b6"},{"author":{"_account_id":9708,"name":"Balazs Gibizer","display_name":"gibi","email":"gibizer@gmail.com","username":"gibi"},"change_message_id":"7d045957ed7123c1ac11eee8627bce0d05b8393c","unresolved":false,"context_lines":[{"line_number":968,"context_line":"    if parent_uuid is None:"},{"line_number":969,"context_line":"        return ancestors"},{"line_number":970,"context_line":"    ancestors.add(parent_uuid)"},{"line_number":971,"context_line":"    return _get_ancestors_by_one_uuid("},{"line_number":972,"context_line":"        parent_uuid, parent_uuid_by_rp_uuid, ancestors\u003dancestors)"}],"source_content_type":"text/x-python","patch_set":7,"id":"7faddb67_62ab011d","line":971,"updated":"2019-07-08 16:01:27.000000000","message":"recursion checks out.","commit_id":"118415f62c8f66bd70d70661d7e6bd5c334bf1b6"},{"author":{"_account_id":14070,"name":"Eric Fried","email":"openstack@fried.cc","username":"efried"},"change_message_id":"39aa82bb81f7c1442878d1349e0274aaff12f3c4","unresolved":false,"context_lines":[{"line_number":902,"context_line":"        # all the resource_requests are satisfied by the same provider"},{"line_number":903,"context_line":"        # by definition because use_same_provider is True."},{"line_number":904,"context_line":"        list(areq.mappings.values())[0] for areq in areqs"},{"line_number":905,"context_line":"        if areq.use_same_provider)))"},{"line_number":906,"context_line":"    if num_granular_groups \u003d\u003d num_granular_groups_in_areqs:"},{"line_number":907,"context_line":"        return True"},{"line_number":908,"context_line":"    LOG.debug(\u0027Excluding the following set of AllocationRequest because \u0027"}],"source_content_type":"text/x-python","patch_set":8,"id":"7faddb67_dfcb9950","line":905,"updated":"2019-07-09 18:13:48.000000000","message":"Clever. Confusing, but clever.","commit_id":"8395e3f099022d8506ed5e6624582ec03e46c3b9"},{"author":{"_account_id":14070,"name":"Eric Fried","email":"openstack@fried.cc","username":"efried"},"change_message_id":"39aa82bb81f7c1442878d1349e0274aaff12f3c4","unresolved":false,"context_lines":[{"line_number":928,"context_line":"    \"\"\""},{"line_number":929,"context_line":"    for same_subtree in same_subtrees:"},{"line_number":930,"context_line":"        # Collect RP uuids that must satisfy a single same_subtree constraint."},{"line_number":931,"context_line":"        rp_uuids \u003d set().union(*(areq.mappings.get(suffix) for areq in areqs"},{"line_number":932,"context_line":"                               for suffix in same_subtree"},{"line_number":933,"context_line":"                               if areq.mappings.get(suffix)))"},{"line_number":934,"context_line":"        if not _check_same_subtree(rp_uuids, parent_uuid_by_rp_uuid):"}],"source_content_type":"text/x-python","patch_set":8,"id":"7faddb67_bfd57de7","line":931,"range":{"start_line":931,"start_character":33,"end_line":931,"end_character":58},"updated":"2019-07-09 18:13:48.000000000","message":"or\n\n areq.mappings[suffix]\n\nsince L933 ensures it exists","commit_id":"8395e3f099022d8506ed5e6624582ec03e46c3b9"},{"author":{"_account_id":14070,"name":"Eric Fried","email":"openstack@fried.cc","username":"efried"},"change_message_id":"39aa82bb81f7c1442878d1349e0274aaff12f3c4","unresolved":false,"context_lines":[{"line_number":930,"context_line":"        # Collect RP uuids that must satisfy a single same_subtree constraint."},{"line_number":931,"context_line":"        rp_uuids \u003d set().union(*(areq.mappings.get(suffix) for areq in areqs"},{"line_number":932,"context_line":"                               for suffix in same_subtree"},{"line_number":933,"context_line":"                               if areq.mappings.get(suffix)))"},{"line_number":934,"context_line":"        if not _check_same_subtree(rp_uuids, parent_uuid_by_rp_uuid):"},{"line_number":935,"context_line":"            return False"},{"line_number":936,"context_line":"    return True"}],"source_content_type":"text/x-python","patch_set":8,"id":"7faddb67_bf1c9dc1","line":933,"updated":"2019-07-09 18:13:48.000000000","message":"This could probably be made more efficient if we had built up a reverse mapping (RP: suffixes) along with the existing mapping. But that\u0027s probably not worth the added complexity.","commit_id":"8395e3f099022d8506ed5e6624582ec03e46c3b9"},{"author":{"_account_id":14070,"name":"Eric Fried","email":"openstack@fried.cc","username":"efried"},"change_message_id":"39aa82bb81f7c1442878d1349e0274aaff12f3c4","unresolved":false,"context_lines":[{"line_number":954,"context_line":"    return len(common_ancestors.intersection(rp_uuids)) !\u003d 0"},{"line_number":955,"context_line":""},{"line_number":956,"context_line":""},{"line_number":957,"context_line":"def _get_ancestors_by_one_uuid("},{"line_number":958,"context_line":"        rp_uuid, parent_uuid_by_rp_uuid, ancestors\u003dNone):"},{"line_number":959,"context_line":"    \"\"\"Returns a set of uuids of ancestors for a given rp uuid\"\"\""},{"line_number":960,"context_line":"    if ancestors is None:"}],"source_content_type":"text/x-python","patch_set":8,"id":"7faddb67_3fbbcd72","line":957,"range":{"start_line":957,"start_character":4,"end_line":957,"end_character":30},"updated":"2019-07-09 18:13:48.000000000","message":"Could cache these.\n\nAgain, the gain would be slight, but in this case it\u0027s a fairly easy code addition.","commit_id":"8395e3f099022d8506ed5e6624582ec03e46c3b9"}],"placement/objects/research_context.py":[{"author":{"_account_id":9708,"name":"Balazs Gibizer","display_name":"gibi","email":"gibizer@gmail.com","username":"gibi"},"change_message_id":"7d045957ed7123c1ac11eee8627bce0d05b8393c","unresolved":false,"context_lines":[{"line_number":566,"context_line":"            return []"},{"line_number":567,"context_line":""},{"line_number":568,"context_line":"    if not rg_ctx.resources:"},{"line_number":569,"context_line":"        provs_with_resource \u003d get_providers_with_root("},{"line_number":570,"context_line":"            rg_ctx.context, filtered_rps, forbidden_rp_ids)"},{"line_number":571,"context_line":""},{"line_number":572,"context_line":"    # provs_with_resource will contain a superset of providers with IDs still"}],"source_content_type":"text/x-python","patch_set":7,"id":"7faddb67_b585b5af","line":569,"updated":"2019-07-08 16:01:27.000000000","message":"This does an extra sql query that could be avoided if all the smaller queries in get_provider_ids_for_traits_and_aggs() would return the internal ID and the root ID as well for each RP.\n\nI see that would be a lot more code to change. So I agree with the approach here. If we figure out that this extra query is a bottleneck later, then we can optimize it away.\n\nStill a code comment explaining the situation and the possibility would be nice.","commit_id":"118415f62c8f66bd70d70661d7e6bd5c334bf1b6"},{"author":{"_account_id":25625,"name":"Tetsuro Nakamura","email":"tetsuro.nakamura.bc@hco.ntt.co.jp","username":"tetsuro0907"},"change_message_id":"c3a42d708d31dbfd7c529a5b2e2024a7f96eabce","unresolved":false,"context_lines":[{"line_number":566,"context_line":"            return []"},{"line_number":567,"context_line":""},{"line_number":568,"context_line":"    if not rg_ctx.resources:"},{"line_number":569,"context_line":"        provs_with_resource \u003d get_providers_with_root("},{"line_number":570,"context_line":"            rg_ctx.context, filtered_rps, forbidden_rp_ids)"},{"line_number":571,"context_line":""},{"line_number":572,"context_line":"    # provs_with_resource will contain a superset of providers with IDs still"}],"source_content_type":"text/x-python","patch_set":7,"id":"7faddb67_a8054fc4","line":569,"in_reply_to":"7faddb67_b585b5af","updated":"2019-07-09 07:23:26.000000000","message":"Done","commit_id":"118415f62c8f66bd70d70661d7e6bd5c334bf1b6"}],"placement/rest_api_version_history.rst":[{"author":{"_account_id":14070,"name":"Eric Fried","email":"openstack@fried.cc","username":"efried"},"change_message_id":"c16b08c7254561508678cd37ddbeece7adfdd929","unresolved":false,"context_lines":[{"line_number":661,"context_line":"/allocation_candidates`` API. It accepts a comma-separated list of request"},{"line_number":662,"context_line":"group suffix strings $S. Each must exactly match a suffix on a granular group"},{"line_number":663,"context_line":"somewhere else in the request. Importantly, the identified request groups need"},{"line_number":664,"context_line":"not have a resources[$S]. If this is provided, at least one of the resource"},{"line_number":665,"context_line":"providers satisfying the specified request group must be an ancestor of the"},{"line_number":666,"context_line":"rest. The ``same_subtree`` query parameter can be repeated and each repeat"},{"line_number":667,"context_line":"group is treated independently."}],"source_content_type":"text/x-rst","patch_set":2,"id":"7faddb67_c05f820c","line":664,"range":{"start_line":664,"start_character":11,"end_line":664,"end_character":24},"updated":"2019-07-03 22:39:15.000000000","message":"this should be spelled ``resources$S`` (no square brackets) since we\u0027re talking about that one specific request group.","commit_id":"8810d5e5d2840c31191bb2f48f7bc57f1682a77e"},{"author":{"_account_id":14070,"name":"Eric Fried","email":"openstack@fried.cc","username":"efried"},"change_message_id":"39aa82bb81f7c1442878d1349e0274aaff12f3c4","unresolved":false,"context_lines":[{"line_number":662,"context_line":"group suffix strings $S. Each must exactly match a suffix on a granular group"},{"line_number":663,"context_line":"somewhere else in the request. Importantly, the identified request groups need"},{"line_number":664,"context_line":"not have a resources$S. If this is provided, at least one of the resource"},{"line_number":665,"context_line":"providers satisfying the specified request group must be an ancestor of the"},{"line_number":666,"context_line":"rest. The ``same_subtree`` query parameter can be repeated and each repeat"},{"line_number":667,"context_line":"group is treated independently."}],"source_content_type":"text/x-rst","patch_set":8,"id":"7faddb67_22573005","line":665,"range":{"start_line":665,"start_character":21,"end_line":665,"end_character":24},"updated":"2019-07-09 18:13:48.000000000","message":"ditto","commit_id":"8395e3f099022d8506ed5e6624582ec03e46c3b9"}],"placement/tests/functional/fixtures/gabbits.py":[{"author":{"_account_id":14070,"name":"Eric Fried","email":"openstack@fried.cc","username":"efried"},"change_message_id":"39aa82bb81f7c1442878d1349e0274aaff12f3c4","unresolved":false,"context_lines":[{"line_number":526,"context_line":"            # TODO(efried): Use standard HW_NIC_ROOT trait"},{"line_number":527,"context_line":"            tb.set_traits(nic, \u0027CUSTOM_HW_NIC_ROOT\u0027)"},{"line_number":528,"context_line":"            nics.append(nic)"},{"line_number":529,"context_line":"            os.environ[\u0027NIC%s_UUID\u0027 % i] \u003d nic.uuid"},{"line_number":530,"context_line":"        # PFs for NIC1"},{"line_number":531,"context_line":"        for i in (1, 2):"},{"line_number":532,"context_line":"            suf \u003d \u00271_%d\u0027 % i"}],"source_content_type":"text/x-python","patch_set":8,"id":"7faddb67_e26918be","line":529,"updated":"2019-07-09 18:13:48.000000000","message":"oops\n\nStill prefer %d, but whatevs.","commit_id":"8395e3f099022d8506ed5e6624582ec03e46c3b9"}],"placement/tests/functional/gabbits/granular-same-subtree.yaml":[{"author":{"_account_id":11564,"name":"Chris Dent","email":"cdent@anticdent.org","username":"chdent"},"change_message_id":"9fb6ffea935788a5c7a309646a90f0cf6e37b1f8","unresolved":false,"context_lines":[],"source_content_type":"","patch_set":2,"id":"9fb8cfa7_3f922da1","updated":"2019-07-03 11:44:09.000000000","message":"we should have at least one group_policy\u003disolate in here to confirm what happens when mixed with same_subtree","commit_id":"8810d5e5d2840c31191bb2f48f7bc57f1682a77e"},{"author":{"_account_id":11564,"name":"Chris Dent","email":"cdent@anticdent.org","username":"chdent"},"change_message_id":"9fb6ffea935788a5c7a309646a90f0cf6e37b1f8","unresolved":false,"context_lines":[{"line_number":8,"context_line":"        x-auth-token: admin"},{"line_number":9,"context_line":"        content-type: application/json"},{"line_number":10,"context_line":"        accept: application/json"},{"line_number":11,"context_line":"        # version of request groups without resources"},{"line_number":12,"context_line":"        openstack-api-version: placement 1.36"},{"line_number":13,"context_line":""},{"line_number":14,"context_line":"tests:"}],"source_content_type":"text/x-yaml","patch_set":2,"id":"9fb8cfa7_dfb51134","line":11,"updated":"2019-07-03 11:44:09.000000000","message":"might be more clear to say same_subtree here","commit_id":"8810d5e5d2840c31191bb2f48f7bc57f1682a77e"},{"author":{"_account_id":25625,"name":"Tetsuro Nakamura","email":"tetsuro.nakamura.bc@hco.ntt.co.jp","username":"tetsuro0907"},"change_message_id":"b754246e8bfffdcff2368f7bce30a67870565603","unresolved":false,"context_lines":[{"line_number":127,"context_line":"      $.allocation_requests..allocations[\u0027$ENVIRON[\"PF2_1_UUID\"]\u0027].resources.CUSTOM_VF: [2, 2]"},{"line_number":128,"context_line":"      $.allocation_requests..allocations[\u0027$ENVIRON[\"PF2_2_UUID\"]\u0027].resources.CUSTOM_VF: [2, 2]"},{"line_number":129,"context_line":"      $.allocation_requests..allocations[\u0027$ENVIRON[\"PF2_3_UUID\"]\u0027].resources.CUSTOM_VF: [2, 2]"},{"line_number":130,"context_line":"      $.allocation_requests..allocations[\u0027$ENVIRON[\"PF2_4_UUID\"]\u0027].resources.CUSTOM_VF: [2, 2]"}],"source_content_type":"text/x-yaml","patch_set":2,"id":"9fb8cfa7_3bd1f4cc","line":130,"updated":"2019-07-02 14:06:19.000000000","message":"Need to check if we have \"mappings\" for the resourceless group with this patch","commit_id":"8810d5e5d2840c31191bb2f48f7bc57f1682a77e"},{"author":{"_account_id":9708,"name":"Balazs Gibizer","display_name":"gibi","email":"gibizer@gmail.com","username":"gibi"},"change_message_id":"7d045957ed7123c1ac11eee8627bce0d05b8393c","unresolved":false,"context_lines":[{"line_number":51,"context_line":"      $.errors[0].title: Bad Request"},{"line_number":52,"context_line":"      $.errors[0].code: placement.query.missing_value"},{"line_number":53,"context_line":""},{"line_number":54,"context_line":"- name: invalid same subtree missing underscores"},{"line_number":55,"context_line":"  GET: /allocation_candidates"},{"line_number":56,"context_line":"  query_parameters:"},{"line_number":57,"context_line":"      resources_COMPUTE: VCPU:1"}],"source_content_type":"text/x-yaml","patch_set":7,"id":"7faddb67_f571ede1","line":54,"range":{"start_line":54,"start_character":29,"end_line":54,"end_character":48},"updated":"2019-07-08 16:01:27.000000000","message":"thanks. This helped finding why this fails :)","commit_id":"118415f62c8f66bd70d70661d7e6bd5c334bf1b6"},{"author":{"_account_id":9708,"name":"Balazs Gibizer","display_name":"gibi","email":"gibizer@gmail.com","username":"gibi"},"change_message_id":"7d045957ed7123c1ac11eee8627bce0d05b8393c","unresolved":false,"context_lines":[{"line_number":150,"context_line":"  response_json_paths:"},{"line_number":151,"context_line":"      $.allocation_requests.`len`: 0"},{"line_number":152,"context_line":""},{"line_number":153,"context_line":"- name: resourceful without same subtree"},{"line_number":154,"context_line":"  GET: /allocation_candidates"},{"line_number":155,"context_line":"  query_parameters:"},{"line_number":156,"context_line":"      resources: VCPU:1"}],"source_content_type":"text/x-yaml","patch_set":7,"id":"7faddb67_b52135b7","line":153,"updated":"2019-07-08 16:01:27.000000000","message":"Is it different from \"no resourceless without same subtree\" ?","commit_id":"118415f62c8f66bd70d70661d7e6bd5c334bf1b6"},{"author":{"_account_id":14070,"name":"Eric Fried","email":"openstack@fried.cc","username":"efried"},"change_message_id":"39aa82bb81f7c1442878d1349e0274aaff12f3c4","unresolved":false,"context_lines":[{"line_number":60,"context_line":"      group_policy: none"},{"line_number":61,"context_line":"  status: 400"},{"line_number":62,"context_line":"  response_strings:"},{"line_number":63,"context_line":"      - \"Real suffixes should be specified in `same_subtree`:\""},{"line_number":64,"context_line":"  response_json_paths:"},{"line_number":65,"context_line":"      $.errors[0].title: Bad Request"},{"line_number":66,"context_line":"      $.errors[0].code: placement.query.bad_value"}],"source_content_type":"text/x-yaml","patch_set":8,"id":"7faddb67_a291e09b","line":63,"updated":"2019-07-09 18:13:48.000000000","message":"This (with the remainder of the message) is very clear, ++\n\n Real suffixes should be specified in `same_subtree`: [u\u0027COMPUTE\u0027] not found in [u\u0027_COMPUTE\u0027, u\u0027_ACCEL\u0027].","commit_id":"8395e3f099022d8506ed5e6624582ec03e46c3b9"},{"author":{"_account_id":14070,"name":"Eric Fried","email":"openstack@fried.cc","username":"efried"},"change_message_id":"39aa82bb81f7c1442878d1349e0274aaff12f3c4","unresolved":false,"context_lines":[{"line_number":79,"context_line":"      $.errors[0].title: Bad Request"},{"line_number":80,"context_line":"      $.errors[0].code: placement.query.bad_value"},{"line_number":81,"context_line":""},{"line_number":82,"context_line":"- name: no resourceless without same subtree"},{"line_number":83,"context_line":"  GET: /allocation_candidates"},{"line_number":84,"context_line":"  query_parameters:"},{"line_number":85,"context_line":"      resources_COMPUTE: VCPU:1"}],"source_content_type":"text/x-yaml","patch_set":8,"id":"7faddb67_e2c5988f","line":82,"updated":"2019-07-09 18:13:48.000000000","message":"This test seems (harmless but) redundant with ones in other gabbits - we\u0027re not exercising any of the new syntax - unless we\u0027re just making sure old-ish requests still work at the new microversion.\n\n[Later] Ah, read in sequence with the subsequent two tests, we\u0027re showing how adding same_subtree-ness affects the results. ++","commit_id":"8395e3f099022d8506ed5e6624582ec03e46c3b9"},{"author":{"_account_id":14070,"name":"Eric Fried","email":"openstack@fried.cc","username":"efried"},"change_message_id":"39aa82bb81f7c1442878d1349e0274aaff12f3c4","unresolved":false,"context_lines":[{"line_number":121,"context_line":"      $.allocation_requests..allocations[\u0027$ENVIRON[\"NUMA1_UUID\"]\u0027].resources.VCPU: [1, 1]"},{"line_number":122,"context_line":"      $.allocation_requests..allocations[\u0027$ENVIRON[\"FPGA0_UUID\"]\u0027].resources.CUSTOM_FPGA: 1"},{"line_number":123,"context_line":"      $.allocation_requests..allocations[\u0027$ENVIRON[\"FPGA1_0_UUID\"]\u0027].resources.CUSTOM_FPGA: 1"},{"line_number":124,"context_line":"      $.allocation_requests..allocations[\u0027$ENVIRON[\"FPGA1_1_UUID\"]\u0027].resources.CUSTOM_FPGA: 1"},{"line_number":125,"context_line":""},{"line_number":126,"context_line":"- name: no resourceless with same subtree same provider"},{"line_number":127,"context_line":"  # Ensure that \"myself\" is in the same subtree"}],"source_content_type":"text/x-yaml","patch_set":8,"id":"7faddb67_02e23402","line":124,"updated":"2019-07-09 18:13:48.000000000","message":"It would be nice if we had a way to show that the FPGA$N_* were tied to the corresponding NUMA$N.","commit_id":"8395e3f099022d8506ed5e6624582ec03e46c3b9"},{"author":{"_account_id":14070,"name":"Eric Fried","email":"openstack@fried.cc","username":"efried"},"change_message_id":"39aa82bb81f7c1442878d1349e0274aaff12f3c4","unresolved":false,"context_lines":[{"line_number":129,"context_line":"  query_parameters:"},{"line_number":130,"context_line":"      resources_COMPUTE1: VCPU:1"},{"line_number":131,"context_line":"      resources_COMPUTE2: MEMORY_MB:1024"},{"line_number":132,"context_line":"      same_subtree: _COMPUTE1,_COMPUTE2"},{"line_number":133,"context_line":"      group_policy: none"},{"line_number":134,"context_line":"  response_json_paths:"},{"line_number":135,"context_line":"      $.allocation_requests.`len`: 3"}],"source_content_type":"text/x-yaml","patch_set":8,"id":"7faddb67_a29ec060","line":132,"updated":"2019-07-09 18:13:48.000000000","message":"Nice, we\u0027re showing that we can force two request groups to land on the same provider.","commit_id":"8395e3f099022d8506ed5e6624582ec03e46c3b9"},{"author":{"_account_id":14070,"name":"Eric Fried","email":"openstack@fried.cc","username":"efried"},"change_message_id":"39aa82bb81f7c1442878d1349e0274aaff12f3c4","unresolved":false,"context_lines":[{"line_number":148,"context_line":"      same_subtree: _COMPUTE1,_COMPUTE2"},{"line_number":149,"context_line":"      group_policy: isolate"},{"line_number":150,"context_line":"  response_json_paths:"},{"line_number":151,"context_line":"      $.allocation_requests.`len`: 0"},{"line_number":152,"context_line":""},{"line_number":153,"context_line":"- name: resourceful without same subtree"},{"line_number":154,"context_line":"  GET: /allocation_candidates"}],"source_content_type":"text/x-yaml","patch_set":8,"id":"7faddb67_c2997c79","line":151,"updated":"2019-07-09 18:13:48.000000000","message":"✔","commit_id":"8395e3f099022d8506ed5e6624582ec03e46c3b9"},{"author":{"_account_id":14070,"name":"Eric Fried","email":"openstack@fried.cc","username":"efried"},"change_message_id":"39aa82bb81f7c1442878d1349e0274aaff12f3c4","unresolved":false,"context_lines":[{"line_number":150,"context_line":"  response_json_paths:"},{"line_number":151,"context_line":"      $.allocation_requests.`len`: 0"},{"line_number":152,"context_line":""},{"line_number":153,"context_line":"- name: resourceful without same subtree"},{"line_number":154,"context_line":"  GET: /allocation_candidates"},{"line_number":155,"context_line":"  query_parameters:"},{"line_number":156,"context_line":"      resources: VCPU:1"}],"source_content_type":"text/x-yaml","patch_set":8,"id":"7faddb67_826384b1","line":153,"updated":"2019-07-09 18:13:48.000000000","message":"Likewise above, this one doesn\u0027t do anything new, just sets us up for the following, which is cool.\n\n(Wouldn\u0027t mind commentary to that effect.)","commit_id":"8395e3f099022d8506ed5e6624582ec03e46c3b9"},{"author":{"_account_id":14070,"name":"Eric Fried","email":"openstack@fried.cc","username":"efried"},"change_message_id":"39aa82bb81f7c1442878d1349e0274aaff12f3c4","unresolved":false,"context_lines":[{"line_number":185,"context_line":"      $.allocation_requests..allocations[\u0027$ENVIRON[\"PF1_2_UUID\"]\u0027].resources.CUSTOM_VF: 4"},{"line_number":186,"context_line":"      $.allocation_requests..mappings.`len`: 4"},{"line_number":187,"context_line":"      $.allocation_requests..mappings[\u0027\u0027][0]: $ENVIRON[\"CN2_UUID\"]"},{"line_number":188,"context_line":"      $.allocation_requests..mappings[\u0027_NIC\u0027][0]: $ENVIRON[\"NIC1_UUID\"]"},{"line_number":189,"context_line":"      $.allocation_requests..mappings[\u0027_PORT1\u0027][0]: $ENVIRON[\"PF1_1_UUID\"]"},{"line_number":190,"context_line":"      $.allocation_requests..mappings[\u0027_PORT2\u0027][0]: $ENVIRON[\"PF1_2_UUID\"]"},{"line_number":191,"context_line":""}],"source_content_type":"text/x-yaml","patch_set":8,"id":"7faddb67_029eb453","line":188,"range":{"start_line":188,"start_character":60,"end_line":188,"end_character":69},"updated":"2019-07-09 18:13:48.000000000","message":"✔ resourceless group shows up in mappings","commit_id":"8395e3f099022d8506ed5e6624582ec03e46c3b9"},{"author":{"_account_id":14070,"name":"Eric Fried","email":"openstack@fried.cc","username":"efried"},"change_message_id":"39aa82bb81f7c1442878d1349e0274aaff12f3c4","unresolved":false,"context_lines":[{"line_number":208,"context_line":"      $.allocation_requests..allocations[\u0027$ENVIRON[\"PF2_1_UUID\"]\u0027].resources.CUSTOM_VF: [2, 2]"},{"line_number":209,"context_line":"      $.allocation_requests..allocations[\u0027$ENVIRON[\"PF2_2_UUID\"]\u0027].resources.CUSTOM_VF: [2, 2]"},{"line_number":210,"context_line":"      $.allocation_requests..allocations[\u0027$ENVIRON[\"PF2_3_UUID\"]\u0027].resources.CUSTOM_VF: [2, 2]"},{"line_number":211,"context_line":"      $.allocation_requests..allocations[\u0027$ENVIRON[\"PF2_4_UUID\"]\u0027].resources.CUSTOM_VF: [2, 2]"},{"line_number":212,"context_line":""},{"line_number":213,"context_line":"- name: resourceless with same subtree 2VFs isolate"},{"line_number":214,"context_line":"  GET: /allocation_candidates"}],"source_content_type":"text/x-yaml","patch_set":8,"id":"7faddb67_62dd2813","line":211,"updated":"2019-07-09 18:13:48.000000000","message":"Again, it would be nice to prove the right VFs are tied together. But I believe you :)","commit_id":"8395e3f099022d8506ed5e6624582ec03e46c3b9"},{"author":{"_account_id":14070,"name":"Eric Fried","email":"openstack@fried.cc","username":"efried"},"change_message_id":"39aa82bb81f7c1442878d1349e0274aaff12f3c4","unresolved":false,"context_lines":[{"line_number":229,"context_line":"      $.allocation_requests..allocations[\u0027$ENVIRON[\"PF2_1_UUID\"]\u0027].resources.CUSTOM_VF: [2, 2]"},{"line_number":230,"context_line":"      $.allocation_requests..allocations[\u0027$ENVIRON[\"PF2_2_UUID\"]\u0027].resources.CUSTOM_VF: [2, 2]"},{"line_number":231,"context_line":"      $.allocation_requests..allocations[\u0027$ENVIRON[\"PF2_3_UUID\"]\u0027].resources.CUSTOM_VF: [2, 2]"},{"line_number":232,"context_line":"      $.allocation_requests..allocations[\u0027$ENVIRON[\"PF2_4_UUID\"]\u0027].resources.CUSTOM_VF: [2, 2]"},{"line_number":233,"context_line":""},{"line_number":234,"context_line":"- name: resourceless with same subtree same provider"},{"line_number":235,"context_line":"  GET: /allocation_candidates"}],"source_content_type":"text/x-yaml","patch_set":8,"id":"7faddb67_c2ee5cb3","line":232,"updated":"2019-07-09 18:13:48.000000000","message":"Okay, this is the same as above, because we\u0027re only asking for one (VF*2+NETX) per request group. What might be interesting is blowing at least one of the request groups out, e.g. change\n\n      resources_PORT2: CUSTOM_VF:2\n      required_PORT2: CUSTOM_PHYSNET2\n\nto\n\n      resources_PORT2A: CUSTOM_VF:1\n      required_PORT2A: CUSTOM_PHYSNET2\n      resources_PORT2B: CUSTOM_VF:1\n      required_PORT2B: CUSTOM_PHYSNET2\n\n...and that would have different results with group_policy\u003dnone vs isolate.","commit_id":"8395e3f099022d8506ed5e6624582ec03e46c3b9"},{"author":{"_account_id":14070,"name":"Eric Fried","email":"openstack@fried.cc","username":"efried"},"change_message_id":"9fba6abaead1578bd092711bfd7f6723bc0f2b2e","unresolved":false,"context_lines":[{"line_number":229,"context_line":"      $.allocation_requests..allocations[\u0027$ENVIRON[\"PF2_1_UUID\"]\u0027].resources.CUSTOM_VF: [2, 2]"},{"line_number":230,"context_line":"      $.allocation_requests..allocations[\u0027$ENVIRON[\"PF2_2_UUID\"]\u0027].resources.CUSTOM_VF: [2, 2]"},{"line_number":231,"context_line":"      $.allocation_requests..allocations[\u0027$ENVIRON[\"PF2_3_UUID\"]\u0027].resources.CUSTOM_VF: [2, 2]"},{"line_number":232,"context_line":"      $.allocation_requests..allocations[\u0027$ENVIRON[\"PF2_4_UUID\"]\u0027].resources.CUSTOM_VF: [2, 2]"},{"line_number":233,"context_line":""},{"line_number":234,"context_line":"- name: resourceless with same subtree same provider"},{"line_number":235,"context_line":"  GET: /allocation_candidates"}],"source_content_type":"text/x-yaml","patch_set":8,"id":"7faddb67_b0028a0a","line":232,"in_reply_to":"7faddb67_c2ee5cb3","updated":"2019-07-09 20:33:59.000000000","message":"Done","commit_id":"8395e3f099022d8506ed5e6624582ec03e46c3b9"},{"author":{"_account_id":14070,"name":"Eric Fried","email":"openstack@fried.cc","username":"efried"},"change_message_id":"39aa82bb81f7c1442878d1349e0274aaff12f3c4","unresolved":false,"context_lines":[{"line_number":293,"context_line":"      same_subtree: _NUMA,_ACCEL1,_ACCEL2"},{"line_number":294,"context_line":"      group_policy: isolate"},{"line_number":295,"context_line":"  response_json_paths:"},{"line_number":296,"context_line":"      $.allocation_requests.`len`: 2"},{"line_number":297,"context_line":"      $.allocation_requests..allocations[\u0027$ENVIRON[\"FPGA1_0_UUID\"]\u0027].resources.CUSTOM_FPGA: [1, 1]"},{"line_number":298,"context_line":"      $.allocation_requests..allocations[\u0027$ENVIRON[\"FPGA1_1_UUID\"]\u0027].resources.CUSTOM_FPGA: [1, 1]"},{"line_number":299,"context_line":"      $.allocation_requests..mappings.`len`: [3, 3]"}],"source_content_type":"text/x-yaml","patch_set":8,"id":"7faddb67_0268f41e","line":296,"updated":"2019-07-09 18:13:48.000000000","message":"Oh, we get two results here which are identical *except* in their mappings. Yeah, that checks out.","commit_id":"8395e3f099022d8506ed5e6624582ec03e46c3b9"},{"author":{"_account_id":14070,"name":"Eric Fried","email":"openstack@fried.cc","username":"efried"},"change_message_id":"39aa82bb81f7c1442878d1349e0274aaff12f3c4","unresolved":false,"context_lines":[],"source_content_type":"","patch_set":8,"id":"7faddb67_820864d9","line":314,"updated":"2019-07-09 18:13:48.000000000","message":"Missing tests:\n- Duplicate suffixes in one same_subtree (prove that we squash them and succeed).\n- Multiple same_subtree qparams (which you\u0027ll have to do with a querystring rather than the query_parameters dict)","commit_id":"8395e3f099022d8506ed5e6624582ec03e46c3b9"},{"author":{"_account_id":11564,"name":"Chris Dent","email":"cdent@anticdent.org","username":"chdent"},"change_message_id":"aed0a08f8a4994670e7f8675715d5cb4ab0d03e3","unresolved":false,"context_lines":[],"source_content_type":"","patch_set":8,"id":"7faddb67_b0fdaab2","line":314,"in_reply_to":"7faddb67_820864d9","updated":"2019-07-09 19:54:45.000000000","message":"\u003e - Multiple same_subtree qparams (which you\u0027ll have to do with a\n \u003e querystring rather than the query_parameters dict)\n\nyou can \n\n    query_parameters:\n        foobar:\n         - baz\n         - boom\n\nif I remeber right","commit_id":"8395e3f099022d8506ed5e6624582ec03e46c3b9"},{"author":{"_account_id":14070,"name":"Eric Fried","email":"openstack@fried.cc","username":"efried"},"change_message_id":"fe56f7c99ed0e36cdd1f35bbbc744014a04f15b0","unresolved":false,"context_lines":[],"source_content_type":"","patch_set":8,"id":"7faddb67_f008022e","line":314,"in_reply_to":"7faddb67_b0fdaab2","updated":"2019-07-09 20:28:44.000000000","message":"Thanks Chris, that works.","commit_id":"8395e3f099022d8506ed5e6624582ec03e46c3b9"},{"author":{"_account_id":14070,"name":"Eric Fried","email":"openstack@fried.cc","username":"efried"},"change_message_id":"9fba6abaead1578bd092711bfd7f6723bc0f2b2e","unresolved":false,"context_lines":[],"source_content_type":"","patch_set":8,"id":"7faddb67_4bffe700","line":314,"in_reply_to":"7faddb67_f008022e","updated":"2019-07-09 20:33:59.000000000","message":"Done","commit_id":"8395e3f099022d8506ed5e6624582ec03e46c3b9"}],"releasenotes/notes/allocation-candidate-same_subtree-aeed7b2570293dfb.yaml":[{"author":{"_account_id":14070,"name":"Eric Fried","email":"openstack@fried.cc","username":"efried"},"change_message_id":"c16b08c7254561508678cd37ddbeece7adfdd929","unresolved":false,"context_lines":[{"line_number":5,"context_line":"    ``GET /allocation_candidates`` is supported. It accepts a comma-separated"},{"line_number":6,"context_line":"    list of request group suffix strings ($S). Each must exactly match a suffix"},{"line_number":7,"context_line":"    on a granular group somewhere else in the request. Importantly, the"},{"line_number":8,"context_line":"    identified request groups need not have a resources[$S]. If this is"},{"line_number":9,"context_line":"    provided, at least one of the resource providers satisfying the specified"},{"line_number":10,"context_line":"    request group must be an ancestor of the rest. The ``same_subtree`` query"},{"line_number":11,"context_line":"    parameter can be repeated and each repeat group is treated independently."}],"source_content_type":"text/x-yaml","patch_set":2,"id":"7faddb67_a06286d7","line":8,"range":{"start_line":8,"start_character":46,"end_line":8,"end_character":59},"updated":"2019-07-03 22:39:15.000000000","message":"this should be spelled ``resources$S``","commit_id":"8810d5e5d2840c31191bb2f48f7bc57f1682a77e"},{"author":{"_account_id":9708,"name":"Balazs Gibizer","display_name":"gibi","email":"gibizer@gmail.com","username":"gibi"},"change_message_id":"7d045957ed7123c1ac11eee8627bce0d05b8393c","unresolved":false,"context_lines":[{"line_number":8,"context_line":"    identified request groups need not have a resources$S. If this is provided,"},{"line_number":9,"context_line":"    at least one of the resource providers satisfying the specified request"},{"line_number":10,"context_line":"    group must be an ancestor of the rest. The ``same_subtree`` query parameter"},{"line_number":11,"context_line":"    can be repeated and each repeat group is treated independently."}],"source_content_type":"text/x-yaml","patch_set":7,"id":"7faddb67_95b19992","line":11,"range":{"start_line":11,"start_character":24,"end_line":11,"end_character":41},"updated":"2019-07-08 16:01:27.000000000","message":"each repeated group?","commit_id":"118415f62c8f66bd70d70661d7e6bd5c334bf1b6"},{"author":{"_account_id":25625,"name":"Tetsuro Nakamura","email":"tetsuro.nakamura.bc@hco.ntt.co.jp","username":"tetsuro0907"},"change_message_id":"c3a42d708d31dbfd7c529a5b2e2024a7f96eabce","unresolved":false,"context_lines":[{"line_number":8,"context_line":"    identified request groups need not have a resources$S. If this is provided,"},{"line_number":9,"context_line":"    at least one of the resource providers satisfying the specified request"},{"line_number":10,"context_line":"    group must be an ancestor of the rest. The ``same_subtree`` query parameter"},{"line_number":11,"context_line":"    can be repeated and each repeat group is treated independently."}],"source_content_type":"text/x-yaml","patch_set":7,"id":"7faddb67_8812d308","line":11,"range":{"start_line":11,"start_character":24,"end_line":11,"end_character":41},"in_reply_to":"7faddb67_95b19992","updated":"2019-07-09 07:23:26.000000000","message":"Done","commit_id":"118415f62c8f66bd70d70661d7e6bd5c334bf1b6"},{"author":{"_account_id":14070,"name":"Eric Fried","email":"openstack@fried.cc","username":"efried"},"change_message_id":"39aa82bb81f7c1442878d1349e0274aaff12f3c4","unresolved":false,"context_lines":[{"line_number":6,"context_line":"    list of request group suffix strings ($S). Each must exactly match a suffix"},{"line_number":7,"context_line":"    on a granular group somewhere else in the request. Importantly, the"},{"line_number":8,"context_line":"    identified request groups need not have a resources$S. If this is provided,"},{"line_number":9,"context_line":"    at least one of the resource providers satisfying the specified request"},{"line_number":10,"context_line":"    group must be an ancestor of the rest. The ``same_subtree`` query parameter"},{"line_number":11,"context_line":"    can be repeated and each repeated group is treated independently."}],"source_content_type":"text/x-yaml","patch_set":8,"id":"7faddb67_0251d462","line":9,"range":{"start_line":9,"start_character":54,"end_line":9,"end_character":57},"updated":"2019-07-09 18:13:48.000000000","message":"ditto","commit_id":"8395e3f099022d8506ed5e6624582ec03e46c3b9"}]}
