)]}'
{"nova/api/openstack/placement/handler.py":[{"author":{"_account_id":11564,"name":"Chris Dent","email":"cdent@anticdent.org","username":"chdent"},"change_message_id":"1286b719cd2e5428de21d7912f4953fc33845bb9","unresolved":false,"context_lines":[{"line_number":59,"context_line":"    },"},{"line_number":60,"context_line":"    \u0027/resource_classes\u0027: {"},{"line_number":61,"context_line":"        \u0027GET\u0027: resource_class.list_resource_classes,"},{"line_number":62,"context_line":"        \u0027POST\u0027: resource_class.create_resource_class"},{"line_number":63,"context_line":"    },"},{"line_number":64,"context_line":"    \u0027/resource_classes/{name}\u0027: {"},{"line_number":65,"context_line":"        \u0027GET\u0027: resource_class.get_resource_class,"}],"source_content_type":"text/x-python","patch_set":2,"id":"ba5da102_7c471177","line":62,"updated":"2016-11-01 13:38:42.000000000","message":"For reference we may wish to do PUT /resource_classes/{name} instead of POST /resource_classes since there is no (platonic) effective state change going on when creating the resource class: we know the name and the name is the id and no additional information is created.\n\nThe second bullet here http://specs.openstack.org/openstack/api-wg/guidelines/http.html#http-methods has some notes on when to POST or PUT.\n\nThis isn\u0027t a big deal, just something to consider in the pot.\n\n\"That is, if the id of the resource being created is known, use PUT\"","commit_id":"fbe63a4aff60a326ecb26abebc06620e1fdb2887"},{"author":{"_account_id":11564,"name":"Chris Dent","email":"cdent@anticdent.org","username":"chdent"},"change_message_id":"4b67bd708162c85c1ff7659ba8e093dd6a0b9244","unresolved":false,"context_lines":[{"line_number":59,"context_line":"    },"},{"line_number":60,"context_line":"    \u0027/resource_classes\u0027: {"},{"line_number":61,"context_line":"        \u0027GET\u0027: resource_class.list_resource_classes,"},{"line_number":62,"context_line":"        \u0027POST\u0027: resource_class.create_resource_class"},{"line_number":63,"context_line":"    },"},{"line_number":64,"context_line":"    \u0027/resource_classes/{name}\u0027: {"},{"line_number":65,"context_line":"        \u0027GET\u0027: resource_class.get_resource_class,"}],"source_content_type":"text/x-python","patch_set":2,"id":"ba5da102_32c93d27","line":62,"in_reply_to":"ba5da102_72ae5582","updated":"2016-11-01 15:08:07.000000000","message":"word","commit_id":"fbe63a4aff60a326ecb26abebc06620e1fdb2887"},{"author":{"_account_id":7,"name":"Jay Pipes","email":"jaypipes@gmail.com","username":"jaypipes"},"change_message_id":"eda8aee5cac9920d9162e769ad327109c1b08dbb","unresolved":false,"context_lines":[{"line_number":59,"context_line":"    },"},{"line_number":60,"context_line":"    \u0027/resource_classes\u0027: {"},{"line_number":61,"context_line":"        \u0027GET\u0027: resource_class.list_resource_classes,"},{"line_number":62,"context_line":"        \u0027POST\u0027: resource_class.create_resource_class"},{"line_number":63,"context_line":"    },"},{"line_number":64,"context_line":"    \u0027/resource_classes/{name}\u0027: {"},{"line_number":65,"context_line":"        \u0027GET\u0027: resource_class.get_resource_class,"}],"source_content_type":"text/x-python","patch_set":2,"id":"ba5da102_72ae5582","line":62,"in_reply_to":"ba5da102_7c471177","updated":"2016-11-01 15:03:30.000000000","message":"Yeah, I had the same thoughts actually, and then I considered that eventually I might want to add a \"description\" field to the resource_classes table that would hold a more human-friendly text description of what the resource class represented...\n\nAnd thus I left it at POST /resource_classes to kind of future-proof it.","commit_id":"fbe63a4aff60a326ecb26abebc06620e1fdb2887"}],"nova/api/openstack/placement/handlers/resource_class.py":[{"author":{"_account_id":11564,"name":"Chris Dent","email":"cdent@anticdent.org","username":"chdent"},"change_message_id":"1286b719cd2e5428de21d7912f4953fc33845bb9","unresolved":false,"context_lines":[{"line_number":60,"context_line":""},{"line_number":61,"context_line":"def _raise_404_before_api_1_1(req):"},{"line_number":62,"context_line":"    want_version \u003d req.environ[microversion.MICROVERSION_ENVIRON]"},{"line_number":63,"context_line":"    if want_version \u003c (1, 1):"},{"line_number":64,"context_line":"        raise webob.exc.HTTPNotFound"},{"line_number":65,"context_line":""},{"line_number":66,"context_line":"@webob.dec.wsgify"}],"source_content_type":"text/x-python","patch_set":2,"id":"ba5da102_f7bfbaa7","line":63,"updated":"2016-11-01 13:38:42.000000000","message":"This works just fine, but if you wanted to you could use the \u0027matches\u0027 method on the Version if you wanted, something like (untested):\n\n   if not want_version.matches((1, 1))\n       raise ...\n\nsee Version.matches in nova.api.openstack.placement.microversion","commit_id":"fbe63a4aff60a326ecb26abebc06620e1fdb2887"},{"author":{"_account_id":5754,"name":"Alex Xu","email":"hejie.xu@intel.com","username":"xuhj"},"change_message_id":"d503573f44afc94de71b30be60a413ba0c9f043e","unresolved":false,"context_lines":[{"line_number":26,"context_line":"    \"properties\": {"},{"line_number":27,"context_line":"        \"name\": {"},{"line_number":28,"context_line":"            \"type\": \"string\","},{"line_number":29,"context_line":"            \"pattern\": \"^CUSTOM\\_[A-Z0-9_]+$\","},{"line_number":30,"context_line":"        },"},{"line_number":31,"context_line":"    },"},{"line_number":32,"context_line":"    \"required\": ["}],"source_content_type":"text/x-python","patch_set":10,"id":"ba5da102_bbe73dab","line":29,"updated":"2016-11-07 05:47:01.000000000","message":"If we haven\u0027t max length limit at here, it will make db raise that error.","commit_id":"8413b683b737f3f0b1bea621d29fe7c9222b92d3"},{"author":{"_account_id":5754,"name":"Alex Xu","email":"hejie.xu@intel.com","username":"xuhj"},"change_message_id":"a08f71be35ccafc4a6e6fae85ca81a4a310e60f4","unresolved":false,"context_lines":[{"line_number":26,"context_line":"    \"properties\": {"},{"line_number":27,"context_line":"        \"name\": {"},{"line_number":28,"context_line":"            \"type\": \"string\","},{"line_number":29,"context_line":"            \"pattern\": \"^CUSTOM\\_[A-Z0-9_]+$\","},{"line_number":30,"context_line":"        },"},{"line_number":31,"context_line":"    },"},{"line_number":32,"context_line":"    \"required\": ["}],"source_content_type":"text/x-python","patch_set":10,"id":"9a629dbe_a5b6653b","line":29,"in_reply_to":"9a629dbe_4add966f","updated":"2016-11-07 13:57:08.000000000","message":"I prefer to API layer shows the API contract explicitly. If we leave the API contract decided by under layer code, we may break the API contract in the future, due to we forget there are some under layer code may change the API contract.","commit_id":"8413b683b737f3f0b1bea621d29fe7c9222b92d3"},{"author":{"_account_id":11564,"name":"Chris Dent","email":"cdent@anticdent.org","username":"chdent"},"change_message_id":"9061ded17ec29aa13b5c7ee0bbf99e345d5155b6","unresolved":false,"context_lines":[{"line_number":26,"context_line":"    \"properties\": {"},{"line_number":27,"context_line":"        \"name\": {"},{"line_number":28,"context_line":"            \"type\": \"string\","},{"line_number":29,"context_line":"            \"pattern\": \"^CUSTOM\\_[A-Z0-9_]+$\","},{"line_number":30,"context_line":"        },"},{"line_number":31,"context_line":"    },"},{"line_number":32,"context_line":"    \"required\": ["}],"source_content_type":"text/x-python","patch_set":10,"id":"9a629dbe_4add966f","line":29,"in_reply_to":"ba5da102_bbe73dab","updated":"2016-11-07 13:49:36.000000000","message":"This raises a question I\u0027ve had about our use of json schema: Is the expectation that the json schema is the first of several lines of defence against incorrect input or the primary lilne of defence?\n\nIf it is the latter, then I agree that having a length check here makes sense. If not, then letting the database exception happen and lead to a 400 seems just as good.","commit_id":"8413b683b737f3f0b1bea621d29fe7c9222b92d3"},{"author":{"_account_id":11564,"name":"Chris Dent","email":"cdent@anticdent.org","username":"chdent"},"change_message_id":"9061ded17ec29aa13b5c7ee0bbf99e345d5155b6","unresolved":false,"context_lines":[{"line_number":58,"context_line":"    return {\"resource_classes\": output}"},{"line_number":59,"context_line":""},{"line_number":60,"context_line":""},{"line_number":61,"context_line":"def _raise_404_before_api_1_1(req):"},{"line_number":62,"context_line":"    want_version \u003d req.environ[microversion.MICROVERSION_ENVIRON]"},{"line_number":63,"context_line":"    if want_version \u003c (1, 1):"},{"line_number":64,"context_line":"        raise webob.exc.HTTPNotFound"}],"source_content_type":"text/x-python","patch_set":10,"id":"9a629dbe_0add5e42","line":61,"updated":"2016-11-07 13:49:36.000000000","message":"For future reference I made a utility method for this that might sense for this. It\u0027s not yet merged, however:\n\nhttps://review.openstack.org/#/c/357993/33/nova/api/openstack/placement/microversion.py","commit_id":"8413b683b737f3f0b1bea621d29fe7c9222b92d3"},{"author":{"_account_id":5754,"name":"Alex Xu","email":"hejie.xu@intel.com","username":"xuhj"},"change_message_id":"d503573f44afc94de71b30be60a413ba0c9f043e","unresolved":false,"context_lines":[{"line_number":78,"context_line":""},{"line_number":79,"context_line":"    try:"},{"line_number":80,"context_line":"        rc \u003d objects.ResourceClass(context, name\u003ddata[\u0027name\u0027])"},{"line_number":81,"context_line":"        rc.create()"},{"line_number":82,"context_line":"    except exception.ResourceClassExists:"},{"line_number":83,"context_line":"        raise webob.exc.HTTPConflict("},{"line_number":84,"context_line":"            _(\u0027Conflicting resource class already exists: %(name)s\u0027) %"}],"source_content_type":"text/x-python","patch_set":10,"id":"ba5da102_db48718a","line":81,"range":{"start_line":81,"start_character":8,"end_line":81,"end_character":19},"updated":"2016-11-07 05:47:01.000000000","message":"there is no quota control, but looks like fine, due to this is admin API.","commit_id":"8413b683b737f3f0b1bea621d29fe7c9222b92d3"},{"author":{"_account_id":5754,"name":"Alex Xu","email":"hejie.xu@intel.com","username":"xuhj"},"change_message_id":"d503573f44afc94de71b30be60a413ba0c9f043e","unresolved":false,"context_lines":[{"line_number":140,"context_line":"    rc \u003d objects.ResourceClass.get_by_name(context, name)"},{"line_number":141,"context_line":""},{"line_number":142,"context_line":"    req.response.body \u003d jsonutils.dumps("},{"line_number":143,"context_line":"        _serialize_resource_class(req.environ, rc)"},{"line_number":144,"context_line":"    )"},{"line_number":145,"context_line":"    req.response.content_type \u003d \u0027application/json\u0027"},{"line_number":146,"context_line":"    return req.response"}],"source_content_type":"text/x-python","patch_set":10,"id":"ba5da102_9b67d924","line":143,"range":{"start_line":143,"start_character":8,"end_line":143,"end_character":50},"updated":"2016-11-07 05:47:01.000000000","message":"This body includes the name and the link, both of them looks like useless. How about we return 204 and no response body? This is same with tag api https://github.com/openstack/api-wg/blob/master/guidelines/tags.rst","commit_id":"8413b683b737f3f0b1bea621d29fe7c9222b92d3"},{"author":{"_account_id":5754,"name":"Alex Xu","email":"hejie.xu@intel.com","username":"xuhj"},"change_message_id":"293961fe8793bb4d23347307d6656411077a65cd","unresolved":false,"context_lines":[{"line_number":140,"context_line":"    rc \u003d objects.ResourceClass.get_by_name(context, name)"},{"line_number":141,"context_line":""},{"line_number":142,"context_line":"    req.response.body \u003d jsonutils.dumps("},{"line_number":143,"context_line":"        _serialize_resource_class(req.environ, rc)"},{"line_number":144,"context_line":"    )"},{"line_number":145,"context_line":"    req.response.content_type \u003d \u0027application/json\u0027"},{"line_number":146,"context_line":"    return req.response"}],"source_content_type":"text/x-python","patch_set":10,"id":"9a629dbe_69ac3e8c","line":143,"range":{"start_line":143,"start_character":8,"end_line":143,"end_character":50},"in_reply_to":"9a629dbe_5ddbbd7b","updated":"2016-11-12 06:31:14.000000000","message":"Ah, that makes sense, thanks for the reply","commit_id":"8413b683b737f3f0b1bea621d29fe7c9222b92d3"},{"author":{"_account_id":7,"name":"Jay Pipes","email":"jaypipes@gmail.com","username":"jaypipes"},"change_message_id":"daf9900195dd7a15ed24bc7a57840fd88c7fb625","unresolved":false,"context_lines":[{"line_number":140,"context_line":"    rc \u003d objects.ResourceClass.get_by_name(context, name)"},{"line_number":141,"context_line":""},{"line_number":142,"context_line":"    req.response.body \u003d jsonutils.dumps("},{"line_number":143,"context_line":"        _serialize_resource_class(req.environ, rc)"},{"line_number":144,"context_line":"    )"},{"line_number":145,"context_line":"    req.response.content_type \u003d \u0027application/json\u0027"},{"line_number":146,"context_line":"    return req.response"}],"source_content_type":"text/x-python","patch_set":10,"id":"9a629dbe_5ddbbd7b","line":143,"range":{"start_line":143,"start_character":8,"end_line":143,"end_character":50},"in_reply_to":"ba5da102_9b67d924","updated":"2016-11-11 20:56:08.000000000","message":"@alex_xu: I could imagine in the future having a \"description\" field that has a more human-readable entry for users to understand what an amount of the resource actually entails.","commit_id":"8413b683b737f3f0b1bea621d29fe7c9222b92d3"},{"author":{"_account_id":1063,"name":"Ed Leafe","email":"ed@leafe.com","username":"ed-leafe"},"change_message_id":"aa4acd6a67aea03b44a8a9be2af043c24feb1a3c","unresolved":false,"context_lines":[{"line_number":72,"context_line":"    On success return a 201 response with an empty body and a location"},{"line_number":73,"context_line":"    header pointing to the newly created resource class."},{"line_number":74,"context_line":"    \"\"\""},{"line_number":75,"context_line":"    _raise_404_before_api_1_1(req)"},{"line_number":76,"context_line":"    context \u003d req.environ[\u0027placement.context\u0027]"},{"line_number":77,"context_line":"    data \u003d util.extract_json(req.body, POST_RC_SCHEMA_V1_0)"},{"line_number":78,"context_line":""}],"source_content_type":"text/x-python","patch_set":12,"id":"7a77a97e_6d7da46d","line":75,"range":{"start_line":75,"start_character":4,"end_line":75,"end_character":29},"updated":"2016-11-16 22:15:19.000000000","message":"This would read more easily as a decorator, IMO.","commit_id":"cfefa10e4fc1a361c82acfafb87e9daddb3cca85"},{"author":{"_account_id":11564,"name":"Chris Dent","email":"cdent@anticdent.org","username":"chdent"},"change_message_id":"538e2c8512e0578a14be8c9e0c45af468c020efa","unresolved":false,"context_lines":[{"line_number":62,"context_line":"    return {\"resource_classes\": output}"},{"line_number":63,"context_line":""},{"line_number":64,"context_line":""},{"line_number":65,"context_line":"def raise_404_before_api_1_2(func):"},{"line_number":66,"context_line":"    def wrapped(req):"},{"line_number":67,"context_line":"        want_version \u003d req.environ[microversion.MICROVERSION_ENVIRON]"},{"line_number":68,"context_line":"        if want_version \u003c (1, 2):"}],"source_content_type":"text/x-python","patch_set":18,"id":"5a74a57a_6aa8d677","line":65,"updated":"2016-11-28 18:43:06.000000000","message":"there are two generic methods that accomplishes things like this now:\n\n* https://github.com/openstack/nova/blob/ce92ffec701633d9265873537bd371afa405c839/nova/api/openstack/placement/microversion.py#L72\n* https://github.com/openstack/nova/blob/4e747092bcb015303efc2ab13da98ef5ce575ec8/nova/api/openstack/placement/microversion.py#L217\n\nOne is a decorator, one is not. The latter behaves essentially like this method but in a generic way.","commit_id":"8581362feedea67270c59b1a55cbded46ed05453"},{"author":{"_account_id":11564,"name":"Chris Dent","email":"cdent@anticdent.org","username":"chdent"},"change_message_id":"538e2c8512e0578a14be8c9e0c45af468c020efa","unresolved":false,"context_lines":[{"line_number":112,"context_line":"    \"\"\""},{"line_number":113,"context_line":"    name \u003d util.wsgi_path_item(req.environ, \u0027name\u0027)"},{"line_number":114,"context_line":"    context \u003d req.environ[\u0027placement.context\u0027]"},{"line_number":115,"context_line":"    # The containing application will catch a not found here."},{"line_number":116,"context_line":"    rc \u003d objects.ResourceClass.get_by_name(context, name)"},{"line_number":117,"context_line":"    try:"},{"line_number":118,"context_line":"        rc.destroy()"}],"source_content_type":"text/x-python","patch_set":18,"id":"5a74a57a_e5b6d9f7","line":115,"updated":"2016-11-28 18:43:06.000000000","message":"There have been changes in the other handlers to stop doing this so that exception handling is more local to each handler as well as to ensure that the generated error messages are as laden with context as possible.\n\nIf the underlying NotFound is verbose, then cool, but thought I ought to mention it.","commit_id":"8581362feedea67270c59b1a55cbded46ed05453"},{"author":{"_account_id":11564,"name":"Chris Dent","email":"cdent@anticdent.org","username":"chdent"},"change_message_id":"538e2c8512e0578a14be8c9e0c45af468c020efa","unresolved":false,"context_lines":[{"line_number":141,"context_line":"    the resource class."},{"line_number":142,"context_line":"    \"\"\""},{"line_number":143,"context_line":"    name \u003d util.wsgi_path_item(req.environ, \u0027name\u0027)"},{"line_number":144,"context_line":"    # The containing application will catch a not found here."},{"line_number":145,"context_line":"    context \u003d req.environ[\u0027placement.context\u0027]"},{"line_number":146,"context_line":""},{"line_number":147,"context_line":"    rc \u003d objects.ResourceClass.get_by_name(context, name)"}],"source_content_type":"text/x-python","patch_set":18,"id":"5a74a57a_65c3a957","line":144,"updated":"2016-11-28 18:43:06.000000000","message":"ditto","commit_id":"8581362feedea67270c59b1a55cbded46ed05453"},{"author":{"_account_id":6873,"name":"Matt Riedemann","email":"mriedem.os@gmail.com","username":"mriedem"},"change_message_id":"f8b989265df715742047f29b571fccef7631ee42","unresolved":false,"context_lines":[{"line_number":34,"context_line":"    },"},{"line_number":35,"context_line":"    \"required\": ["},{"line_number":36,"context_line":"        \"name\""},{"line_number":37,"context_line":"     ],"},{"line_number":38,"context_line":"    \"additionalProperties\": False,"},{"line_number":39,"context_line":"}"},{"line_number":40,"context_line":"PUT_RC_SCHEMA_V1_2 \u003d copy.deepcopy(POST_RC_SCHEMA_V1_2)"}],"source_content_type":"text/x-python","patch_set":23,"id":"3a71b18c_124ae0c5","line":37,"range":{"start_line":37,"start_character":4,"end_line":37,"end_character":6},"updated":"2016-12-01 19:04:39.000000000","message":"micronit: alignment is a titch off here.","commit_id":"1fb095ac1bb284914018f307ab903a5468841194"},{"author":{"_account_id":6873,"name":"Matt Riedemann","email":"mriedem.os@gmail.com","username":"mriedem"},"change_message_id":"f8b989265df715742047f29b571fccef7631ee42","unresolved":false,"context_lines":[{"line_number":64,"context_line":""},{"line_number":65,"context_line":"@webob.dec.wsgify"},{"line_number":66,"context_line":"@util.require_content(\u0027application/json\u0027)"},{"line_number":67,"context_line":"@microversion.version_handler(1.2)"},{"line_number":68,"context_line":"def create_resource_class(req):"},{"line_number":69,"context_line":"    \"\"\"POST to create a resource class."},{"line_number":70,"context_line":""}],"source_content_type":"text/x-python","patch_set":23,"id":"3a71b18c_124f40be","line":67,"range":{"start_line":67,"start_character":30,"end_line":67,"end_character":33},"updated":"2016-12-01 19:04:39.000000000","message":"nit: the docstring for this expects a string, but its cast to a float anyway so that\u0027s why it works.","commit_id":"1fb095ac1bb284914018f307ab903a5468841194"},{"author":{"_account_id":6873,"name":"Matt Riedemann","email":"mriedem.os@gmail.com","username":"mriedem"},"change_message_id":"f8b989265df715742047f29b571fccef7631ee42","unresolved":false,"context_lines":[{"line_number":82,"context_line":"            _(\u0027Conflicting resource class already exists: %(name)s\u0027) %"},{"line_number":83,"context_line":"            {\u0027name\u0027: data[\u0027name\u0027]},"},{"line_number":84,"context_line":"            json_formatter\u003dutil.json_error_formatter)"},{"line_number":85,"context_line":"    except exception.ObjectActionError as exc:"},{"line_number":86,"context_line":"        raise webob.exc.HTTPBadRequest("},{"line_number":87,"context_line":"            _(\u0027Unable to create resource class %(name)s: %(error)s\u0027) %"},{"line_number":88,"context_line":"            {\u0027name\u0027: data[\u0027name\u0027], \u0027error\u0027: exc},"},{"line_number":89,"context_line":"            json_formatter\u003dutil.json_error_formatter)"},{"line_number":90,"context_line":""},{"line_number":91,"context_line":"    req.response.location \u003d util.resource_class_url(req.environ, rc)"},{"line_number":92,"context_line":"    req.response.status \u003d 201"}],"source_content_type":"text/x-python","patch_set":23,"id":"3a71b18c_b2176c50","line":89,"range":{"start_line":85,"start_character":4,"end_line":89,"end_character":53},"updated":"2016-12-01 19:04:39.000000000","message":"I don\u0027t think we\u0027d actually hit this. The only things that the create() method raises up for this are:\n\n1. id is set - it wouldn\u0027t be here\n2. name is missing - jsonschema validation would catch that before this.\n3. name doesn\u0027t start with CUSTOM_, again, jsonschema validation will catch that for us before we get here.","commit_id":"1fb095ac1bb284914018f307ab903a5468841194"},{"author":{"_account_id":6873,"name":"Matt Riedemann","email":"mriedem.os@gmail.com","username":"mriedem"},"change_message_id":"6be40bae4845491bd7b95dbfbf3cc2d7e100a512","unresolved":false,"context_lines":[{"line_number":132,"context_line":"    the resource class."},{"line_number":133,"context_line":"    \"\"\""},{"line_number":134,"context_line":"    name \u003d util.wsgi_path_item(req.environ, \u0027name\u0027)"},{"line_number":135,"context_line":"    # The containing application will catch a not found here."},{"line_number":136,"context_line":"    context \u003d req.environ[\u0027placement.context\u0027]"},{"line_number":137,"context_line":""},{"line_number":138,"context_line":"    rc \u003d objects.ResourceClass.get_by_name(context, name)"}],"source_content_type":"text/x-python","patch_set":23,"id":"3a71b18c_adaab1d2","line":135,"updated":"2016-12-01 19:10:05.000000000","message":"nit: this should go right above:\n\nrc \u003d objects.ResourceClass.get_by_name(context, name)","commit_id":"1fb095ac1bb284914018f307ab903a5468841194"},{"author":{"_account_id":6873,"name":"Matt Riedemann","email":"mriedem.os@gmail.com","username":"mriedem"},"change_message_id":"94ef95b62776279af5875a7e0034a6f51f6a68b3","unresolved":false,"context_lines":[{"line_number":147,"context_line":"@webob.dec.wsgify"},{"line_number":148,"context_line":"@util.check_accept(\u0027application/json\u0027)"},{"line_number":149,"context_line":"@microversion.version_handler(1.2)"},{"line_number":150,"context_line":"def list_resource_classes(req):"},{"line_number":151,"context_line":"    \"\"\"GET a list of resource classes."},{"line_number":152,"context_line":""},{"line_number":153,"context_line":"    On success return a 200 and an application/json body representing"}],"source_content_type":"text/x-python","patch_set":23,"id":"3a71b18c_0d6d6598","line":150,"updated":"2016-12-01 19:17:36.000000000","message":"We had talked about supporting paging at some point, but that could always be built in later.","commit_id":"1fb095ac1bb284914018f307ab903a5468841194"},{"author":{"_account_id":6873,"name":"Matt Riedemann","email":"mriedem.os@gmail.com","username":"mriedem"},"change_message_id":"94ef95b62776279af5875a7e0034a6f51f6a68b3","unresolved":false,"context_lines":[{"line_number":179,"context_line":"    # The containing application will catch a not found here."},{"line_number":180,"context_line":"    rc \u003d objects.ResourceClass.get_by_name(context, name)"},{"line_number":181,"context_line":""},{"line_number":182,"context_line":"    data \u003d util.extract_json(req.body, PUT_RC_SCHEMA_V1_2)"},{"line_number":183,"context_line":""},{"line_number":184,"context_line":"    rc.name \u003d data[\u0027name\u0027]"},{"line_number":185,"context_line":""}],"source_content_type":"text/x-python","patch_set":23,"id":"3a71b18c_8db095df","line":182,"updated":"2016-12-01 19:17:36.000000000","message":"nit: do this before getting the RC from the DB in case the request is invalid, saves us a trip to the DB.","commit_id":"1fb095ac1bb284914018f307ab903a5468841194"},{"author":{"_account_id":6873,"name":"Matt Riedemann","email":"mriedem.os@gmail.com","username":"mriedem"},"change_message_id":"94ef95b62776279af5875a7e0034a6f51f6a68b3","unresolved":false,"context_lines":[{"line_number":185,"context_line":""},{"line_number":186,"context_line":"    try:"},{"line_number":187,"context_line":"        rc.save()"},{"line_number":188,"context_line":"    except db_exc.DBDuplicateEntry as exc:"},{"line_number":189,"context_line":"        raise webob.exc.HTTPConflict("},{"line_number":190,"context_line":"            _(\u0027Resource class already exists: %(name)s\u0027) %"},{"line_number":191,"context_line":"            {\u0027name\u0027: name},"}],"source_content_type":"text/x-python","patch_set":23,"id":"3a71b18c_cda36d9d","line":188,"range":{"start_line":188,"start_character":18,"end_line":188,"end_character":34},"updated":"2016-12-01 19:17:36.000000000","message":"See comments in https://review.openstack.org/#/c/400448/5/nova/objects/resource_provider.py@1273 - I think this should be ResourceClassExists to be consistent with POST.","commit_id":"1fb095ac1bb284914018f307ab903a5468841194"},{"author":{"_account_id":6873,"name":"Matt Riedemann","email":"mriedem.os@gmail.com","username":"mriedem"},"change_message_id":"94ef95b62776279af5875a7e0034a6f51f6a68b3","unresolved":false,"context_lines":[{"line_number":190,"context_line":"            _(\u0027Resource class already exists: %(name)s\u0027) %"},{"line_number":191,"context_line":"            {\u0027name\u0027: name},"},{"line_number":192,"context_line":"            json_formatter\u003dutil.json_error_formatter)"},{"line_number":193,"context_line":"    except exception.ObjectActionError as exc:"},{"line_number":194,"context_line":"        raise webob.exc.HTTPBadRequest("},{"line_number":195,"context_line":"            _(\u0027Unable to save resource class %(name)s: %(error)s\u0027) %"},{"line_number":196,"context_line":"            {\u0027name\u0027: data[\u0027name\u0027], \u0027error\u0027: exc},"}],"source_content_type":"text/x-python","patch_set":23,"id":"3a71b18c_cdd1adfd","line":193,"updated":"2016-12-01 19:17:36.000000000","message":"I don\u0027t think we\u0027d actually this this.\n\nAlso, we should be handling ResourceClassCannotUpdateStandard in here as a 400.","commit_id":"1fb095ac1bb284914018f307ab903a5468841194"},{"author":{"_account_id":6873,"name":"Matt Riedemann","email":"mriedem.os@gmail.com","username":"mriedem"},"change_message_id":"94ef95b62776279af5875a7e0034a6f51f6a68b3","unresolved":false,"context_lines":[{"line_number":199,"context_line":"    req.response.body \u003d jsonutils.dumps("},{"line_number":200,"context_line":"        _serialize_resource_class(req.environ, rc)"},{"line_number":201,"context_line":"    )"},{"line_number":202,"context_line":"    req.response.status \u003d 200"},{"line_number":203,"context_line":"    req.response.content_type \u003d \u0027application/json\u0027"},{"line_number":204,"context_line":"    return req.response"}],"source_content_type":"text/x-python","patch_set":23,"id":"3a71b18c_ad039172","line":202,"range":{"start_line":202,"start_character":26,"end_line":202,"end_character":29},"updated":"2016-12-01 19:17:36.000000000","message":"The spec says this would be a 204:\n\nhttps://specs.openstack.org/openstack/nova-specs/specs/ocata/approved/custom-resource-classes.html#put-resource-classes-name","commit_id":"1fb095ac1bb284914018f307ab903a5468841194"},{"author":{"_account_id":6873,"name":"Matt Riedemann","email":"mriedem.os@gmail.com","username":"mriedem"},"change_message_id":"e66c4c6a96bb0fc107c5d27593699ac929c4cc33","unresolved":false,"context_lines":[{"line_number":199,"context_line":"    req.response.body \u003d jsonutils.dumps("},{"line_number":200,"context_line":"        _serialize_resource_class(req.environ, rc)"},{"line_number":201,"context_line":"    )"},{"line_number":202,"context_line":"    req.response.status \u003d 200"},{"line_number":203,"context_line":"    req.response.content_type \u003d \u0027application/json\u0027"},{"line_number":204,"context_line":"    return req.response"}],"source_content_type":"text/x-python","patch_set":23,"id":"3a71b18c_a34e0894","line":202,"range":{"start_line":202,"start_character":26,"end_line":202,"end_character":29},"in_reply_to":"3a71b18c_ad039172","updated":"2016-12-02 17:49:02.000000000","message":"So either the spec is wrong, or we shouldn\u0027t be returning content with this...","commit_id":"1fb095ac1bb284914018f307ab903a5468841194"},{"author":{"_account_id":6873,"name":"Matt Riedemann","email":"mriedem.os@gmail.com","username":"mriedem"},"change_message_id":"809c5f41b44041a3be4e6bb71afde3677e755aa4","unresolved":false,"context_lines":[{"line_number":106,"context_line":"            _(\u0027Cannot delete standard resource class %(rp_name)s: %(error)s\u0027) %"},{"line_number":107,"context_line":"            {\u0027rp_name\u0027: name, \u0027error\u0027: exc},"},{"line_number":108,"context_line":"            json_formatter\u003dutil.json_error_formatter)"},{"line_number":109,"context_line":"    except exception.ResourceClassInUse as exc:"},{"line_number":110,"context_line":"        raise webob.exc.HTTPConflict("},{"line_number":111,"context_line":"            _(\u0027Unable to delete resource class %(rp_name)s: %(error)s\u0027) %"},{"line_number":112,"context_line":"            {\u0027rp_name\u0027: name, \u0027error\u0027: exc},"},{"line_number":113,"context_line":"            json_formatter\u003dutil.json_error_formatter)"},{"line_number":114,"context_line":"    req.response.status \u003d 204"},{"line_number":115,"context_line":"    req.response.content_type \u003d None"},{"line_number":116,"context_line":"    return req.response"}],"source_content_type":"text/x-python","patch_set":24,"id":"3a71b18c_7aee4ded","line":113,"range":{"start_line":109,"start_character":4,"end_line":113,"end_character":53},"updated":"2016-12-02 19:49:49.000000000","message":"I don\u0027t think we have a test for this in the gabbi functional tests, but I\u0027m not really sure how you would. I know the object code has a functional test though, so maybe that\u0027s sufficient, although it doesn\u0027t mean we\u0027re handling it here...","commit_id":"020bc0b16db8fa597948c3148d2dd3af5bd520d0"},{"author":{"_account_id":11564,"name":"Chris Dent","email":"cdent@anticdent.org","username":"chdent"},"change_message_id":"d5c6a7416168668d0c1b324384455c0950b74cba","unresolved":false,"context_lines":[{"line_number":63,"context_line":""},{"line_number":64,"context_line":"@webob.dec.wsgify"},{"line_number":65,"context_line":"@util.require_content(\u0027application/json\u0027)"},{"line_number":66,"context_line":"@microversion.version_handler(1.2)"},{"line_number":67,"context_line":"def create_resource_class(req):"},{"line_number":68,"context_line":"    \"\"\"POST to create a resource class."},{"line_number":69,"context_line":""}],"source_content_type":"text/x-python","patch_set":25,"id":"3a71b18c_f067aee6","line":66,"updated":"2016-12-05 12:53:24.000000000","message":"It probably doesn\u0027t matter in any significant way, but it may make sense to have the version_handler before require_content as sending a 404 before a 415 feels more logically correct.\n\nIn this order if someone does a request like this:\n\n    POST /resource_classes\n    content-type: text/plain\n    openstack-api-version: 1.1\n\nthey will get a 415. If they then correct the content-type to application/json without changing the microversion they will then get a 404 (and at that point flip the table).","commit_id":"1ffc7f0b7c3b34fc8519950ccb36f48ddaad4467"}],"nova/api/openstack/placement/microversion.py":[{"author":{"_account_id":11564,"name":"Chris Dent","email":"cdent@anticdent.org","username":"chdent"},"change_message_id":"9061ded17ec29aa13b5c7ee0bbf99e345d5155b6","unresolved":false,"context_lines":[{"line_number":33,"context_line":"# The Canonical Version List"},{"line_number":34,"context_line":"VERSIONS \u003d ["},{"line_number":35,"context_line":"    \u00271.0\u0027,"},{"line_number":36,"context_line":"    \u00271.1\u0027,  # Adds /resource-classes resource endpoint"},{"line_number":37,"context_line":"]"},{"line_number":38,"context_line":""},{"line_number":39,"context_line":""}],"source_content_type":"text/x-python","patch_set":10,"id":"9a629dbe_ca8e0627","line":36,"updated":"2016-11-07 13:49:36.000000000","message":"Just so you\u0027re aware: This is going to race with get_ set_aggregates: https://review.openstack.org/#/c/357993/","commit_id":"8413b683b737f3f0b1bea621d29fe7c9222b92d3"},{"author":{"_account_id":2750,"name":"Sean Dague","email":"sean@dague.net","username":"sdague"},"change_message_id":"8181fba43cc1c76428a915a951b9162b3914184f","unresolved":false,"context_lines":[{"line_number":36,"context_line":"VERSIONS \u003d ["},{"line_number":37,"context_line":"    \u00271.0\u0027,"},{"line_number":38,"context_line":"    \u00271.1\u0027,  # initial support for aggregate.get_aggregates and set_aggregates"},{"line_number":39,"context_line":"    \u00271.2\u0027,  # Adds /resource-classes resource endpoint"},{"line_number":40,"context_line":"]"},{"line_number":41,"context_line":""},{"line_number":42,"context_line":""}],"source_content_type":"text/x-python","patch_set":26,"id":"3a71b18c_e237af4a","line":39,"range":{"start_line":39,"start_character":28,"end_line":39,"end_character":29},"updated":"2016-12-06 13:09:10.000000000","message":"nanonit: can we be consistent with - vs. _?","commit_id":"1067c44663df2e6ebf03236ce6c00a935350ce20"},{"author":{"_account_id":11564,"name":"Chris Dent","email":"cdent@anticdent.org","username":"chdent"},"change_message_id":"b019551ea2ed438c3355bab5d5436422cb422590","unresolved":false,"context_lines":[{"line_number":36,"context_line":"VERSIONS \u003d ["},{"line_number":37,"context_line":"    \u00271.0\u0027,"},{"line_number":38,"context_line":"    \u00271.1\u0027,  # initial support for aggregate.get_aggregates and set_aggregates"},{"line_number":39,"context_line":"    \u00271.2\u0027,  # Adds /resource-classes resource endpoint"},{"line_number":40,"context_line":"]"},{"line_number":41,"context_line":""},{"line_number":42,"context_line":""}],"source_content_type":"text/x-python","patch_set":26,"id":"3a71b18c_d85c627f","line":39,"in_reply_to":"3a71b18c_e237af4a","updated":"2016-12-06 13:57:49.000000000","message":"looks like this is just a typo, the real uri has a _, I\u0027ll fix it with a followup.","commit_id":"1067c44663df2e6ebf03236ce6c00a935350ce20"}],"nova/api/openstack/placement/rest_api_version_history.rst":[{"author":{"_account_id":6873,"name":"Matt Riedemann","email":"mriedem.os@gmail.com","username":"mriedem"},"change_message_id":"6be40bae4845491bd7b95dbfbf3cc2d7e100a512","unresolved":false,"context_lines":[{"line_number":30,"context_line":"1.2 Custom resource classes"},{"line_number":31,"context_line":"---------------------------"},{"line_number":32,"context_line":""},{"line_number":33,"context_line":"Placement API version 1.1 adds basic operations allowing an admin to create,"},{"line_number":34,"context_line":"list and delete custom resource classes."},{"line_number":35,"context_line":""},{"line_number":36,"context_line":"The following new route is added:"}],"source_content_type":"text/x-rst","patch_set":23,"id":"3a71b18c_0d91e599","line":33,"range":{"start_line":33,"start_character":22,"end_line":33,"end_character":25},"updated":"2016-12-01 19:10:05.000000000","message":"1.2; -1 for this.","commit_id":"1fb095ac1bb284914018f307ab903a5468841194"},{"author":{"_account_id":6873,"name":"Matt Riedemann","email":"mriedem.os@gmail.com","username":"mriedem"},"change_message_id":"809c5f41b44041a3be4e6bb71afde3677e755aa4","unresolved":false,"context_lines":[{"line_number":35,"context_line":""},{"line_number":36,"context_line":"The following new route is added:"},{"line_number":37,"context_line":""},{"line_number":38,"context_line":"* /resource_classes"}],"source_content_type":"text/x-rst","patch_set":24,"id":"3a71b18c_ba51c510","line":38,"updated":"2016-12-02 19:49:49.000000000","message":"Might be nice to take the details from the commit message and put those in here since we don\u0027t have api reference docs yet:\n\n* GET /resource_classes: return all resource classes\n* POST /resource_classes: create a new custom resource class\n* PUT /resource_classes/{name}: update name of custom resource class\n* DELETE /resource_classes/{name}: deletes a custom resource class\n* GET /resource_classes/{name}: get a single resource class","commit_id":"020bc0b16db8fa597948c3148d2dd3af5bd520d0"},{"author":{"_account_id":6873,"name":"Matt Riedemann","email":"mriedem.os@gmail.com","username":"mriedem"},"change_message_id":"6c9ad1b773a9a6e0197af9273db12ae3afa62c22","unresolved":false,"context_lines":[{"line_number":35,"context_line":""},{"line_number":36,"context_line":"The following new route is added:"},{"line_number":37,"context_line":""},{"line_number":38,"context_line":"* /resource_classes"}],"source_content_type":"text/x-rst","patch_set":24,"id":"3a71b18c_3a74d5cd","line":38,"in_reply_to":"3a71b18c_ba51c510","updated":"2016-12-02 20:06:16.000000000","message":"Done","commit_id":"020bc0b16db8fa597948c3148d2dd3af5bd520d0"}],"nova/api/openstack/placement/util.py":[{"author":{"_account_id":6873,"name":"Matt Riedemann","email":"mriedem.os@gmail.com","username":"mriedem"},"change_message_id":"809c5f41b44041a3be4e6bb71afde3677e755aa4","unresolved":false,"context_lines":[{"line_number":141,"context_line":"    If SCRIPT_NAME is present, it is the mount point of the placement"},{"line_number":142,"context_line":"    WSGI app."},{"line_number":143,"context_line":"    \"\"\""},{"line_number":144,"context_line":"    prefix \u003d environ.get(\u0027SCRIPT_NAME\u0027, \u0027\u0027)"},{"line_number":145,"context_line":"    return \u0027%s/resource_classes/%s\u0027 % (prefix, resource_class.name)"},{"line_number":146,"context_line":""},{"line_number":147,"context_line":""}],"source_content_type":"text/x-python","patch_set":24,"id":"3a71b18c_fa725dac","line":144,"range":{"start_line":144,"start_character":4,"end_line":144,"end_character":43},"updated":"2016-12-02 19:49:49.000000000","message":"We don\u0027t have any testing for the SCRIPT_NAME part of this...we could do that in TestPlacementURLs.","commit_id":"020bc0b16db8fa597948c3148d2dd3af5bd520d0"},{"author":{"_account_id":6873,"name":"Matt Riedemann","email":"mriedem.os@gmail.com","username":"mriedem"},"change_message_id":"6c9ad1b773a9a6e0197af9273db12ae3afa62c22","unresolved":false,"context_lines":[{"line_number":141,"context_line":"    If SCRIPT_NAME is present, it is the mount point of the placement"},{"line_number":142,"context_line":"    WSGI app."},{"line_number":143,"context_line":"    \"\"\""},{"line_number":144,"context_line":"    prefix \u003d environ.get(\u0027SCRIPT_NAME\u0027, \u0027\u0027)"},{"line_number":145,"context_line":"    return \u0027%s/resource_classes/%s\u0027 % (prefix, resource_class.name)"},{"line_number":146,"context_line":""},{"line_number":147,"context_line":""}],"source_content_type":"text/x-python","patch_set":24,"id":"3a71b18c_556402e3","line":144,"range":{"start_line":144,"start_character":4,"end_line":144,"end_character":43},"in_reply_to":"3a71b18c_fa725dac","updated":"2016-12-02 20:06:16.000000000","message":"Done","commit_id":"020bc0b16db8fa597948c3148d2dd3af5bd520d0"}],"nova/tests/functional/api/openstack/placement/gabbits/resource-classes.yaml":[{"author":{"_account_id":5754,"name":"Alex Xu","email":"hejie.xu@intel.com","username":"xuhj"},"change_message_id":"d503573f44afc94de71b30be60a413ba0c9f043e","unresolved":false,"context_lines":[{"line_number":52,"context_line":"  response_forbidden_headers:"},{"line_number":53,"context_line":"      - content-type"},{"line_number":54,"context_line":""},{"line_number":55,"context_line":"- name: try to create same again"},{"line_number":56,"context_line":"  POST: /resource_classes"},{"line_number":57,"context_line":"  request_headers:"},{"line_number":58,"context_line":"    content-type: application/json"}],"source_content_type":"text/x-yaml","patch_set":10,"id":"ba5da102_4d3108ec","line":55,"range":{"start_line":55,"start_character":8,"end_line":55,"end_character":32},"updated":"2016-11-07 05:47:01.000000000","message":"one more case for create same name with standard resource class","commit_id":"8413b683b737f3f0b1bea621d29fe7c9222b92d3"},{"author":{"_account_id":1063,"name":"Ed Leafe","email":"ed@leafe.com","username":"ed-leafe"},"change_message_id":"aee0421141a005cfb0d045f056f1a556d306d1a7","unresolved":false,"context_lines":[{"line_number":17,"context_line":""},{"line_number":18,"context_line":"- name: what is at resource classes"},{"line_number":19,"context_line":"  GET: /resource_classes"},{"line_number":20,"context_line":"  response_json_paths:"},{"line_number":21,"context_line":"  response_json_paths:"},{"line_number":22,"context_line":"      $.resource_classes.`len`: 10  #  Number of standard resource classes"},{"line_number":23,"context_line":"      $.resource_classes[0].name: VCPU"},{"line_number":24,"context_line":""}],"source_content_type":"text/x-yaml","patch_set":11,"id":"7a77a97e_57cb191e","line":21,"range":{"start_line":20,"start_character":0,"end_line":21,"end_character":22},"updated":"2016-11-16 21:49:08.000000000","message":"dupe?","commit_id":"f93d9f496fe3dbcbe5882034cae829db930a6fd0"},{"author":{"_account_id":6873,"name":"Matt Riedemann","email":"mriedem.os@gmail.com","username":"mriedem"},"change_message_id":"19d995968fbc8a573e79d735956e2b59857097b5","unresolved":false,"context_lines":[{"line_number":19,"context_line":"  GET: /resource_classes"},{"line_number":20,"context_line":"  response_json_paths:"},{"line_number":21,"context_line":"  response_json_paths:"},{"line_number":22,"context_line":"      $.resource_classes.`len`: 10  #  Number of standard resource classes"},{"line_number":23,"context_line":"      $.resource_classes[0].name: VCPU"},{"line_number":24,"context_line":""},{"line_number":25,"context_line":"- name: non admin forbidden"}],"source_content_type":"text/x-yaml","patch_set":12,"id":"7a77a97e_cdcdd85e","line":22,"updated":"2016-11-16 22:03:47.000000000","message":"Can we do at least 10 otherwise this has to change every time we add a new standard resource class. Maybe that won\u0027t happen often enough for us to care.","commit_id":"cfefa10e4fc1a361c82acfafb87e9daddb3cca85"},{"author":{"_account_id":1063,"name":"Ed Leafe","email":"ed@leafe.com","username":"ed-leafe"},"change_message_id":"aa4acd6a67aea03b44a8a9be2af043c24feb1a3c","unresolved":false,"context_lines":[{"line_number":19,"context_line":"  GET: /resource_classes"},{"line_number":20,"context_line":"  response_json_paths:"},{"line_number":21,"context_line":"  response_json_paths:"},{"line_number":22,"context_line":"      $.resource_classes.`len`: 10  #  Number of standard resource classes"},{"line_number":23,"context_line":"      $.resource_classes[0].name: VCPU"},{"line_number":24,"context_line":""},{"line_number":25,"context_line":"- name: non admin forbidden"}],"source_content_type":"text/x-yaml","patch_set":12,"id":"7a77a97e_8d168053","line":22,"in_reply_to":"7a77a97e_cdcdd85e","updated":"2016-11-16 22:15:19.000000000","message":"Since adding a standard class is a code change, this should change. But I agree it\u0027s a very fragile test.","commit_id":"cfefa10e4fc1a361c82acfafb87e9daddb3cca85"},{"author":{"_account_id":6873,"name":"Matt Riedemann","email":"mriedem.os@gmail.com","username":"mriedem"},"change_message_id":"809c5f41b44041a3be4e6bb71afde3677e755aa4","unresolved":false,"context_lines":[{"line_number":11,"context_line":"- name: test microversion masks entire resource-classes endpoint with 404"},{"line_number":12,"context_line":"  GET: /resource_classes"},{"line_number":13,"context_line":"  request_headers:"},{"line_number":14,"context_line":"    OpenStack-API-Version: placement 1.0"},{"line_number":15,"context_line":"    content-type: application/json"},{"line_number":16,"context_line":"  status: 404"},{"line_number":17,"context_line":""}],"source_content_type":"text/x-yaml","patch_set":24,"id":"3a71b18c_faceddb2","line":14,"range":{"start_line":14,"start_character":37,"end_line":14,"end_character":40},"updated":"2016-12-02 19:49:49.000000000","message":"Maybe this should be 1.1 now?","commit_id":"020bc0b16db8fa597948c3148d2dd3af5bd520d0"},{"author":{"_account_id":6873,"name":"Matt Riedemann","email":"mriedem.os@gmail.com","username":"mriedem"},"change_message_id":"6c9ad1b773a9a6e0197af9273db12ae3afa62c22","unresolved":false,"context_lines":[{"line_number":11,"context_line":"- name: test microversion masks entire resource-classes endpoint with 404"},{"line_number":12,"context_line":"  GET: /resource_classes"},{"line_number":13,"context_line":"  request_headers:"},{"line_number":14,"context_line":"    OpenStack-API-Version: placement 1.0"},{"line_number":15,"context_line":"    content-type: application/json"},{"line_number":16,"context_line":"  status: 404"},{"line_number":17,"context_line":""}],"source_content_type":"text/x-yaml","patch_set":24,"id":"3a71b18c_5a7991f5","line":14,"range":{"start_line":14,"start_character":37,"end_line":14,"end_character":40},"in_reply_to":"3a71b18c_faceddb2","updated":"2016-12-02 20:06:16.000000000","message":"Done","commit_id":"020bc0b16db8fa597948c3148d2dd3af5bd520d0"},{"author":{"_account_id":6873,"name":"Matt Riedemann","email":"mriedem.os@gmail.com","username":"mriedem"},"change_message_id":"809c5f41b44041a3be4e6bb71afde3677e755aa4","unresolved":false,"context_lines":[{"line_number":50,"context_line":"  response_strings:"},{"line_number":51,"context_line":"      - JSON does not validate"},{"line_number":52,"context_line":""},{"line_number":53,"context_line":"- name: post new resource class"},{"line_number":54,"context_line":"  POST: /resource_classes"},{"line_number":55,"context_line":"  request_headers:"},{"line_number":56,"context_line":"    content-type: application/json"}],"source_content_type":"text/x-yaml","patch_set":24,"id":"3a71b18c_7a69ed8a","line":53,"updated":"2016-12-02 19:49:49.000000000","message":"Do we have a test for posting a new resource class with the name of a standard resource class in here?","commit_id":"020bc0b16db8fa597948c3148d2dd3af5bd520d0"},{"author":{"_account_id":6873,"name":"Matt Riedemann","email":"mriedem.os@gmail.com","username":"mriedem"},"change_message_id":"6c9ad1b773a9a6e0197af9273db12ae3afa62c22","unresolved":false,"context_lines":[{"line_number":50,"context_line":"  response_strings:"},{"line_number":51,"context_line":"      - JSON does not validate"},{"line_number":52,"context_line":""},{"line_number":53,"context_line":"- name: post new resource class"},{"line_number":54,"context_line":"  POST: /resource_classes"},{"line_number":55,"context_line":"  request_headers:"},{"line_number":56,"context_line":"    content-type: application/json"}],"source_content_type":"text/x-yaml","patch_set":24,"id":"3a71b18c_5afef137","line":53,"in_reply_to":"3a71b18c_7a69ed8a","updated":"2016-12-02 20:06:16.000000000","message":"Oh \"post bad resource class name IRON_NFV\" catches that case.","commit_id":"020bc0b16db8fa597948c3148d2dd3af5bd520d0"}],"releasenotes/notes/placement-rest-custom-resource-classes-a3f2175772983b0a.yaml":[{"author":{"_account_id":6873,"name":"Matt Riedemann","email":"mriedem.os@gmail.com","username":"mriedem"},"change_message_id":"7ecbfebf2f08cc7e230b2ff5b590f54ccc983bdf","unresolved":false,"context_lines":[{"line_number":1,"context_line":"---"},{"line_number":2,"context_line":"prelude: \u003e"},{"line_number":3,"context_line":"    A new /resource_classes resource endpoint was added to the OpenStack"},{"line_number":4,"context_line":"    Placement REST API for managing custom resource classes. Custom resource"},{"line_number":5,"context_line":"    classes represent deployment-specific types of quantitative resources that"},{"line_number":6,"context_line":"    are not interoperable between OpenStack clouds."},{"line_number":7,"context_line":"features:"},{"line_number":8,"context_line":"  - A new administrator-only resource endpoint was added to the OpenStack"},{"line_number":9,"context_line":"    Placement REST API for managing custom resource classes. Custom resource"}],"source_content_type":"text/x-yaml","patch_set":24,"id":"3a71b18c_babaa5be","line":6,"range":{"start_line":3,"start_character":4,"end_line":6,"end_character":51},"updated":"2016-12-02 19:51:13.000000000","message":"I\u0027m not sure we need this prelude if we have basically the same thing in the features section.","commit_id":"020bc0b16db8fa597948c3148d2dd3af5bd520d0"},{"author":{"_account_id":6873,"name":"Matt Riedemann","email":"mriedem.os@gmail.com","username":"mriedem"},"change_message_id":"6c9ad1b773a9a6e0197af9273db12ae3afa62c22","unresolved":false,"context_lines":[{"line_number":1,"context_line":"---"},{"line_number":2,"context_line":"prelude: \u003e"},{"line_number":3,"context_line":"    A new /resource_classes resource endpoint was added to the OpenStack"},{"line_number":4,"context_line":"    Placement REST API for managing custom resource classes. Custom resource"},{"line_number":5,"context_line":"    classes represent deployment-specific types of quantitative resources that"},{"line_number":6,"context_line":"    are not interoperable between OpenStack clouds."},{"line_number":7,"context_line":"features:"},{"line_number":8,"context_line":"  - A new administrator-only resource endpoint was added to the OpenStack"},{"line_number":9,"context_line":"    Placement REST API for managing custom resource classes. Custom resource"}],"source_content_type":"text/x-yaml","patch_set":24,"id":"3a71b18c_1a79d9c8","line":6,"range":{"start_line":3,"start_character":4,"end_line":6,"end_character":51},"in_reply_to":"3a71b18c_babaa5be","updated":"2016-12-02 20:06:16.000000000","message":"Done","commit_id":"020bc0b16db8fa597948c3148d2dd3af5bd520d0"},{"author":{"_account_id":6873,"name":"Matt Riedemann","email":"mriedem.os@gmail.com","username":"mriedem"},"change_message_id":"7ecbfebf2f08cc7e230b2ff5b590f54ccc983bdf","unresolved":false,"context_lines":[{"line_number":9,"context_line":"    Placement REST API for managing custom resource classes. Custom resource"},{"line_number":10,"context_line":"    classes are specific to a deployment and represent types of quantitative"},{"line_number":11,"context_line":"    resources that are not interoperable between OpenStack clouds."},{"line_number":12,"context_line":"    Administrators can add a new custom resource class using POST"},{"line_number":13,"context_line":"    /resource-classes, remove a custom resource class using DELETE"},{"line_number":14,"context_line":"    /resource-classes/{name} and list one or more than one resource class"},{"line_number":15,"context_line":"    (including standard resource classes) using GET /resource-classes. Custom"},{"line_number":16,"context_line":"    resource classes must begin with the prefix \"CUSTOM\\_\" and contain only the"},{"line_number":17,"context_line":"    letters A through Z, the numbers 0 through 9 and the underscore \"\\_\""},{"line_number":18,"context_line":"    character."}],"source_content_type":"text/x-yaml","patch_set":24,"id":"3a71b18c_7aaacd71","line":18,"range":{"start_line":12,"start_character":4,"end_line":18,"end_character":14},"updated":"2016-12-02 19:51:13.000000000","message":"If we added the details to the rest_api_version_history doc as suggested, and then threw this bit about the regex in there, I think that would be a better place for those details to live as a reference rather than in this release note.","commit_id":"020bc0b16db8fa597948c3148d2dd3af5bd520d0"},{"author":{"_account_id":6873,"name":"Matt Riedemann","email":"mriedem.os@gmail.com","username":"mriedem"},"change_message_id":"cdbf04954ad560d83594826aab74ee0a969aed0b","unresolved":false,"context_lines":[{"line_number":9,"context_line":"    Placement REST API for managing custom resource classes. Custom resource"},{"line_number":10,"context_line":"    classes are specific to a deployment and represent types of quantitative"},{"line_number":11,"context_line":"    resources that are not interoperable between OpenStack clouds."},{"line_number":12,"context_line":"    Administrators can add a new custom resource class using POST"},{"line_number":13,"context_line":"    /resource-classes, remove a custom resource class using DELETE"},{"line_number":14,"context_line":"    /resource-classes/{name} and list one or more than one resource class"},{"line_number":15,"context_line":"    (including standard resource classes) using GET /resource-classes. Custom"},{"line_number":16,"context_line":"    resource classes must begin with the prefix \"CUSTOM\\_\" and contain only the"},{"line_number":17,"context_line":"    letters A through Z, the numbers 0 through 9 and the underscore \"\\_\""},{"line_number":18,"context_line":"    character."}],"source_content_type":"text/x-yaml","patch_set":24,"id":"3a71b18c_9a1329b8","line":18,"range":{"start_line":12,"start_character":4,"end_line":18,"end_character":14},"in_reply_to":"3a71b18c_7aaacd71","updated":"2016-12-02 19:55:10.000000000","message":"Done","commit_id":"020bc0b16db8fa597948c3148d2dd3af5bd520d0"},{"author":{"_account_id":6873,"name":"Matt Riedemann","email":"mriedem.os@gmail.com","username":"mriedem"},"change_message_id":"2b059aff90fb609262d3494a9b6a5ceb19796e5a","unresolved":false,"context_lines":[{"line_number":7,"context_line":"    resources that are not interoperable between OpenStack clouds. See the"},{"line_number":8,"context_line":"    `Placement REST API Version History`_ documentation for usage details."},{"line_number":9,"context_line":""},{"line_number":10,"context_line":"    .. _Placement REST API Version History: http://docs.openstack.org/developer/nova/placement.html#id3"}],"source_content_type":"text/x-yaml","patch_set":25,"id":"3a71b18c_55ca426e","line":10,"updated":"2016-12-02 20:15:13.000000000","message":"This link doesn\u0027t exist yet but it will one this change lands, assuming we get microversion 1.2. If we don\u0027t, this link needs to change.","commit_id":"1ffc7f0b7c3b34fc8519950ccb36f48ddaad4467"}]}
