)]}'
{"/COMMIT_MSG":[{"author":{"_account_id":15648,"name":"Yingxin","email":"yingxin.cheng@intel.com","username":"Yingxin"},"change_message_id":"85e70d3d244ba1e6b538092d5d9db894cb97f6b7","unresolved":false,"context_lines":[{"line_number":11,"context_line":"GET \u0027/traits\u0027 should return the standard traits which defined"},{"line_number":12,"context_line":"in os-traits library and the user custom traits from the DB."},{"line_number":13,"context_line":""},{"line_number":14,"context_line":"TODO: integrate with os-traits"},{"line_number":15,"context_line":""},{"line_number":16,"context_line":"Partial implement blueprint resource-provider-tags"},{"line_number":17,"context_line":""}],"source_content_type":"text/x-gerrit-commit-message","patch_set":7,"id":"ba5201f7_418ec0d0","line":14,"updated":"2017-01-06 07:55:14.000000000","message":"Another TODO.\nThere is an \"associated\" parameter to query the traits that have been associated with resource provider in the placement service.","commit_id":"69b9ae8d40e89bba329965663db2d099a251601d"},{"author":{"_account_id":5754,"name":"Alex Xu","email":"hejie.xu@intel.com","username":"xuhj"},"change_message_id":"5f35fe56a86824e51bb5a0c23d76d3d5e651de6c","unresolved":false,"context_lines":[{"line_number":11,"context_line":"GET \u0027/traits\u0027 should return the standard traits which defined"},{"line_number":12,"context_line":"in os-traits library and the user custom traits from the DB."},{"line_number":13,"context_line":""},{"line_number":14,"context_line":"TODO: integrate with os-traits"},{"line_number":15,"context_line":""},{"line_number":16,"context_line":"Partial implement blueprint resource-provider-tags"},{"line_number":17,"context_line":""}],"source_content_type":"text/x-gerrit-commit-message","patch_set":7,"id":"ba5201f7_df3967f4","line":14,"in_reply_to":"ba5201f7_418ec0d0","updated":"2017-01-09 11:41:33.000000000","message":"ah, thanks","commit_id":"69b9ae8d40e89bba329965663db2d099a251601d"},{"author":{"_account_id":7,"name":"Jay Pipes","email":"jaypipes@gmail.com","username":"jaypipes"},"change_message_id":"6f1ad85216421959eda399b9c9c5fa9a8b512586","unresolved":false,"context_lines":[{"line_number":9,"context_line":"This patch adds support for a REST API for CRUD operations on traits."},{"line_number":10,"context_line":""},{"line_number":11,"context_line":"  GET /traits: Returns all resource classes."},{"line_number":12,"context_line":"  PUT /trait/{trait_name}: To insert a single custom trait."},{"line_number":13,"context_line":"  GET /trait/{trait_name}: To check if a trait name exists."},{"line_number":14,"context_line":"  DELETE /trait/{trait_name}: To delete the specified trait."},{"line_number":15,"context_line":"  GET /resource_providers/{uuid}/traits: a list of traits associated"}],"source_content_type":"text/x-gerrit-commit-message","patch_set":26,"id":"ffe62b97_c1911549","line":12,"updated":"2017-03-29 19:47:41.000000000","message":"should be:\n\n PUT /traits/{trait_name}","commit_id":"7a6ff8d185ac6830e0e6a3725a8046f28321c8ff"},{"author":{"_account_id":6167,"name":"Ken\u0027ichi Ohmichi","email":"ken1ohmichi@gmail.com","username":"oomichi"},"change_message_id":"f94c1bfc3ae336319d9b2b79e0fe7dcb27f253b8","unresolved":false,"context_lines":[{"line_number":10,"context_line":""},{"line_number":11,"context_line":"  GET /traits: Returns all resource classes."},{"line_number":12,"context_line":"  PUT /trait/{trait_name}: To insert a single custom trait."},{"line_number":13,"context_line":"  GET /trait/{trait_name}: To check if a trait name exists."},{"line_number":14,"context_line":"  DELETE /trait/{trait_name}: To delete the specified trait."},{"line_number":15,"context_line":"  GET /resource_providers/{uuid}/traits: a list of traits associated"},{"line_number":16,"context_line":"  with a specific resource provider"}],"source_content_type":"text/x-gerrit-commit-message","patch_set":26,"id":"ffe62b97_ce3bf6e8","line":13,"range":{"start_line":13,"start_character":2,"end_line":13,"end_character":59},"updated":"2017-03-27 17:35:42.000000000","message":"again: If we just want the existence of resource, HEAD could be accurate from api-wg guideline.\n\nhttps://github.com/openstack/api-wg/blob/master/guidelines/http.rst#http-methods","commit_id":"7a6ff8d185ac6830e0e6a3725a8046f28321c8ff"},{"author":{"_account_id":11564,"name":"Chris Dent","email":"cdent@anticdent.org","username":"chdent"},"change_message_id":"35dd6bab3e1098db12d933185cd0ace147377b83","unresolved":false,"context_lines":[{"line_number":10,"context_line":""},{"line_number":11,"context_line":"  GET /traits: Returns all resource classes."},{"line_number":12,"context_line":"  PUT /trait/{trait_name}: To insert a single custom trait."},{"line_number":13,"context_line":"  GET /trait/{trait_name}: To check if a trait name exists."},{"line_number":14,"context_line":"  DELETE /trait/{trait_name}: To delete the specified trait."},{"line_number":15,"context_line":"  GET /resource_providers/{uuid}/traits: a list of traits associated"},{"line_number":16,"context_line":"  with a specific resource provider"}],"source_content_type":"text/x-gerrit-commit-message","patch_set":26,"id":"ffe62b97_810c2d94","line":13,"in_reply_to":"ffe62b97_610a4920","updated":"2017-03-29 19:32:34.000000000","message":"I disagree. The resource is the trait, we must be able to GET it.\n\nI\u0027ve responded on the bug as well.","commit_id":"7a6ff8d185ac6830e0e6a3725a8046f28321c8ff"},{"author":{"_account_id":7,"name":"Jay Pipes","email":"jaypipes@gmail.com","username":"jaypipes"},"change_message_id":"6f1ad85216421959eda399b9c9c5fa9a8b512586","unresolved":false,"context_lines":[{"line_number":10,"context_line":""},{"line_number":11,"context_line":"  GET /traits: Returns all resource classes."},{"line_number":12,"context_line":"  PUT /trait/{trait_name}: To insert a single custom trait."},{"line_number":13,"context_line":"  GET /trait/{trait_name}: To check if a trait name exists."},{"line_number":14,"context_line":"  DELETE /trait/{trait_name}: To delete the specified trait."},{"line_number":15,"context_line":"  GET /resource_providers/{uuid}/traits: a list of traits associated"},{"line_number":16,"context_line":"  with a specific resource provider"}],"source_content_type":"text/x-gerrit-commit-message","patch_set":26,"id":"ffe62b97_81978d3a","line":13,"range":{"start_line":13,"start_character":2,"end_line":13,"end_character":59},"in_reply_to":"ffe62b97_610a4920","updated":"2017-03-29 19:47:41.000000000","message":"Should be:\n\n GET /traits/{trait_name}","commit_id":"7a6ff8d185ac6830e0e6a3725a8046f28321c8ff"},{"author":{"_account_id":6167,"name":"Ken\u0027ichi Ohmichi","email":"ken1ohmichi@gmail.com","username":"oomichi"},"change_message_id":"256e5913376848e554d3acd3b400341d0e5bc0f8","unresolved":false,"context_lines":[{"line_number":10,"context_line":""},{"line_number":11,"context_line":"  GET /traits: Returns all resource classes."},{"line_number":12,"context_line":"  PUT /trait/{trait_name}: To insert a single custom trait."},{"line_number":13,"context_line":"  GET /trait/{trait_name}: To check if a trait name exists."},{"line_number":14,"context_line":"  DELETE /trait/{trait_name}: To delete the specified trait."},{"line_number":15,"context_line":"  GET /resource_providers/{uuid}/traits: a list of traits associated"},{"line_number":16,"context_line":"  with a specific resource provider"}],"source_content_type":"text/x-gerrit-commit-message","patch_set":26,"id":"dfeb2761_872aeae4","line":13,"range":{"start_line":13,"start_character":2,"end_line":13,"end_character":59},"in_reply_to":"ffe62b97_81978d3a","updated":"2017-03-30 18:05:32.000000000","message":"https://review.openstack.org/#/c/451536 is a good place to discuss it.","commit_id":"7a6ff8d185ac6830e0e6a3725a8046f28321c8ff"},{"author":{"_account_id":5754,"name":"Alex Xu","email":"hejie.xu@intel.com","username":"xuhj"},"change_message_id":"8c746b5c5c7d90c251b3b5f7ad8a6882ed56cbde","unresolved":false,"context_lines":[{"line_number":10,"context_line":""},{"line_number":11,"context_line":"  GET /traits: Returns all resource classes."},{"line_number":12,"context_line":"  PUT /trait/{trait_name}: To insert a single custom trait."},{"line_number":13,"context_line":"  GET /trait/{trait_name}: To check if a trait name exists."},{"line_number":14,"context_line":"  DELETE /trait/{trait_name}: To delete the specified trait."},{"line_number":15,"context_line":"  GET /resource_providers/{uuid}/traits: a list of traits associated"},{"line_number":16,"context_line":"  with a specific resource provider"}],"source_content_type":"text/x-gerrit-commit-message","patch_set":26,"id":"ffe62b97_ef66a6c1","line":13,"range":{"start_line":13,"start_character":2,"end_line":13,"end_character":59},"in_reply_to":"ffe62b97_ce3bf6e8","updated":"2017-03-28 01:43:31.000000000","message":"Good point. But looks like we have conflict between http guide and tags guide in the api-wg https://github.com/openstack/api-wg/blob/master/guidelines/tags.rst","commit_id":"7a6ff8d185ac6830e0e6a3725a8046f28321c8ff"},{"author":{"_account_id":1063,"name":"Ed Leafe","email":"ed@leafe.com","username":"ed-leafe"},"change_message_id":"bfe1f82ffea982db2a954ee4fb12f2343aa7f69b","unresolved":false,"context_lines":[{"line_number":10,"context_line":""},{"line_number":11,"context_line":"  GET /traits: Returns all resource classes."},{"line_number":12,"context_line":"  PUT /trait/{trait_name}: To insert a single custom trait."},{"line_number":13,"context_line":"  GET /trait/{trait_name}: To check if a trait name exists."},{"line_number":14,"context_line":"  DELETE /trait/{trait_name}: To delete the specified trait."},{"line_number":15,"context_line":"  GET /resource_providers/{uuid}/traits: a list of traits associated"},{"line_number":16,"context_line":"  with a specific resource provider"}],"source_content_type":"text/x-gerrit-commit-message","patch_set":26,"id":"ffe62b97_610a4920","line":13,"range":{"start_line":13,"start_character":2,"end_line":13,"end_character":59},"in_reply_to":"ffe62b97_ef66a6c1","updated":"2017-03-29 19:18:45.000000000","message":"HEAD is the correct method; the tags guidance is wrong. I\u0027ve entered a bug to fix this: https://bugs.launchpad.net/openstack-api-wg/+bug/1677360","commit_id":"7a6ff8d185ac6830e0e6a3725a8046f28321c8ff"},{"author":{"_account_id":7,"name":"Jay Pipes","email":"jaypipes@gmail.com","username":"jaypipes"},"change_message_id":"6f1ad85216421959eda399b9c9c5fa9a8b512586","unresolved":false,"context_lines":[{"line_number":11,"context_line":"  GET /traits: Returns all resource classes."},{"line_number":12,"context_line":"  PUT /trait/{trait_name}: To insert a single custom trait."},{"line_number":13,"context_line":"  GET /trait/{trait_name}: To check if a trait name exists."},{"line_number":14,"context_line":"  DELETE /trait/{trait_name}: To delete the specified trait."},{"line_number":15,"context_line":"  GET /resource_providers/{uuid}/traits: a list of traits associated"},{"line_number":16,"context_line":"  with a specific resource provider"},{"line_number":17,"context_line":"  PUT /resource_providers/{uuid}/traits: Set all the traits for a"}],"source_content_type":"text/x-gerrit-commit-message","patch_set":26,"id":"ffe62b97_01ab7d74","line":14,"updated":"2017-03-29 19:47:41.000000000","message":"Should be:\n\n DELETE /traits/{trait_name}","commit_id":"7a6ff8d185ac6830e0e6a3725a8046f28321c8ff"},{"author":{"_account_id":11564,"name":"Chris Dent","email":"cdent@anticdent.org","username":"chdent"},"change_message_id":"851ac94c5f241ed3cc1b11b842405b88a3ad08ee","unresolved":false,"context_lines":[{"line_number":10,"context_line":""},{"line_number":11,"context_line":"  GET /traits: Returns all resource classes."},{"line_number":12,"context_line":"  PUT /traits/{trait_name}: To insert a single custom trait."},{"line_number":13,"context_line":"  GET /traits/{trait_name}: To check if a trait name exists."},{"line_number":14,"context_line":"  DELETE /traits/{trait_name}: To delete the specified trait."},{"line_number":15,"context_line":"  GET /resource_providers/{uuid}/traits: a list of traits associated"},{"line_number":16,"context_line":"  with a specific resource provider"}],"source_content_type":"text/x-gerrit-commit-message","patch_set":28,"id":"dfeb2761_c718d7d4","line":13,"updated":"2017-03-31 11:26:24.000000000","message":"If you make another version you could leave out \"name\" here because you are checking if the trait (having name trait_name) exists, not that the name exists.","commit_id":"a7bcb493917900d1610b7447b991668ee05abf3a"},{"author":{"_account_id":5754,"name":"Alex Xu","email":"hejie.xu@intel.com","username":"xuhj"},"change_message_id":"718615f3ffcaef7548fff521c093770f87d5f936","unresolved":false,"context_lines":[{"line_number":10,"context_line":""},{"line_number":11,"context_line":"  GET /traits: Returns all resource classes."},{"line_number":12,"context_line":"  PUT /traits/{trait_name}: To insert a single custom trait."},{"line_number":13,"context_line":"  GET /traits/{trait_name}: To check if a trait name exists."},{"line_number":14,"context_line":"  DELETE /traits/{trait_name}: To delete the specified trait."},{"line_number":15,"context_line":"  GET /resource_providers/{uuid}/traits: a list of traits associated"},{"line_number":16,"context_line":"  with a specific resource provider"}],"source_content_type":"text/x-gerrit-commit-message","patch_set":28,"id":"bff0334d_df6c1b0a","line":13,"in_reply_to":"dfeb2761_c718d7d4","updated":"2017-04-06 07:38:30.000000000","message":"Done","commit_id":"a7bcb493917900d1610b7447b991668ee05abf3a"}],"nova/api/openstack/placement/handler.py":[{"author":{"_account_id":15648,"name":"Yingxin","email":"yingxin.cheng@intel.com","username":"Yingxin"},"change_message_id":"953a571db6122a39b1f59d20279fb05baedef82f","unresolved":false,"context_lines":[{"line_number":81,"context_line":"    },"},{"line_number":82,"context_line":"    \u0027/traits\u0027: {"},{"line_number":83,"context_line":"        \u0027GET\u0027: trait.list_all_traits,"},{"line_number":84,"context_line":"        \u0027PUT\u0027: trait.update_all_traits,"},{"line_number":85,"context_line":"        \u0027DELETE\u0027: trait.delete_all_traits,"},{"line_number":86,"context_line":"    }"},{"line_number":87,"context_line":"}"},{"line_number":88,"context_line":""}],"source_content_type":"text/x-python","patch_set":1,"id":"5a8bc5a2_0fe6c343","line":85,"range":{"start_line":84,"start_character":8,"end_line":85,"end_character":42},"updated":"2016-09-26 07:29:26.000000000","message":"Any explicit reasons to expose APIs to modify the global trait list? It is even unsafe to delete any traits if it still associates a resource provider object.\n\nI can only figure out use cases to manage/update traits through individual resource providers.","commit_id":"ddc00f9ab00f053a36fb3875a4b5d4c28fcc86c5"},{"author":{"_account_id":5754,"name":"Alex Xu","email":"hejie.xu@intel.com","username":"xuhj"},"change_message_id":"c203730ddfbd22bd9cd9370f8842485ce3449d25","unresolved":false,"context_lines":[{"line_number":81,"context_line":"    },"},{"line_number":82,"context_line":"    \u0027/traits\u0027: {"},{"line_number":83,"context_line":"        \u0027GET\u0027: trait.list_all_traits,"},{"line_number":84,"context_line":"        \u0027PUT\u0027: trait.update_all_traits,"},{"line_number":85,"context_line":"        \u0027DELETE\u0027: trait.delete_all_traits,"},{"line_number":86,"context_line":"    }"},{"line_number":87,"context_line":"}"},{"line_number":88,"context_line":""}],"source_content_type":"text/x-python","patch_set":1,"id":"5a8bc5a2_502dccfc","line":85,"range":{"start_line":84,"start_character":8,"end_line":85,"end_character":42},"in_reply_to":"5a8bc5a2_0fe6c343","updated":"2016-09-26 08:38:45.000000000","message":"Admin needs to add custom trait through /traits. The API call on individual resource providers needs to validate whether the trait is valid( valid trait come from /traits\u0027","commit_id":"ddc00f9ab00f053a36fb3875a4b5d4c28fcc86c5"}],"nova/api/openstack/placement/handlers/trait.py":[{"author":{"_account_id":15648,"name":"Yingxin","email":"yingxin.cheng@intel.com","username":"Yingxin"},"change_message_id":"953a571db6122a39b1f59d20279fb05baedef82f","unresolved":false,"context_lines":[{"line_number":72,"context_line":"    filters \u003d {}"},{"line_number":73,"context_line":"    if \u0027traits\u0027 in req.GET:"},{"line_number":74,"context_line":"        filters[\u0027traits\u0027] \u003d req.GET.get(\u0027traits\u0027).split(\u0027,\u0027)"},{"line_number":75,"context_line":"    traits \u003d objects.TraitList.get_all(context, filters)"},{"line_number":76,"context_line":""},{"line_number":77,"context_line":"    req.response.status \u003d 200"},{"line_number":78,"context_line":"    req.response.body \u003d jsonutils.dumps(_serialize_traits(traits))"}],"source_content_type":"text/x-python","patch_set":1,"id":"5a8bc5a2_4fb8cbc8","line":75,"range":{"start_line":75,"start_character":48,"end_line":75,"end_character":55},"updated":"2016-09-26 07:29:26.000000000","message":"Is it really useful to expose filters directly to traits API?\n\nI can figure out some use cases to filter traits by namespaces, or filter out user-defined traits, but they don\u0027t implement like this.","commit_id":"ddc00f9ab00f053a36fb3875a4b5d4c28fcc86c5"},{"author":{"_account_id":11564,"name":"Chris Dent","email":"cdent@anticdent.org","username":"chdent"},"change_message_id":"92e0ab05d936003774f8c5cd441213890019d129","unresolved":false,"context_lines":[{"line_number":49,"context_line":"    return ret"},{"line_number":50,"context_line":""},{"line_number":51,"context_line":""},{"line_number":52,"context_line":"def _extra_traits(body, schema):"},{"line_number":53,"context_line":"    try:"},{"line_number":54,"context_line":"        data \u003d jsonutils.loads(body)"},{"line_number":55,"context_line":"    except ValueError as exc:"}],"source_content_type":"text/x-python","patch_set":2,"id":"3a98d1f4_0a90bc42","line":52,"updated":"2016-09-29 15:05:15.000000000","message":"I think you meant extract here?\n\nThere\u0027s now a method in nova.api.openstack.placement.util that will take any body and any schema and do this so you could replace this with that.","commit_id":"64d217668df42a84f55c90ecb94a4c4a76c99ec9"},{"author":{"_account_id":5754,"name":"Alex Xu","email":"hejie.xu@intel.com","username":"xuhj"},"change_message_id":"320f2c05bcc0dd7b481d14946417fd31642247d2","unresolved":false,"context_lines":[{"line_number":49,"context_line":"    return ret"},{"line_number":50,"context_line":""},{"line_number":51,"context_line":""},{"line_number":52,"context_line":"def _extra_traits(body, schema):"},{"line_number":53,"context_line":"    try:"},{"line_number":54,"context_line":"        data \u003d jsonutils.loads(body)"},{"line_number":55,"context_line":"    except ValueError as exc:"}],"source_content_type":"text/x-python","patch_set":2,"id":"3a98d1f4_c3c9ba27","line":52,"in_reply_to":"3a98d1f4_0a90bc42","updated":"2016-10-04 06:37:48.000000000","message":"that\u0027s cool, thanks, will replace with that common method.","commit_id":"64d217668df42a84f55c90ecb94a4c4a76c99ec9"},{"author":{"_account_id":11564,"name":"Chris Dent","email":"cdent@anticdent.org","username":"chdent"},"change_message_id":"92e0ab05d936003774f8c5cd441213890019d129","unresolved":false,"context_lines":[{"line_number":82,"context_line":""},{"line_number":83,"context_line":"@webob.dec.wsgify"},{"line_number":84,"context_line":"@util.require_content(\u0027application/json\u0027)"},{"line_number":85,"context_line":"def update_all_traits(req):"},{"line_number":86,"context_line":"    context \u003d req.environ[\u0027placement.context\u0027]"},{"line_number":87,"context_line":"    traits \u003d _extra_traits(req.body, PUT_TRAITS_SCHEMA)"},{"line_number":88,"context_line":""}],"source_content_type":"text/x-python","patch_set":2,"id":"3a98d1f4_455b9587","line":85,"updated":"2016-09-29 15:05:15.000000000","message":"As I said on the spec, what will this really mean: we\u0027re not updating all the trains, because some of them are static from the os-traits library? Or does this URI only represent local/custom traits?","commit_id":"64d217668df42a84f55c90ecb94a4c4a76c99ec9"},{"author":{"_account_id":5754,"name":"Alex Xu","email":"hejie.xu@intel.com","username":"xuhj"},"change_message_id":"320f2c05bcc0dd7b481d14946417fd31642247d2","unresolved":false,"context_lines":[{"line_number":82,"context_line":""},{"line_number":83,"context_line":"@webob.dec.wsgify"},{"line_number":84,"context_line":"@util.require_content(\u0027application/json\u0027)"},{"line_number":85,"context_line":"def update_all_traits(req):"},{"line_number":86,"context_line":"    context \u003d req.environ[\u0027placement.context\u0027]"},{"line_number":87,"context_line":"    traits \u003d _extra_traits(req.body, PUT_TRAITS_SCHEMA)"},{"line_number":88,"context_line":""}],"source_content_type":"text/x-python","patch_set":2,"id":"3a98d1f4_03e722ac","line":85,"in_reply_to":"3a98d1f4_455b9587","updated":"2016-10-04 06:37:48.000000000","message":"emm...yes, this won\u0027t update all the traits. Only the user-defined one. But I\u0027m a little confuse on what we should return at here, all the traits or user-defined traits, both are strange.\n\nOr maybe we just need API POST and DELETE, The POST method only need to return the new created traits.","commit_id":"64d217668df42a84f55c90ecb94a4c4a76c99ec9"},{"author":{"_account_id":6062,"name":"jichenjc","email":"jichenjc@cn.ibm.com","username":"jichenjc"},"change_message_id":"e814842fba0ceb2bdd33def0af949fbbdc07a23b","unresolved":false,"context_lines":[{"line_number":35,"context_line":"            \"items\": TRAIT,"},{"line_number":36,"context_line":"            # NOTE(alex_xu): There isn\u0027t quota support in the placement API"},{"line_number":37,"context_line":"            # yet. 1000 custom traits is enough for now."},{"line_number":38,"context_line":"            \"maxItems\": 1000"},{"line_number":39,"context_line":"        }"},{"line_number":40,"context_line":"    },"},{"line_number":41,"context_line":"    \u0027required\u0027: [\u0027traits\u0027],"}],"source_content_type":"text/x-python","patch_set":7,"id":"ba5201f7_9f18fcd4","line":38,"range":{"start_line":38,"start_character":24,"end_line":38,"end_character":28},"updated":"2017-01-06 10:58:37.000000000","message":"seems no need quota? tag seems use MAX_TAG_COUNT \u003d 50 now","commit_id":"69b9ae8d40e89bba329965663db2d099a251601d"},{"author":{"_account_id":5754,"name":"Alex Xu","email":"hejie.xu@intel.com","username":"xuhj"},"change_message_id":"5f35fe56a86824e51bb5a0c23d76d3d5e651de6c","unresolved":false,"context_lines":[{"line_number":35,"context_line":"            \"items\": TRAIT,"},{"line_number":36,"context_line":"            # NOTE(alex_xu): There isn\u0027t quota support in the placement API"},{"line_number":37,"context_line":"            # yet. 1000 custom traits is enough for now."},{"line_number":38,"context_line":"            \"maxItems\": 1000"},{"line_number":39,"context_line":"        }"},{"line_number":40,"context_line":"    },"},{"line_number":41,"context_line":"    \u0027required\u0027: [\u0027traits\u0027],"}],"source_content_type":"text/x-python","patch_set":7,"id":"ba5201f7_6ab8bb2b","line":38,"range":{"start_line":38,"start_character":24,"end_line":38,"end_character":28},"in_reply_to":"ba5201f7_9f18fcd4","updated":"2017-01-09 11:41:33.000000000","message":"This is admin-API, so no quota is fine. And check the resource class API, there is no limit also. So maybe we can relax the limit at here also.","commit_id":"69b9ae8d40e89bba329965663db2d099a251601d"},{"author":{"_account_id":6062,"name":"jichenjc","email":"jichenjc@cn.ibm.com","username":"jichenjc"},"change_message_id":"e814842fba0ceb2bdd33def0af949fbbdc07a23b","unresolved":false,"context_lines":[{"line_number":111,"context_line":"        raise webob.exc.HTTPBadRequest("},{"line_number":112,"context_line":"            explanation\u003dex.format_message(),"},{"line_number":113,"context_line":"            json_formatter\u003dutil.json_error_formatter)"},{"line_number":114,"context_line":"    except exception.TraitCannotDeleteStandard as ex:"},{"line_number":115,"context_line":"        raise webob.exc.HTTPConflict("},{"line_number":116,"context_line":"            explanation\u003dex.format_message(),"},{"line_number":117,"context_line":"            json_formatter\u003dutil.json_error_formatter)"}],"source_content_type":"text/x-python","patch_set":7,"id":"ba5201f7_3f4e30c1","line":114,"range":{"start_line":114,"start_character":21,"end_line":114,"end_character":46},"updated":"2017-01-06 10:58:37.000000000","message":"will validate CUSTOM_ prefix can find issue earily?","commit_id":"69b9ae8d40e89bba329965663db2d099a251601d"},{"author":{"_account_id":5754,"name":"Alex Xu","email":"hejie.xu@intel.com","username":"xuhj"},"change_message_id":"5f35fe56a86824e51bb5a0c23d76d3d5e651de6c","unresolved":false,"context_lines":[{"line_number":111,"context_line":"        raise webob.exc.HTTPBadRequest("},{"line_number":112,"context_line":"            explanation\u003dex.format_message(),"},{"line_number":113,"context_line":"            json_formatter\u003dutil.json_error_formatter)"},{"line_number":114,"context_line":"    except exception.TraitCannotDeleteStandard as ex:"},{"line_number":115,"context_line":"        raise webob.exc.HTTPConflict("},{"line_number":116,"context_line":"            explanation\u003dex.format_message(),"},{"line_number":117,"context_line":"            json_formatter\u003dutil.json_error_formatter)"}],"source_content_type":"text/x-python","patch_set":7,"id":"ba5201f7_ca77e79d","line":114,"range":{"start_line":114,"start_character":21,"end_line":114,"end_character":46},"in_reply_to":"ba5201f7_3f4e30c1","updated":"2017-01-09 11:41:33.000000000","message":"yes, But we validate the standard trait first, we can get better error message I guess","commit_id":"69b9ae8d40e89bba329965663db2d099a251601d"},{"author":{"_account_id":6062,"name":"jichenjc","email":"jichenjc@cn.ibm.com","username":"jichenjc"},"change_message_id":"e814842fba0ceb2bdd33def0af949fbbdc07a23b","unresolved":false,"context_lines":[{"line_number":155,"context_line":"            explanation\u003dex.format_message(),"},{"line_number":156,"context_line":"            json_formatter\u003dutil.json_error_formatter)"},{"line_number":157,"context_line":""},{"line_number":158,"context_line":"    req.response.status \u003d 200"},{"line_number":159,"context_line":"    req.response.body \u003d jsonutils.dumps(_serialize_traits(traits))"},{"line_number":160,"context_line":"    req.response.content_type \u003d \u0027application/json\u0027"},{"line_number":161,"context_line":"    return req.response"}],"source_content_type":"text/x-python","patch_set":7,"id":"ba5201f7_dfd364d3","line":158,"range":{"start_line":158,"start_character":26,"end_line":158,"end_character":29},"updated":"2017-01-06 10:58:37.000000000","message":"why this return 200 while update_traits return 204?","commit_id":"69b9ae8d40e89bba329965663db2d099a251601d"},{"author":{"_account_id":5754,"name":"Alex Xu","email":"hejie.xu@intel.com","username":"xuhj"},"change_message_id":"5f35fe56a86824e51bb5a0c23d76d3d5e651de6c","unresolved":false,"context_lines":[{"line_number":155,"context_line":"            explanation\u003dex.format_message(),"},{"line_number":156,"context_line":"            json_formatter\u003dutil.json_error_formatter)"},{"line_number":157,"context_line":""},{"line_number":158,"context_line":"    req.response.status \u003d 200"},{"line_number":159,"context_line":"    req.response.body \u003d jsonutils.dumps(_serialize_traits(traits))"},{"line_number":160,"context_line":"    req.response.content_type \u003d \u0027application/json\u0027"},{"line_number":161,"context_line":"    return req.response"}],"source_content_type":"text/x-python","patch_set":7,"id":"ba5201f7_6a619bd3","line":158,"range":{"start_line":158,"start_character":26,"end_line":158,"end_character":29},"in_reply_to":"ba5201f7_dfd364d3","updated":"2017-01-09 11:41:33.000000000","message":"204 is for no-body response. This is response body.","commit_id":"69b9ae8d40e89bba329965663db2d099a251601d"},{"author":{"_account_id":11564,"name":"Chris Dent","email":"cdent@anticdent.org","username":"chdent"},"change_message_id":"39fd458c02a810045c497dc77ad1917636055319","unresolved":false,"context_lines":[{"line_number":52,"context_line":"    return data[\u0027traits\u0027]"},{"line_number":53,"context_line":""},{"line_number":54,"context_line":""},{"line_number":55,"context_line":"@webob.dec.wsgify"},{"line_number":56,"context_line":"def put_trait(req):"},{"line_number":57,"context_line":"    context \u003d req.environ[\u0027placement.context\u0027]"},{"line_number":58,"context_line":"    name \u003d util.wsgi_path_item(req.environ, \u0027name\u0027)"}],"source_content_type":"text/x-python","patch_set":10,"id":"fa31d9ce_b2eca8f4","line":55,"updated":"2017-02-17 14:54:48.000000000","message":"With the changes in commit 227a4dff25b69a4ee4daf6dc2240831ae72071c7 there\u0027s now a new wsgi wrapper which means the json_formatter you\u0027ve forgotten below is no longer needed.","commit_id":"082b203e48de9ddd284f79f24711a5e31bda8609"},{"author":{"_account_id":6062,"name":"jichenjc","email":"jichenjc@cn.ibm.com","username":"jichenjc"},"change_message_id":"88592042b585a318c0df580042960b76023624b9","unresolved":false,"context_lines":[{"line_number":61,"context_line":"        jsonschema.validate(name, TRAIT)"},{"line_number":62,"context_line":"    except jsonschema.ValidationError:"},{"line_number":63,"context_line":"        raise webob.exc.HTTPBadRequest("},{"line_number":64,"context_line":"            _(\u0027The trait is invalid. The valid trait must include prefix\u0027"},{"line_number":65,"context_line":"              \u0027\"CUSTOM_\". The valid characters are \"A\"-\"Z\", \"0\"-\"9\" and \"_\"\u0027))"},{"line_number":66,"context_line":""},{"line_number":67,"context_line":"    trait \u003d objects.Trait(context)"}],"source_content_type":"text/x-python","patch_set":10,"id":"fa31d9ce_eeae45e6","line":64,"range":{"start_line":64,"start_character":72,"end_line":64,"end_character":73},"updated":"2017-02-17 10:35:12.000000000","message":"nit need a blank","commit_id":"082b203e48de9ddd284f79f24711a5e31bda8609"},{"author":{"_account_id":11564,"name":"Chris Dent","email":"cdent@anticdent.org","username":"chdent"},"change_message_id":"39fd458c02a810045c497dc77ad1917636055319","unresolved":false,"context_lines":[{"line_number":62,"context_line":"    except jsonschema.ValidationError:"},{"line_number":63,"context_line":"        raise webob.exc.HTTPBadRequest("},{"line_number":64,"context_line":"            _(\u0027The trait is invalid. The valid trait must include prefix\u0027"},{"line_number":65,"context_line":"              \u0027\"CUSTOM_\". The valid characters are \"A\"-\"Z\", \"0\"-\"9\" and \"_\"\u0027))"},{"line_number":66,"context_line":""},{"line_number":67,"context_line":"    trait \u003d objects.Trait(context)"},{"line_number":68,"context_line":"    trait.name \u003d name"}],"source_content_type":"text/x-python","patch_set":10,"id":"fa31d9ce_52ce0c84","line":65,"updated":"2017-02-17 14:54:48.000000000","message":"json_formatter is left off here, but if you use the new wrapper mentioned above it\u0027s no longer needed","commit_id":"082b203e48de9ddd284f79f24711a5e31bda8609"},{"author":{"_account_id":11564,"name":"Chris Dent","email":"cdent@anticdent.org","username":"chdent"},"change_message_id":"39fd458c02a810045c497dc77ad1917636055319","unresolved":false,"context_lines":[{"line_number":71,"context_line":"    except exception.TraitExists as ex:"},{"line_number":72,"context_line":"        raise webob.exc.HTTPBadRequest("},{"line_number":73,"context_line":"                explanation\u003dex.format_message(),"},{"line_number":74,"context_line":"                json_formatter\u003dutil.json_error_formatter)"},{"line_number":75,"context_line":""},{"line_number":76,"context_line":"    req.response.status \u003d 204"},{"line_number":77,"context_line":"    req.response.content_type \u003d None"}],"source_content_type":"text/x-python","patch_set":10,"id":"fa31d9ce_b2a58848","line":74,"updated":"2017-02-17 14:54:48.000000000","message":"can go when the new wrapper is in place. I\u0027ll not mark the others but safe to say that json_formatter arg is no longer needed throughout this file if the new wrapper is being used.","commit_id":"082b203e48de9ddd284f79f24711a5e31bda8609"},{"author":{"_account_id":6062,"name":"jichenjc","email":"jichenjc@cn.ibm.com","username":"jichenjc"},"change_message_id":"88592042b585a318c0df580042960b76023624b9","unresolved":false,"context_lines":[{"line_number":73,"context_line":"                explanation\u003dex.format_message(),"},{"line_number":74,"context_line":"                json_formatter\u003dutil.json_error_formatter)"},{"line_number":75,"context_line":""},{"line_number":76,"context_line":"    req.response.status \u003d 204"},{"line_number":77,"context_line":"    req.response.content_type \u003d None"},{"line_number":78,"context_line":"    req.response.location \u003d util.trait_url(req.environ, trait)"},{"line_number":79,"context_line":"    return req.response"}],"source_content_type":"text/x-python","patch_set":10,"id":"fa31d9ce_8eba29bf","line":76,"range":{"start_line":76,"start_character":26,"end_line":76,"end_character":29},"updated":"2017-02-17 10:35:12.000000000","message":"seems tag return 201 here\nhttps://github.com/openstack/nova/blob/master/nova/api/openstack/compute/server_tags.py#L123","commit_id":"082b203e48de9ddd284f79f24711a5e31bda8609"},{"author":{"_account_id":11564,"name":"Chris Dent","email":"cdent@anticdent.org","username":"chdent"},"change_message_id":"39fd458c02a810045c497dc77ad1917636055319","unresolved":false,"context_lines":[{"line_number":80,"context_line":""},{"line_number":81,"context_line":""},{"line_number":82,"context_line":"@webob.dec.wsgify"},{"line_number":83,"context_line":"def get_trait(req):"},{"line_number":84,"context_line":"    context \u003d req.environ[\u0027placement.context\u0027]"},{"line_number":85,"context_line":"    name \u003d util.wsgi_path_item(req.environ, \u0027name\u0027)"},{"line_number":86,"context_line":""}],"source_content_type":"text/x-python","patch_set":10,"id":"fa31d9ce_32151849","line":83,"updated":"2017-02-17 14:54:48.000000000","message":"I think it would be useful to explain that an empty body is what\u0027s expected here and what this method does is verify the existing of the trait.","commit_id":"082b203e48de9ddd284f79f24711a5e31bda8609"},{"author":{"_account_id":11564,"name":"Chris Dent","email":"cdent@anticdent.org","username":"chdent"},"change_message_id":"39fd458c02a810045c497dc77ad1917636055319","unresolved":false,"context_lines":[{"line_number":89,"context_line":"    except exception.TraitNotFound as ex:"},{"line_number":90,"context_line":"        raise webob.exc.HTTPBadRequest("},{"line_number":91,"context_line":"            explanation\u003dex.format_message(),"},{"line_number":92,"context_line":"            json_formatter\u003dutil.json_error_formatter)"},{"line_number":93,"context_line":""},{"line_number":94,"context_line":"    req.response.status \u003d 204"},{"line_number":95,"context_line":"    req.response.content_type \u003d None"}],"source_content_type":"text/x-python","patch_set":10,"id":"fa31d9ce_126d7404","line":92,"updated":"2017-02-17 14:54:48.000000000","message":"can go","commit_id":"082b203e48de9ddd284f79f24711a5e31bda8609"},{"author":{"_account_id":11564,"name":"Chris Dent","email":"cdent@anticdent.org","username":"chdent"},"change_message_id":"39fd458c02a810045c497dc77ad1917636055319","unresolved":false,"context_lines":[{"line_number":126,"context_line":"    if \u0027traits\u0027 in req.GET:"},{"line_number":127,"context_line":"        filters[\u0027traits\u0027] \u003d req.GET.get(\u0027traits\u0027).split(\u0027,\u0027)"},{"line_number":128,"context_line":"    if \u0027namespace\u0027 in req.GET:"},{"line_number":129,"context_line":"        filters[\u0027namespace\u0027] \u003d req.GET.get(\u0027namespace\u0027)"},{"line_number":130,"context_line":""},{"line_number":131,"context_line":"    try:"},{"line_number":132,"context_line":"        traits \u003d objects.TraitList.get_all(context, filters)"}],"source_content_type":"text/x-python","patch_set":10,"id":"fa31d9ce_357182a9","line":129,"updated":"2017-02-17 14:54:48.000000000","message":"jsonschema for queries was introduced in  Ia8b534d20c064eb3a767f95ca22814925acfaa77 so we should use that here too.","commit_id":"082b203e48de9ddd284f79f24711a5e31bda8609"},{"author":{"_account_id":5754,"name":"Alex Xu","email":"hejie.xu@intel.com","username":"xuhj"},"change_message_id":"f0903111505f2c4df01e66070acedb034ff2ae43","unresolved":false,"context_lines":[{"line_number":149,"context_line":"    try:"},{"line_number":150,"context_line":"        traits \u003d objects.TraitList.update_all(context, traits)"},{"line_number":151,"context_line":"    except exception.TraitCannotUpdateStandard as ex:"},{"line_number":152,"context_line":"        raise webob.exc.HTTPBadRequest("},{"line_number":153,"context_line":"            explanation\u003dex.format_message(),"},{"line_number":154,"context_line":"            json_formatter\u003dutil.json_error_formatter)"},{"line_number":155,"context_line":""}],"source_content_type":"text/x-python","patch_set":10,"id":"fa31d9ce_80abb11c","line":152,"range":{"start_line":152,"start_character":15,"end_line":152,"end_character":39},"updated":"2017-02-13 07:44:43.000000000","message":"this should be 409\u0027\n\nAnd TraitInUse need to be catch.","commit_id":"082b203e48de9ddd284f79f24711a5e31bda8609"},{"author":{"_account_id":1063,"name":"Ed Leafe","email":"ed@leafe.com","username":"ed-leafe"},"change_message_id":"51fecea79345c95fa18df4a90366d9f351b529d3","unresolved":false,"context_lines":[{"line_number":87,"context_line":"def _serialize_traits(traits):"},{"line_number":88,"context_line":"    ret \u003d {\u0027traits\u0027: []}"},{"line_number":89,"context_line":"    for trait in traits:"},{"line_number":90,"context_line":"        ret[\u0027traits\u0027].append(trait.name)"},{"line_number":91,"context_line":"    return ret"},{"line_number":92,"context_line":""},{"line_number":93,"context_line":""}],"source_content_type":"text/x-python","patch_set":19,"id":"1a1ced50_fde31e03","line":90,"updated":"2017-03-20 19:58:14.000000000","message":"How about we do this as:\n\n    trait_list \u003d [trait.name for trait in traits]\n    return {\"traits\": trait_list}\n\nOr, if you want to get fancy and do a one-liner:\n\n    return {\"traits\": [trait.name for trait in traits]}","commit_id":"a273d29bd1611816d16edb1d1d61b9116b8529a8"},{"author":{"_account_id":5754,"name":"Alex Xu","email":"hejie.xu@intel.com","username":"xuhj"},"change_message_id":"676c037b29fb7bcaee57e1219b33ea3fc37c1ecd","unresolved":false,"context_lines":[{"line_number":87,"context_line":"def _serialize_traits(traits):"},{"line_number":88,"context_line":"    ret \u003d {\u0027traits\u0027: []}"},{"line_number":89,"context_line":"    for trait in traits:"},{"line_number":90,"context_line":"        ret[\u0027traits\u0027].append(trait.name)"},{"line_number":91,"context_line":"    return ret"},{"line_number":92,"context_line":""},{"line_number":93,"context_line":""}],"source_content_type":"text/x-python","patch_set":19,"id":"1a1ced50_46ea59ad","line":90,"in_reply_to":"1a1ced50_fde31e03","updated":"2017-03-22 12:38:36.000000000","message":"yea, let me do a one-liner","commit_id":"a273d29bd1611816d16edb1d1d61b9116b8529a8"},{"author":{"_account_id":11564,"name":"Chris Dent","email":"cdent@anticdent.org","username":"chdent"},"change_message_id":"8d710a8f2fb402b84d658fddba01c525fda18dd9","unresolved":false,"context_lines":[{"line_number":91,"context_line":"    return ret"},{"line_number":92,"context_line":""},{"line_number":93,"context_line":""},{"line_number":94,"context_line":"def _extra_traits(body, schema):"},{"line_number":95,"context_line":"    data \u003d util.extract_json(body, schema)"},{"line_number":96,"context_line":"    return data[\u0027traits\u0027]"},{"line_number":97,"context_line":""}],"source_content_type":"text/x-python","patch_set":19,"id":"1a1ced50_e778ec2d","line":94,"updated":"2017-03-20 21:18:51.000000000","message":"This method doesn\u0027t look like it is being used, and if it were I think you probably meant the name _extract_traits","commit_id":"a273d29bd1611816d16edb1d1d61b9116b8529a8"},{"author":{"_account_id":5754,"name":"Alex Xu","email":"hejie.xu@intel.com","username":"xuhj"},"change_message_id":"676c037b29fb7bcaee57e1219b33ea3fc37c1ecd","unresolved":false,"context_lines":[{"line_number":91,"context_line":"    return ret"},{"line_number":92,"context_line":""},{"line_number":93,"context_line":""},{"line_number":94,"context_line":"def _extra_traits(body, schema):"},{"line_number":95,"context_line":"    data \u003d util.extract_json(body, schema)"},{"line_number":96,"context_line":"    return data[\u0027traits\u0027]"},{"line_number":97,"context_line":""}],"source_content_type":"text/x-python","patch_set":19,"id":"1a1ced50_a6d94d24","line":94,"in_reply_to":"1a1ced50_e778ec2d","updated":"2017-03-22 12:38:36.000000000","message":"yea, this is used by put /traits, but that api is removed. then I forget remove this one.","commit_id":"a273d29bd1611816d16edb1d1d61b9116b8529a8"},{"author":{"_account_id":1063,"name":"Ed Leafe","email":"ed@leafe.com","username":"ed-leafe"},"change_message_id":"51fecea79345c95fa18df4a90366d9f351b529d3","unresolved":false,"context_lines":[{"line_number":106,"context_line":"        jsonschema.validate(name, CUSTOM_TRAIT)"},{"line_number":107,"context_line":"    except jsonschema.ValidationError:"},{"line_number":108,"context_line":"        raise webob.exc.HTTPBadRequest("},{"line_number":109,"context_line":"            _(\u0027The trait is invalid. The valid trait must include prefix \u0027"},{"line_number":110,"context_line":"              \u0027\"CUSTOM_\". The valid characters are \"A\"-\"Z\", \"0\"-\"9\" and \"_\"\u0027))"},{"line_number":111,"context_line":""},{"line_number":112,"context_line":"    trait \u003d objects.Trait(context)"}],"source_content_type":"text/x-python","patch_set":19,"id":"1a1ced50_5d899225","line":109,"range":{"start_line":109,"start_character":37,"end_line":109,"end_character":41},"updated":"2017-03-20 19:58:14.000000000","message":"s/The/A","commit_id":"a273d29bd1611816d16edb1d1d61b9116b8529a8"},{"author":{"_account_id":5754,"name":"Alex Xu","email":"hejie.xu@intel.com","username":"xuhj"},"change_message_id":"676c037b29fb7bcaee57e1219b33ea3fc37c1ecd","unresolved":false,"context_lines":[{"line_number":106,"context_line":"        jsonschema.validate(name, CUSTOM_TRAIT)"},{"line_number":107,"context_line":"    except jsonschema.ValidationError:"},{"line_number":108,"context_line":"        raise webob.exc.HTTPBadRequest("},{"line_number":109,"context_line":"            _(\u0027The trait is invalid. The valid trait must include prefix \u0027"},{"line_number":110,"context_line":"              \u0027\"CUSTOM_\". The valid characters are \"A\"-\"Z\", \"0\"-\"9\" and \"_\"\u0027))"},{"line_number":111,"context_line":""},{"line_number":112,"context_line":"    trait \u003d objects.Trait(context)"}],"source_content_type":"text/x-python","patch_set":19,"id":"1a1ced50_c6d649f0","line":109,"range":{"start_line":109,"start_character":37,"end_line":109,"end_character":41},"in_reply_to":"1a1ced50_5d899225","updated":"2017-03-22 12:38:36.000000000","message":"Done","commit_id":"a273d29bd1611816d16edb1d1d61b9116b8529a8"},{"author":{"_account_id":11564,"name":"Chris Dent","email":"cdent@anticdent.org","username":"chdent"},"change_message_id":"8d710a8f2fb402b84d658fddba01c525fda18dd9","unresolved":false,"context_lines":[{"line_number":107,"context_line":"    except jsonschema.ValidationError:"},{"line_number":108,"context_line":"        raise webob.exc.HTTPBadRequest("},{"line_number":109,"context_line":"            _(\u0027The trait is invalid. The valid trait must include prefix \u0027"},{"line_number":110,"context_line":"              \u0027\"CUSTOM_\". The valid characters are \"A\"-\"Z\", \"0\"-\"9\" and \"_\"\u0027))"},{"line_number":111,"context_line":""},{"line_number":112,"context_line":"    trait \u003d objects.Trait(context)"},{"line_number":113,"context_line":"    trait.name \u003d name"}],"source_content_type":"text/x-python","patch_set":19,"id":"1a1ced50_c7cbf051","line":110,"updated":"2017-03-20 21:18:51.000000000","message":"I\u0027d change it a bit more than that:\n\nThe trait is invalid. A valid trait must include the prefix \"CUSTOM_\" and use the following characters: \"A\"-\"Z\", \"0\"-\"9\" and \"_\"\n\nor something more like that","commit_id":"a273d29bd1611816d16edb1d1d61b9116b8529a8"},{"author":{"_account_id":5754,"name":"Alex Xu","email":"hejie.xu@intel.com","username":"xuhj"},"change_message_id":"676c037b29fb7bcaee57e1219b33ea3fc37c1ecd","unresolved":false,"context_lines":[{"line_number":107,"context_line":"    except jsonschema.ValidationError:"},{"line_number":108,"context_line":"        raise webob.exc.HTTPBadRequest("},{"line_number":109,"context_line":"            _(\u0027The trait is invalid. The valid trait must include prefix \u0027"},{"line_number":110,"context_line":"              \u0027\"CUSTOM_\". The valid characters are \"A\"-\"Z\", \"0\"-\"9\" and \"_\"\u0027))"},{"line_number":111,"context_line":""},{"line_number":112,"context_line":"    trait \u003d objects.Trait(context)"},{"line_number":113,"context_line":"    trait.name \u003d name"}],"source_content_type":"text/x-python","patch_set":19,"id":"1a1ced50_662835e3","line":110,"in_reply_to":"1a1ced50_c7cbf051","updated":"2017-03-22 12:38:36.000000000","message":"Done","commit_id":"a273d29bd1611816d16edb1d1d61b9116b8529a8"},{"author":{"_account_id":11564,"name":"Chris Dent","email":"cdent@anticdent.org","username":"chdent"},"change_message_id":"8d710a8f2fb402b84d658fddba01c525fda18dd9","unresolved":false,"context_lines":[{"line_number":154,"context_line":"            explanation\u003dex.format_message())"},{"line_number":155,"context_line":"    except exception.TraitCannotDeleteStandard as ex:"},{"line_number":156,"context_line":"        raise webob.exc.HTTPBadRequest("},{"line_number":157,"context_line":"            explanation\u003dex.format_message())"},{"line_number":158,"context_line":""},{"line_number":159,"context_line":"    req.response.status \u003d 204"},{"line_number":160,"context_line":"    req.response.content_type \u003d None"}],"source_content_type":"text/x-python","patch_set":19,"id":"1a1ced50_677ddce6","line":157,"updated":"2017-03-20 21:18:51.000000000","message":"Does there need to be an exception for the case when a trait is in use (meaning associated with at least one resource provider) and thus cannot be deleted?\n\nYeah, we need to catch TraitInUse here, and raise a 409?","commit_id":"a273d29bd1611816d16edb1d1d61b9116b8529a8"},{"author":{"_account_id":5754,"name":"Alex Xu","email":"hejie.xu@intel.com","username":"xuhj"},"change_message_id":"676c037b29fb7bcaee57e1219b33ea3fc37c1ecd","unresolved":false,"context_lines":[{"line_number":154,"context_line":"            explanation\u003dex.format_message())"},{"line_number":155,"context_line":"    except exception.TraitCannotDeleteStandard as ex:"},{"line_number":156,"context_line":"        raise webob.exc.HTTPBadRequest("},{"line_number":157,"context_line":"            explanation\u003dex.format_message())"},{"line_number":158,"context_line":""},{"line_number":159,"context_line":"    req.response.status \u003d 204"},{"line_number":160,"context_line":"    req.response.content_type \u003d None"}],"source_content_type":"text/x-python","patch_set":19,"id":"1a1ced50_0667814d","line":157,"in_reply_to":"1a1ced50_677ddce6","updated":"2017-03-22 12:38:36.000000000","message":"ah, yes, i missed that one.","commit_id":"a273d29bd1611816d16edb1d1d61b9116b8529a8"},{"author":{"_account_id":1063,"name":"Ed Leafe","email":"ed@leafe.com","username":"ed-leafe"},"change_message_id":"51fecea79345c95fa18df4a90366d9f351b529d3","unresolved":false,"context_lines":[{"line_number":228,"context_line":""},{"line_number":229,"context_line":"    if resource_provider.generation !\u003d rp_gen:"},{"line_number":230,"context_line":"        raise webob.exc.HTTPConflict("},{"line_number":231,"context_line":"            _(\u0027resource provider generation conflict\u0027),"},{"line_number":232,"context_line":"            json_formatter\u003dutil.json_error_formatter)"},{"line_number":233,"context_line":""},{"line_number":234,"context_line":"    try:"}],"source_content_type":"text/x-python","patch_set":19,"id":"1a1ced50_bd39a643","line":231,"range":{"start_line":231,"start_character":15,"end_line":231,"end_character":52},"updated":"2017-03-20 19:58:14.000000000","message":"I\u0027d prefer a more descriptive error message, such as \"Someone else has modified the resource provider \u0027%s\u0027. Please update and re-try your request.\"","commit_id":"a273d29bd1611816d16edb1d1d61b9116b8529a8"},{"author":{"_account_id":5754,"name":"Alex Xu","email":"hejie.xu@intel.com","username":"xuhj"},"change_message_id":"676c037b29fb7bcaee57e1219b33ea3fc37c1ecd","unresolved":false,"context_lines":[{"line_number":228,"context_line":""},{"line_number":229,"context_line":"    if resource_provider.generation !\u003d rp_gen:"},{"line_number":230,"context_line":"        raise webob.exc.HTTPConflict("},{"line_number":231,"context_line":"            _(\u0027resource provider generation conflict\u0027),"},{"line_number":232,"context_line":"            json_formatter\u003dutil.json_error_formatter)"},{"line_number":233,"context_line":""},{"line_number":234,"context_line":"    try:"}],"source_content_type":"text/x-python","patch_set":19,"id":"1a1ced50_e1b7afd5","line":231,"range":{"start_line":231,"start_character":15,"end_line":231,"end_character":52},"in_reply_to":"1a1ced50_bd39a643","updated":"2017-03-22 12:38:36.000000000","message":"Done","commit_id":"a273d29bd1611816d16edb1d1d61b9116b8529a8"},{"author":{"_account_id":6167,"name":"Ken\u0027ichi Ohmichi","email":"ken1ohmichi@gmail.com","username":"oomichi"},"change_message_id":"6a5016d41636579aae4473c47bb39ac37e4f76e6","unresolved":false,"context_lines":[{"line_number":256,"context_line":"    resource_provider.set_traits(objects.TraitList(objects\u003d[]))"},{"line_number":257,"context_line":""},{"line_number":258,"context_line":"    req.response.status \u003d 204"},{"line_number":259,"context_line":"    req.response.content_type \u003d \u0027application/json\u0027"},{"line_number":260,"context_line":"    return req.response"}],"source_content_type":"text/x-python","patch_set":20,"id":"1a1ced50_fb9e5861","line":259,"range":{"start_line":259,"start_character":4,"end_line":259,"end_character":50},"updated":"2017-03-22 23:34:41.000000000","message":"The code is 204(No Content), so we don\u0027t need to specify content_type.","commit_id":"24d3370afaf7a5bfdf6b7054f1095f1da3c68ef5"},{"author":{"_account_id":5754,"name":"Alex Xu","email":"hejie.xu@intel.com","username":"xuhj"},"change_message_id":"c7f745c0672808672e8e76ef195f01ee0997857f","unresolved":false,"context_lines":[{"line_number":256,"context_line":"    resource_provider.set_traits(objects.TraitList(objects\u003d[]))"},{"line_number":257,"context_line":""},{"line_number":258,"context_line":"    req.response.status \u003d 204"},{"line_number":259,"context_line":"    req.response.content_type \u003d \u0027application/json\u0027"},{"line_number":260,"context_line":"    return req.response"}],"source_content_type":"text/x-python","patch_set":20,"id":"1a1ced50_e51a36c5","line":259,"range":{"start_line":259,"start_character":4,"end_line":259,"end_character":50},"in_reply_to":"1a1ced50_fb9e5861","updated":"2017-03-23 02:12:56.000000000","message":"nice catch!","commit_id":"24d3370afaf7a5bfdf6b7054f1095f1da3c68ef5"},{"author":{"_account_id":6167,"name":"Ken\u0027ichi Ohmichi","email":"ken1ohmichi@gmail.com","username":"oomichi"},"change_message_id":"5f5b8209008843143e428a35046ee920f360bfc6","unresolved":false,"context_lines":[{"line_number":98,"context_line":"        jsonschema.validate(name, CUSTOM_TRAIT)"},{"line_number":99,"context_line":"    except jsonschema.ValidationError:"},{"line_number":100,"context_line":"        raise webob.exc.HTTPBadRequest("},{"line_number":101,"context_line":"            _(\u0027The trait is invalid. A valid trait must include prefix \u0027"},{"line_number":102,"context_line":"              \u0027\"CUSTOM_\" and use following characters: \"A\"-\"Z\", \"0\"-\"9\" and \u0027"},{"line_number":103,"context_line":"              \u0027\"_\"\u0027))"},{"line_number":104,"context_line":""},{"line_number":105,"context_line":"    trait \u003d objects.Trait(context)"},{"line_number":106,"context_line":"    trait.name \u003d name"}],"source_content_type":"text/x-python","patch_set":22,"id":"ffe62b97_884c3b77","line":103,"range":{"start_line":101,"start_character":14,"end_line":103,"end_character":19},"updated":"2017-03-23 20:47:36.000000000","message":"ValidationError could show the detail error message, so why don\u0027t we use it instead of this hard-coded message?\nI feel this message will be fragile in long-term maintenance.","commit_id":"92885a8f394d5e23d735526f1539be69e4ac51a7"},{"author":{"_account_id":5754,"name":"Alex Xu","email":"hejie.xu@intel.com","username":"xuhj"},"change_message_id":"92e0b8e54091fe7b4cf103cb14fff080facc5cc9","unresolved":false,"context_lines":[{"line_number":98,"context_line":"        jsonschema.validate(name, CUSTOM_TRAIT)"},{"line_number":99,"context_line":"    except jsonschema.ValidationError:"},{"line_number":100,"context_line":"        raise webob.exc.HTTPBadRequest("},{"line_number":101,"context_line":"            _(\u0027The trait is invalid. A valid trait must include prefix \u0027"},{"line_number":102,"context_line":"              \u0027\"CUSTOM_\" and use following characters: \"A\"-\"Z\", \"0\"-\"9\" and \u0027"},{"line_number":103,"context_line":"              \u0027\"_\"\u0027))"},{"line_number":104,"context_line":""},{"line_number":105,"context_line":"    trait \u003d objects.Trait(context)"},{"line_number":106,"context_line":"    trait.name \u003d name"}],"source_content_type":"text/x-python","patch_set":22,"id":"ffe62b97_9aeafa72","line":103,"range":{"start_line":101,"start_character":14,"end_line":103,"end_character":19},"in_reply_to":"ffe62b97_884c3b77","updated":"2017-03-26 10:29:59.000000000","message":"Yea, we have consistent error message in the nova rest API. Actually I copy this from the resource class API, it also provide a custom message, have to say it is more readable than the ValidationError one.","commit_id":"92885a8f394d5e23d735526f1539be69e4ac51a7"},{"author":{"_account_id":6167,"name":"Ken\u0027ichi Ohmichi","email":"ken1ohmichi@gmail.com","username":"oomichi"},"change_message_id":"5f5b8209008843143e428a35046ee920f360bfc6","unresolved":false,"context_lines":[{"line_number":109,"context_line":"        trait.create()"},{"line_number":110,"context_line":"        req.response.status \u003d 201"},{"line_number":111,"context_line":"    except exception.TraitExists:"},{"line_number":112,"context_line":"        req.response.status \u003d 204"},{"line_number":113,"context_line":""},{"line_number":114,"context_line":"    req.response.content_type \u003d None"},{"line_number":115,"context_line":"    req.response.location \u003d util.trait_url(req.environ, trait)"}],"source_content_type":"text/x-python","patch_set":22,"id":"ffe62b97_88bb1be4","line":112,"range":{"start_line":112,"start_character":8,"end_line":112,"end_character":33},"updated":"2017-03-23 20:47:36.000000000","message":"I never see this kind of different status code.\nIn most cases in Nova, this case could be 409(conflict).\nBut I guess this 204 intentionally comes from the api-wg guideline:\n\n * If a request attempts to put a resource into a state which it is\n   already in (for example, locking an instance which is already locked), the\n   return code should be in the **2xx Successful** range (usually matching the\n   return code which would be given if the state had changed). It is not\n   appropriate to use **409 Conflict** when the resulting state of the resource\n   is as the user requested.\n\nI just wanted to confirm this status code at this time.","commit_id":"92885a8f394d5e23d735526f1539be69e4ac51a7"},{"author":{"_account_id":5754,"name":"Alex Xu","email":"hejie.xu@intel.com","username":"xuhj"},"change_message_id":"92e0b8e54091fe7b4cf103cb14fff080facc5cc9","unresolved":false,"context_lines":[{"line_number":109,"context_line":"        trait.create()"},{"line_number":110,"context_line":"        req.response.status \u003d 201"},{"line_number":111,"context_line":"    except exception.TraitExists:"},{"line_number":112,"context_line":"        req.response.status \u003d 204"},{"line_number":113,"context_line":""},{"line_number":114,"context_line":"    req.response.content_type \u003d None"},{"line_number":115,"context_line":"    req.response.location \u003d util.trait_url(req.environ, trait)"}],"source_content_type":"text/x-python","patch_set":22,"id":"ffe62b97_3aff6e35","line":112,"range":{"start_line":112,"start_character":8,"end_line":112,"end_character":33},"in_reply_to":"ffe62b97_88bb1be4","updated":"2017-03-26 10:29:59.000000000","message":"This is suggested by Chris https://review.openstack.org/#/c/345138/23@436\n\nIt is about to have a idempotent API.","commit_id":"92885a8f394d5e23d735526f1539be69e4ac51a7"},{"author":{"_account_id":7,"name":"Jay Pipes","email":"jaypipes@gmail.com","username":"jaypipes"},"change_message_id":"6f1ad85216421959eda399b9c9c5fa9a8b512586","unresolved":false,"context_lines":[{"line_number":48,"context_line":"SET_TRAITS_FOR_RP_SCHEMA \u003d copy.deepcopy(PUT_TRAITS_SCHEMA)"},{"line_number":49,"context_line":"SET_TRAITS_FOR_RP_SCHEMA[\u0027properties\u0027][\u0027traits\u0027][\u0027items\u0027] \u003d TRAIT"},{"line_number":50,"context_line":"SET_TRAITS_FOR_RP_SCHEMA[\u0027properties\u0027]["},{"line_number":51,"context_line":"    \u0027resource_provider_generation\u0027] \u003d {\u0027type\u0027: \u0027integer\u0027}"},{"line_number":52,"context_line":""},{"line_number":53,"context_line":""},{"line_number":54,"context_line":"LIST_TRAIT_SCHEMA \u003d {"}],"source_content_type":"text/x-python","patch_set":26,"id":"ffe62b97_01f25d9a","line":51,"updated":"2017-03-29 19:47:41.000000000","message":"Anything that references resource providers should be in /api/openstack/placement/handlers/resource_provider.py","commit_id":"7a6ff8d185ac6830e0e6a3725a8046f28321c8ff"},{"author":{"_account_id":5754,"name":"Alex Xu","email":"hejie.xu@intel.com","username":"xuhj"},"change_message_id":"21123dd7486a6022d99fdd7b2b5dac883a1cfbd9","unresolved":false,"context_lines":[{"line_number":48,"context_line":"SET_TRAITS_FOR_RP_SCHEMA \u003d copy.deepcopy(PUT_TRAITS_SCHEMA)"},{"line_number":49,"context_line":"SET_TRAITS_FOR_RP_SCHEMA[\u0027properties\u0027][\u0027traits\u0027][\u0027items\u0027] \u003d TRAIT"},{"line_number":50,"context_line":"SET_TRAITS_FOR_RP_SCHEMA[\u0027properties\u0027]["},{"line_number":51,"context_line":"    \u0027resource_provider_generation\u0027] \u003d {\u0027type\u0027: \u0027integer\u0027}"},{"line_number":52,"context_line":""},{"line_number":53,"context_line":""},{"line_number":54,"context_line":"LIST_TRAIT_SCHEMA \u003d {"}],"source_content_type":"text/x-python","patch_set":26,"id":"ffe62b97_3bdb464f","line":51,"in_reply_to":"ffe62b97_01f25d9a","updated":"2017-03-30 03:15:32.000000000","message":"Emm....the \u0027/resource_providers/{uuid}/allocations\u0027 and the \u0027/resource_providers/{uuid}/inventories\u0027 aren\u0027t in the resource_provider.py also.\n\nBut I can do that, let me know if that is really the thing you like it.","commit_id":"7a6ff8d185ac6830e0e6a3725a8046f28321c8ff"},{"author":{"_account_id":7,"name":"Jay Pipes","email":"jaypipes@gmail.com","username":"jaypipes"},"change_message_id":"6f1ad85216421959eda399b9c9c5fa9a8b512586","unresolved":false,"context_lines":[{"line_number":189,"context_line":"    req.response.content_type \u003d \u0027application/json\u0027"},{"line_number":190,"context_line":"    return req.response"},{"line_number":191,"context_line":""},{"line_number":192,"context_line":""},{"line_number":193,"context_line":"@wsgi_wrapper.PlacementWsgify"},{"line_number":194,"context_line":"@microversion.version_handler(\u00271.6\u0027)"},{"line_number":195,"context_line":"@util.check_accept(\u0027application/json\u0027)"}],"source_content_type":"text/x-python","patch_set":26,"id":"ffe62b97_414185a8","line":192,"updated":"2017-03-29 19:47:41.000000000","message":"Anything that references resource providers should be in /api/openstack/placement/handlers/resource_provider.py","commit_id":"7a6ff8d185ac6830e0e6a3725a8046f28321c8ff"},{"author":{"_account_id":11564,"name":"Chris Dent","email":"cdent@anticdent.org","username":"chdent"},"change_message_id":"851ac94c5f241ed3cc1b11b842405b88a3ad08ee","unresolved":false,"context_lines":[{"line_number":69,"context_line":"    try:"},{"line_number":70,"context_line":"        op, value \u003d qs.split(\u0027:\u0027, 1)"},{"line_number":71,"context_line":"    except ValueError:"},{"line_number":72,"context_line":"        msg \u003d _(\u0027Badly format name parameter. Expected name query string \u0027"},{"line_number":73,"context_line":"                \u0027parameter in form: \u0027"},{"line_number":74,"context_line":"                \u0027?name\u003d[in|starts_with]:[name1,name2|prefix]. Got: \"%s\"\u0027)"},{"line_number":75,"context_line":"        msg \u003d msg % qs"}],"source_content_type":"text/x-python","patch_set":28,"id":"dfeb2761_071ebfb9","line":72,"updated":"2017-03-31 11:26:24.000000000","message":"s/format/formatted/","commit_id":"a7bcb493917900d1610b7447b991668ee05abf3a"},{"author":{"_account_id":5754,"name":"Alex Xu","email":"hejie.xu@intel.com","username":"xuhj"},"change_message_id":"718615f3ffcaef7548fff521c093770f87d5f936","unresolved":false,"context_lines":[{"line_number":69,"context_line":"    try:"},{"line_number":70,"context_line":"        op, value \u003d qs.split(\u0027:\u0027, 1)"},{"line_number":71,"context_line":"    except ValueError:"},{"line_number":72,"context_line":"        msg \u003d _(\u0027Badly format name parameter. Expected name query string \u0027"},{"line_number":73,"context_line":"                \u0027parameter in form: \u0027"},{"line_number":74,"context_line":"                \u0027?name\u003d[in|starts_with]:[name1,name2|prefix]. Got: \"%s\"\u0027)"},{"line_number":75,"context_line":"        msg \u003d msg % qs"}],"source_content_type":"text/x-python","patch_set":28,"id":"bff0334d_9f7693d8","line":72,"in_reply_to":"dfeb2761_071ebfb9","updated":"2017-04-06 07:38:30.000000000","message":"Done","commit_id":"a7bcb493917900d1610b7447b991668ee05abf3a"},{"author":{"_account_id":7,"name":"Jay Pipes","email":"jaypipes@gmail.com","username":"jaypipes"},"change_message_id":"39ef66537c32c453a6881dc97555e4ff24c7f1b1","unresolved":false,"context_lines":[{"line_number":71,"context_line":"    except ValueError:"},{"line_number":72,"context_line":"        msg \u003d _(\u0027Badly format name parameter. Expected name query string \u0027"},{"line_number":73,"context_line":"                \u0027parameter in form: \u0027"},{"line_number":74,"context_line":"                \u0027?name\u003d[in|starts_with]:[name1,name2|prefix]. Got: \"%s\"\u0027)"},{"line_number":75,"context_line":"        msg \u003d msg % qs"},{"line_number":76,"context_line":"        raise webob.exc.HTTPBadRequest(msg)"},{"line_number":77,"context_line":""}],"source_content_type":"text/x-python","patch_set":28,"id":"dfeb2761_f07a6586","line":74,"updated":"2017-03-31 19:28:09.000000000","message":"It\u0027s \"startswith\", not \"starts_with\"","commit_id":"a7bcb493917900d1610b7447b991668ee05abf3a"},{"author":{"_account_id":5754,"name":"Alex Xu","email":"hejie.xu@intel.com","username":"xuhj"},"change_message_id":"718615f3ffcaef7548fff521c093770f87d5f936","unresolved":false,"context_lines":[{"line_number":71,"context_line":"    except ValueError:"},{"line_number":72,"context_line":"        msg \u003d _(\u0027Badly format name parameter. Expected name query string \u0027"},{"line_number":73,"context_line":"                \u0027parameter in form: \u0027"},{"line_number":74,"context_line":"                \u0027?name\u003d[in|starts_with]:[name1,name2|prefix]. Got: \"%s\"\u0027)"},{"line_number":75,"context_line":"        msg \u003d msg % qs"},{"line_number":76,"context_line":"        raise webob.exc.HTTPBadRequest(msg)"},{"line_number":77,"context_line":""}],"source_content_type":"text/x-python","patch_set":28,"id":"bff0334d_7f73cfe8","line":74,"in_reply_to":"dfeb2761_f07a6586","updated":"2017-04-06 07:38:30.000000000","message":"Done","commit_id":"a7bcb493917900d1610b7447b991668ee05abf3a"},{"author":{"_account_id":7,"name":"Jay Pipes","email":"jaypipes@gmail.com","username":"jaypipes"},"change_message_id":"39ef66537c32c453a6881dc97555e4ff24c7f1b1","unresolved":false,"context_lines":[{"line_number":160,"context_line":"@wsgi_wrapper.PlacementWsgify"},{"line_number":161,"context_line":"@microversion.version_handler(\u00271.6\u0027)"},{"line_number":162,"context_line":"@util.check_accept(\u0027application/json\u0027)"},{"line_number":163,"context_line":"def list_all_traits(req):"},{"line_number":164,"context_line":"    context \u003d req.environ[\u0027placement.context\u0027]"},{"line_number":165,"context_line":"    filters \u003d {}"},{"line_number":166,"context_line":""}],"source_content_type":"text/x-python","patch_set":28,"id":"dfeb2761_f09f05b2","line":163,"updated":"2017-03-31 19:28:09.000000000","message":"To be consistent with other handlers, this should be \"list_traits\", not \"list_all_traits\":\n\nhttps://github.com/openstack/nova/blob/master/nova/api/openstack/placement/handlers/resource_provider.py#L250","commit_id":"a7bcb493917900d1610b7447b991668ee05abf3a"},{"author":{"_account_id":5754,"name":"Alex Xu","email":"hejie.xu@intel.com","username":"xuhj"},"change_message_id":"718615f3ffcaef7548fff521c093770f87d5f936","unresolved":false,"context_lines":[{"line_number":160,"context_line":"@wsgi_wrapper.PlacementWsgify"},{"line_number":161,"context_line":"@microversion.version_handler(\u00271.6\u0027)"},{"line_number":162,"context_line":"@util.check_accept(\u0027application/json\u0027)"},{"line_number":163,"context_line":"def list_all_traits(req):"},{"line_number":164,"context_line":"    context \u003d req.environ[\u0027placement.context\u0027]"},{"line_number":165,"context_line":"    filters \u003d {}"},{"line_number":166,"context_line":""}],"source_content_type":"text/x-python","patch_set":28,"id":"bff0334d_3f7d47b1","line":163,"in_reply_to":"dfeb2761_f09f05b2","updated":"2017-04-06 07:38:30.000000000","message":"Done","commit_id":"a7bcb493917900d1610b7447b991668ee05abf3a"},{"author":{"_account_id":7,"name":"Jay Pipes","email":"jaypipes@gmail.com","username":"jaypipes"},"change_message_id":"39ef66537c32c453a6881dc97555e4ff24c7f1b1","unresolved":false,"context_lines":[{"line_number":182,"context_line":"        filters[\u0027associated\u0027] \u003d ("},{"line_number":183,"context_line":"            True if req.GET[\u0027associated\u0027].lower() \u003d\u003d \u0027true\u0027 else False)"},{"line_number":184,"context_line":""},{"line_number":185,"context_line":"    traits \u003d objects.TraitList.get_all(context, filters)"},{"line_number":186,"context_line":"    req.response.status \u003d 200"},{"line_number":187,"context_line":"    req.response.body \u003d encodeutils.to_utf8("},{"line_number":188,"context_line":"        jsonutils.dumps(_serialize_traits(traits)))"}],"source_content_type":"text/x-python","patch_set":28,"id":"dfeb2761_90dc3975","line":185,"updated":"2017-03-31 19:28:09.000000000","message":"The TraitList.get_all() method should be renamed to get_all_by_filters() to be consistent with other methods that accept a set of filters:\n\nhttps://github.com/openstack/nova/blob/master/nova/api/openstack/placement/handlers/resource_provider.py#L297\n\nThe ResourceClass.get_all() method does not accept a list of filters and therefore isn\u0027t named get_all_by_filters()","commit_id":"a7bcb493917900d1610b7447b991668ee05abf3a"},{"author":{"_account_id":5754,"name":"Alex Xu","email":"hejie.xu@intel.com","username":"xuhj"},"change_message_id":"718615f3ffcaef7548fff521c093770f87d5f936","unresolved":false,"context_lines":[{"line_number":182,"context_line":"        filters[\u0027associated\u0027] \u003d ("},{"line_number":183,"context_line":"            True if req.GET[\u0027associated\u0027].lower() \u003d\u003d \u0027true\u0027 else False)"},{"line_number":184,"context_line":""},{"line_number":185,"context_line":"    traits \u003d objects.TraitList.get_all(context, filters)"},{"line_number":186,"context_line":"    req.response.status \u003d 200"},{"line_number":187,"context_line":"    req.response.body \u003d encodeutils.to_utf8("},{"line_number":188,"context_line":"        jsonutils.dumps(_serialize_traits(traits)))"}],"source_content_type":"text/x-python","patch_set":28,"id":"bff0334d_df453b72","line":185,"in_reply_to":"dfeb2761_90dc3975","updated":"2017-04-06 07:38:30.000000000","message":"I will rename this in later patch.","commit_id":"a7bcb493917900d1610b7447b991668ee05abf3a"},{"author":{"_account_id":11564,"name":"Chris Dent","email":"cdent@anticdent.org","username":"chdent"},"change_message_id":"851ac94c5f241ed3cc1b11b842405b88a3ad08ee","unresolved":false,"context_lines":[{"line_number":231,"context_line":"    try:"},{"line_number":232,"context_line":"        trait_objs \u003d objects.TraitList.get_all("},{"line_number":233,"context_line":"            context, filters\u003d{\u0027traits\u0027: traits})"},{"line_number":234,"context_line":"    except exception.CacheStrNotFound as ex:"},{"line_number":235,"context_line":"        raise webob.exc.HTTPBadRequest("},{"line_number":236,"context_line":"            explanation\u003dex.format_message())"},{"line_number":237,"context_line":""}],"source_content_type":"text/x-python","patch_set":28,"id":"dfeb2761_077d9fb0","line":234,"updated":"2017-03-31 11:26:24.000000000","message":"It\u0027s non-obvious from this exception name what the problem was here. Maybe add a comment?","commit_id":"a7bcb493917900d1610b7447b991668ee05abf3a"},{"author":{"_account_id":5754,"name":"Alex Xu","email":"hejie.xu@intel.com","username":"xuhj"},"change_message_id":"718615f3ffcaef7548fff521c093770f87d5f936","unresolved":false,"context_lines":[{"line_number":231,"context_line":"    try:"},{"line_number":232,"context_line":"        trait_objs \u003d objects.TraitList.get_all("},{"line_number":233,"context_line":"            context, filters\u003d{\u0027traits\u0027: traits})"},{"line_number":234,"context_line":"    except exception.CacheStrNotFound as ex:"},{"line_number":235,"context_line":"        raise webob.exc.HTTPBadRequest("},{"line_number":236,"context_line":"            explanation\u003dex.format_message())"},{"line_number":237,"context_line":""}],"source_content_type":"text/x-python","patch_set":28,"id":"bff0334d_5f592b58","line":234,"in_reply_to":"dfeb2761_077d9fb0","updated":"2017-04-06 07:38:30.000000000","message":"oops, this should be removed, as we removed the cache layer now.","commit_id":"a7bcb493917900d1610b7447b991668ee05abf3a"},{"author":{"_account_id":11564,"name":"Chris Dent","email":"cdent@anticdent.org","username":"chdent"},"change_message_id":"851ac94c5f241ed3cc1b11b842405b88a3ad08ee","unresolved":false,"context_lines":[{"line_number":253,"context_line":"    uuid \u003d util.wsgi_path_item(req.environ, \u0027uuid\u0027)"},{"line_number":254,"context_line":""},{"line_number":255,"context_line":"    resource_provider \u003d objects.ResourceProvider.get_by_uuid(context, uuid)"},{"line_number":256,"context_line":"    resource_provider.set_traits(objects.TraitList(objects\u003d[]))"},{"line_number":257,"context_line":""},{"line_number":258,"context_line":"    req.response.status \u003d 204"},{"line_number":259,"context_line":"    req.response.content_type \u003d None"}],"source_content_type":"text/x-python","patch_set":28,"id":"dfeb2761_820d1d39","line":256,"updated":"2017-03-31 11:26:24.000000000","message":"There\u0027s a slim chance that  exception.ConcurrentUpdateDetected could happen during these two lines of code if some other process manages to update the resource provider between lines 255 and 256, thus changing the generation. It\u0027s unlikely, but we should guard against it by catching the exception and turning it into an HTTPConflict.","commit_id":"a7bcb493917900d1610b7447b991668ee05abf3a"},{"author":{"_account_id":5754,"name":"Alex Xu","email":"hejie.xu@intel.com","username":"xuhj"},"change_message_id":"718615f3ffcaef7548fff521c093770f87d5f936","unresolved":false,"context_lines":[{"line_number":253,"context_line":"    uuid \u003d util.wsgi_path_item(req.environ, \u0027uuid\u0027)"},{"line_number":254,"context_line":""},{"line_number":255,"context_line":"    resource_provider \u003d objects.ResourceProvider.get_by_uuid(context, uuid)"},{"line_number":256,"context_line":"    resource_provider.set_traits(objects.TraitList(objects\u003d[]))"},{"line_number":257,"context_line":""},{"line_number":258,"context_line":"    req.response.status \u003d 204"},{"line_number":259,"context_line":"    req.response.content_type \u003d None"}],"source_content_type":"text/x-python","patch_set":28,"id":"bff0334d_1f31630c","line":256,"in_reply_to":"dfeb2761_1005c9c2","updated":"2017-04-06 07:38:30.000000000","message":"Yea, thanks Chris","commit_id":"a7bcb493917900d1610b7447b991668ee05abf3a"},{"author":{"_account_id":7,"name":"Jay Pipes","email":"jaypipes@gmail.com","username":"jaypipes"},"change_message_id":"39ef66537c32c453a6881dc97555e4ff24c7f1b1","unresolved":false,"context_lines":[{"line_number":253,"context_line":"    uuid \u003d util.wsgi_path_item(req.environ, \u0027uuid\u0027)"},{"line_number":254,"context_line":""},{"line_number":255,"context_line":"    resource_provider \u003d objects.ResourceProvider.get_by_uuid(context, uuid)"},{"line_number":256,"context_line":"    resource_provider.set_traits(objects.TraitList(objects\u003d[]))"},{"line_number":257,"context_line":""},{"line_number":258,"context_line":"    req.response.status \u003d 204"},{"line_number":259,"context_line":"    req.response.content_type \u003d None"}],"source_content_type":"text/x-python","patch_set":28,"id":"dfeb2761_1005c9c2","line":256,"in_reply_to":"dfeb2761_820d1d39","updated":"2017-03-31 19:28:09.000000000","message":"Yes, nice catch Chris.","commit_id":"a7bcb493917900d1610b7447b991668ee05abf3a"},{"author":{"_account_id":7,"name":"Jay Pipes","email":"jaypipes@gmail.com","username":"jaypipes"},"change_message_id":"779dd5a659798b441ae740d1164179f0b47fdcf1","unresolved":false,"context_lines":[{"line_number":177,"context_line":"        filters \u003d _normalize_traits_qs_param(req.GET[\u0027name\u0027])"},{"line_number":178,"context_line":"    if \u0027associated\u0027 in req.GET:"},{"line_number":179,"context_line":"        if req.GET[\u0027associated\u0027].lower() not in [\u0027true\u0027, \u0027false\u0027]:"},{"line_number":180,"context_line":"            raise webob.exc.HTTPBadRequest("},{"line_number":181,"context_line":"                explanation\u003d_(\u0027The query parameter \"associated\" only accepts \u0027"},{"line_number":182,"context_line":"                              \u0027\"true\" or \"false\"\u0027))"},{"line_number":183,"context_line":"        filters[\u0027associated\u0027] \u003d ("}],"source_content_type":"text/x-python","patch_set":30,"id":"bff0334d_bf5e7e41","line":180,"updated":"2017-04-10 14:11:29.000000000","message":"This conditional and 400 response needs a functional test added.","commit_id":"a3ac699a62dc5a40357a67355d388ea40e0a64d7"},{"author":{"_account_id":5754,"name":"Alex Xu","email":"hejie.xu@intel.com","username":"xuhj"},"change_message_id":"64b6bb281954292ae5b55f38c912d3ab5a3290ef","unresolved":false,"context_lines":[{"line_number":177,"context_line":"        filters \u003d _normalize_traits_qs_param(req.GET[\u0027name\u0027])"},{"line_number":178,"context_line":"    if \u0027associated\u0027 in req.GET:"},{"line_number":179,"context_line":"        if req.GET[\u0027associated\u0027].lower() not in [\u0027true\u0027, \u0027false\u0027]:"},{"line_number":180,"context_line":"            raise webob.exc.HTTPBadRequest("},{"line_number":181,"context_line":"                explanation\u003d_(\u0027The query parameter \"associated\" only accepts \u0027"},{"line_number":182,"context_line":"                              \u0027\"true\" or \"false\"\u0027))"},{"line_number":183,"context_line":"        filters[\u0027associated\u0027] \u003d ("}],"source_content_type":"text/x-python","patch_set":30,"id":"bff0334d_f8776ad3","line":180,"in_reply_to":"bff0334d_bf5e7e41","updated":"2017-04-11 02:11:08.000000000","message":"Done","commit_id":"a3ac699a62dc5a40357a67355d388ea40e0a64d7"},{"author":{"_account_id":11564,"name":"Chris Dent","email":"cdent@anticdent.org","username":"chdent"},"change_message_id":"ae5c39ca923cf1e9c048ae4634a6cfe339144490","unresolved":false,"context_lines":[{"line_number":176,"context_line":"    if \u0027name\u0027 in req.GET:"},{"line_number":177,"context_line":"        filters \u003d _normalize_traits_qs_param(req.GET[\u0027name\u0027])"},{"line_number":178,"context_line":"    if \u0027associated\u0027 in req.GET:"},{"line_number":179,"context_line":"        if req.GET[\u0027associated\u0027].lower() not in [\u0027true\u0027, \u0027false\u0027]:"},{"line_number":180,"context_line":"            raise webob.exc.HTTPBadRequest("},{"line_number":181,"context_line":"                explanation\u003d_(\u0027The query parameter \"associated\" only accepts \u0027"},{"line_number":182,"context_line":"                              \u0027\"true\" or \"false\"\u0027))"}],"source_content_type":"text/x-python","patch_set":31,"id":"bff0334d_4fb8c0e3","line":179,"updated":"2017-04-11 11:29:24.000000000","message":"I had a moment of wondering if we could use jsonschema enum for this, but apparently there\u0027s no good solution for case-insensitivity.","commit_id":"9c975b6bd803ecca2e37082251247d356f4027fe"}],"nova/api/openstack/placement/microversion.py":[{"author":{"_account_id":7,"name":"Jay Pipes","email":"jaypipes@gmail.com","username":"jaypipes"},"change_message_id":"6f1ad85216421959eda399b9c9c5fa9a8b512586","unresolved":false,"context_lines":[{"line_number":41,"context_line":"            # that are members of any of the listed aggregates"},{"line_number":42,"context_line":"    \u00271.4\u0027,  # Adds resources query string parameter in GET /resource_providers"},{"line_number":43,"context_line":"    \u00271.5\u0027,  # Adds DELETE /resource_providers/{uuid}/inventories"},{"line_number":44,"context_line":"    \u00271.6\u0027,  # Adds /traits resource endpoint"},{"line_number":45,"context_line":"]"},{"line_number":46,"context_line":""},{"line_number":47,"context_line":""}],"source_content_type":"text/x-python","patch_set":26,"id":"ffe62b97_21256109","line":44,"updated":"2017-03-29 19:47:41.000000000","message":"It\u0027s not *just* the new /traits resource endpoint that is added in this patch. There is also the new /resource_providers/{uuid}/traits resource endpoint.","commit_id":"7a6ff8d185ac6830e0e6a3725a8046f28321c8ff"},{"author":{"_account_id":5754,"name":"Alex Xu","email":"hejie.xu@intel.com","username":"xuhj"},"change_message_id":"21123dd7486a6022d99fdd7b2b5dac883a1cfbd9","unresolved":false,"context_lines":[{"line_number":41,"context_line":"            # that are members of any of the listed aggregates"},{"line_number":42,"context_line":"    \u00271.4\u0027,  # Adds resources query string parameter in GET /resource_providers"},{"line_number":43,"context_line":"    \u00271.5\u0027,  # Adds DELETE /resource_providers/{uuid}/inventories"},{"line_number":44,"context_line":"    \u00271.6\u0027,  # Adds /traits resource endpoint"},{"line_number":45,"context_line":"]"},{"line_number":46,"context_line":""},{"line_number":47,"context_line":""}],"source_content_type":"text/x-python","patch_set":26,"id":"ffe62b97_db945a8d","line":44,"in_reply_to":"ffe62b97_21256109","updated":"2017-03-30 03:15:32.000000000","message":"Done","commit_id":"7a6ff8d185ac6830e0e6a3725a8046f28321c8ff"},{"author":{"_account_id":11564,"name":"Chris Dent","email":"cdent@anticdent.org","username":"chdent"},"change_message_id":"851ac94c5f241ed3cc1b11b842405b88a3ad08ee","unresolved":false,"context_lines":[{"line_number":42,"context_line":"    \u00271.4\u0027,  # Adds resources query string parameter in GET /resource_providers"},{"line_number":43,"context_line":"    \u00271.5\u0027,  # Adds DELETE /resource_providers/{uuid}/inventories"},{"line_number":44,"context_line":"    \u00271.6\u0027,  # Adds /traits and /resource_providers{uuid}/traits resource"},{"line_number":45,"context_line":"            # endpoint"},{"line_number":46,"context_line":"]"},{"line_number":47,"context_line":""},{"line_number":48,"context_line":""}],"source_content_type":"text/x-python","patch_set":28,"id":"dfeb2761_02190d78","line":45,"updated":"2017-03-31 11:26:24.000000000","message":"endpoints","commit_id":"a7bcb493917900d1610b7447b991668ee05abf3a"}],"nova/api/openstack/placement/rest_api_version_history.rst":[{"author":{"_account_id":6167,"name":"Ken\u0027ichi Ohmichi","email":"ken1ohmichi@gmail.com","username":"oomichi"},"change_message_id":"5f5b8209008843143e428a35046ee920f360bfc6","unresolved":false,"context_lines":[{"line_number":101,"context_line":""},{"line_number":102,"context_line":"* GET /traits: Returns all resource classes."},{"line_number":103,"context_line":"* PUT /trait/{trait_name}: To insert a single custom trait."},{"line_number":104,"context_line":"* GET /trait/{trait_name}: To check if a trait name exists."},{"line_number":105,"context_line":"* DELETE /trait/{trait_name}: To delete the specified trait."},{"line_number":106,"context_line":"* GET /resource_providers/{uuid}/traits: a list of traits associated"},{"line_number":107,"context_line":"  with a specific resource provider"}],"source_content_type":"text/x-rst","patch_set":22,"id":"ffe62b97_8889db27","line":104,"range":{"start_line":104,"start_character":2,"end_line":104,"end_character":59},"updated":"2017-03-23 20:47:36.000000000","message":"If we just want the existence of resource, HEAD could be accurate.","commit_id":"92885a8f394d5e23d735526f1539be69e4ac51a7"},{"author":{"_account_id":7,"name":"Jay Pipes","email":"jaypipes@gmail.com","username":"jaypipes"},"change_message_id":"6f1ad85216421959eda399b9c9c5fa9a8b512586","unresolved":false,"context_lines":[{"line_number":100,"context_line":"The following new routes are added:"},{"line_number":101,"context_line":""},{"line_number":102,"context_line":"* GET /traits: Returns all resource classes."},{"line_number":103,"context_line":"* PUT /trait/{trait_name}: To insert a single custom trait."},{"line_number":104,"context_line":"* GET /trait/{trait_name}: To check if a trait name exists."},{"line_number":105,"context_line":"* DELETE /trait/{trait_name}: To delete the specified trait."},{"line_number":106,"context_line":"* GET /resource_providers/{uuid}/traits: a list of traits associated"}],"source_content_type":"text/x-rst","patch_set":26,"id":"ffe62b97_c17b55f2","line":103,"updated":"2017-03-29 19:47:41.000000000","message":"Should be:\n\n PUT /traits/{trait_name}","commit_id":"7a6ff8d185ac6830e0e6a3725a8046f28321c8ff"},{"author":{"_account_id":7,"name":"Jay Pipes","email":"jaypipes@gmail.com","username":"jaypipes"},"change_message_id":"6f1ad85216421959eda399b9c9c5fa9a8b512586","unresolved":false,"context_lines":[{"line_number":101,"context_line":""},{"line_number":102,"context_line":"* GET /traits: Returns all resource classes."},{"line_number":103,"context_line":"* PUT /trait/{trait_name}: To insert a single custom trait."},{"line_number":104,"context_line":"* GET /trait/{trait_name}: To check if a trait name exists."},{"line_number":105,"context_line":"* DELETE /trait/{trait_name}: To delete the specified trait."},{"line_number":106,"context_line":"* GET /resource_providers/{uuid}/traits: a list of traits associated"},{"line_number":107,"context_line":"  with a specific resource provider"}],"source_content_type":"text/x-rst","patch_set":26,"id":"ffe62b97_216a0119","line":104,"updated":"2017-03-29 19:47:41.000000000","message":"Should be:\n\n GET /traits/{trait_name}","commit_id":"7a6ff8d185ac6830e0e6a3725a8046f28321c8ff"},{"author":{"_account_id":7,"name":"Jay Pipes","email":"jaypipes@gmail.com","username":"jaypipes"},"change_message_id":"6f1ad85216421959eda399b9c9c5fa9a8b512586","unresolved":false,"context_lines":[{"line_number":102,"context_line":"* GET /traits: Returns all resource classes."},{"line_number":103,"context_line":"* PUT /trait/{trait_name}: To insert a single custom trait."},{"line_number":104,"context_line":"* GET /trait/{trait_name}: To check if a trait name exists."},{"line_number":105,"context_line":"* DELETE /trait/{trait_name}: To delete the specified trait."},{"line_number":106,"context_line":"* GET /resource_providers/{uuid}/traits: a list of traits associated"},{"line_number":107,"context_line":"  with a specific resource provider"},{"line_number":108,"context_line":"* PUT /resource_providers/{uuid}/traits: Set all the traits for a"}],"source_content_type":"text/x-rst","patch_set":26,"id":"ffe62b97_a167314d","line":105,"updated":"2017-03-29 19:47:41.000000000","message":"Should be:\n\n DELETE /traits/{trait_name}","commit_id":"7a6ff8d185ac6830e0e6a3725a8046f28321c8ff"},{"author":{"_account_id":11564,"name":"Chris Dent","email":"cdent@anticdent.org","username":"chdent"},"change_message_id":"851ac94c5f241ed3cc1b11b842405b88a3ad08ee","unresolved":false,"context_lines":[{"line_number":101,"context_line":""},{"line_number":102,"context_line":"* GET /traits: Returns all resource classes."},{"line_number":103,"context_line":"* PUT /traits/{trait_name}: To insert a single custom trait."},{"line_number":104,"context_line":"* GET /traits/{trait_name}: To check if a trait name exists."},{"line_number":105,"context_line":"* DELETE /traits/{trait_name}: To delete the specified trait."},{"line_number":106,"context_line":"* GET /resource_providers/{uuid}/traits: a list of traits associated"},{"line_number":107,"context_line":"  with a specific resource provider"}],"source_content_type":"text/x-rst","patch_set":28,"id":"dfeb2761_623b39d1","line":104,"updated":"2017-03-31 11:26:24.000000000","message":"Same comment as on commit message.","commit_id":"a7bcb493917900d1610b7447b991668ee05abf3a"}],"nova/tests/functional/api/openstack/placement/gabbits/traits.yaml":[{"author":{"_account_id":11564,"name":"Chris Dent","email":"cdent@anticdent.org","username":"chdent"},"change_message_id":"39fd458c02a810045c497dc77ad1917636055319","unresolved":false,"context_lines":[{"line_number":15,"context_line":"  data:"},{"line_number":16,"context_line":"    traits:"},{"line_number":17,"context_line":"        - abcde"},{"line_number":18,"context_line":"  status: 400"},{"line_number":19,"context_line":""},{"line_number":20,"context_line":"- name: put traits without custom namespace"},{"line_number":21,"context_line":"  PUT: /traits"}],"source_content_type":"text/x-yaml","patch_set":10,"id":"fa31d9ce_55c43691","line":18,"updated":"2017-02-17 14:54:48.000000000","message":"When checking error responses, it\u0027s usually good to also check response_strings to make sure what\u0027s expected in the error message is there:\n\n   response_strings:\n      - some expected string","commit_id":"082b203e48de9ddd284f79f24711a5e31bda8609"},{"author":{"_account_id":11564,"name":"Chris Dent","email":"cdent@anticdent.org","username":"chdent"},"change_message_id":"39fd458c02a810045c497dc77ad1917636055319","unresolved":false,"context_lines":[{"line_number":47,"context_line":"  status: 200"},{"line_number":48,"context_line":"  response_strings:"},{"line_number":49,"context_line":"    - CUSTOM:TRAIT:A"},{"line_number":50,"context_line":"    - CUSTOM:TRAIT:B"},{"line_number":51,"context_line":""},{"line_number":52,"context_line":"- name: what is at traits"},{"line_number":53,"context_line":"  GET: /traits"}],"source_content_type":"text/x-yaml","patch_set":10,"id":"fa31d9ce_95030eb8","line":50,"updated":"2017-02-17 14:54:48.000000000","message":"If you want to get measure of the structure of the json being returned, then using response_json_paths may be more useful here. If things like ordering are a problem there are ways to do sorts:\n\nhttp://gabbi.readthedocs.io/en/latest/jsonpath.html","commit_id":"082b203e48de9ddd284f79f24711a5e31bda8609"},{"author":{"_account_id":5754,"name":"Alex Xu","email":"hejie.xu@intel.com","username":"xuhj"},"change_message_id":"1af4739b0ffd576bf78791b6026c95a1462dbfd1","unresolved":false,"context_lines":[{"line_number":12,"context_line":"- name: create a trait without custom namespace"},{"line_number":13,"context_line":"  PUT: /traits/TRAIT_X"},{"line_number":14,"context_line":"  request_headers:"},{"line_number":15,"context_line":"    content-type: application/json"},{"line_number":16,"context_line":"  status: 400"},{"line_number":17,"context_line":"  response_strings:"},{"line_number":18,"context_line":"    - The trait is invalid. The valid trait must include prefix \"CUSTOM_\". The valid characters are \"A\"-\"Z\", \"0\"-\"9\" and \"_\""}],"source_content_type":"text/x-yaml","patch_set":15,"id":"9a30ddce_9b1e3f0a","line":15,"range":{"start_line":15,"start_character":4,"end_line":15,"end_character":34},"updated":"2017-03-13 02:54:11.000000000","message":"I have to send this header even without body.","commit_id":"759f923569043734c44d2ba4523b50a2f9a1cf29"},{"author":{"_account_id":5754,"name":"Alex Xu","email":"hejie.xu@intel.com","username":"xuhj"},"change_message_id":"9efc60f38b5f112c5a6a434a91f3b2f7a4fff07c","unresolved":false,"context_lines":[{"line_number":37,"context_line":""},{"line_number":38,"context_line":"- name: create a trait which existed"},{"line_number":39,"context_line":"  PUT: /traits/CUSTOM_TRAIT_1"},{"line_number":40,"context_line":"  request_headers:"},{"line_number":41,"context_line":"    content-type: application/json"},{"line_number":42,"context_line":"  status: 204"},{"line_number":43,"context_line":"  response_headers:"},{"line_number":44,"context_line":"    location: //traits/CUSTOM_TRAIT_1/"}],"source_content_type":"text/x-yaml","patch_set":19,"id":"1a1ced50_dc2f5a3c","line":41,"range":{"start_line":40,"start_character":2,"end_line":41,"end_character":34},"updated":"2017-03-20 12:19:43.000000000","message":"I have to send a http header \u0027content-type\u0027 even without request body.\n\nIs that correct? I will try to mention this in the scheduler meeting","commit_id":"a273d29bd1611816d16edb1d1d61b9116b8529a8"},{"author":{"_account_id":11564,"name":"Chris Dent","email":"cdent@anticdent.org","username":"chdent"},"change_message_id":"657248af147cf628ddf63fdfe91696284e8d0224","unresolved":false,"context_lines":[{"line_number":38,"context_line":"- name: create a trait which existed"},{"line_number":39,"context_line":"  PUT: /traits/CUSTOM_TRAIT_1"},{"line_number":40,"context_line":"  request_headers:"},{"line_number":41,"context_line":"    content-type: application/json"},{"line_number":42,"context_line":"  status: 204"},{"line_number":43,"context_line":"  response_headers:"},{"line_number":44,"context_line":"    location: //traits/CUSTOM_TRAIT_1/"}],"source_content_type":"text/x-yaml","patch_set":19,"id":"1a1ced50_84365650","line":41,"in_reply_to":"1a1ced50_5d96f2f0","updated":"2017-03-20 20:45:57.000000000","message":"https://review.openstack.org/#/c/447625/ fixes it","commit_id":"a273d29bd1611816d16edb1d1d61b9116b8529a8"},{"author":{"_account_id":1063,"name":"Ed Leafe","email":"ed@leafe.com","username":"ed-leafe"},"change_message_id":"51fecea79345c95fa18df4a90366d9f351b529d3","unresolved":false,"context_lines":[{"line_number":37,"context_line":""},{"line_number":38,"context_line":"- name: create a trait which existed"},{"line_number":39,"context_line":"  PUT: /traits/CUSTOM_TRAIT_1"},{"line_number":40,"context_line":"  request_headers:"},{"line_number":41,"context_line":"    content-type: application/json"},{"line_number":42,"context_line":"  status: 204"},{"line_number":43,"context_line":"  response_headers:"},{"line_number":44,"context_line":"    location: //traits/CUSTOM_TRAIT_1/"}],"source_content_type":"text/x-yaml","patch_set":19,"id":"1a1ced50_5d96f2f0","line":41,"range":{"start_line":40,"start_character":2,"end_line":41,"end_character":34},"in_reply_to":"1a1ced50_cb1b0e7f","updated":"2017-03-20 19:58:14.000000000","message":"As discussed in the scheduler meeting, we should not be rejecting requests without a content-type when the request has no content.","commit_id":"a273d29bd1611816d16edb1d1d61b9116b8529a8"},{"author":{"_account_id":7166,"name":"Sylvain Bauza","email":"sbauza@redhat.com","username":"sbauza"},"change_message_id":"2ebf80827d1c6114a9573d2beaca0b96f4d28875","unresolved":false,"context_lines":[{"line_number":37,"context_line":""},{"line_number":38,"context_line":"- name: create a trait which existed"},{"line_number":39,"context_line":"  PUT: /traits/CUSTOM_TRAIT_1"},{"line_number":40,"context_line":"  request_headers:"},{"line_number":41,"context_line":"    content-type: application/json"},{"line_number":42,"context_line":"  status: 204"},{"line_number":43,"context_line":"  response_headers:"},{"line_number":44,"context_line":"    location: //traits/CUSTOM_TRAIT_1/"}],"source_content_type":"text/x-yaml","patch_set":19,"id":"1a1ced50_cb1b0e7f","line":41,"range":{"start_line":40,"start_character":2,"end_line":41,"end_character":34},"in_reply_to":"1a1ced50_dc2f5a3c","updated":"2017-03-20 14:25:35.000000000","message":"As I tried to guess during the IRC meeting, I think it\u0027s related to the RFC, in particular https://tools.ietf.org/html/rfc7231#section-3.1.1.5 where it\u0027s asked to implementers to try not guessing the content type, but rather having it always explicit.\n\nI\u0027ll leave Chris bite my explanation if he disagrees with it :-)","commit_id":"a273d29bd1611816d16edb1d1d61b9116b8529a8"},{"author":{"_account_id":5754,"name":"Alex Xu","email":"hejie.xu@intel.com","username":"xuhj"},"change_message_id":"9efc60f38b5f112c5a6a434a91f3b2f7a4fff07c","unresolved":false,"context_lines":[{"line_number":50,"context_line":"  status: 204"},{"line_number":51,"context_line":"  response_forbidden_headers:"},{"line_number":52,"context_line":"      - content-type"},{"line_number":53,"context_line":"  "},{"line_number":54,"context_line":"- name: get a non-existed trait"},{"line_number":55,"context_line":"  GET: /traits/NON_EXISTED"},{"line_number":56,"context_line":"  status: 404"}],"source_content_type":"text/x-yaml","patch_set":19,"id":"1a1ced50_dc083adc","line":53,"updated":"2017-03-20 12:19:43.000000000","message":"A useless blankspace","commit_id":"a273d29bd1611816d16edb1d1d61b9116b8529a8"},{"author":{"_account_id":7,"name":"Jay Pipes","email":"jaypipes@gmail.com","username":"jaypipes"},"change_message_id":"6f1ad85216421959eda399b9c9c5fa9a8b512586","unresolved":false,"context_lines":[{"line_number":81,"context_line":"    - CUSTOM_TRAIT_2"},{"line_number":82,"context_line":""},{"line_number":83,"context_line":"- name: list traits with invalid format of name parameter"},{"line_number":84,"context_line":"  GET: /traits?name\u003din_abc"},{"line_number":85,"context_line":"  status: 400"},{"line_number":86,"context_line":"  response_strings:"},{"line_number":87,"context_line":"    - \u0027Badly format name parameter. Expected name query string parameter in form: ?name\u003d[in|startswith]:[name1,name2|prefix]. Got: \"in_abc\"\u0027"}],"source_content_type":"text/x-yaml","patch_set":26,"id":"ffe62b97_5c0a8e1f","line":84,"updated":"2017-03-29 19:47:41.000000000","message":"What if the user wanted to search for a trait called \"in_abc\"?","commit_id":"7a6ff8d185ac6830e0e6a3725a8046f28321c8ff"},{"author":{"_account_id":5754,"name":"Alex Xu","email":"hejie.xu@intel.com","username":"xuhj"},"change_message_id":"21123dd7486a6022d99fdd7b2b5dac883a1cfbd9","unresolved":false,"context_lines":[{"line_number":81,"context_line":"    - CUSTOM_TRAIT_2"},{"line_number":82,"context_line":""},{"line_number":83,"context_line":"- name: list traits with invalid format of name parameter"},{"line_number":84,"context_line":"  GET: /traits?name\u003din_abc"},{"line_number":85,"context_line":"  status: 400"},{"line_number":86,"context_line":"  response_strings:"},{"line_number":87,"context_line":"    - \u0027Badly format name parameter. Expected name query string parameter in form: ?name\u003d[in|startswith]:[name1,name2|prefix]. Got: \"in_abc\"\u0027"}],"source_content_type":"text/x-yaml","patch_set":26,"id":"ffe62b97_fbdefe6a","line":84,"in_reply_to":"ffe62b97_5c0a8e1f","updated":"2017-03-30 03:15:32.000000000","message":"The user should input \u0027GET /traits?name\u003din:in_abc\u0027","commit_id":"7a6ff8d185ac6830e0e6a3725a8046f28321c8ff"},{"author":{"_account_id":7,"name":"Jay Pipes","email":"jaypipes@gmail.com","username":"jaypipes"},"change_message_id":"6f1ad85216421959eda399b9c9c5fa9a8b512586","unresolved":false,"context_lines":[{"line_number":84,"context_line":"  GET: /traits?name\u003din_abc"},{"line_number":85,"context_line":"  status: 400"},{"line_number":86,"context_line":"  response_strings:"},{"line_number":87,"context_line":"    - \u0027Badly format name parameter. Expected name query string parameter in form: ?name\u003d[in|startswith]:[name1,name2|prefix]. Got: \"in_abc\"\u0027"},{"line_number":88,"context_line":""},{"line_number":89,"context_line":"- name: list traits with name\u003din filter"},{"line_number":90,"context_line":"  GET: /traits?name\u003din:CUSTOM_TRAIT_1,CUSTOM_TRAIT_2"}],"source_content_type":"text/x-yaml","patch_set":26,"id":"ffe62b97_9c2db696","line":87,"updated":"2017-03-29 19:47:41.000000000","message":"The above response string says \"startswith\" but the below uses \"starts_with\".","commit_id":"7a6ff8d185ac6830e0e6a3725a8046f28321c8ff"},{"author":{"_account_id":5754,"name":"Alex Xu","email":"hejie.xu@intel.com","username":"xuhj"},"change_message_id":"21123dd7486a6022d99fdd7b2b5dac883a1cfbd9","unresolved":false,"context_lines":[{"line_number":84,"context_line":"  GET: /traits?name\u003din_abc"},{"line_number":85,"context_line":"  status: 400"},{"line_number":86,"context_line":"  response_strings:"},{"line_number":87,"context_line":"    - \u0027Badly format name parameter. Expected name query string parameter in form: ?name\u003d[in|startswith]:[name1,name2|prefix]. Got: \"in_abc\"\u0027"},{"line_number":88,"context_line":""},{"line_number":89,"context_line":"- name: list traits with name\u003din filter"},{"line_number":90,"context_line":"  GET: /traits?name\u003din:CUSTOM_TRAIT_1,CUSTOM_TRAIT_2"}],"source_content_type":"text/x-yaml","patch_set":26,"id":"ffe62b97_3bca26a0","line":87,"in_reply_to":"ffe62b97_9c2db696","updated":"2017-03-30 03:15:32.000000000","message":"oops, I will fix the inconsistent.","commit_id":"7a6ff8d185ac6830e0e6a3725a8046f28321c8ff"},{"author":{"_account_id":11564,"name":"Chris Dent","email":"cdent@anticdent.org","username":"chdent"},"change_message_id":"851ac94c5f241ed3cc1b11b842405b88a3ad08ee","unresolved":false,"context_lines":[{"line_number":190,"context_line":"    - CUSTOM_TRAIT_1"},{"line_number":191,"context_line":"    - CUSTOM_TRAIT_2"},{"line_number":192,"context_line":""},{"line_number":193,"context_line":"- name: delete a in-use trait"},{"line_number":194,"context_line":"  DELETE: /traits/CUSTOM_TRAIT_1"},{"line_number":195,"context_line":"  status: 409"},{"line_number":196,"context_line":"  response_strings:"}],"source_content_type":"text/x-yaml","patch_set":28,"id":"dfeb2761_224ad154","line":193,"updated":"2017-03-31 11:26:24.000000000","message":"an","commit_id":"a7bcb493917900d1610b7447b991668ee05abf3a"}],"releasenotes/notes/placement-traits-api-efa17d46ea1b616b.yaml":[{"author":{"_account_id":7,"name":"Jay Pipes","email":"jaypipes@gmail.com","username":"jaypipes"},"change_message_id":"6f1ad85216421959eda399b9c9c5fa9a8b512586","unresolved":false,"context_lines":[{"line_number":4,"context_line":"    The Traits API is added in the placement with Microversion 1.6."},{"line_number":5,"context_line":""},{"line_number":6,"context_line":"    * GET /traits: Returns all resource classes."},{"line_number":7,"context_line":"    * PUT /trait/{trait_name}: To insert a single custom trait."},{"line_number":8,"context_line":"    * GET /trait/{trait_name}: To check if a trait name exists."},{"line_number":9,"context_line":"    * DELETE /trait/{trait_name}: To delete the specified trait."},{"line_number":10,"context_line":"    * GET /resource_providers/{uuid}/traits: a list of traits associated"}],"source_content_type":"text/x-yaml","patch_set":26,"id":"ffe62b97_5c5baef4","line":7,"updated":"2017-03-29 19:47:41.000000000","message":"Should be:\n\n PUT /traits/{trait_name}","commit_id":"7a6ff8d185ac6830e0e6a3725a8046f28321c8ff"},{"author":{"_account_id":7,"name":"Jay Pipes","email":"jaypipes@gmail.com","username":"jaypipes"},"change_message_id":"6f1ad85216421959eda399b9c9c5fa9a8b512586","unresolved":false,"context_lines":[{"line_number":5,"context_line":""},{"line_number":6,"context_line":"    * GET /traits: Returns all resource classes."},{"line_number":7,"context_line":"    * PUT /trait/{trait_name}: To insert a single custom trait."},{"line_number":8,"context_line":"    * GET /trait/{trait_name}: To check if a trait name exists."},{"line_number":9,"context_line":"    * DELETE /trait/{trait_name}: To delete the specified trait."},{"line_number":10,"context_line":"    * GET /resource_providers/{uuid}/traits: a list of traits associated"},{"line_number":11,"context_line":"      with a specific resource provider"}],"source_content_type":"text/x-yaml","patch_set":26,"id":"ffe62b97_1cf646d8","line":8,"updated":"2017-03-29 19:47:41.000000000","message":"Should be:\n\n GET /traits/{trait_name}","commit_id":"7a6ff8d185ac6830e0e6a3725a8046f28321c8ff"},{"author":{"_account_id":7,"name":"Jay Pipes","email":"jaypipes@gmail.com","username":"jaypipes"},"change_message_id":"6f1ad85216421959eda399b9c9c5fa9a8b512586","unresolved":false,"context_lines":[{"line_number":6,"context_line":"    * GET /traits: Returns all resource classes."},{"line_number":7,"context_line":"    * PUT /trait/{trait_name}: To insert a single custom trait."},{"line_number":8,"context_line":"    * GET /trait/{trait_name}: To check if a trait name exists."},{"line_number":9,"context_line":"    * DELETE /trait/{trait_name}: To delete the specified trait."},{"line_number":10,"context_line":"    * GET /resource_providers/{uuid}/traits: a list of traits associated"},{"line_number":11,"context_line":"      with a specific resource provider"},{"line_number":12,"context_line":"    * PUT /resource_providers/{uuid}/traits: Set all the traits for a"}],"source_content_type":"text/x-yaml","patch_set":26,"id":"ffe62b97_5c296e34","line":9,"updated":"2017-03-29 19:47:41.000000000","message":"Should be:\n\n DELETE /traits/{trait_name}","commit_id":"7a6ff8d185ac6830e0e6a3725a8046f28321c8ff"},{"author":{"_account_id":11564,"name":"Chris Dent","email":"cdent@anticdent.org","username":"chdent"},"change_message_id":"851ac94c5f241ed3cc1b11b842405b88a3ad08ee","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":"    The Traits API is added in the placement with Microversion 1.6."},{"line_number":5,"context_line":""},{"line_number":6,"context_line":"    * GET /traits: Returns all resource classes."},{"line_number":7,"context_line":"    * PUT /traits/{trait_name}: To insert a single custom trait."}],"source_content_type":"text/x-yaml","patch_set":28,"id":"dfeb2761_a27dc16f","line":4,"updated":"2017-03-31 11:26:24.000000000","message":"Traits are added to the placement API in microversion 1.6.","commit_id":"a7bcb493917900d1610b7447b991668ee05abf3a"},{"author":{"_account_id":11564,"name":"Chris Dent","email":"cdent@anticdent.org","username":"chdent"},"change_message_id":"851ac94c5f241ed3cc1b11b842405b88a3ad08ee","unresolved":false,"context_lines":[{"line_number":5,"context_line":""},{"line_number":6,"context_line":"    * GET /traits: Returns all resource classes."},{"line_number":7,"context_line":"    * PUT /traits/{trait_name}: To insert a single custom trait."},{"line_number":8,"context_line":"    * GET /traits/{trait_name}: To check if a trait name exists."},{"line_number":9,"context_line":"    * DELETE /traits/{trait_name}: To delete the specified trait."},{"line_number":10,"context_line":"    * GET /resource_providers/{uuid}/traits: a list of traits associated"},{"line_number":11,"context_line":"      with a specific resource provider"}],"source_content_type":"text/x-yaml","patch_set":28,"id":"dfeb2761_6297b992","line":8,"updated":"2017-03-31 11:26:24.000000000","message":"same comment from commit message","commit_id":"a7bcb493917900d1610b7447b991668ee05abf3a"}]}
