)]}'
{"nova/api/openstack/placement/handlers/resource_provider.py":[{"author":{"_account_id":27336,"name":"XiaojueGuan","email":"xiaojueguan@gmail.com","username":"XiaojueGuan"},"change_message_id":"d169c69b8bfae8e72b474db6074a4de6269dec20","unresolved":false,"context_lines":[{"line_number":186,"context_line":"    util.validate_query_params(req, schema)"},{"line_number":187,"context_line":""},{"line_number":188,"context_line":"    filters \u003d {}"},{"line_number":189,"context_line":"    qpkeys \u003d (\u0027uuid\u0027, \u0027name\u0027, \u0027member_of\u0027, \u0027in_tree\u0027, \u0027resources\u0027, \u0027required\u0027)"},{"line_number":190,"context_line":"    for attr in qpkeys:"},{"line_number":191,"context_line":"        if attr in req.GET:"},{"line_number":192,"context_line":"            value \u003d req.GET[attr]"}],"source_content_type":"text/x-python","patch_set":3,"id":"3fa0c359_16675eb9","line":189,"range":{"start_line":189,"start_character":3,"end_line":189,"end_character":15},"updated":"2018-02-22 14:55:01.000000000","message":"i think it is not necessary to add a new variable","commit_id":"be9f1b81b2a26973b4b325a2e63718561783c2cf"},{"author":{"_account_id":14070,"name":"Eric Fried","email":"openstack@fried.cc","username":"efried"},"change_message_id":"298cd8485bb67a35706bc0985e826b898912deee","unresolved":false,"context_lines":[{"line_number":186,"context_line":"    util.validate_query_params(req, schema)"},{"line_number":187,"context_line":""},{"line_number":188,"context_line":"    filters \u003d {}"},{"line_number":189,"context_line":"    qpkeys \u003d (\u0027uuid\u0027, \u0027name\u0027, \u0027member_of\u0027, \u0027in_tree\u0027, \u0027resources\u0027, \u0027required\u0027)"},{"line_number":190,"context_line":"    for attr in qpkeys:"},{"line_number":191,"context_line":"        if attr in req.GET:"},{"line_number":192,"context_line":"            value \u003d req.GET[attr]"}],"source_content_type":"text/x-python","patch_set":3,"id":"3fa0c359_29e79c14","line":189,"range":{"start_line":189,"start_character":3,"end_line":189,"end_character":15},"in_reply_to":"3fa0c359_16675eb9","updated":"2018-02-22 15:04:15.000000000","message":"Not necessary, no; just makes the loop control statement prettier.  (Otherwise I have to split lines before a colon, which I hate :)","commit_id":"be9f1b81b2a26973b4b325a2e63718561783c2cf"},{"author":{"_account_id":1063,"name":"Ed Leafe","email":"ed@leafe.com","username":"ed-leafe"},"change_message_id":"b74d91486e38a2fa3ca8198b311276947405b68d","unresolved":false,"context_lines":[{"line_number":219,"context_line":"            _(\u0027Invalid resource class in resources parameter: %(error)s\u0027) %"},{"line_number":220,"context_line":"            {\u0027error\u0027: exc})"},{"line_number":221,"context_line":"    except exception.TraitNotFound as exc:"},{"line_number":222,"context_line":"        raise webob.exc.HTTPBadRequest("},{"line_number":223,"context_line":"            _(\u0027Invalid trait(s) in \"required\" parameter: %(error)s\u0027) %"},{"line_number":224,"context_line":"            {\u0027error\u0027: exc})"},{"line_number":225,"context_line":""}],"source_content_type":"text/x-python","patch_set":3,"id":"3fa0c359_49e4680d","line":222,"range":{"start_line":222,"start_character":24,"end_line":222,"end_character":38},"updated":"2018-02-22 15:26:08.000000000","message":"+1","commit_id":"be9f1b81b2a26973b4b325a2e63718561783c2cf"}],"nova/api/openstack/placement/rest_api_version_history.rst":[{"author":{"_account_id":1063,"name":"Ed Leafe","email":"ed@leafe.com","username":"ed-leafe"},"change_message_id":"b74d91486e38a2fa3ca8198b311276947405b68d","unresolved":false,"context_lines":[{"line_number":226,"context_line":"---------------------------------------------------------------------"},{"line_number":227,"context_line":""},{"line_number":228,"context_line":"Add support for the `required` query parameter to the `GET /resource_providers`"},{"line_number":229,"context_line":"API.  It accepts a comma-separated list of string trait names. When specified,"},{"line_number":230,"context_line":"the API results will be filtered to include only resource providers marked with"},{"line_number":231,"context_line":"all the specified traits. This is in addition to (logical AND) any filtering"},{"line_number":232,"context_line":"based on other query parameters."}],"source_content_type":"text/x-rst","patch_set":3,"id":"3fa0c359_e9c5345d","line":229,"range":{"start_line":229,"start_character":4,"end_line":229,"end_character":6},"updated":"2018-02-22 15:26:08.000000000","message":"One space, please, as in the rest of the document.","commit_id":"be9f1b81b2a26973b4b325a2e63718561783c2cf"},{"author":{"_account_id":14070,"name":"Eric Fried","email":"openstack@fried.cc","username":"efried"},"change_message_id":"029cc89c6d7703ac852e7d09e1f14468c5dea428","unresolved":false,"context_lines":[{"line_number":226,"context_line":"---------------------------------------------------------------------"},{"line_number":227,"context_line":""},{"line_number":228,"context_line":"Add support for the `required` query parameter to the `GET /resource_providers`"},{"line_number":229,"context_line":"API.  It accepts a comma-separated list of string trait names. When specified,"},{"line_number":230,"context_line":"the API results will be filtered to include only resource providers marked with"},{"line_number":231,"context_line":"all the specified traits. This is in addition to (logical AND) any filtering"},{"line_number":232,"context_line":"based on other query parameters."}],"source_content_type":"text/x-rst","patch_set":3,"id":"3fa0c359_9dff0600","line":229,"range":{"start_line":229,"start_character":4,"end_line":229,"end_character":6},"in_reply_to":"3fa0c359_e9c5345d","updated":"2018-02-22 17:16:42.000000000","message":"Done","commit_id":"be9f1b81b2a26973b4b325a2e63718561783c2cf"},{"author":{"_account_id":7,"name":"Jay Pipes","email":"jaypipes@gmail.com","username":"jaypipes"},"change_message_id":"e0ea1a6ccca012694231988d66e9d86a92bd53ba","unresolved":false,"context_lines":[{"line_number":231,"context_line":"all the specified traits. This is in addition to (logical AND) any filtering"},{"line_number":232,"context_line":"based on other query parameters."},{"line_number":233,"context_line":""},{"line_number":234,"context_line":"Trait names which are empty, do not exist in the Trait database, or are"},{"line_number":235,"context_line":"otherwise invalid will result in a 400 error."}],"source_content_type":"text/x-rst","patch_set":3,"id":"3fa0c359_1d745667","line":234,"range":{"start_line":234,"start_character":41,"end_line":234,"end_character":63},"updated":"2018-02-22 17:26:11.000000000","message":"remove","commit_id":"be9f1b81b2a26973b4b325a2e63718561783c2cf"},{"author":{"_account_id":14070,"name":"Eric Fried","email":"openstack@fried.cc","username":"efried"},"change_message_id":"ba9d3b250164d1016380437ac87e95f3fcb9ed43","unresolved":false,"context_lines":[{"line_number":231,"context_line":"all the specified traits. This is in addition to (logical AND) any filtering"},{"line_number":232,"context_line":"based on other query parameters."},{"line_number":233,"context_line":""},{"line_number":234,"context_line":"Trait names which are empty, do not exist in the Trait database, or are"},{"line_number":235,"context_line":"otherwise invalid will result in a 400 error."}],"source_content_type":"text/x-rst","patch_set":3,"id":"3fa0c359_f3fbd9ba","line":234,"range":{"start_line":234,"start_character":41,"end_line":234,"end_character":63},"in_reply_to":"3fa0c359_1d745667","updated":"2018-02-22 18:52:05.000000000","message":"Done","commit_id":"be9f1b81b2a26973b4b325a2e63718561783c2cf"},{"author":{"_account_id":6873,"name":"Matt Riedemann","email":"mriedem.os@gmail.com","username":"mriedem"},"change_message_id":"13ac0013d962551edf245ff29dc121e0a60e9421","unresolved":false,"context_lines":[{"line_number":158,"context_line":""},{"line_number":159,"context_line":"The ``/resource_providers/{rp_uuid}/allocations`` endpoint has been available"},{"line_number":160,"context_line":"since version 1.0, but was not listed in the ``links`` section of the"},{"line_number":161,"context_line":"``GET /resource_providers`` response. The link is included as of version 1.11."},{"line_number":162,"context_line":""},{"line_number":163,"context_line":"1.12 PUT dict format to /allocations/{consumer_uuid}"},{"line_number":164,"context_line":"----------------------------------------------------"}],"source_content_type":"text/x-rst","patch_set":5,"id":"3fa0c359_8ae817e2","line":161,"updated":"2018-02-22 21:17:31.000000000","message":"geez","commit_id":"4acb6c9ff7d57ecb7bc7b2602ac5cd1aae372979"},{"author":{"_account_id":14070,"name":"Eric Fried","email":"openstack@fried.cc","username":"efried"},"change_message_id":"570d8f5b85ea913020fc4ce992079bc6c29e72f0","unresolved":false,"context_lines":[{"line_number":158,"context_line":""},{"line_number":159,"context_line":"The ``/resource_providers/{rp_uuid}/allocations`` endpoint has been available"},{"line_number":160,"context_line":"since version 1.0, but was not listed in the ``links`` section of the"},{"line_number":161,"context_line":"``GET /resource_providers`` response. The link is included as of version 1.11."},{"line_number":162,"context_line":""},{"line_number":163,"context_line":"1.12 PUT dict format to /allocations/{consumer_uuid}"},{"line_number":164,"context_line":"----------------------------------------------------"}],"source_content_type":"text/x-rst","patch_set":5,"id":"3fa0c359_caa85f8d","line":161,"in_reply_to":"3fa0c359_8ae817e2","updated":"2018-02-22 21:25:02.000000000","message":"I know, I know, but I didn\u0027t want to make a liar out of edleafe\n\nhttps://review.openstack.org/#/c/546837/3/nova/api/openstack/placement/rest_api_version_history.rst@229","commit_id":"4acb6c9ff7d57ecb7bc7b2602ac5cd1aae372979"},{"author":{"_account_id":5754,"name":"Alex Xu","email":"hejie.xu@intel.com","username":"xuhj"},"change_message_id":"3dea5c225d2792b624c7f15a5bd5364a2a7c20c4","unresolved":false,"context_lines":[{"line_number":228,"context_line":"Add support for the `required` query parameter to the `GET /resource_providers`"},{"line_number":229,"context_line":"API. It accepts a comma-separated list of string trait names. When specified,"},{"line_number":230,"context_line":"the API results will be filtered to include only resource providers marked with"},{"line_number":231,"context_line":"all the specified traits. This is in addition to (logical AND) any filtering"},{"line_number":232,"context_line":"based on other query parameters."},{"line_number":233,"context_line":""},{"line_number":234,"context_line":"Trait names which are empty, do not exist, or are otherwise invalid will result"},{"line_number":235,"context_line":"in a 400 error."}],"source_content_type":"text/x-rst","patch_set":6,"id":"3fa0c359_ab7f1213","line":232,"range":{"start_line":231,"start_character":26,"end_line":232,"end_character":32},"updated":"2018-02-23 05:35:00.000000000","message":"This isn\u0027t true for \u0027resources\u0027 param. The \u0027resources\u0027 param doesn\u0027t work with other params","commit_id":"7e0b137aad9a2de8447516c34d2d3e908cd12fce"}],"nova/api/openstack/placement/schemas/resource_provider.py":[{"author":{"_account_id":1063,"name":"Ed Leafe","email":"ed@leafe.com","username":"ed-leafe"},"change_message_id":"b74d91486e38a2fa3ca8198b311276947405b68d","unresolved":false,"context_lines":[{"line_number":96,"context_line":"}"},{"line_number":97,"context_line":""},{"line_number":98,"context_line":"# Microversion 1.18 adds support for the `required` query parameter to the"},{"line_number":99,"context_line":"# `GET /resource_providers` API.  It accepts a comma-separated list of string"},{"line_number":100,"context_line":"# trait names. When specified, the API results will be filtered to include only"},{"line_number":101,"context_line":"# resource providers marked with all the specified traits. This is in addition"},{"line_number":102,"context_line":"# to (logical AND) any filtering based on other query parameters."}],"source_content_type":"text/x-python","patch_set":3,"id":"3fa0c359_497b0827","line":99,"range":{"start_line":99,"start_character":32,"end_line":99,"end_character":34},"updated":"2018-02-22 15:26:08.000000000","message":"s/  / /","commit_id":"be9f1b81b2a26973b4b325a2e63718561783c2cf"},{"author":{"_account_id":14070,"name":"Eric Fried","email":"openstack@fried.cc","username":"efried"},"change_message_id":"029cc89c6d7703ac852e7d09e1f14468c5dea428","unresolved":false,"context_lines":[{"line_number":96,"context_line":"}"},{"line_number":97,"context_line":""},{"line_number":98,"context_line":"# Microversion 1.18 adds support for the `required` query parameter to the"},{"line_number":99,"context_line":"# `GET /resource_providers` API.  It accepts a comma-separated list of string"},{"line_number":100,"context_line":"# trait names. When specified, the API results will be filtered to include only"},{"line_number":101,"context_line":"# resource providers marked with all the specified traits. This is in addition"},{"line_number":102,"context_line":"# to (logical AND) any filtering based on other query parameters."}],"source_content_type":"text/x-python","patch_set":3,"id":"3fa0c359_dd182e77","line":99,"range":{"start_line":99,"start_character":32,"end_line":99,"end_character":34},"in_reply_to":"3fa0c359_497b0827","updated":"2018-02-22 17:16:42.000000000","message":"Done","commit_id":"be9f1b81b2a26973b4b325a2e63718561783c2cf"}],"nova/objects/resource_provider.py":[{"author":{"_account_id":14070,"name":"Eric Fried","email":"openstack@fried.cc","username":"efried"},"change_message_id":"ba9d3b250164d1016380437ac87e95f3fcb9ed43","unresolved":false,"context_lines":[{"line_number":1491,"context_line":"            #         HAVING COUNT(resource_provider_id) \u003d\u003d len($trait_ids))"},{"line_number":1492,"context_line":"            rpt \u003d sa.alias(_RP_TRAIT_TBL, name\u003d\u0027rpt\u0027)"},{"line_number":1493,"context_line":"            query \u003d query.where("},{"line_number":1494,"context_line":"                sa.and_("},{"line_number":1495,"context_line":"                    rp.c.id.in_("},{"line_number":1496,"context_line":"                        sa.select("},{"line_number":1497,"context_line":"                            [rpt.c.resource_provider_id]"}],"source_content_type":"text/x-python","patch_set":3,"id":"3fa0c359_739a6962","line":1494,"range":{"start_line":1494,"start_character":16,"end_line":1494,"end_character":24},"updated":"2018-02-22 18:52:05.000000000","message":"This is redundant","commit_id":"be9f1b81b2a26973b4b325a2e63718561783c2cf"},{"author":{"_account_id":1063,"name":"Ed Leafe","email":"ed@leafe.com","username":"ed-leafe"},"change_message_id":"b74d91486e38a2fa3ca8198b311276947405b68d","unresolved":false,"context_lines":[{"line_number":1496,"context_line":"                        sa.select("},{"line_number":1497,"context_line":"                            [rpt.c.resource_provider_id]"},{"line_number":1498,"context_line":"                        ).select_from("},{"line_number":1499,"context_line":"                            rpt"},{"line_number":1500,"context_line":"                        ).where("},{"line_number":1501,"context_line":"                            rpt.c.trait_id.in_("},{"line_number":1502,"context_line":"                                trait_map.values()"}],"source_content_type":"text/x-python","patch_set":3,"id":"3fa0c359_497468cf","line":1499,"updated":"2018-02-22 15:26:08.000000000","message":"Can we be a little less whitespacey? There is no need for all these isolated terms and hanging parens.","commit_id":"be9f1b81b2a26973b4b325a2e63718561783c2cf"},{"author":{"_account_id":14070,"name":"Eric Fried","email":"openstack@fried.cc","username":"efried"},"change_message_id":"029cc89c6d7703ac852e7d09e1f14468c5dea428","unresolved":false,"context_lines":[{"line_number":1496,"context_line":"                        sa.select("},{"line_number":1497,"context_line":"                            [rpt.c.resource_provider_id]"},{"line_number":1498,"context_line":"                        ).select_from("},{"line_number":1499,"context_line":"                            rpt"},{"line_number":1500,"context_line":"                        ).where("},{"line_number":1501,"context_line":"                            rpt.c.trait_id.in_("},{"line_number":1502,"context_line":"                                trait_map.values()"}],"source_content_type":"text/x-python","patch_set":3,"id":"3fa0c359_9d9b86c7","line":1499,"in_reply_to":"3fa0c359_497468cf","updated":"2018-02-22 17:16:42.000000000","message":"Done\n\n/me sheds a tear for Jay","commit_id":"be9f1b81b2a26973b4b325a2e63718561783c2cf"},{"author":{"_account_id":7,"name":"Jay Pipes","email":"jaypipes@gmail.com","username":"jaypipes"},"change_message_id":"e0ea1a6ccca012694231988d66e9d86a92bd53ba","unresolved":false,"context_lines":[{"line_number":1496,"context_line":"                        sa.select("},{"line_number":1497,"context_line":"                            [rpt.c.resource_provider_id]"},{"line_number":1498,"context_line":"                        ).select_from("},{"line_number":1499,"context_line":"                            rpt"},{"line_number":1500,"context_line":"                        ).where("},{"line_number":1501,"context_line":"                            rpt.c.trait_id.in_("},{"line_number":1502,"context_line":"                                trait_map.values()"}],"source_content_type":"text/x-python","patch_set":3,"id":"3fa0c359_bd0a02cf","line":1499,"in_reply_to":"3fa0c359_9d9b86c7","updated":"2018-02-22 17:26:11.000000000","message":"lol","commit_id":"be9f1b81b2a26973b4b325a2e63718561783c2cf"},{"author":{"_account_id":7,"name":"Jay Pipes","email":"jaypipes@gmail.com","username":"jaypipes"},"change_message_id":"e0ea1a6ccca012694231988d66e9d86a92bd53ba","unresolved":false,"context_lines":[{"line_number":1475,"context_line":"                [resource_provider_id]).select_from(join_statement)"},{"line_number":1476,"context_line":"            query \u003d query.where(rp.c.id.in_(rps_in_aggregates))"},{"line_number":1477,"context_line":""},{"line_number":1478,"context_line":"        # If \u0027required\u0027 has values, join with ResourceProviderTrait to get"},{"line_number":1479,"context_line":"        # providers possessing *all* of the listed traits."},{"line_number":1480,"context_line":"        if required:"},{"line_number":1481,"context_line":"            # NOTE(efried): Do this instead of an embedded join so we can check"},{"line_number":1482,"context_line":"            # for missing traits."},{"line_number":1483,"context_line":"            trait_map \u003d _trait_ids_from_names(context, required)"},{"line_number":1484,"context_line":"            if len(trait_map) !\u003d len(required):"},{"line_number":1485,"context_line":"                missing \u003d required - set(trait_map)"},{"line_number":1486,"context_line":"                raise exception.TraitNotFound(names\u003d\u0027, \u0027.join(missing))"},{"line_number":1487,"context_line":"            # ...AND rp.id IN ("},{"line_number":1488,"context_line":"            #       SELECT resource_provider_id FROM resource_provider_traits"},{"line_number":1489,"context_line":"            #         WHERE trait_id IN $trait_ids"},{"line_number":1490,"context_line":"            #         GROUP BY resource_provider_id"},{"line_number":1491,"context_line":"            #         HAVING COUNT(resource_provider_id) \u003d\u003d len($trait_ids))"},{"line_number":1492,"context_line":"            rpt \u003d sa.alias(_RP_TRAIT_TBL, name\u003d\u0027rpt\u0027)"},{"line_number":1493,"context_line":"            query \u003d query.where("},{"line_number":1494,"context_line":"                sa.and_("},{"line_number":1495,"context_line":"                    rp.c.id.in_("},{"line_number":1496,"context_line":"                        sa.select("},{"line_number":1497,"context_line":"                            [rpt.c.resource_provider_id]"},{"line_number":1498,"context_line":"                        ).select_from("},{"line_number":1499,"context_line":"                            rpt"},{"line_number":1500,"context_line":"                        ).where("},{"line_number":1501,"context_line":"                            rpt.c.trait_id.in_("},{"line_number":1502,"context_line":"                                trait_map.values()"},{"line_number":1503,"context_line":"                            )"},{"line_number":1504,"context_line":"                        ).group_by("},{"line_number":1505,"context_line":"                            rpt.c.resource_provider_id"},{"line_number":1506,"context_line":"                        ).having("},{"line_number":1507,"context_line":"                            sql.func.count("},{"line_number":1508,"context_line":"                                rpt.c.resource_provider_id"},{"line_number":1509,"context_line":"                            ) \u003d\u003d len(required)"},{"line_number":1510,"context_line":"                        )"},{"line_number":1511,"context_line":"                    )"},{"line_number":1512,"context_line":"                )"},{"line_number":1513,"context_line":"            )"},{"line_number":1514,"context_line":""},{"line_number":1515,"context_line":"        if not resources:"},{"line_number":1516,"context_line":"            # Returns quickly the list in case we don\u0027t need to check the"}],"source_content_type":"text/x-python","patch_set":3,"id":"3fa0c359_bdc1a256","line":1513,"range":{"start_line":1478,"start_character":0,"end_line":1513,"end_character":13},"updated":"2018-02-22 17:26:11.000000000","message":"All of this code can be replaced with a single call to _get_provider_ids_having_all_traits():\n\nhttps://github.com/openstack/nova/blob/master/nova/objects/resource_provider.py#L2712","commit_id":"be9f1b81b2a26973b4b325a2e63718561783c2cf"},{"author":{"_account_id":14070,"name":"Eric Fried","email":"openstack@fried.cc","username":"efried"},"change_message_id":"ba9d3b250164d1016380437ac87e95f3fcb9ed43","unresolved":false,"context_lines":[{"line_number":1475,"context_line":"                [resource_provider_id]).select_from(join_statement)"},{"line_number":1476,"context_line":"            query \u003d query.where(rp.c.id.in_(rps_in_aggregates))"},{"line_number":1477,"context_line":""},{"line_number":1478,"context_line":"        # If \u0027required\u0027 has values, join with ResourceProviderTrait to get"},{"line_number":1479,"context_line":"        # providers possessing *all* of the listed traits."},{"line_number":1480,"context_line":"        if required:"},{"line_number":1481,"context_line":"            # NOTE(efried): Do this instead of an embedded join so we can check"},{"line_number":1482,"context_line":"            # for missing traits."},{"line_number":1483,"context_line":"            trait_map \u003d _trait_ids_from_names(context, required)"},{"line_number":1484,"context_line":"            if len(trait_map) !\u003d len(required):"},{"line_number":1485,"context_line":"                missing \u003d required - set(trait_map)"},{"line_number":1486,"context_line":"                raise exception.TraitNotFound(names\u003d\u0027, \u0027.join(missing))"},{"line_number":1487,"context_line":"            # ...AND rp.id IN ("},{"line_number":1488,"context_line":"            #       SELECT resource_provider_id FROM resource_provider_traits"},{"line_number":1489,"context_line":"            #         WHERE trait_id IN $trait_ids"},{"line_number":1490,"context_line":"            #         GROUP BY resource_provider_id"},{"line_number":1491,"context_line":"            #         HAVING COUNT(resource_provider_id) \u003d\u003d len($trait_ids))"},{"line_number":1492,"context_line":"            rpt \u003d sa.alias(_RP_TRAIT_TBL, name\u003d\u0027rpt\u0027)"},{"line_number":1493,"context_line":"            query \u003d query.where("},{"line_number":1494,"context_line":"                sa.and_("},{"line_number":1495,"context_line":"                    rp.c.id.in_("},{"line_number":1496,"context_line":"                        sa.select("},{"line_number":1497,"context_line":"                            [rpt.c.resource_provider_id]"},{"line_number":1498,"context_line":"                        ).select_from("},{"line_number":1499,"context_line":"                            rpt"},{"line_number":1500,"context_line":"                        ).where("},{"line_number":1501,"context_line":"                            rpt.c.trait_id.in_("},{"line_number":1502,"context_line":"                                trait_map.values()"},{"line_number":1503,"context_line":"                            )"},{"line_number":1504,"context_line":"                        ).group_by("},{"line_number":1505,"context_line":"                            rpt.c.resource_provider_id"},{"line_number":1506,"context_line":"                        ).having("},{"line_number":1507,"context_line":"                            sql.func.count("},{"line_number":1508,"context_line":"                                rpt.c.resource_provider_id"},{"line_number":1509,"context_line":"                            ) \u003d\u003d len(required)"},{"line_number":1510,"context_line":"                        )"},{"line_number":1511,"context_line":"                    )"},{"line_number":1512,"context_line":"                )"},{"line_number":1513,"context_line":"            )"},{"line_number":1514,"context_line":""},{"line_number":1515,"context_line":"        if not resources:"},{"line_number":1516,"context_line":"            # Returns quickly the list in case we don\u0027t need to check the"}],"source_content_type":"text/x-python","patch_set":3,"id":"3fa0c359_53ae4d81","line":1513,"range":{"start_line":1478,"start_character":0,"end_line":1513,"end_character":13},"in_reply_to":"3fa0c359_bdc1a256","updated":"2018-02-22 18:52:05.000000000","message":"Son of a....\n\nOkay, I\u0027m going to chalk up those couple hours rederiving this SQL as a learning experience.  Else I go mad.\n\nDone.","commit_id":"be9f1b81b2a26973b4b325a2e63718561783c2cf"},{"author":{"_account_id":7,"name":"Jay Pipes","email":"jaypipes@gmail.com","username":"jaypipes"},"change_message_id":"52c16b0ebfd397d91ec781a9bab2da92e0555866","unresolved":false,"context_lines":[{"line_number":1475,"context_line":"                [resource_provider_id]).select_from(join_statement)"},{"line_number":1476,"context_line":"            query \u003d query.where(rp.c.id.in_(rps_in_aggregates))"},{"line_number":1477,"context_line":""},{"line_number":1478,"context_line":"        # If \u0027required\u0027 has values, join with ResourceProviderTrait to get"},{"line_number":1479,"context_line":"        # providers possessing *all* of the listed traits."},{"line_number":1480,"context_line":"        if required:"},{"line_number":1481,"context_line":"            # NOTE(efried): Do this instead of an embedded join so we can check"},{"line_number":1482,"context_line":"            # for missing traits."},{"line_number":1483,"context_line":"            trait_map \u003d _trait_ids_from_names(context, required)"},{"line_number":1484,"context_line":"            if len(trait_map) !\u003d len(required):"},{"line_number":1485,"context_line":"                missing \u003d required - set(trait_map)"},{"line_number":1486,"context_line":"                raise exception.TraitNotFound(names\u003d\u0027, \u0027.join(missing))"},{"line_number":1487,"context_line":"            # ...AND rp.id IN ("},{"line_number":1488,"context_line":"            #       SELECT resource_provider_id FROM resource_provider_traits"},{"line_number":1489,"context_line":"            #         WHERE trait_id IN $trait_ids"},{"line_number":1490,"context_line":"            #         GROUP BY resource_provider_id"},{"line_number":1491,"context_line":"            #         HAVING COUNT(resource_provider_id) \u003d\u003d len($trait_ids))"},{"line_number":1492,"context_line":"            rpt \u003d sa.alias(_RP_TRAIT_TBL, name\u003d\u0027rpt\u0027)"},{"line_number":1493,"context_line":"            query \u003d query.where("},{"line_number":1494,"context_line":"                sa.and_(rp.c.id.in_("},{"line_number":1495,"context_line":"                    sa.select([rpt.c.resource_provider_id]).select_from(rpt)"},{"line_number":1496,"context_line":"                        .where(rpt.c.trait_id.in_(trait_map.values()))"},{"line_number":1497,"context_line":"                        .group_by(rpt.c.resource_provider_id)"},{"line_number":1498,"context_line":"                        .having(sql.func.count("},{"line_number":1499,"context_line":"                            rpt.c.resource_provider_id) \u003d\u003d len(required)))))"},{"line_number":1500,"context_line":""},{"line_number":1501,"context_line":"        if not resources:"},{"line_number":1502,"context_line":"            # Returns quickly the list in case we don\u0027t need to check the"}],"source_content_type":"text/x-python","patch_set":4,"id":"3fa0c359_bda682c0","line":1499,"range":{"start_line":1478,"start_character":0,"end_line":1499,"end_character":76},"updated":"2018-02-22 17:26:58.000000000","message":"this may all be replaced with a call to the existing _get_provider_ids_having_all_traits() function:\n\nhttps://github.com/openstack/nova/blob/master/nova/objects/resource_provider.py#L2712","commit_id":"c3cc3507681c7f84a1d3a62a4d265683d6c948b3"},{"author":{"_account_id":14070,"name":"Eric Fried","email":"openstack@fried.cc","username":"efried"},"change_message_id":"ba9d3b250164d1016380437ac87e95f3fcb9ed43","unresolved":false,"context_lines":[{"line_number":1475,"context_line":"                [resource_provider_id]).select_from(join_statement)"},{"line_number":1476,"context_line":"            query \u003d query.where(rp.c.id.in_(rps_in_aggregates))"},{"line_number":1477,"context_line":""},{"line_number":1478,"context_line":"        # If \u0027required\u0027 has values, join with ResourceProviderTrait to get"},{"line_number":1479,"context_line":"        # providers possessing *all* of the listed traits."},{"line_number":1480,"context_line":"        if required:"},{"line_number":1481,"context_line":"            # NOTE(efried): Do this instead of an embedded join so we can check"},{"line_number":1482,"context_line":"            # for missing traits."},{"line_number":1483,"context_line":"            trait_map \u003d _trait_ids_from_names(context, required)"},{"line_number":1484,"context_line":"            if len(trait_map) !\u003d len(required):"},{"line_number":1485,"context_line":"                missing \u003d required - set(trait_map)"},{"line_number":1486,"context_line":"                raise exception.TraitNotFound(names\u003d\u0027, \u0027.join(missing))"},{"line_number":1487,"context_line":"            # ...AND rp.id IN ("},{"line_number":1488,"context_line":"            #       SELECT resource_provider_id FROM resource_provider_traits"},{"line_number":1489,"context_line":"            #         WHERE trait_id IN $trait_ids"},{"line_number":1490,"context_line":"            #         GROUP BY resource_provider_id"},{"line_number":1491,"context_line":"            #         HAVING COUNT(resource_provider_id) \u003d\u003d len($trait_ids))"},{"line_number":1492,"context_line":"            rpt \u003d sa.alias(_RP_TRAIT_TBL, name\u003d\u0027rpt\u0027)"},{"line_number":1493,"context_line":"            query \u003d query.where("},{"line_number":1494,"context_line":"                sa.and_(rp.c.id.in_("},{"line_number":1495,"context_line":"                    sa.select([rpt.c.resource_provider_id]).select_from(rpt)"},{"line_number":1496,"context_line":"                        .where(rpt.c.trait_id.in_(trait_map.values()))"},{"line_number":1497,"context_line":"                        .group_by(rpt.c.resource_provider_id)"},{"line_number":1498,"context_line":"                        .having(sql.func.count("},{"line_number":1499,"context_line":"                            rpt.c.resource_provider_id) \u003d\u003d len(required)))))"},{"line_number":1500,"context_line":""},{"line_number":1501,"context_line":"        if not resources:"},{"line_number":1502,"context_line":"            # Returns quickly the list in case we don\u0027t need to check the"}],"source_content_type":"text/x-python","patch_set":4,"id":"3fa0c359_9395b5e6","line":1499,"range":{"start_line":1478,"start_character":0,"end_line":1499,"end_character":76},"in_reply_to":"3fa0c359_1d0e963a","updated":"2018-02-22 18:52:05.000000000","message":"Agree it\u0027s *slightly* less efficient because we\u0027re doing an extra round trip to the database, pulling those RP ID values into python, and sending them back in.  But negligible, and totally worth it for readability \u0026 maintainability.\n\nDone.","commit_id":"c3cc3507681c7f84a1d3a62a4d265683d6c948b3"},{"author":{"_account_id":7,"name":"Jay Pipes","email":"jaypipes@gmail.com","username":"jaypipes"},"change_message_id":"e92503834299b6f2a6c2a5ff9aaf9b18a735f87b","unresolved":false,"context_lines":[{"line_number":1475,"context_line":"                [resource_provider_id]).select_from(join_statement)"},{"line_number":1476,"context_line":"            query \u003d query.where(rp.c.id.in_(rps_in_aggregates))"},{"line_number":1477,"context_line":""},{"line_number":1478,"context_line":"        # If \u0027required\u0027 has values, join with ResourceProviderTrait to get"},{"line_number":1479,"context_line":"        # providers possessing *all* of the listed traits."},{"line_number":1480,"context_line":"        if required:"},{"line_number":1481,"context_line":"            # NOTE(efried): Do this instead of an embedded join so we can check"},{"line_number":1482,"context_line":"            # for missing traits."},{"line_number":1483,"context_line":"            trait_map \u003d _trait_ids_from_names(context, required)"},{"line_number":1484,"context_line":"            if len(trait_map) !\u003d len(required):"},{"line_number":1485,"context_line":"                missing \u003d required - set(trait_map)"},{"line_number":1486,"context_line":"                raise exception.TraitNotFound(names\u003d\u0027, \u0027.join(missing))"},{"line_number":1487,"context_line":"            # ...AND rp.id IN ("},{"line_number":1488,"context_line":"            #       SELECT resource_provider_id FROM resource_provider_traits"},{"line_number":1489,"context_line":"            #         WHERE trait_id IN $trait_ids"},{"line_number":1490,"context_line":"            #         GROUP BY resource_provider_id"},{"line_number":1491,"context_line":"            #         HAVING COUNT(resource_provider_id) \u003d\u003d len($trait_ids))"},{"line_number":1492,"context_line":"            rpt \u003d sa.alias(_RP_TRAIT_TBL, name\u003d\u0027rpt\u0027)"},{"line_number":1493,"context_line":"            query \u003d query.where("},{"line_number":1494,"context_line":"                sa.and_(rp.c.id.in_("},{"line_number":1495,"context_line":"                    sa.select([rpt.c.resource_provider_id]).select_from(rpt)"},{"line_number":1496,"context_line":"                        .where(rpt.c.trait_id.in_(trait_map.values()))"},{"line_number":1497,"context_line":"                        .group_by(rpt.c.resource_provider_id)"},{"line_number":1498,"context_line":"                        .having(sql.func.count("},{"line_number":1499,"context_line":"                            rpt.c.resource_provider_id) \u003d\u003d len(required)))))"},{"line_number":1500,"context_line":""},{"line_number":1501,"context_line":"        if not resources:"},{"line_number":1502,"context_line":"            # Returns quickly the list in case we don\u0027t need to check the"}],"source_content_type":"text/x-python","patch_set":4,"id":"3fa0c359_1d0e963a","line":1499,"range":{"start_line":1478,"start_character":0,"end_line":1499,"end_character":76},"in_reply_to":"3fa0c359_7d5d5a77","updated":"2018-02-22 17:41:29.000000000","message":"It\u0027s the same thing. The query above does an IN () subquery.","commit_id":"c3cc3507681c7f84a1d3a62a4d265683d6c948b3"},{"author":{"_account_id":1063,"name":"Ed Leafe","email":"ed@leafe.com","username":"ed-leafe"},"change_message_id":"69e4b2300f0247ad549fddfd77dff15ae3fa3ce7","unresolved":false,"context_lines":[{"line_number":1475,"context_line":"                [resource_provider_id]).select_from(join_statement)"},{"line_number":1476,"context_line":"            query \u003d query.where(rp.c.id.in_(rps_in_aggregates))"},{"line_number":1477,"context_line":""},{"line_number":1478,"context_line":"        # If \u0027required\u0027 has values, join with ResourceProviderTrait to get"},{"line_number":1479,"context_line":"        # providers possessing *all* of the listed traits."},{"line_number":1480,"context_line":"        if required:"},{"line_number":1481,"context_line":"            # NOTE(efried): Do this instead of an embedded join so we can check"},{"line_number":1482,"context_line":"            # for missing traits."},{"line_number":1483,"context_line":"            trait_map \u003d _trait_ids_from_names(context, required)"},{"line_number":1484,"context_line":"            if len(trait_map) !\u003d len(required):"},{"line_number":1485,"context_line":"                missing \u003d required - set(trait_map)"},{"line_number":1486,"context_line":"                raise exception.TraitNotFound(names\u003d\u0027, \u0027.join(missing))"},{"line_number":1487,"context_line":"            # ...AND rp.id IN ("},{"line_number":1488,"context_line":"            #       SELECT resource_provider_id FROM resource_provider_traits"},{"line_number":1489,"context_line":"            #         WHERE trait_id IN $trait_ids"},{"line_number":1490,"context_line":"            #         GROUP BY resource_provider_id"},{"line_number":1491,"context_line":"            #         HAVING COUNT(resource_provider_id) \u003d\u003d len($trait_ids))"},{"line_number":1492,"context_line":"            rpt \u003d sa.alias(_RP_TRAIT_TBL, name\u003d\u0027rpt\u0027)"},{"line_number":1493,"context_line":"            query \u003d query.where("},{"line_number":1494,"context_line":"                sa.and_(rp.c.id.in_("},{"line_number":1495,"context_line":"                    sa.select([rpt.c.resource_provider_id]).select_from(rpt)"},{"line_number":1496,"context_line":"                        .where(rpt.c.trait_id.in_(trait_map.values()))"},{"line_number":1497,"context_line":"                        .group_by(rpt.c.resource_provider_id)"},{"line_number":1498,"context_line":"                        .having(sql.func.count("},{"line_number":1499,"context_line":"                            rpt.c.resource_provider_id) \u003d\u003d len(required)))))"},{"line_number":1500,"context_line":""},{"line_number":1501,"context_line":"        if not resources:"},{"line_number":1502,"context_line":"            # Returns quickly the list in case we don\u0027t need to check the"}],"source_content_type":"text/x-python","patch_set":4,"id":"3fa0c359_7d5d5a77","line":1499,"range":{"start_line":1478,"start_character":0,"end_line":1499,"end_character":76},"in_reply_to":"3fa0c359_bda682c0","updated":"2018-02-22 17:37:30.000000000","message":"@Jay - that method executes the query, returning the IDs. Then this method would have to add in \"where rp_id in \u003clist from first call\u003e\", and then execute that. So with your suggestion, there would be 2 SQL executions, while this approach only uses 1 call.","commit_id":"c3cc3507681c7f84a1d3a62a4d265683d6c948b3"},{"author":{"_account_id":7,"name":"Jay Pipes","email":"jaypipes@gmail.com","username":"jaypipes"},"change_message_id":"fec42027e32175c240de13dc687e6a34494ca117","unresolved":false,"context_lines":[{"line_number":1486,"context_line":"            if not rp_ids:"},{"line_number":1487,"context_line":"                # If no providers have the required traits, we\u0027re done"},{"line_number":1488,"context_line":"                return []"},{"line_number":1489,"context_line":"            query \u003d query.where(rp.c.id.in_(rp_ids))"},{"line_number":1490,"context_line":""},{"line_number":1491,"context_line":"        if not resources:"},{"line_number":1492,"context_line":"            # Returns quickly the list in case we don\u0027t need to check the"}],"source_content_type":"text/x-python","patch_set":5,"id":"3fa0c359_2eda3a77","line":1489,"updated":"2018-02-22 19:00:19.000000000","message":"\\o/","commit_id":"4acb6c9ff7d57ecb7bc7b2602ac5cd1aae372979"},{"author":{"_account_id":5754,"name":"Alex Xu","email":"hejie.xu@intel.com","username":"xuhj"},"change_message_id":"3dea5c225d2792b624c7f15a5bd5364a2a7c20c4","unresolved":false,"context_lines":[{"line_number":1475,"context_line":"                [resource_provider_id]).select_from(join_statement)"},{"line_number":1476,"context_line":"            query \u003d query.where(rp.c.id.in_(rps_in_aggregates))"},{"line_number":1477,"context_line":""},{"line_number":1478,"context_line":"        # If \u0027required\u0027 has values, join with ResourceProviderTrait to get"},{"line_number":1479,"context_line":"        # providers possessing *all* of the listed traits."},{"line_number":1480,"context_line":"        if required:"},{"line_number":1481,"context_line":"            trait_map \u003d _trait_ids_from_names(context, required)"}],"source_content_type":"text/x-python","patch_set":6,"id":"3fa0c359_8be9f6e3","line":1478,"range":{"start_line":1478,"start_character":36,"end_line":1478,"end_character":40},"updated":"2018-02-23 05:35:00.000000000","message":"If this \u0027join\u0027 is the same meaning with SQL JOIN, then this isn\u0027t true. This is separate SQL query.","commit_id":"7e0b137aad9a2de8447516c34d2d3e908cd12fce"},{"author":{"_account_id":14070,"name":"Eric Fried","email":"openstack@fried.cc","username":"efried"},"change_message_id":"3c57b9849382960d7a93e8eb2f7c42b61563d649","unresolved":false,"context_lines":[{"line_number":1475,"context_line":"                [resource_provider_id]).select_from(join_statement)"},{"line_number":1476,"context_line":"            query \u003d query.where(rp.c.id.in_(rps_in_aggregates))"},{"line_number":1477,"context_line":""},{"line_number":1478,"context_line":"        # If \u0027required\u0027 has values, join with ResourceProviderTrait to get"},{"line_number":1479,"context_line":"        # providers possessing *all* of the listed traits."},{"line_number":1480,"context_line":"        if required:"},{"line_number":1481,"context_line":"            trait_map \u003d _trait_ids_from_names(context, required)"}],"source_content_type":"text/x-python","patch_set":6,"id":"3fa0c359_2b41b3a6","line":1478,"range":{"start_line":1478,"start_character":36,"end_line":1478,"end_character":40},"in_reply_to":"3fa0c359_8be9f6e3","updated":"2018-02-23 18:10:12.000000000","message":"Thanks, I started off using a JOIN for this, but then we decided we wanted missing traits to error.  Fixed.","commit_id":"7e0b137aad9a2de8447516c34d2d3e908cd12fce"}],"nova/tests/functional/api/openstack/placement/gabbits/resource-provider.yaml":[{"author":{"_account_id":1063,"name":"Ed Leafe","email":"ed@leafe.com","username":"ed-leafe"},"change_message_id":"b74d91486e38a2fa3ca8198b311276947405b68d","unresolved":false,"context_lines":[{"line_number":403,"context_line":"    content-type: application/json"},{"line_number":404,"context_line":"  data:"},{"line_number":405,"context_line":"      resource_provider_generation: 0"},{"line_number":406,"context_line":"      traits: [\u0027HW_CPU_X86_SGX\u0027, \u0027HW_CPU_X86_TSX\u0027]"},{"line_number":407,"context_line":""},{"line_number":408,"context_line":"- name: add traits to another provider"},{"line_number":409,"context_line":"  PUT: /resource_providers/$ENVIRON[\u0027ALT_PARENT_PROVIDER_UUID\u0027]/traits"}],"source_content_type":"text/x-yaml","patch_set":3,"id":"3fa0c359_acff3aff","line":406,"range":{"start_line":406,"start_character":16,"end_line":406,"end_character":48},"updated":"2018-02-22 15:26:08.000000000","message":"I get what you\u0027re doing with these tests. My comment is that choosing trait names that are so nearly identical makes the tests harder to read than necessary. Either pick standard traits with very different names, or use custom traits like CUSTOM_AAA, CUSTOM_BBB, etc., to make the differences in this section more readily understandable.","commit_id":"be9f1b81b2a26973b4b325a2e63718561783c2cf"},{"author":{"_account_id":14070,"name":"Eric Fried","email":"openstack@fried.cc","username":"efried"},"change_message_id":"029cc89c6d7703ac852e7d09e1f14468c5dea428","unresolved":false,"context_lines":[{"line_number":403,"context_line":"    content-type: application/json"},{"line_number":404,"context_line":"  data:"},{"line_number":405,"context_line":"      resource_provider_generation: 0"},{"line_number":406,"context_line":"      traits: [\u0027HW_CPU_X86_SGX\u0027, \u0027HW_CPU_X86_TSX\u0027]"},{"line_number":407,"context_line":""},{"line_number":408,"context_line":"- name: add traits to another provider"},{"line_number":409,"context_line":"  PUT: /resource_providers/$ENVIRON[\u0027ALT_PARENT_PROVIDER_UUID\u0027]/traits"}],"source_content_type":"text/x-yaml","patch_set":3,"id":"3fa0c359_fddf2a63","line":406,"range":{"start_line":406,"start_character":16,"end_line":406,"end_character":48},"in_reply_to":"3fa0c359_acff3aff","updated":"2018-02-22 17:16:42.000000000","message":"Done","commit_id":"be9f1b81b2a26973b4b325a2e63718561783c2cf"},{"author":{"_account_id":7,"name":"Jay Pipes","email":"jaypipes@gmail.com","username":"jaypipes"},"change_message_id":"e0ea1a6ccca012694231988d66e9d86a92bd53ba","unresolved":false,"context_lines":[{"line_number":403,"context_line":"    content-type: application/json"},{"line_number":404,"context_line":"  data:"},{"line_number":405,"context_line":"      resource_provider_generation: 0"},{"line_number":406,"context_line":"      traits: [\u0027HW_CPU_X86_SGX\u0027, \u0027HW_CPU_X86_TSX\u0027]"},{"line_number":407,"context_line":""},{"line_number":408,"context_line":"- name: add traits to another provider"},{"line_number":409,"context_line":"  PUT: /resource_providers/$ENVIRON[\u0027ALT_PARENT_PROVIDER_UUID\u0027]/traits"}],"source_content_type":"text/x-yaml","patch_set":3,"id":"3fa0c359_7db79af6","line":406,"range":{"start_line":406,"start_character":16,"end_line":406,"end_character":48},"in_reply_to":"3fa0c359_acff3aff","updated":"2018-02-22 17:26:11.000000000","message":"agree with @edleafe","commit_id":"be9f1b81b2a26973b4b325a2e63718561783c2cf"}],"releasenotes/notes/placement-required-traits-on-list-resource-providers-fab11cdb36cd3502.yaml":[{"author":{"_account_id":1063,"name":"Ed Leafe","email":"ed@leafe.com","username":"ed-leafe"},"change_message_id":"b74d91486e38a2fa3ca8198b311276947405b68d","unresolved":false,"context_lines":[{"line_number":2,"context_line":"features:"},{"line_number":3,"context_line":"  - |"},{"line_number":4,"context_line":"    Microversion 1.18 adds support for the `required` query parameter to the"},{"line_number":5,"context_line":"    `GET /resource_providers` API.  It accepts a comma-separated list of string"},{"line_number":6,"context_line":"    trait names. When specified, the API results will be filtered to include"},{"line_number":7,"context_line":"    only resource providers marked with all the specified traits. This is in"},{"line_number":8,"context_line":"    addition to (logical AND) any filtering based on other query parameters."}],"source_content_type":"text/x-yaml","patch_set":3,"id":"3fa0c359_2c41ea39","line":5,"range":{"start_line":5,"start_character":34,"end_line":5,"end_character":36},"updated":"2018-02-22 15:26:08.000000000","message":"Change this...","commit_id":"be9f1b81b2a26973b4b325a2e63718561783c2cf"},{"author":{"_account_id":14070,"name":"Eric Fried","email":"openstack@fried.cc","username":"efried"},"change_message_id":"029cc89c6d7703ac852e7d09e1f14468c5dea428","unresolved":false,"context_lines":[{"line_number":2,"context_line":"features:"},{"line_number":3,"context_line":"  - |"},{"line_number":4,"context_line":"    Microversion 1.18 adds support for the `required` query parameter to the"},{"line_number":5,"context_line":"    `GET /resource_providers` API.  It accepts a comma-separated list of string"},{"line_number":6,"context_line":"    trait names. When specified, the API results will be filtered to include"},{"line_number":7,"context_line":"    only resource providers marked with all the specified traits. This is in"},{"line_number":8,"context_line":"    addition to (logical AND) any filtering based on other query parameters."}],"source_content_type":"text/x-yaml","patch_set":3,"id":"3fa0c359_fdb88a11","line":5,"range":{"start_line":5,"start_character":34,"end_line":5,"end_character":36},"in_reply_to":"3fa0c359_2c41ea39","updated":"2018-02-22 17:16:42.000000000","message":"Done","commit_id":"be9f1b81b2a26973b4b325a2e63718561783c2cf"},{"author":{"_account_id":1063,"name":"Ed Leafe","email":"ed@leafe.com","username":"ed-leafe"},"change_message_id":"b74d91486e38a2fa3ca8198b311276947405b68d","unresolved":false,"context_lines":[{"line_number":4,"context_line":"    Microversion 1.18 adds support for the `required` query parameter to the"},{"line_number":5,"context_line":"    `GET /resource_providers` API.  It accepts a comma-separated list of string"},{"line_number":6,"context_line":"    trait names. When specified, the API results will be filtered to include"},{"line_number":7,"context_line":"    only resource providers marked with all the specified traits. This is in"},{"line_number":8,"context_line":"    addition to (logical AND) any filtering based on other query parameters."},{"line_number":9,"context_line":""},{"line_number":10,"context_line":"    Trait names which are empty, do not exist in the Trait database, or are"}],"source_content_type":"text/x-yaml","patch_set":3,"id":"3fa0c359_ac765aa3","line":7,"range":{"start_line":7,"start_character":65,"end_line":7,"end_character":66},"updated":"2018-02-22 15:26:08.000000000","message":"...to this.","commit_id":"be9f1b81b2a26973b4b325a2e63718561783c2cf"},{"author":{"_account_id":14070,"name":"Eric Fried","email":"openstack@fried.cc","username":"efried"},"change_message_id":"029cc89c6d7703ac852e7d09e1f14468c5dea428","unresolved":false,"context_lines":[{"line_number":4,"context_line":"    Microversion 1.18 adds support for the `required` query parameter to the"},{"line_number":5,"context_line":"    `GET /resource_providers` API.  It accepts a comma-separated list of string"},{"line_number":6,"context_line":"    trait names. When specified, the API results will be filtered to include"},{"line_number":7,"context_line":"    only resource providers marked with all the specified traits. This is in"},{"line_number":8,"context_line":"    addition to (logical AND) any filtering based on other query parameters."},{"line_number":9,"context_line":""},{"line_number":10,"context_line":"    Trait names which are empty, do not exist in the Trait database, or are"}],"source_content_type":"text/x-yaml","patch_set":3,"id":"3fa0c359_9d3706b1","line":7,"range":{"start_line":7,"start_character":65,"end_line":7,"end_character":66},"in_reply_to":"3fa0c359_ac765aa3","updated":"2018-02-22 17:16:42.000000000","message":"Done","commit_id":"be9f1b81b2a26973b4b325a2e63718561783c2cf"},{"author":{"_account_id":6873,"name":"Matt Riedemann","email":"mriedem.os@gmail.com","username":"mriedem"},"change_message_id":"1119db3cdf5e4c353dfa9cfdefcb009405bca5a0","unresolved":false,"context_lines":[{"line_number":1,"context_line":"---"},{"line_number":2,"context_line":"features:"},{"line_number":3,"context_line":"  - |"},{"line_number":4,"context_line":"    Microversion 1.18 adds support for the `required` query parameter to the"},{"line_number":5,"context_line":"    `GET /resource_providers` API. It accepts a comma-separated list of string"},{"line_number":6,"context_line":"    trait names. When specified, the API results will be filtered to include"},{"line_number":7,"context_line":"    only resource providers marked with all the specified traits. This is in"}],"source_content_type":"text/x-yaml","patch_set":5,"id":"3fa0c359_2a3303ad","line":4,"range":{"start_line":4,"start_character":4,"end_line":4,"end_character":16},"updated":"2018-02-22 21:16:01.000000000","message":"Placement API microversion - w/o context this is hard to know which API it\u0027s for in the release notes.","commit_id":"4acb6c9ff7d57ecb7bc7b2602ac5cd1aae372979"},{"author":{"_account_id":14070,"name":"Eric Fried","email":"openstack@fried.cc","username":"efried"},"change_message_id":"570d8f5b85ea913020fc4ce992079bc6c29e72f0","unresolved":false,"context_lines":[{"line_number":1,"context_line":"---"},{"line_number":2,"context_line":"features:"},{"line_number":3,"context_line":"  - |"},{"line_number":4,"context_line":"    Microversion 1.18 adds support for the `required` query parameter to the"},{"line_number":5,"context_line":"    `GET /resource_providers` API. It accepts a comma-separated list of string"},{"line_number":6,"context_line":"    trait names. When specified, the API results will be filtered to include"},{"line_number":7,"context_line":"    only resource providers marked with all the specified traits. This is in"}],"source_content_type":"text/x-yaml","patch_set":5,"id":"3fa0c359_2a8f832a","line":4,"range":{"start_line":4,"start_character":4,"end_line":4,"end_character":16},"in_reply_to":"3fa0c359_2a3303ad","updated":"2018-02-22 21:25:02.000000000","message":"Done","commit_id":"4acb6c9ff7d57ecb7bc7b2602ac5cd1aae372979"},{"author":{"_account_id":5754,"name":"Alex Xu","email":"hejie.xu@intel.com","username":"xuhj"},"change_message_id":"3dea5c225d2792b624c7f15a5bd5364a2a7c20c4","unresolved":false,"context_lines":[{"line_number":6,"context_line":"    comma-separated list of string trait names. When specified, the API"},{"line_number":7,"context_line":"    results will be filtered to include only resource providers marked with"},{"line_number":8,"context_line":"    all the specified traits. This is in addition to (logical AND) any"},{"line_number":9,"context_line":"    filtering based on other query parameters."},{"line_number":10,"context_line":""},{"line_number":11,"context_line":"    Trait names which are empty, do not exist, or are otherwise invalid will"},{"line_number":12,"context_line":"    result in a 400 error."}],"source_content_type":"text/x-yaml","patch_set":6,"id":"3fa0c359_6beeeaed","line":9,"range":{"start_line":9,"start_character":23,"end_line":9,"end_character":46},"updated":"2018-02-23 05:35:00.000000000","message":"This isn\u0027t true for \u0027resources\u0027 parameter, \u0027resources\u0027 parameter doesn\u0027t work with other params","commit_id":"7e0b137aad9a2de8447516c34d2d3e908cd12fce"},{"author":{"_account_id":5754,"name":"Alex Xu","email":"hejie.xu@intel.com","username":"xuhj"},"change_message_id":"382bdcd80673a9c7f18d63ee43adeba1b131c737","unresolved":false,"context_lines":[{"line_number":6,"context_line":"    comma-separated list of string trait names. When specified, the API"},{"line_number":7,"context_line":"    results will be filtered to include only resource providers marked with"},{"line_number":8,"context_line":"    all the specified traits. This is in addition to (logical AND) any"},{"line_number":9,"context_line":"    filtering based on other query parameters."},{"line_number":10,"context_line":""},{"line_number":11,"context_line":"    Trait names which are empty, do not exist, or are otherwise invalid will"},{"line_number":12,"context_line":"    result in a 400 error."}],"source_content_type":"text/x-yaml","patch_set":6,"id":"3fa0c359_c03ee989","line":9,"range":{"start_line":9,"start_character":23,"end_line":9,"end_character":46},"in_reply_to":"3fa0c359_2bec53b9","updated":"2018-02-23 19:09:17.000000000","message":"oh..yea, I missed this line https://review.openstack.org/#/c/546837/7/nova/objects/resource_provider.py@1563, must the jetlag","commit_id":"7e0b137aad9a2de8447516c34d2d3e908cd12fce"},{"author":{"_account_id":7,"name":"Jay Pipes","email":"jaypipes@gmail.com","username":"jaypipes"},"change_message_id":"bca23494002491d69cde60ddbbe5c8ddabcfed84","unresolved":false,"context_lines":[{"line_number":6,"context_line":"    comma-separated list of string trait names. When specified, the API"},{"line_number":7,"context_line":"    results will be filtered to include only resource providers marked with"},{"line_number":8,"context_line":"    all the specified traits. This is in addition to (logical AND) any"},{"line_number":9,"context_line":"    filtering based on other query parameters."},{"line_number":10,"context_line":""},{"line_number":11,"context_line":"    Trait names which are empty, do not exist, or are otherwise invalid will"},{"line_number":12,"context_line":"    result in a 400 error."}],"source_content_type":"text/x-yaml","patch_set":6,"id":"3fa0c359_90527934","line":9,"range":{"start_line":9,"start_character":23,"end_line":9,"end_character":46},"in_reply_to":"3fa0c359_6beeeaed","updated":"2018-02-23 12:31:56.000000000","message":"Yes, it does:\n\nhttps://github.com/openstack/nova/blob/master/nova/objects/resource_provider.py#L1516-L1553","commit_id":"7e0b137aad9a2de8447516c34d2d3e908cd12fce"},{"author":{"_account_id":14070,"name":"Eric Fried","email":"openstack@fried.cc","username":"efried"},"change_message_id":"3c57b9849382960d7a93e8eb2f7c42b61563d649","unresolved":false,"context_lines":[{"line_number":6,"context_line":"    comma-separated list of string trait names. When specified, the API"},{"line_number":7,"context_line":"    results will be filtered to include only resource providers marked with"},{"line_number":8,"context_line":"    all the specified traits. This is in addition to (logical AND) any"},{"line_number":9,"context_line":"    filtering based on other query parameters."},{"line_number":10,"context_line":""},{"line_number":11,"context_line":"    Trait names which are empty, do not exist, or are otherwise invalid will"},{"line_number":12,"context_line":"    result in a 400 error."}],"source_content_type":"text/x-yaml","patch_set":6,"id":"3fa0c359_2bec53b9","line":9,"range":{"start_line":9,"start_character":23,"end_line":9,"end_character":46},"in_reply_to":"3fa0c359_90527934","updated":"2018-02-23 18:10:12.000000000","message":"I added a gabbit to validate it.","commit_id":"7e0b137aad9a2de8447516c34d2d3e908cd12fce"}]}
