)]}'
{"/COMMIT_MSG":[{"author":{"_account_id":6873,"name":"Matt Riedemann","email":"mriedem.os@gmail.com","username":"mriedem"},"change_message_id":"1ff7704ce7aecd4e0b9447b4abe4b8df83f28451","unresolved":false,"context_lines":[{"line_number":4,"context_line":"Commit:     Dan Peschman \u003cdpeschman@godaddy.com\u003e"},{"line_number":5,"context_line":"CommitDate: 2017-05-13 11:24:57 -0700"},{"line_number":6,"context_line":""},{"line_number":7,"context_line":"Use uuid for id in Services API"},{"line_number":8,"context_line":""},{"line_number":9,"context_line":"This patch introduces API version 2.46 to idendify services by uuid"},{"line_number":10,"context_line":"instead of id, to ensure uniqueness across cells. GET /os-services"}],"source_content_type":"text/x-gerrit-commit-message","patch_set":2,"id":"1f013ff3_132de094","line":7,"updated":"2017-05-15 15:41:19.000000000","message":"Might want to prefix this with WIP since the plan is to do the services and hypervisors API changes in separate patches, but the same microversion, and then once they are good, we\u0027ll squash them into a single change.","commit_id":"6c717170713c378d9708f53e8a09566f21772b5f"},{"author":{"_account_id":23882,"name":"Dan Peschman","email":"dpeschman@godaddy.com","username":"dtp"},"change_message_id":"bc6261299b30f49e47f7abaee9a6414a569ce1bc","unresolved":false,"context_lines":[{"line_number":4,"context_line":"Commit:     Dan Peschman \u003cdpeschman@godaddy.com\u003e"},{"line_number":5,"context_line":"CommitDate: 2017-05-13 11:24:57 -0700"},{"line_number":6,"context_line":""},{"line_number":7,"context_line":"Use uuid for id in Services API"},{"line_number":8,"context_line":""},{"line_number":9,"context_line":"This patch introduces API version 2.46 to idendify services by uuid"},{"line_number":10,"context_line":"instead of id, to ensure uniqueness across cells. GET /os-services"}],"source_content_type":"text/x-gerrit-commit-message","patch_set":2,"id":"ff0f0b1f_38d24229","line":7,"in_reply_to":"1f013ff3_132de094","updated":"2017-05-25 00:31:28.000000000","message":"Done","commit_id":"6c717170713c378d9708f53e8a09566f21772b5f"},{"author":{"_account_id":14070,"name":"Eric Fried","email":"openstack@fried.cc","username":"efried"},"change_message_id":"153c818e47c96f61ade859d8fcd0a604038567b9","unresolved":false,"context_lines":[{"line_number":6,"context_line":""},{"line_number":7,"context_line":"Use uuid for id in Services API"},{"line_number":8,"context_line":""},{"line_number":9,"context_line":"This patch introduces API version 2.46 to idendify services by uuid"},{"line_number":10,"context_line":"instead of id, to ensure uniqueness across cells. GET /os-services"},{"line_number":11,"context_line":"returns uuid in the id field, and uuid must be provided to delete a"},{"line_number":12,"context_line":"service with DELETE /os-services/{service_uuid}."}],"source_content_type":"text/x-gerrit-commit-message","patch_set":4,"id":"ff0f0b1f_a5641323","line":9,"range":{"start_line":9,"start_character":42,"end_line":9,"end_character":50},"updated":"2017-05-23 21:57:06.000000000","message":"identify","commit_id":"c74d8041edf6f49edd79fb364a46d83eda0556e6"},{"author":{"_account_id":23882,"name":"Dan Peschman","email":"dpeschman@godaddy.com","username":"dtp"},"change_message_id":"4a2a138a90da983263d2ba0dc4ab22701e4e791f","unresolved":false,"context_lines":[{"line_number":6,"context_line":""},{"line_number":7,"context_line":"Use uuid for id in Services API"},{"line_number":8,"context_line":""},{"line_number":9,"context_line":"This patch introduces API version 2.46 to idendify services by uuid"},{"line_number":10,"context_line":"instead of id, to ensure uniqueness across cells. GET /os-services"},{"line_number":11,"context_line":"returns uuid in the id field, and uuid must be provided to delete a"},{"line_number":12,"context_line":"service with DELETE /os-services/{service_uuid}."}],"source_content_type":"text/x-gerrit-commit-message","patch_set":4,"id":"ff0f0b1f_f8c72a63","line":9,"in_reply_to":"ff0f0b1f_a5641323","updated":"2017-05-25 00:31:45.000000000","message":"Done","commit_id":"c74d8041edf6f49edd79fb364a46d83eda0556e6"},{"author":{"_account_id":6873,"name":"Matt Riedemann","email":"mriedem.os@gmail.com","username":"mriedem"},"change_message_id":"a3ac0b85d2b336d04226beb35fadf39c4fdb0045","unresolved":false,"context_lines":[{"line_number":1,"context_line":"Parent:     ae34b673 (Handle uuid in HostAPI.compute_node_get)"},{"line_number":2,"context_line":"Author:     Matt Riedemann \u003cmriedem.os@gmail.com\u003e"},{"line_number":3,"context_line":"AuthorDate: 2017-06-13 10:38:44 -0400"},{"line_number":4,"context_line":"Commit:     Matt Riedemann \u003cmriedem.os@gmail.com\u003e"},{"line_number":5,"context_line":"CommitDate: 2017-06-13 13:50:32 -0400"}],"source_content_type":"text/x-gerrit-commit-message","patch_set":12,"id":"7f231b9d_d52016af","line":2,"range":{"start_line":2,"start_character":12,"end_line":2,"end_character":49},"updated":"2017-06-14 16:04:58.000000000","message":"This should be dtp - git review / rebase keeps screwing this up for me somehow.","commit_id":"9583e24deda2b2e7f7148e48f1f224db620a24e5"},{"author":{"_account_id":6873,"name":"Matt Riedemann","email":"mriedem.os@gmail.com","username":"mriedem"},"change_message_id":"4056eb0044cd53cda39d40fab5c23b59f37bc9fc","unresolved":false,"context_lines":[{"line_number":6,"context_line":""},{"line_number":7,"context_line":"Use uuid for id in os-services API"},{"line_number":8,"context_line":""},{"line_number":9,"context_line":"This patch introduces API version 2.49 to identify services by uuid"},{"line_number":10,"context_line":"instead of id, to ensure uniqueness across cells. GET /os-services"},{"line_number":11,"context_line":"returns uuid in the id field, and uuid must be provided to delete a"},{"line_number":12,"context_line":"service with DELETE /os-services/{service_uuid}."}],"source_content_type":"text/x-gerrit-commit-message","patch_set":20,"id":"3f1d235d_c3c27259","line":9,"range":{"start_line":9,"start_character":34,"end_line":9,"end_character":38},"updated":"2017-07-05 17:15:12.000000000","message":"2.50","commit_id":"2f3416367e2927905acf73166ce13b16d7b3d238"},{"author":{"_account_id":6873,"name":"Matt Riedemann","email":"mriedem.os@gmail.com","username":"mriedem"},"change_message_id":"4056eb0044cd53cda39d40fab5c23b59f37bc9fc","unresolved":false,"context_lines":[{"line_number":11,"context_line":"returns uuid in the id field, and uuid must be provided to delete a"},{"line_number":12,"context_line":"service with DELETE /os-services/{service_uuid}."},{"line_number":13,"context_line":""},{"line_number":14,"context_line":"The old PUT /os-services/* APIs are now capped at 2.48 and replaced"},{"line_number":15,"context_line":"with a new PUT /os-services/{service_uuid} which takes a uuid path"},{"line_number":16,"context_line":"parameter to uniquely identify the service to update. It also restricts"},{"line_number":17,"context_line":"updates to nova-compute services only, since disabling or forcing-down"}],"source_content_type":"text/x-gerrit-commit-message","patch_set":20,"id":"3f1d235d_83b8fae4","line":14,"range":{"start_line":14,"start_character":50,"end_line":14,"end_character":54},"updated":"2017-07-05 17:15:12.000000000","message":"2.49","commit_id":"2f3416367e2927905acf73166ce13b16d7b3d238"},{"author":{"_account_id":6873,"name":"Matt Riedemann","email":"mriedem.os@gmail.com","username":"mriedem"},"change_message_id":"4056eb0044cd53cda39d40fab5c23b59f37bc9fc","unresolved":false,"context_lines":[{"line_number":18,"context_line":"a non-compute service like nova-scheduler doesn\u0027t make sense as it"},{"line_number":19,"context_line":"doesn\u0027t do anything."},{"line_number":20,"context_line":""},{"line_number":21,"context_line":"The new update() method for 2.49 also avoids trying to re-use the"},{"line_number":22,"context_line":"existing private action methods like _enable and _disable since those"},{"line_number":23,"context_line":"are predicated on looking up the service by host/binary, are confusing"},{"line_number":24,"context_line":"to follow for code flow, and just don\u0027t really make sense with a pure"}],"source_content_type":"text/x-gerrit-commit-message","patch_set":20,"id":"3f1d235d_63d15e23","line":21,"range":{"start_line":21,"start_character":28,"end_line":21,"end_character":32},"updated":"2017-07-05 17:15:12.000000000","message":"2.50","commit_id":"2f3416367e2927905acf73166ce13b16d7b3d238"}],"api-ref/source/os-services.inc":[{"author":{"_account_id":2750,"name":"Sean Dague","email":"sean@dague.net","username":"sdague"},"change_message_id":"f95033c1c7df2dc226c1605eec2e6ff313590597","unresolved":false,"context_lines":[{"line_number":234,"context_line":"Update Service"},{"line_number":235,"context_line":"\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d"},{"line_number":236,"context_line":""},{"line_number":237,"context_line":".. rest_method:: PUT /os-services/{service_id}"},{"line_number":238,"context_line":""},{"line_number":239,"context_line":"Update a service to enable or disable scheduling, including recording a"},{"line_number":240,"context_line":"reason why a service was disabled from scheduling. Set or unset the"}],"source_content_type":"text/x-c++src","patch_set":11,"id":"7f231b9d_a24b4257","line":237,"range":{"start_line":237,"start_character":34,"end_line":237,"end_character":46},"updated":"2017-06-13 16:40:14.000000000","message":"service_id is not described below","commit_id":"203cae00c7434d9fa8b47a1965a237f6135e7a39"},{"author":{"_account_id":6873,"name":"Matt Riedemann","email":"mriedem.os@gmail.com","username":"mriedem"},"change_message_id":"4d41cf272ba832d82a1cc771a3dbc1664841aa60","unresolved":false,"context_lines":[{"line_number":231,"context_line":".. literalinclude:: ../../doc/api_samples/os-services/v2.11/service-force-down-put-resp.json"},{"line_number":232,"context_line":"   :language: javascript"},{"line_number":233,"context_line":""},{"line_number":234,"context_line":"Update Service"},{"line_number":235,"context_line":"\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d"},{"line_number":236,"context_line":""},{"line_number":237,"context_line":".. rest_method:: PUT /os-services/{service_id}"}],"source_content_type":"text/x-c++src","patch_set":12,"id":"7f231b9d_fa0661ce","line":234,"updated":"2017-06-14 15:22:09.000000000","message":"This should be called \"Update Compute Service\" since it\u0027s specifically only allowing nova-compute services.","commit_id":"9583e24deda2b2e7f7148e48f1f224db620a24e5"},{"author":{"_account_id":6873,"name":"Matt Riedemann","email":"mriedem.os@gmail.com","username":"mriedem"},"change_message_id":"4d41cf272ba832d82a1cc771a3dbc1664841aa60","unresolved":false,"context_lines":[{"line_number":236,"context_line":""},{"line_number":237,"context_line":".. rest_method:: PUT /os-services/{service_id}"},{"line_number":238,"context_line":""},{"line_number":239,"context_line":"Update a service to enable or disable scheduling, including recording a"},{"line_number":240,"context_line":"reason why a service was disabled from scheduling. Set or unset the"},{"line_number":241,"context_line":"``forced_down`` flag for the service."},{"line_number":242,"context_line":""}],"source_content_type":"text/x-c++src","patch_set":12,"id":"7f231b9d_da0ba5d3","line":239,"range":{"start_line":239,"start_character":9,"end_line":239,"end_character":16},"updated":"2017-06-14 15:22:09.000000000","message":"compute service","commit_id":"9583e24deda2b2e7f7148e48f1f224db620a24e5"},{"author":{"_account_id":6873,"name":"Matt Riedemann","email":"mriedem.os@gmail.com","username":"mriedem"},"change_message_id":"4d41cf272ba832d82a1cc771a3dbc1664841aa60","unresolved":false,"context_lines":[{"line_number":237,"context_line":".. rest_method:: PUT /os-services/{service_id}"},{"line_number":238,"context_line":""},{"line_number":239,"context_line":"Update a service to enable or disable scheduling, including recording a"},{"line_number":240,"context_line":"reason why a service was disabled from scheduling. Set or unset the"},{"line_number":241,"context_line":"``forced_down`` flag for the service."},{"line_number":242,"context_line":""},{"line_number":243,"context_line":"This API is available starting with microversion 2.49."}],"source_content_type":"text/x-c++src","patch_set":12,"id":"7f231b9d_7afa51bd","line":240,"range":{"start_line":240,"start_character":13,"end_line":240,"end_character":20},"updated":"2017-06-14 15:22:09.000000000","message":"compute service","commit_id":"9583e24deda2b2e7f7148e48f1f224db620a24e5"}],"api-ref/source/parameters.yaml":[{"author":{"_account_id":5754,"name":"Alex Xu","email":"hejie.xu@intel.com","username":"xuhj"},"change_message_id":"76b05f6e3917971299c072a4b55d685bebd51038","unresolved":false,"context_lines":[{"line_number":1870,"context_line":"# in microversion 2.50."},{"line_number":1871,"context_line":"disabled_reason_2_50_in:"},{"line_number":1872,"context_line":"  description: |"},{"line_number":1873,"context_line":"    The reason for disabling a service."},{"line_number":1874,"context_line":"  in: body"},{"line_number":1875,"context_line":"  required: false"},{"line_number":1876,"context_line":"  type: string"}],"source_content_type":"text/x-yaml","patch_set":21,"id":"3f1d235d_0868ec84","line":1873,"updated":"2017-07-11 08:01:27.000000000","message":"we can say the max length is 255 and the min length is 1","commit_id":"f04c39bbf8e23cfbd07db0bb34548b7ea8e62fdb"},{"author":{"_account_id":6873,"name":"Matt Riedemann","email":"mriedem.os@gmail.com","username":"mriedem"},"change_message_id":"fa5555d21af2bb3119c43d5ea2336e0898786a6d","unresolved":false,"context_lines":[{"line_number":1870,"context_line":"# in microversion 2.50."},{"line_number":1871,"context_line":"disabled_reason_2_50_in:"},{"line_number":1872,"context_line":"  description: |"},{"line_number":1873,"context_line":"    The reason for disabling a service."},{"line_number":1874,"context_line":"  in: body"},{"line_number":1875,"context_line":"  required: false"},{"line_number":1876,"context_line":"  type: string"}],"source_content_type":"text/x-yaml","patch_set":21,"id":"3f1d235d_c94e6c37","line":1873,"in_reply_to":"3f1d235d_0868ec84","updated":"2017-07-11 15:02:32.000000000","message":"OK - and also amend disabled_reason_body below then since they are for the same thing?","commit_id":"f04c39bbf8e23cfbd07db0bb34548b7ea8e62fdb"},{"author":{"_account_id":6873,"name":"Matt Riedemann","email":"mriedem.os@gmail.com","username":"mriedem"},"change_message_id":"0d20899fb366dd3b450abd6192f56994c3cd1d3a","unresolved":false,"context_lines":[{"line_number":1870,"context_line":"# in microversion 2.50."},{"line_number":1871,"context_line":"disabled_reason_2_50_in:"},{"line_number":1872,"context_line":"  description: |"},{"line_number":1873,"context_line":"    The reason for disabling a service."},{"line_number":1874,"context_line":"  in: body"},{"line_number":1875,"context_line":"  required: false"},{"line_number":1876,"context_line":"  type: string"}],"source_content_type":"text/x-yaml","patch_set":21,"id":"1f1a1f67_8a58f655","line":1873,"in_reply_to":"3f1d235d_c94e6c37","updated":"2017-07-18 19:35:46.000000000","message":"Actually I won\u0027t update disabled_reason_body since it\u0027s used in both the request (PUT /os-services/service_id/disable-log-reason) and response. I don\u0027t want the min/max stuff in the response text.","commit_id":"f04c39bbf8e23cfbd07db0bb34548b7ea8e62fdb"}],"nova/api/openstack/compute/rest_api_version_history.rst":[{"author":{"_account_id":5754,"name":"Alex Xu","email":"hejie.xu@intel.com","username":"xuhj"},"change_message_id":"5a407319420d51b31f8b2568fb690e680dd68d9d","unresolved":false,"context_lines":[{"line_number":576,"context_line":"  * ``GET /os-services`` returns a uuid in the ``id`` field of the response"},{"line_number":577,"context_line":"  * ``DELETE /os-services/{service_uuid}`` requires a service uuid in the path"},{"line_number":578,"context_line":"  * The following APIs have been superseded by"},{"line_number":579,"context_line":"    ``PUT /os-services/{service_uuid/``:"},{"line_number":580,"context_line":""},{"line_number":581,"context_line":"    * ``PUT /os-services/disable``"},{"line_number":582,"context_line":"    * ``PUT /os-services/disable-log-reason``"}],"source_content_type":"text/x-rst","patch_set":16,"id":"7f231b9d_be019207","line":579,"range":{"start_line":579,"start_character":23,"end_line":579,"end_character":36},"updated":"2017-06-19 09:42:49.000000000","message":"miss a \u0027}\u0027","commit_id":"080f04b010ebb4408b4732e6ccc3c15780fbccd1"},{"author":{"_account_id":6873,"name":"Matt Riedemann","email":"mriedem.os@gmail.com","username":"mriedem"},"change_message_id":"33024c5b0cc7d84abbaff8df4d57824e32bef2f0","unresolved":false,"context_lines":[{"line_number":576,"context_line":"  * ``GET /os-services`` returns a uuid in the ``id`` field of the response"},{"line_number":577,"context_line":"  * ``DELETE /os-services/{service_uuid}`` requires a service uuid in the path"},{"line_number":578,"context_line":"  * The following APIs have been superseded by"},{"line_number":579,"context_line":"    ``PUT /os-services/{service_uuid/``:"},{"line_number":580,"context_line":""},{"line_number":581,"context_line":"    * ``PUT /os-services/disable``"},{"line_number":582,"context_line":"    * ``PUT /os-services/disable-log-reason``"}],"source_content_type":"text/x-rst","patch_set":16,"id":"7f231b9d_3db69e8b","line":579,"range":{"start_line":579,"start_character":23,"end_line":579,"end_character":36},"in_reply_to":"7f231b9d_be019207","updated":"2017-06-19 15:18:34.000000000","message":"Done","commit_id":"080f04b010ebb4408b4732e6ccc3c15780fbccd1"}],"nova/api/openstack/compute/schemas/services.py":[{"author":{"_account_id":5754,"name":"Alex Xu","email":"hejie.xu@intel.com","username":"xuhj"},"change_message_id":"5a407319420d51b31f8b2568fb690e680dd68d9d","unresolved":false,"context_lines":[{"line_number":57,"context_line":"            \u0027type\u0027: \u0027string\u0027,"},{"line_number":58,"context_line":"            \u0027enum\u0027: [\u0027enabled\u0027, \u0027disabled\u0027],"},{"line_number":59,"context_line":"        },"},{"line_number":60,"context_line":"        \u0027disabled_reason\u0027: {"},{"line_number":61,"context_line":"            \u0027type\u0027: \u0027string\u0027, \u0027minLength\u0027: 1, \u0027maxLength\u0027: 255,"},{"line_number":62,"context_line":"        },"},{"line_number":63,"context_line":"        \u0027forced_down\u0027: parameter_types.boolean"}],"source_content_type":"text/x-python","patch_set":16,"id":"7f231b9d_1e6766eb","line":60,"updated":"2017-06-19 09:42:49.000000000","message":"Specify a \u0027disabled_reason\u0027 without \u0027status\u003ddisable\u0027 should return 400 to the user I guess.","commit_id":"080f04b010ebb4408b4732e6ccc3c15780fbccd1"},{"author":{"_account_id":6873,"name":"Matt Riedemann","email":"mriedem.os@gmail.com","username":"mriedem"},"change_message_id":"33024c5b0cc7d84abbaff8df4d57824e32bef2f0","unresolved":false,"context_lines":[{"line_number":57,"context_line":"            \u0027type\u0027: \u0027string\u0027,"},{"line_number":58,"context_line":"            \u0027enum\u0027: [\u0027enabled\u0027, \u0027disabled\u0027],"},{"line_number":59,"context_line":"        },"},{"line_number":60,"context_line":"        \u0027disabled_reason\u0027: {"},{"line_number":61,"context_line":"            \u0027type\u0027: \u0027string\u0027, \u0027minLength\u0027: 1, \u0027maxLength\u0027: 255,"},{"line_number":62,"context_line":"        },"},{"line_number":63,"context_line":"        \u0027forced_down\u0027: parameter_types.boolean"}],"source_content_type":"text/x-python","patch_set":16,"id":"7f231b9d_9da4924c","line":60,"in_reply_to":"7f231b9d_1e6766eb","updated":"2017-06-19 15:18:34.000000000","message":"Is it possible to define conditionals within jsonschema such that status\u003d\u0027disabled\u0027 if disabled_reason is provided? Otherwise I\u0027m not sure what you\u0027re saying here. Are you asking me to change something in the schema?","commit_id":"080f04b010ebb4408b4732e6ccc3c15780fbccd1"},{"author":{"_account_id":5754,"name":"Alex Xu","email":"hejie.xu@intel.com","username":"xuhj"},"change_message_id":"2060d3fa57b99a0a87e4b2277ecb6a3315e1f342","unresolved":false,"context_lines":[{"line_number":57,"context_line":"            \u0027type\u0027: \u0027string\u0027,"},{"line_number":58,"context_line":"            \u0027enum\u0027: [\u0027enabled\u0027, \u0027disabled\u0027],"},{"line_number":59,"context_line":"        },"},{"line_number":60,"context_line":"        \u0027disabled_reason\u0027: {"},{"line_number":61,"context_line":"            \u0027type\u0027: \u0027string\u0027, \u0027minLength\u0027: 1, \u0027maxLength\u0027: 255,"},{"line_number":62,"context_line":"        },"},{"line_number":63,"context_line":"        \u0027forced_down\u0027: parameter_types.boolean"}],"source_content_type":"text/x-python","patch_set":16,"id":"7f231b9d_f308472e","line":60,"in_reply_to":"7f231b9d_9da4924c","updated":"2017-06-20 00:58:51.000000000","message":"We can implement that check in the python code. Sorry I commented in the wrong place.","commit_id":"080f04b010ebb4408b4732e6ccc3c15780fbccd1"},{"author":{"_account_id":5754,"name":"Alex Xu","email":"hejie.xu@intel.com","username":"xuhj"},"change_message_id":"5a407319420d51b31f8b2568fb690e680dd68d9d","unresolved":false,"context_lines":[{"line_number":60,"context_line":"        \u0027disabled_reason\u0027: {"},{"line_number":61,"context_line":"            \u0027type\u0027: \u0027string\u0027, \u0027minLength\u0027: 1, \u0027maxLength\u0027: 255,"},{"line_number":62,"context_line":"        },"},{"line_number":63,"context_line":"        \u0027forced_down\u0027: parameter_types.boolean"},{"line_number":64,"context_line":"    },"},{"line_number":65,"context_line":"    \u0027additionalProperties\u0027: False"},{"line_number":66,"context_line":"}"}],"source_content_type":"text/x-python","patch_set":16,"id":"7f231b9d_de5c4e1a","line":63,"updated":"2017-06-19 09:42:49.000000000","message":"Specify \u0027forced_down\u0027 and \u0027status\u0027 at same time, sounds ok？","commit_id":"080f04b010ebb4408b4732e6ccc3c15780fbccd1"},{"author":{"_account_id":6873,"name":"Matt Riedemann","email":"mriedem.os@gmail.com","username":"mriedem"},"change_message_id":"33024c5b0cc7d84abbaff8df4d57824e32bef2f0","unresolved":false,"context_lines":[{"line_number":60,"context_line":"        \u0027disabled_reason\u0027: {"},{"line_number":61,"context_line":"            \u0027type\u0027: \u0027string\u0027, \u0027minLength\u0027: 1, \u0027maxLength\u0027: 255,"},{"line_number":62,"context_line":"        },"},{"line_number":63,"context_line":"        \u0027forced_down\u0027: parameter_types.boolean"},{"line_number":64,"context_line":"    },"},{"line_number":65,"context_line":"    \u0027additionalProperties\u0027: False"},{"line_number":66,"context_line":"}"}],"source_content_type":"text/x-python","patch_set":16,"id":"7f231b9d_9d525234","line":63,"in_reply_to":"7f231b9d_de5c4e1a","updated":"2017-06-19 15:18:34.000000000","message":"Yes, you can do that now in this microversion. For example, I could specify:\n\n{\n  \u0027status\u0027: \u0027disabled\u0027,\n  \u0027disabled_reason\u0027: \u0027Hardware fault detected. Initiating evacuation.\u0027,\n  \u0027forced_down\u0027: \u0027true\u0027\n}","commit_id":"080f04b010ebb4408b4732e6ccc3c15780fbccd1"}],"nova/api/openstack/compute/services.py":[{"author":{"_account_id":5754,"name":"Alex Xu","email":"hejie.xu@intel.com","username":"xuhj"},"change_message_id":"b57a383ad0fab8bd08c70f733af3efd8821fa4c6","unresolved":false,"context_lines":[{"line_number":67,"context_line":""},{"line_number":68,"context_line":"        return _services"},{"line_number":69,"context_line":""},{"line_number":70,"context_line":"    def _get_service_detail(self, svc, additional_fields, req\u003dNone):"},{"line_number":71,"context_line":"        alive \u003d self.servicegroup_api.service_is_up(svc)"},{"line_number":72,"context_line":"        state \u003d (alive and \"up\") or \"down\""},{"line_number":73,"context_line":"        active \u003d \u0027enabled\u0027"}],"source_content_type":"text/x-python","patch_set":2,"id":"1f013ff3_f99a60c3","line":70,"range":{"start_line":70,"start_character":61,"end_line":70,"end_character":66},"updated":"2017-05-15 09:17:12.000000000","message":"We needn\u0027t this default value. As you always pass the req down at line 96","commit_id":"6c717170713c378d9708f53e8a09566f21772b5f"},{"author":{"_account_id":23882,"name":"Dan Peschman","email":"dpeschman@godaddy.com","username":"dtp"},"change_message_id":"bc6261299b30f49e47f7abaee9a6414a569ce1bc","unresolved":false,"context_lines":[{"line_number":67,"context_line":""},{"line_number":68,"context_line":"        return _services"},{"line_number":69,"context_line":""},{"line_number":70,"context_line":"    def _get_service_detail(self, svc, additional_fields, req\u003dNone):"},{"line_number":71,"context_line":"        alive \u003d self.servicegroup_api.service_is_up(svc)"},{"line_number":72,"context_line":"        state \u003d (alive and \"up\") or \"down\""},{"line_number":73,"context_line":"        active \u003d \u0027enabled\u0027"}],"source_content_type":"text/x-python","patch_set":2,"id":"ff0f0b1f_98c14e57","line":70,"in_reply_to":"1f013ff3_f99a60c3","updated":"2017-05-25 00:31:28.000000000","message":"Done","commit_id":"6c717170713c378d9708f53e8a09566f21772b5f"},{"author":{"_account_id":5754,"name":"Alex Xu","email":"hejie.xu@intel.com","username":"xuhj"},"change_message_id":"b57a383ad0fab8bd08c70f733af3efd8821fa4c6","unresolved":false,"context_lines":[{"line_number":74,"context_line":"        if svc[\u0027disabled\u0027]:"},{"line_number":75,"context_line":"            active \u003d \u0027disabled\u0027"},{"line_number":76,"context_line":""},{"line_number":77,"context_line":"        uuid_for_id \u003d req and api_version_request.is_supported("},{"line_number":78,"context_line":"            req, min_version\u003dUUID_FOR_ID_MIN_VERSION)"},{"line_number":79,"context_line":""},{"line_number":80,"context_line":"        service_detail \u003d {\u0027binary\u0027: svc[\u0027binary\u0027],"}],"source_content_type":"text/x-python","patch_set":2,"id":"1f013ff3_d99fa4b2","line":77,"range":{"start_line":77,"start_character":22,"end_line":77,"end_character":25},"updated":"2017-05-15 09:17:12.000000000","message":"We needn\u0027t this check, As you always pass the req down at line 96","commit_id":"6c717170713c378d9708f53e8a09566f21772b5f"},{"author":{"_account_id":23882,"name":"Dan Peschman","email":"dpeschman@godaddy.com","username":"dtp"},"change_message_id":"bc6261299b30f49e47f7abaee9a6414a569ce1bc","unresolved":false,"context_lines":[{"line_number":74,"context_line":"        if svc[\u0027disabled\u0027]:"},{"line_number":75,"context_line":"            active \u003d \u0027disabled\u0027"},{"line_number":76,"context_line":""},{"line_number":77,"context_line":"        uuid_for_id \u003d req and api_version_request.is_supported("},{"line_number":78,"context_line":"            req, min_version\u003dUUID_FOR_ID_MIN_VERSION)"},{"line_number":79,"context_line":""},{"line_number":80,"context_line":"        service_detail \u003d {\u0027binary\u0027: svc[\u0027binary\u0027],"}],"source_content_type":"text/x-python","patch_set":2,"id":"ff0f0b1f_78b43af2","line":77,"in_reply_to":"1f013ff3_d99fa4b2","updated":"2017-05-25 00:31:28.000000000","message":"Done","commit_id":"6c717170713c378d9708f53e8a09566f21772b5f"},{"author":{"_account_id":5754,"name":"Alex Xu","email":"hejie.xu@intel.com","username":"xuhj"},"change_message_id":"b57a383ad0fab8bd08c70f733af3efd8821fa4c6","unresolved":false,"context_lines":[{"line_number":209,"context_line":"            explanation \u003d _(\"Service %s not found.\") % id"},{"line_number":210,"context_line":"            raise webob.exc.HTTPNotFound(explanation\u003dexplanation)"},{"line_number":211,"context_line":"        except exception.ServiceNotUnique:"},{"line_number":212,"context_line":"            explanation \u003d _(\"Service id %s refers to multiple services.\") % id"},{"line_number":213,"context_line":"            raise webob.exc.HTTPBadRequest(explanation\u003dexplanation)"},{"line_number":214,"context_line":""},{"line_number":215,"context_line":"    @extensions.expected_errors(())"}],"source_content_type":"text/x-python","patch_set":2,"id":"1f013ff3_b92178a2","line":212,"updated":"2017-05-15 09:17:12.000000000","message":"How about we update the message to mention that the user should use \u0027uuid\u0027 and with microversion 2.46?","commit_id":"6c717170713c378d9708f53e8a09566f21772b5f"},{"author":{"_account_id":23882,"name":"Dan Peschman","email":"dpeschman@godaddy.com","username":"dtp"},"change_message_id":"416689e8ee2d9cb8ceccf5dc4d4ead7371962e30","unresolved":false,"context_lines":[{"line_number":209,"context_line":"            explanation \u003d _(\"Service %s not found.\") % id"},{"line_number":210,"context_line":"            raise webob.exc.HTTPNotFound(explanation\u003dexplanation)"},{"line_number":211,"context_line":"        except exception.ServiceNotUnique:"},{"line_number":212,"context_line":"            explanation \u003d _(\"Service id %s refers to multiple services.\") % id"},{"line_number":213,"context_line":"            raise webob.exc.HTTPBadRequest(explanation\u003dexplanation)"},{"line_number":214,"context_line":""},{"line_number":215,"context_line":"    @extensions.expected_errors(())"}],"source_content_type":"text/x-python","patch_set":2,"id":"ff0f0b1f_ec89b674","line":212,"in_reply_to":"1f013ff3_b92178a2","updated":"2017-05-24 18:17:53.000000000","message":"Line 188 will return a 400 \"Invalid uuid\" if they send in an integer id after version 2.46.  So integer ids cannot be used, and the reason why is returned.  Does that cover what you wanted?","commit_id":"6c717170713c378d9708f53e8a09566f21772b5f"},{"author":{"_account_id":6873,"name":"Matt Riedemann","email":"mriedem.os@gmail.com","username":"mriedem"},"change_message_id":"52ed6994a85b043d96eb44982bc54c5fe2383d58","unresolved":false,"context_lines":[{"line_number":50,"context_line":""},{"line_number":51,"context_line":"        _services \u003d ["},{"line_number":52,"context_line":"           s"},{"line_number":53,"context_line":"           for s in self.host_api.service_get_all(context, set_zones\u003dTrue,"},{"line_number":54,"context_line":"                                                  all_cells\u003dTrue)"},{"line_number":55,"context_line":"           if s[\u0027binary\u0027] not in api_services"},{"line_number":56,"context_line":"        ]"}],"source_content_type":"text/x-python","patch_set":9,"id":"7f231b9d_675af82a","line":53,"range":{"start_line":53,"start_character":59,"end_line":53,"end_character":73},"updated":"2017-06-12 23:39:43.000000000","message":"This is the thing that would eventually make the HostAPI set the AZ on the returned services.","commit_id":"158753eddfed3eb1ae4ee770e7979f4f90ee82f9"},{"author":{"_account_id":23882,"name":"Dan Peschman","email":"dpeschman@godaddy.com","username":"dtp"},"change_message_id":"21b0db19c835d6c55ee7434c48df7104640eb545","unresolved":false,"context_lines":[{"line_number":79,"context_line":"        uuid_for_id \u003d api_version_request.is_supported("},{"line_number":80,"context_line":"            req, min_version\u003dUUID_FOR_ID_MIN_VERSION)"},{"line_number":81,"context_line":""},{"line_number":82,"context_line":"        if \u0027availability_zone\u0027 not in svc:"},{"line_number":83,"context_line":"            # The service wasn\u0027t loaded with the AZ so we need to do it here."},{"line_number":84,"context_line":"            # Yes this looks weird, but set_availability_zones makes a copy of"},{"line_number":85,"context_line":"            # the list passed in and mutates the objects within it, so we have"}],"source_content_type":"text/x-python","patch_set":9,"id":"7f231b9d_a42b6e80","line":82,"updated":"2017-06-12 22:54:17.000000000","message":"Was this a bug or just broken?","commit_id":"158753eddfed3eb1ae4ee770e7979f4f90ee82f9"},{"author":{"_account_id":6873,"name":"Matt Riedemann","email":"mriedem.os@gmail.com","username":"mriedem"},"change_message_id":"52ed6994a85b043d96eb44982bc54c5fe2383d58","unresolved":false,"context_lines":[{"line_number":79,"context_line":"        uuid_for_id \u003d api_version_request.is_supported("},{"line_number":80,"context_line":"            req, min_version\u003dUUID_FOR_ID_MIN_VERSION)"},{"line_number":81,"context_line":""},{"line_number":82,"context_line":"        if \u0027availability_zone\u0027 not in svc:"},{"line_number":83,"context_line":"            # The service wasn\u0027t loaded with the AZ so we need to do it here."},{"line_number":84,"context_line":"            # Yes this looks weird, but set_availability_zones makes a copy of"},{"line_number":85,"context_line":"            # the list passed in and mutates the objects within it, so we have"}],"source_content_type":"text/x-python","patch_set":9,"id":"7f231b9d_e73048eb","line":82,"in_reply_to":"7f231b9d_a42b6e80","updated":"2017-06-12 23:39:43.000000000","message":"No, this method was just used for listing services before, and the way we got those was different, which included setting the availability_zone attribute on the instance before we got this far. Now that I\u0027m pulling the Service object via the HostAPI differently, it wasn\u0027t getting the AZ set. Changing that would require changing the HostAPI interface, which would mean changes to cells v1, which I want to avoid.","commit_id":"158753eddfed3eb1ae4ee770e7979f4f90ee82f9"},{"author":{"_account_id":23882,"name":"Dan Peschman","email":"dpeschman@godaddy.com","username":"dtp"},"change_message_id":"21b0db19c835d6c55ee7434c48df7104640eb545","unresolved":false,"context_lines":[{"line_number":87,"context_line":"            svc.availability_zone \u003d ("},{"line_number":88,"context_line":"                availability_zones.set_availability_zones("},{"line_number":89,"context_line":"                    req.environ[\u0027nova.context\u0027],"},{"line_number":90,"context_line":"                    [svc])[0][\u0027availability_zone\u0027])"},{"line_number":91,"context_line":""},{"line_number":92,"context_line":"        service_detail \u003d {\u0027binary\u0027: svc[\u0027binary\u0027],"},{"line_number":93,"context_line":"                          \u0027host\u0027: svc[\u0027host\u0027],"}],"source_content_type":"text/x-python","patch_set":9,"id":"7f231b9d_0436a2e7","line":90,"updated":"2017-06-12 22:54:17.000000000","message":"Very strange.","commit_id":"158753eddfed3eb1ae4ee770e7979f4f90ee82f9"},{"author":{"_account_id":6873,"name":"Matt Riedemann","email":"mriedem.os@gmail.com","username":"mriedem"},"change_message_id":"6809ad801eb9e0da66b9f52355ddc5b537b21d28","unresolved":false,"context_lines":[{"line_number":278,"context_line":""},{"line_number":279,"context_line":"        # Get the service by uuid."},{"line_number":280,"context_line":"        try:"},{"line_number":281,"context_line":"            service \u003d self.host_api.service_get_by_id(context, service_id)"},{"line_number":282,"context_line":"            # At this point the context is targeted to the cell that the"},{"line_number":283,"context_line":"            # service was found in so we don\u0027t need to do any explicit cell"},{"line_number":284,"context_line":"            # targeting below."}],"source_content_type":"text/x-python","patch_set":9,"id":"7f231b9d_c79b0cc7","line":281,"updated":"2017-06-12 23:45:13.000000000","message":"One thing we need to discuss, is with the PUTs on the previous microversions, those would only work with *compute* services because of how they were looked up. They were looked up via the HostMapping in the API DB to find which cell they were in, and host mappings only exist for compute services. It also wouldn\u0027t really make sense to disable a nova-scheduler service since that doesn\u0027t mean anything.\n\nSo, we should probably put a check in here that it\u0027s a nova-compute binary otherwise it\u0027s a 400 error.\n\nOr we could argue that we broke those APIs when adding cells-aware support such that they would only work if there was a host mapping, thus restricting them to nova-compute services. And we could make this the fix, by allowing you to disable non-compute services, if for whatever reason you needed to do that.","commit_id":"158753eddfed3eb1ae4ee770e7979f4f90ee82f9"},{"author":{"_account_id":23882,"name":"Dan Peschman","email":"dpeschman@godaddy.com","username":"dtp"},"change_message_id":"dbd8a70508bf10f0ab2b06c46942e073896c7a50","unresolved":false,"context_lines":[{"line_number":278,"context_line":""},{"line_number":279,"context_line":"        # Get the service by uuid."},{"line_number":280,"context_line":"        try:"},{"line_number":281,"context_line":"            service \u003d self.host_api.service_get_by_id(context, service_id)"},{"line_number":282,"context_line":"            # At this point the context is targeted to the cell that the"},{"line_number":283,"context_line":"            # service was found in so we don\u0027t need to do any explicit cell"},{"line_number":284,"context_line":"            # targeting below."}],"source_content_type":"text/x-python","patch_set":9,"id":"7f231b9d_78bba0c3","line":281,"in_reply_to":"7f231b9d_c79b0cc7","updated":"2017-06-13 16:21:13.000000000","message":"Huh.  Yeah, I think returning the error is more appropriate in this case.","commit_id":"158753eddfed3eb1ae4ee770e7979f4f90ee82f9"},{"author":{"_account_id":6873,"name":"Matt Riedemann","email":"mriedem.os@gmail.com","username":"mriedem"},"change_message_id":"b78197c3bcca648f731f67158f8f1e8efcc47dac","unresolved":false,"context_lines":[{"line_number":285,"context_line":"        except exception.ServiceNotFound as e:"},{"line_number":286,"context_line":"            raise webob.exc.HTTPNotFound(explanation\u003de.format_message())"},{"line_number":287,"context_line":""},{"line_number":288,"context_line":"        # TODO(mriedem): Return 400 if service.binary is not nova-compute;"},{"line_number":289,"context_line":"        # Before the earlier PUT handlers were made cells-aware, you could"},{"line_number":290,"context_line":"        # technically disable a nova-scheduler service, although that doesn\u0027t"},{"line_number":291,"context_line":"        # really do anything within Nova and is just confusing. Now trying to"}],"source_content_type":"text/x-python","patch_set":11,"id":"7f231b9d_05b680da","line":288,"updated":"2017-06-13 17:35:59.000000000","message":"Posted to the operators and dev lists:\n\nhttp://lists.openstack.org/pipermail/openstack-operators/2017-June/013761.html","commit_id":"203cae00c7434d9fa8b47a1965a237f6135e7a39"},{"author":{"_account_id":6873,"name":"Matt Riedemann","email":"mriedem.os@gmail.com","username":"mriedem"},"change_message_id":"4e52f0f4e7a22e42be0fdba45c265c2661e604d4","unresolved":false,"context_lines":[{"line_number":285,"context_line":"        except exception.ServiceNotFound as e:"},{"line_number":286,"context_line":"            raise webob.exc.HTTPNotFound(explanation\u003de.format_message())"},{"line_number":287,"context_line":""},{"line_number":288,"context_line":"        # Return 400 if service.binary is not nova-compute."},{"line_number":289,"context_line":"        # Before the earlier PUT handlers were made cells-aware, you could"},{"line_number":290,"context_line":"        # technically disable a nova-scheduler service, although that doesn\u0027t"},{"line_number":291,"context_line":"        # really do anything within Nova and is just confusing. Now trying to"},{"line_number":292,"context_line":"        # do that will fail as a nova-scheduler service won\u0027t have a host"},{"line_number":293,"context_line":"        # mapping so you\u0027ll get a 404. In this new microversion, we close that"},{"line_number":294,"context_line":"        # old gap and make sure you can only enable/disable and set forced_down"},{"line_number":295,"context_line":"        # on nova-compute services since those are the only ones that make"},{"line_number":296,"context_line":"        # sense to update for those operations."},{"line_number":297,"context_line":"        if service.binary !\u003d \u0027nova-compute\u0027:"},{"line_number":298,"context_line":"            msg \u003d (_(\u0027Updating a %(binary)s service is not supported.\u0027) %"},{"line_number":299,"context_line":"                   {\u0027binary\u0027: service.binary})"}],"source_content_type":"text/x-python","patch_set":12,"id":"7f231b9d_756b82b6","line":296,"range":{"start_line":288,"start_character":8,"end_line":296,"end_character":47},"updated":"2017-06-14 15:37:23.000000000","message":"Per http://lists.openstack.org/pipermail/openstack-operators/2017-June/013771.html I\u0027m going to push a bug fix such that auto-disabling of newly created services is restricted to nova-compute binaries. That will happen separately.","commit_id":"9583e24deda2b2e7f7148e48f1f224db620a24e5"},{"author":{"_account_id":5754,"name":"Alex Xu","email":"hejie.xu@intel.com","username":"xuhj"},"change_message_id":"5a407319420d51b31f8b2568fb690e680dd68d9d","unresolved":false,"context_lines":[{"line_number":295,"context_line":"        # on nova-compute services since those are the only ones that make"},{"line_number":296,"context_line":"        # sense to update for those operations."},{"line_number":297,"context_line":"        if service.binary !\u003d \u0027nova-compute\u0027:"},{"line_number":298,"context_line":"            msg \u003d (_(\u0027Updating a %(binary)s service is not supported.\u0027) %"},{"line_number":299,"context_line":"                   {\u0027binary\u0027: service.binary})"},{"line_number":300,"context_line":"            raise webob.exc.HTTPBadRequest(explanation\u003dmsg)"},{"line_number":301,"context_line":""}],"source_content_type":"text/x-python","patch_set":16,"id":"7f231b9d_63a00143","line":298,"updated":"2017-06-19 09:42:49.000000000","message":"nit, maybe also say only \u0027nova-compute\u0027 service can be updated.","commit_id":"080f04b010ebb4408b4732e6ccc3c15780fbccd1"},{"author":{"_account_id":6873,"name":"Matt Riedemann","email":"mriedem.os@gmail.com","username":"mriedem"},"change_message_id":"33024c5b0cc7d84abbaff8df4d57824e32bef2f0","unresolved":false,"context_lines":[{"line_number":295,"context_line":"        # on nova-compute services since those are the only ones that make"},{"line_number":296,"context_line":"        # sense to update for those operations."},{"line_number":297,"context_line":"        if service.binary !\u003d \u0027nova-compute\u0027:"},{"line_number":298,"context_line":"            msg \u003d (_(\u0027Updating a %(binary)s service is not supported.\u0027) %"},{"line_number":299,"context_line":"                   {\u0027binary\u0027: service.binary})"},{"line_number":300,"context_line":"            raise webob.exc.HTTPBadRequest(explanation\u003dmsg)"},{"line_number":301,"context_line":""}],"source_content_type":"text/x-python","patch_set":16,"id":"7f231b9d_9d7932c6","line":298,"in_reply_to":"7f231b9d_63a00143","updated":"2017-06-19 15:18:34.000000000","message":"Yeah I can add that.","commit_id":"080f04b010ebb4408b4732e6ccc3c15780fbccd1"},{"author":{"_account_id":5754,"name":"Alex Xu","email":"hejie.xu@intel.com","username":"xuhj"},"change_message_id":"5a407319420d51b31f8b2568fb690e680dd68d9d","unresolved":false,"context_lines":[{"line_number":319,"context_line":"                body[\u0027forced_down\u0027], strict\u003dTrue)"},{"line_number":320,"context_line":""},{"line_number":321,"context_line":"        # Now save our updates to the service record in the database."},{"line_number":322,"context_line":"        service.save()"},{"line_number":323,"context_line":""},{"line_number":324,"context_line":"        # Return the full service record details."},{"line_number":325,"context_line":"        additional_fields \u003d [\u0027forced_down\u0027]"}],"source_content_type":"text/x-python","patch_set":16,"id":"7f231b9d_43062554","line":322,"updated":"2017-06-19 09:42:49.000000000","message":"Emm....Thinking of whether we should allow an empty update.\n\nMaybe we should return 400 for avoid user send wrong request.","commit_id":"080f04b010ebb4408b4732e6ccc3c15780fbccd1"},{"author":{"_account_id":6873,"name":"Matt Riedemann","email":"mriedem.os@gmail.com","username":"mriedem"},"change_message_id":"33024c5b0cc7d84abbaff8df4d57824e32bef2f0","unresolved":false,"context_lines":[{"line_number":319,"context_line":"                body[\u0027forced_down\u0027], strict\u003dTrue)"},{"line_number":320,"context_line":""},{"line_number":321,"context_line":"        # Now save our updates to the service record in the database."},{"line_number":322,"context_line":"        service.save()"},{"line_number":323,"context_line":""},{"line_number":324,"context_line":"        # Return the full service record details."},{"line_number":325,"context_line":"        additional_fields \u003d [\u0027forced_down\u0027]"}],"source_content_type":"text/x-python","patch_set":16,"id":"7f231b9d_3d445e73","line":322,"in_reply_to":"7f231b9d_43062554","updated":"2017-06-19 15:18:34.000000000","message":"Yeah good point since nothing is required in the schema. I\u0027ll add a check for that.","commit_id":"080f04b010ebb4408b4732e6ccc3c15780fbccd1"},{"author":{"_account_id":5754,"name":"Alex Xu","email":"hejie.xu@intel.com","username":"xuhj"},"change_message_id":"15a1d45ce2fe7e3d4832a629c3334d18dd2968f5","unresolved":false,"context_lines":[{"line_number":205,"context_line":"            try:"},{"line_number":206,"context_line":"                utils.validate_integer(id, \u0027id\u0027)"},{"line_number":207,"context_line":"            except exception.InvalidInput as exc:"},{"line_number":208,"context_line":"                raise webob.exc.HTTPBadRequest("},{"line_number":209,"context_line":"                    explanation\u003dexc.format_message())"},{"line_number":210,"context_line":""},{"line_number":211,"context_line":"        try:"},{"line_number":212,"context_line":"            service \u003d self.host_api.service_get_by_id(context, id)"}],"source_content_type":"text/x-python","patch_set":21,"id":"3f1d235d_a8b578f0","line":209,"range":{"start_line":208,"start_character":17,"end_line":209,"end_character":53},"updated":"2017-07-11 08:04:22.000000000","message":"This should be HTTPNotFound, otherwise we changed the API behaviour in the old version.","commit_id":"f04c39bbf8e23cfbd07db0bb34548b7ea8e62fdb"},{"author":{"_account_id":6873,"name":"Matt Riedemann","email":"mriedem.os@gmail.com","username":"mriedem"},"change_message_id":"fa5555d21af2bb3119c43d5ea2336e0898786a6d","unresolved":false,"context_lines":[{"line_number":205,"context_line":"            try:"},{"line_number":206,"context_line":"                utils.validate_integer(id, \u0027id\u0027)"},{"line_number":207,"context_line":"            except exception.InvalidInput as exc:"},{"line_number":208,"context_line":"                raise webob.exc.HTTPBadRequest("},{"line_number":209,"context_line":"                    explanation\u003dexc.format_message())"},{"line_number":210,"context_line":""},{"line_number":211,"context_line":"        try:"},{"line_number":212,"context_line":"            service \u003d self.host_api.service_get_by_id(context, id)"}],"source_content_type":"text/x-python","patch_set":21,"id":"3f1d235d_c9c30c57","line":209,"range":{"start_line":208,"start_character":17,"end_line":209,"end_character":53},"in_reply_to":"3f1d235d_a8b578f0","updated":"2017-07-11 15:02:32.000000000","message":"Not necessarily, if you passed id\u003d1 and you have multiple cells then you\u0027re going to get ServiceNotUnique which returns a 400.\n\nAlso, this else block is exactly the same as before the new microversion:\n\nhttps://review.openstack.org/#/c/464280/21/nova/api/openstack/compute/services.py@a185","commit_id":"f04c39bbf8e23cfbd07db0bb34548b7ea8e62fdb"},{"author":{"_account_id":5754,"name":"Alex Xu","email":"hejie.xu@intel.com","username":"xuhj"},"change_message_id":"f2c8bc7f2a16115b37d2c6588d2d6775b32081e7","unresolved":false,"context_lines":[{"line_number":205,"context_line":"            try:"},{"line_number":206,"context_line":"                utils.validate_integer(id, \u0027id\u0027)"},{"line_number":207,"context_line":"            except exception.InvalidInput as exc:"},{"line_number":208,"context_line":"                raise webob.exc.HTTPBadRequest("},{"line_number":209,"context_line":"                    explanation\u003dexc.format_message())"},{"line_number":210,"context_line":""},{"line_number":211,"context_line":"        try:"},{"line_number":212,"context_line":"            service \u003d self.host_api.service_get_by_id(context, id)"}],"source_content_type":"text/x-python","patch_set":21,"id":"3f1d235d_f2e9fa7f","line":209,"range":{"start_line":208,"start_character":17,"end_line":209,"end_character":53},"in_reply_to":"3f1d235d_c9c30c57","updated":"2017-07-12 02:32:08.000000000","message":"I\u0027m thinking about a UUID passed, before it returned 404, now it is 400. Do you mean it is ok due to the id doesn\u0027t work multiple cell anyway? For single cell, that probably a behaviour change?","commit_id":"f04c39bbf8e23cfbd07db0bb34548b7ea8e62fdb"},{"author":{"_account_id":6873,"name":"Matt Riedemann","email":"mriedem.os@gmail.com","username":"mriedem"},"change_message_id":"c517f11cccf025727740dc0b2356a8b26380a2d6","unresolved":false,"context_lines":[{"line_number":205,"context_line":"            try:"},{"line_number":206,"context_line":"                utils.validate_integer(id, \u0027id\u0027)"},{"line_number":207,"context_line":"            except exception.InvalidInput as exc:"},{"line_number":208,"context_line":"                raise webob.exc.HTTPBadRequest("},{"line_number":209,"context_line":"                    explanation\u003dexc.format_message())"},{"line_number":210,"context_line":""},{"line_number":211,"context_line":"        try:"},{"line_number":212,"context_line":"            service \u003d self.host_api.service_get_by_id(context, id)"}],"source_content_type":"text/x-python","patch_set":21,"id":"1f1a1f67_86d78f24","line":209,"range":{"start_line":208,"start_character":17,"end_line":209,"end_character":53},"in_reply_to":"3f1d235d_f2e9fa7f","updated":"2017-07-12 14:15:52.000000000","message":"The behavior before was a 400 if you passed a non-integer value:\n\ntry:\n    utils.validate_integer(id, \u0027id\u0027)\nexcept exception.InvalidInput as exc:\n    raise webob.exc.HTTPBadRequest(explanation\u003dexc.format_message())\n\nThis is no different.","commit_id":"f04c39bbf8e23cfbd07db0bb34548b7ea8e62fdb"},{"author":{"_account_id":5754,"name":"Alex Xu","email":"hejie.xu@intel.com","username":"xuhj"},"change_message_id":"76b05f6e3917971299c072a4b55d685bebd51038","unresolved":false,"context_lines":[{"line_number":308,"context_line":"        # action functions."},{"line_number":309,"context_line":"        if \u0027status\u0027 in body:"},{"line_number":310,"context_line":"            # This is a status update for either enabled or disabled."},{"line_number":311,"context_line":"            if body[\u0027status\u0027] \u003d\u003d \u0027enabled\u0027:"},{"line_number":312,"context_line":"                service.disabled \u003d False"},{"line_number":313,"context_line":"                service.disabled_reason \u003d None"},{"line_number":314,"context_line":"            elif body[\u0027status\u0027] \u003d\u003d \u0027disabled\u0027:"}],"source_content_type":"text/x-python","patch_set":21,"id":"3f1d235d_e8837055","line":311,"updated":"2017-07-11 08:01:27.000000000","message":"It would be better to have:\n\nif body[\u0027status\u0027] \u003d\u003d \u0027enabled\u0027 and service.diabled\u003dTrue and service.disabled_reason !\u003d None","commit_id":"f04c39bbf8e23cfbd07db0bb34548b7ea8e62fdb"},{"author":{"_account_id":5754,"name":"Alex Xu","email":"hejie.xu@intel.com","username":"xuhj"},"change_message_id":"f2c8bc7f2a16115b37d2c6588d2d6775b32081e7","unresolved":false,"context_lines":[{"line_number":308,"context_line":"        # action functions."},{"line_number":309,"context_line":"        if \u0027status\u0027 in body:"},{"line_number":310,"context_line":"            # This is a status update for either enabled or disabled."},{"line_number":311,"context_line":"            if body[\u0027status\u0027] \u003d\u003d \u0027enabled\u0027:"},{"line_number":312,"context_line":"                service.disabled \u003d False"},{"line_number":313,"context_line":"                service.disabled_reason \u003d None"},{"line_number":314,"context_line":"            elif body[\u0027status\u0027] \u003d\u003d \u0027disabled\u0027:"}],"source_content_type":"text/x-python","patch_set":21,"id":"3f1d235d_35607ca5","line":311,"in_reply_to":"3f1d235d_8465f91f","updated":"2017-07-12 02:32:08.000000000","message":"yes, without the check \u0027service.disabled_reason !\u003d None\u0027 is enough. I\u0027m thinking there is clearnup for disabled_reason. But I found there is cleanup when disabled it at line 317.\n\nYes, it doesn\u0027t hurt anything. I\u0027m just thinking it save a db call.","commit_id":"f04c39bbf8e23cfbd07db0bb34548b7ea8e62fdb"},{"author":{"_account_id":6873,"name":"Matt Riedemann","email":"mriedem.os@gmail.com","username":"mriedem"},"change_message_id":"fa5555d21af2bb3119c43d5ea2336e0898786a6d","unresolved":false,"context_lines":[{"line_number":308,"context_line":"        # action functions."},{"line_number":309,"context_line":"        if \u0027status\u0027 in body:"},{"line_number":310,"context_line":"            # This is a status update for either enabled or disabled."},{"line_number":311,"context_line":"            if body[\u0027status\u0027] \u003d\u003d \u0027enabled\u0027:"},{"line_number":312,"context_line":"                service.disabled \u003d False"},{"line_number":313,"context_line":"                service.disabled_reason \u003d None"},{"line_number":314,"context_line":"            elif body[\u0027status\u0027] \u003d\u003d \u0027disabled\u0027:"}],"source_content_type":"text/x-python","patch_set":21,"id":"3f1d235d_8465f91f","line":311,"in_reply_to":"3f1d235d_e8837055","updated":"2017-07-11 15:02:32.000000000","message":"OK, I think this would suffice:\n\nif body[\u0027status\u0027] \u003d\u003d \u0027enabled\u0027 and service.diabled\u003dTrue\n\nRight? Because when enabling the service, all we really care about is that it\u0027s disabled already, if we add that check.\n\nI initially wasn\u0027t enforcing that the service was already disabled when asking to enable it because I figured it doesn\u0027t hurt to noop if it\u0027s already enabled and you asked to enable it again. And that\u0027s how the API worked before - if you do \u0027nova service-enable\u0027 on an already enabled service, it\u0027s not an error. It doesn\u0027t change anything, but it doesn\u0027t hurt either.","commit_id":"f04c39bbf8e23cfbd07db0bb34548b7ea8e62fdb"},{"author":{"_account_id":5754,"name":"Alex Xu","email":"hejie.xu@intel.com","username":"xuhj"},"change_message_id":"76b05f6e3917971299c072a4b55d685bebd51038","unresolved":false,"context_lines":[{"line_number":310,"context_line":"            # This is a status update for either enabled or disabled."},{"line_number":311,"context_line":"            if body[\u0027status\u0027] \u003d\u003d \u0027enabled\u0027:"},{"line_number":312,"context_line":"                service.disabled \u003d False"},{"line_number":313,"context_line":"                service.disabled_reason \u003d None"},{"line_number":314,"context_line":"            elif body[\u0027status\u0027] \u003d\u003d \u0027disabled\u0027:"},{"line_number":315,"context_line":"                service.disabled \u003d True"},{"line_number":316,"context_line":"                # The disabled reason is optional."}],"source_content_type":"text/x-python","patch_set":21,"id":"3f1d235d_4dca766e","line":313,"range":{"start_line":313,"start_character":16,"end_line":313,"end_character":46},"updated":"2017-07-11 08:01:27.000000000","message":"sorry, I missed this case in the previous review.\n\nWe should return 400 when the \u0027status\u0027 is \u0027enabled\u0027 and \u0027disabled_reason\u0027 is specified.","commit_id":"f04c39bbf8e23cfbd07db0bb34548b7ea8e62fdb"},{"author":{"_account_id":6873,"name":"Matt Riedemann","email":"mriedem.os@gmail.com","username":"mriedem"},"change_message_id":"0d20899fb366dd3b450abd6192f56994c3cd1d3a","unresolved":false,"context_lines":[{"line_number":310,"context_line":"            # This is a status update for either enabled or disabled."},{"line_number":311,"context_line":"            if body[\u0027status\u0027] \u003d\u003d \u0027enabled\u0027:"},{"line_number":312,"context_line":"                service.disabled \u003d False"},{"line_number":313,"context_line":"                service.disabled_reason \u003d None"},{"line_number":314,"context_line":"            elif body[\u0027status\u0027] \u003d\u003d \u0027disabled\u0027:"},{"line_number":315,"context_line":"                service.disabled \u003d True"},{"line_number":316,"context_line":"                # The disabled reason is optional."}],"source_content_type":"text/x-python","patch_set":21,"id":"1f1a1f67_4d9e78b9","line":313,"range":{"start_line":313,"start_character":16,"end_line":313,"end_character":46},"in_reply_to":"1f1a1f67_06cc9f87","updated":"2017-07-18 19:35:46.000000000","message":"Done","commit_id":"f04c39bbf8e23cfbd07db0bb34548b7ea8e62fdb"},{"author":{"_account_id":6873,"name":"Matt Riedemann","email":"mriedem.os@gmail.com","username":"mriedem"},"change_message_id":"fa5555d21af2bb3119c43d5ea2336e0898786a6d","unresolved":false,"context_lines":[{"line_number":310,"context_line":"            # This is a status update for either enabled or disabled."},{"line_number":311,"context_line":"            if body[\u0027status\u0027] \u003d\u003d \u0027enabled\u0027:"},{"line_number":312,"context_line":"                service.disabled \u003d False"},{"line_number":313,"context_line":"                service.disabled_reason \u003d None"},{"line_number":314,"context_line":"            elif body[\u0027status\u0027] \u003d\u003d \u0027disabled\u0027:"},{"line_number":315,"context_line":"                service.disabled \u003d True"},{"line_number":316,"context_line":"                # The disabled reason is optional."}],"source_content_type":"text/x-python","patch_set":21,"id":"3f1d235d_ffd67653","line":313,"range":{"start_line":313,"start_character":16,"end_line":313,"end_character":46},"in_reply_to":"3f1d235d_4dca766e","updated":"2017-07-11 15:02:32.000000000","message":"To be clear, do you mean:\n\n1. if service.status \u003d\u003d \u0027enabled\u0027 and \u0027disabled_reason\u0027 in body, then fail? In other words, setting the disabled_reason on an enabled service is an error.\n\nor do you mean\n\n2. if body[\u0027status\u0027] \u003d\u003d \u0027enabled\u0027 and \u0027disabled_reason\u0027 in body, then fail? In other words, requesting to enable a disable service and specifying a disabled_reason (which we\u0027d ignore) is an error.\n\n--\n\nFWIW, the existing behavior for ``PUT /os-services/disable-log-reason`` is to also disable the service, but include the reason. The way I wrote this, there are no required fields in the request, since you either request force_down or status, and status can be enabled or disabled, and disabled_reason only makes sense for disabling the service, so that\u0027s why I only checked it in that case. But it\u0027s OK if we want to be strict.","commit_id":"f04c39bbf8e23cfbd07db0bb34548b7ea8e62fdb"},{"author":{"_account_id":6873,"name":"Matt Riedemann","email":"mriedem.os@gmail.com","username":"mriedem"},"change_message_id":"c517f11cccf025727740dc0b2356a8b26380a2d6","unresolved":false,"context_lines":[{"line_number":310,"context_line":"            # This is a status update for either enabled or disabled."},{"line_number":311,"context_line":"            if body[\u0027status\u0027] \u003d\u003d \u0027enabled\u0027:"},{"line_number":312,"context_line":"                service.disabled \u003d False"},{"line_number":313,"context_line":"                service.disabled_reason \u003d None"},{"line_number":314,"context_line":"            elif body[\u0027status\u0027] \u003d\u003d \u0027disabled\u0027:"},{"line_number":315,"context_line":"                service.disabled \u003d True"},{"line_number":316,"context_line":"                # The disabled reason is optional."}],"source_content_type":"text/x-python","patch_set":21,"id":"1f1a1f67_06cc9f87","line":313,"range":{"start_line":313,"start_character":16,"end_line":313,"end_character":46},"in_reply_to":"3f1d235d_554ad8ab","updated":"2017-07-12 14:15:52.000000000","message":"OK I\u0027ll add validation for that.","commit_id":"f04c39bbf8e23cfbd07db0bb34548b7ea8e62fdb"},{"author":{"_account_id":5754,"name":"Alex Xu","email":"hejie.xu@intel.com","username":"xuhj"},"change_message_id":"f2c8bc7f2a16115b37d2c6588d2d6775b32081e7","unresolved":false,"context_lines":[{"line_number":310,"context_line":"            # This is a status update for either enabled or disabled."},{"line_number":311,"context_line":"            if body[\u0027status\u0027] \u003d\u003d \u0027enabled\u0027:"},{"line_number":312,"context_line":"                service.disabled \u003d False"},{"line_number":313,"context_line":"                service.disabled_reason \u003d None"},{"line_number":314,"context_line":"            elif body[\u0027status\u0027] \u003d\u003d \u0027disabled\u0027:"},{"line_number":315,"context_line":"                service.disabled \u003d True"},{"line_number":316,"context_line":"                # The disabled reason is optional."}],"source_content_type":"text/x-python","patch_set":21,"id":"3f1d235d_554ad8ab","line":313,"range":{"start_line":313,"start_character":16,"end_line":313,"end_character":46},"in_reply_to":"3f1d235d_ffd67653","updated":"2017-07-12 02:32:08.000000000","message":"I mean the #2, ignore the \u0027disabled_reason\u0027 quietly isn\u0027t right.","commit_id":"f04c39bbf8e23cfbd07db0bb34548b7ea8e62fdb"},{"author":{"_account_id":5754,"name":"Alex Xu","email":"hejie.xu@intel.com","username":"xuhj"},"change_message_id":"76b05f6e3917971299c072a4b55d685bebd51038","unresolved":false,"context_lines":[{"line_number":311,"context_line":"            if body[\u0027status\u0027] \u003d\u003d \u0027enabled\u0027:"},{"line_number":312,"context_line":"                service.disabled \u003d False"},{"line_number":313,"context_line":"                service.disabled_reason \u003d None"},{"line_number":314,"context_line":"            elif body[\u0027status\u0027] \u003d\u003d \u0027disabled\u0027:"},{"line_number":315,"context_line":"                service.disabled \u003d True"},{"line_number":316,"context_line":"                # The disabled reason is optional."},{"line_number":317,"context_line":"                service.disabled_reason \u003d body.get(\u0027disabled_reason\u0027)"}],"source_content_type":"text/x-python","patch_set":21,"id":"3f1d235d_68dc0074","line":314,"updated":"2017-07-11 08:01:27.000000000","message":"ditto, we also can save a DB call if we have more conditions check","commit_id":"f04c39bbf8e23cfbd07db0bb34548b7ea8e62fdb"},{"author":{"_account_id":6873,"name":"Matt Riedemann","email":"mriedem.os@gmail.com","username":"mriedem"},"change_message_id":"e9f7ebaa138a05010a5c7cac6cad9d4abd9a9a13","unresolved":false,"context_lines":[{"line_number":311,"context_line":"            if body[\u0027status\u0027] \u003d\u003d \u0027enabled\u0027:"},{"line_number":312,"context_line":"                service.disabled \u003d False"},{"line_number":313,"context_line":"                service.disabled_reason \u003d None"},{"line_number":314,"context_line":"            elif body[\u0027status\u0027] \u003d\u003d \u0027disabled\u0027:"},{"line_number":315,"context_line":"                service.disabled \u003d True"},{"line_number":316,"context_line":"                # The disabled reason is optional."},{"line_number":317,"context_line":"                service.disabled_reason \u003d body.get(\u0027disabled_reason\u0027)"}],"source_content_type":"text/x-python","patch_set":21,"id":"3f1d235d_b2738280","line":314,"in_reply_to":"3f1d235d_3f43ce15","updated":"2017-07-12 01:20:36.000000000","message":"I\u0027ve posted to the dev ML for discussion on how we want this to behave:\n\nhttp://lists.openstack.org/pipermail/openstack-dev/2017-July/119581.html\n\nPersonally I think the existing behavior in the older APIs is correct, in that if you try to enable an enabled service it\u0027s not an error, and the same for trying to disable a disabled service.","commit_id":"f04c39bbf8e23cfbd07db0bb34548b7ea8e62fdb"},{"author":{"_account_id":5754,"name":"Alex Xu","email":"hejie.xu@intel.com","username":"xuhj"},"change_message_id":"f2c8bc7f2a16115b37d2c6588d2d6775b32081e7","unresolved":false,"context_lines":[{"line_number":311,"context_line":"            if body[\u0027status\u0027] \u003d\u003d \u0027enabled\u0027:"},{"line_number":312,"context_line":"                service.disabled \u003d False"},{"line_number":313,"context_line":"                service.disabled_reason \u003d None"},{"line_number":314,"context_line":"            elif body[\u0027status\u0027] \u003d\u003d \u0027disabled\u0027:"},{"line_number":315,"context_line":"                service.disabled \u003d True"},{"line_number":316,"context_line":"                # The disabled reason is optional."},{"line_number":317,"context_line":"                service.disabled_reason \u003d body.get(\u0027disabled_reason\u0027)"}],"source_content_type":"text/x-python","patch_set":21,"id":"3f1d235d_f5b1e4e2","line":314,"in_reply_to":"3f1d235d_3f43ce15","updated":"2017-07-12 02:32:08.000000000","message":"Sorry, I mean we can add a check \"If body[\u0027status\u0027] \u003d\u003d \u0027disabled and service.disabled\u003d\u003dFalse and service.disabled_reason !\u003d body.get(\u0027disabled_reason\u0027)\", if it is false, then we can save a db call, not to return fault to the user.","commit_id":"f04c39bbf8e23cfbd07db0bb34548b7ea8e62fdb"},{"author":{"_account_id":6873,"name":"Matt Riedemann","email":"mriedem.os@gmail.com","username":"mriedem"},"change_message_id":"fa5555d21af2bb3119c43d5ea2336e0898786a6d","unresolved":false,"context_lines":[{"line_number":311,"context_line":"            if body[\u0027status\u0027] \u003d\u003d \u0027enabled\u0027:"},{"line_number":312,"context_line":"                service.disabled \u003d False"},{"line_number":313,"context_line":"                service.disabled_reason \u003d None"},{"line_number":314,"context_line":"            elif body[\u0027status\u0027] \u003d\u003d \u0027disabled\u0027:"},{"line_number":315,"context_line":"                service.disabled \u003d True"},{"line_number":316,"context_line":"                # The disabled reason is optional."},{"line_number":317,"context_line":"                service.disabled_reason \u003d body.get(\u0027disabled_reason\u0027)"}],"source_content_type":"text/x-python","patch_set":21,"id":"3f1d235d_3f43ce15","line":314,"in_reply_to":"3f1d235d_68dc0074","updated":"2017-07-11 15:02:32.000000000","message":"So, fail if requesting to disable an already disabled service? Note that in the existing behavior, it would not be an error to disable an already disabled service, which is why I wasn\u0027t making this strict.","commit_id":"f04c39bbf8e23cfbd07db0bb34548b7ea8e62fdb"},{"author":{"_account_id":6873,"name":"Matt Riedemann","email":"mriedem.os@gmail.com","username":"mriedem"},"change_message_id":"c517f11cccf025727740dc0b2356a8b26380a2d6","unresolved":false,"context_lines":[{"line_number":311,"context_line":"            if body[\u0027status\u0027] \u003d\u003d \u0027enabled\u0027:"},{"line_number":312,"context_line":"                service.disabled \u003d False"},{"line_number":313,"context_line":"                service.disabled_reason \u003d None"},{"line_number":314,"context_line":"            elif body[\u0027status\u0027] \u003d\u003d \u0027disabled\u0027:"},{"line_number":315,"context_line":"                service.disabled \u003d True"},{"line_number":316,"context_line":"                # The disabled reason is optional."},{"line_number":317,"context_line":"                service.disabled_reason \u003d body.get(\u0027disabled_reason\u0027)"}],"source_content_type":"text/x-python","patch_set":21,"id":"1f1a1f67_06c81f53","line":314,"in_reply_to":"3f1d235d_f5b1e4e2","updated":"2017-07-12 14:15:52.000000000","message":"OK, I\u0027ll look into that. Personally I care less about the wasted DB call - I\u0027d prefer to not add a bunch of complexity in here for state checking to avoid the DB call on an API that is (1) admin-only by default and (2) probably doesn\u0027t get called that often.","commit_id":"f04c39bbf8e23cfbd07db0bb34548b7ea8e62fdb"},{"author":{"_account_id":5754,"name":"Alex Xu","email":"hejie.xu@intel.com","username":"xuhj"},"change_message_id":"76b05f6e3917971299c072a4b55d685bebd51038","unresolved":false,"context_lines":[{"line_number":318,"context_line":""},{"line_number":319,"context_line":"        # This is intentionally not an elif, i.e. it\u0027s in addition to the"},{"line_number":320,"context_line":"        # status update."},{"line_number":321,"context_line":"        if \u0027forced_down\u0027 in body:"},{"line_number":322,"context_line":"            service.forced_down \u003d strutils.bool_from_string("},{"line_number":323,"context_line":"                body[\u0027forced_down\u0027], strict\u003dTrue)"},{"line_number":324,"context_line":""}],"source_content_type":"text/x-python","patch_set":21,"id":"3f1d235d_88a75c0c","line":321,"updated":"2017-07-11 08:01:27.000000000","message":"it would be better to have:\n\nforced_down \u003d strutils.bool_from_string(body[\u0027forced_down\u0027], strict\u003dTrue)\nif \u0027forced_down\u0027 in body and service.forced_down !\u003d forced_down:\n       service.forced_down \u003d forced_down","commit_id":"f04c39bbf8e23cfbd07db0bb34548b7ea8e62fdb"},{"author":{"_account_id":6873,"name":"Matt Riedemann","email":"mriedem.os@gmail.com","username":"mriedem"},"change_message_id":"fa5555d21af2bb3119c43d5ea2336e0898786a6d","unresolved":false,"context_lines":[{"line_number":318,"context_line":""},{"line_number":319,"context_line":"        # This is intentionally not an elif, i.e. it\u0027s in addition to the"},{"line_number":320,"context_line":"        # status update."},{"line_number":321,"context_line":"        if \u0027forced_down\u0027 in body:"},{"line_number":322,"context_line":"            service.forced_down \u003d strutils.bool_from_string("},{"line_number":323,"context_line":"                body[\u0027forced_down\u0027], strict\u003dTrue)"},{"line_number":324,"context_line":""}],"source_content_type":"text/x-python","patch_set":21,"id":"3f1d235d_9fa0a2a7","line":321,"in_reply_to":"3f1d235d_88a75c0c","updated":"2017-07-11 15:02:32.000000000","message":"You can\u0027t do:\n\nforced_down \u003d strutils.bool_from_string(body[\u0027forced_down\u0027], strict\u003dTrue)\n\nBecause body[\u0027forced_down\u0027] will result in a KeyError if it\u0027s not specified, and it\u0027s not a required field so it may not be specified.","commit_id":"f04c39bbf8e23cfbd07db0bb34548b7ea8e62fdb"},{"author":{"_account_id":5754,"name":"Alex Xu","email":"hejie.xu@intel.com","username":"xuhj"},"change_message_id":"f2c8bc7f2a16115b37d2c6588d2d6775b32081e7","unresolved":false,"context_lines":[{"line_number":318,"context_line":""},{"line_number":319,"context_line":"        # This is intentionally not an elif, i.e. it\u0027s in addition to the"},{"line_number":320,"context_line":"        # status update."},{"line_number":321,"context_line":"        if \u0027forced_down\u0027 in body:"},{"line_number":322,"context_line":"            service.forced_down \u003d strutils.bool_from_string("},{"line_number":323,"context_line":"                body[\u0027forced_down\u0027], strict\u003dTrue)"},{"line_number":324,"context_line":""}],"source_content_type":"text/x-python","patch_set":21,"id":"3f1d235d_55c0982a","line":321,"in_reply_to":"3f1d235d_9fa0a2a7","updated":"2017-07-12 02:32:08.000000000","message":"oh, sorry, you are right. I also think about save db call at here.","commit_id":"f04c39bbf8e23cfbd07db0bb34548b7ea8e62fdb"},{"author":{"_account_id":5754,"name":"Alex Xu","email":"hejie.xu@intel.com","username":"xuhj"},"change_message_id":"76b05f6e3917971299c072a4b55d685bebd51038","unresolved":false,"context_lines":[{"line_number":324,"context_line":""},{"line_number":325,"context_line":"        # Check to see if anything was actually updated since the schema does"},{"line_number":326,"context_line":"        # not define any required fields."},{"line_number":327,"context_line":"        if not service.obj_what_changed():"},{"line_number":328,"context_line":"            msg \u003d _(\"No updates were requested. Fields \u0027status\u0027 or \""},{"line_number":329,"context_line":"                    \"\u0027forced_down\u0027 should be specified.\")"},{"line_number":330,"context_line":"            raise webob.exc.HTTPBadRequest(explanation\u003dmsg)"}],"source_content_type":"text/x-python","patch_set":21,"id":"3f1d235d_483b84c7","line":327,"updated":"2017-07-11 08:01:27.000000000","message":"This also return 400 when only \u0027disabled_reason\u0027 is specified, but I didn\u0027t found a unittest for this case.","commit_id":"f04c39bbf8e23cfbd07db0bb34548b7ea8e62fdb"},{"author":{"_account_id":6873,"name":"Matt Riedemann","email":"mriedem.os@gmail.com","username":"mriedem"},"change_message_id":"fa5555d21af2bb3119c43d5ea2336e0898786a6d","unresolved":false,"context_lines":[{"line_number":324,"context_line":""},{"line_number":325,"context_line":"        # Check to see if anything was actually updated since the schema does"},{"line_number":326,"context_line":"        # not define any required fields."},{"line_number":327,"context_line":"        if not service.obj_what_changed():"},{"line_number":328,"context_line":"            msg \u003d _(\"No updates were requested. Fields \u0027status\u0027 or \""},{"line_number":329,"context_line":"                    \"\u0027forced_down\u0027 should be specified.\")"},{"line_number":330,"context_line":"            raise webob.exc.HTTPBadRequest(explanation\u003dmsg)"}],"source_content_type":"text/x-python","patch_set":21,"id":"3f1d235d_5aa45808","line":327,"in_reply_to":"3f1d235d_483b84c7","updated":"2017-07-11 15:02:32.000000000","message":"I\u0027ll add one. test_update_empty_body was close, but not exactly the same thing you pointed out - nice catch.","commit_id":"f04c39bbf8e23cfbd07db0bb34548b7ea8e62fdb"},{"author":{"_account_id":6873,"name":"Matt Riedemann","email":"mriedem.os@gmail.com","username":"mriedem"},"change_message_id":"0d20899fb366dd3b450abd6192f56994c3cd1d3a","unresolved":false,"context_lines":[{"line_number":324,"context_line":""},{"line_number":325,"context_line":"        # Check to see if anything was actually updated since the schema does"},{"line_number":326,"context_line":"        # not define any required fields."},{"line_number":327,"context_line":"        if not service.obj_what_changed():"},{"line_number":328,"context_line":"            msg \u003d _(\"No updates were requested. Fields \u0027status\u0027 or \""},{"line_number":329,"context_line":"                    \"\u0027forced_down\u0027 should be specified.\")"},{"line_number":330,"context_line":"            raise webob.exc.HTTPBadRequest(explanation\u003dmsg)"}],"source_content_type":"text/x-python","patch_set":21,"id":"1f1a1f67_6da6d4ad","line":327,"in_reply_to":"3f1d235d_5aa45808","updated":"2017-07-18 19:35:46.000000000","message":"Done","commit_id":"f04c39bbf8e23cfbd07db0bb34548b7ea8e62fdb"},{"author":{"_account_id":2750,"name":"Sean Dague","email":"sean@dague.net","username":"sdague"},"change_message_id":"a9da9aa201909eebc44d2e61b08e34f38745106b","unresolved":false,"context_lines":[{"line_number":271,"context_line":"        \"\"\""},{"line_number":272,"context_line":"        service_id \u003d id"},{"line_number":273,"context_line":"        # Validate that the service ID is a UUID."},{"line_number":274,"context_line":"        if not uuidutils.is_uuid_like(service_id):"},{"line_number":275,"context_line":"            msg \u003d _(\u0027Invalid uuid %s\u0027) % service_id"},{"line_number":276,"context_line":"            raise webob.exc.HTTPBadRequest(explanation\u003dmsg)"},{"line_number":277,"context_line":""}],"source_content_type":"text/x-python","patch_set":22,"id":"1f1a1f67_989a7011","line":274,"updated":"2017-07-19 13:34:41.000000000","message":"so, we do realize that this is not actually a hard uuid, right?  We might want to follow on with a more strict is uuid json validation.","commit_id":"2f7bf29d472d349759ffd8aece23a75f4e27a4f9"},{"author":{"_account_id":6873,"name":"Matt Riedemann","email":"mriedem.os@gmail.com","username":"mriedem"},"change_message_id":"0ca0cab73046dbac1a24e2ffa0fdd1ed50408862","unresolved":false,"context_lines":[{"line_number":271,"context_line":"        \"\"\""},{"line_number":272,"context_line":"        service_id \u003d id"},{"line_number":273,"context_line":"        # Validate that the service ID is a UUID."},{"line_number":274,"context_line":"        if not uuidutils.is_uuid_like(service_id):"},{"line_number":275,"context_line":"            msg \u003d _(\u0027Invalid uuid %s\u0027) % service_id"},{"line_number":276,"context_line":"            raise webob.exc.HTTPBadRequest(explanation\u003dmsg)"},{"line_number":277,"context_line":""}],"source_content_type":"text/x-python","patch_set":22,"id":"1f1a1f67_91cc8b35","line":274,"in_reply_to":"1f1a1f67_989a7011","updated":"2017-07-19 14:51:43.000000000","message":"Yeah, I never dug into all of the details on that. We can\u0027t use json query parameter validation for this though since it\u0027s not a query parameter, it\u0027s a path parameter.","commit_id":"2f7bf29d472d349759ffd8aece23a75f4e27a4f9"},{"author":{"_account_id":2750,"name":"Sean Dague","email":"sean@dague.net","username":"sdague"},"change_message_id":"a9da9aa201909eebc44d2e61b08e34f38745106b","unresolved":false,"context_lines":[{"line_number":297,"context_line":"        # old gap and make sure you can only enable/disable and set forced_down"},{"line_number":298,"context_line":"        # on nova-compute services since those are the only ones that make"},{"line_number":299,"context_line":"        # sense to update for those operations."},{"line_number":300,"context_line":"        if service.binary !\u003d \u0027nova-compute\u0027:"},{"line_number":301,"context_line":"            msg \u003d (_(\u0027Updating a %(binary)s service is not supported. Only \u0027"},{"line_number":302,"context_line":"                     \u0027nova-compute services can be updated.\u0027) %"},{"line_number":303,"context_line":"                   {\u0027binary\u0027: service.binary})"}],"source_content_type":"text/x-python","patch_set":22,"id":"1f1a1f67_58473878","line":300,"updated":"2017-07-19 13:34:41.000000000","message":"nit: for typo proofing it would probably be better to have nova-compute actually be a COMPUTE_BINARY constant somewhere, then python helps typo bugs around this.","commit_id":"2f7bf29d472d349759ffd8aece23a75f4e27a4f9"},{"author":{"_account_id":2750,"name":"Sean Dague","email":"sean@dague.net","username":"sdague"},"change_message_id":"a9da9aa201909eebc44d2e61b08e34f38745106b","unresolved":false,"context_lines":[{"line_number":322,"context_line":"            elif body[\u0027status\u0027] \u003d\u003d \u0027disabled\u0027:"},{"line_number":323,"context_line":"                service.disabled \u003d True"},{"line_number":324,"context_line":"                # The disabled reason is optional."},{"line_number":325,"context_line":"                service.disabled_reason \u003d body.get(\u0027disabled_reason\u0027)"},{"line_number":326,"context_line":""},{"line_number":327,"context_line":"        # This is intentionally not an elif, i.e. it\u0027s in addition to the"},{"line_number":328,"context_line":"        # status update."}],"source_content_type":"text/x-python","patch_set":22,"id":"1f1a1f67_38791cc7","line":325,"updated":"2017-07-19 13:34:41.000000000","message":"a friendly future bit of validation would be rejecting a disabled_reason if status doesn\u0027t exist.","commit_id":"2f7bf29d472d349759ffd8aece23a75f4e27a4f9"},{"author":{"_account_id":6873,"name":"Matt Riedemann","email":"mriedem.os@gmail.com","username":"mriedem"},"change_message_id":"0ca0cab73046dbac1a24e2ffa0fdd1ed50408862","unresolved":false,"context_lines":[{"line_number":322,"context_line":"            elif body[\u0027status\u0027] \u003d\u003d \u0027disabled\u0027:"},{"line_number":323,"context_line":"                service.disabled \u003d True"},{"line_number":324,"context_line":"                # The disabled reason is optional."},{"line_number":325,"context_line":"                service.disabled_reason \u003d body.get(\u0027disabled_reason\u0027)"},{"line_number":326,"context_line":""},{"line_number":327,"context_line":"        # This is intentionally not an elif, i.e. it\u0027s in addition to the"},{"line_number":328,"context_line":"        # status update."}],"source_content_type":"text/x-python","patch_set":22,"id":"1f1a1f67_b1f2e76e","line":325,"in_reply_to":"1f1a1f67_38791cc7","updated":"2017-07-19 14:51:43.000000000","message":"That happens on L335 and there is a unit test for it.","commit_id":"2f7bf29d472d349759ffd8aece23a75f4e27a4f9"}],"nova/tests/functional/api_sample_tests/test_services.py":[{"author":{"_account_id":6873,"name":"Matt Riedemann","email":"mriedem.os@gmail.com","username":"mriedem"},"change_message_id":"9e485a04e563fb909ddaf64da98a3f32cc146f0b","unresolved":false,"context_lines":[{"line_number":120,"context_line":"        self.assertEqual(204, response.status_code)"},{"line_number":121,"context_line":"        self.assertEqual(\"\", response.text)"},{"line_number":122,"context_line":""},{"line_number":123,"context_line":"    def test_delete_with_database_id_returns_invalid_uuid(self):"},{"line_number":124,"context_line":"        response \u003d self._do_delete(\u0027os-services/1\u0027)"},{"line_number":125,"context_line":"        self.assertEqual(400, response.status_code)"},{"line_number":126,"context_line":"        self.assertIn(\u0027Invalid uuid\u0027, response.text)"}],"source_content_type":"text/x-python","patch_set":8,"id":"7f231b9d_f4a47b0a","line":123,"updated":"2017-06-12 20:44:19.000000000","message":"The API samples tests are generally only for things that work against the samples. We can do the negative test in unit tests.","commit_id":"5e995d57fe22170c4ff3b69581ce387d5efbdbeb"}],"nova/tests/functional/api_samples_test_base.py":[{"author":{"_account_id":6873,"name":"Matt Riedemann","email":"mriedem.os@gmail.com","username":"mriedem"},"change_message_id":"1ea99b578e9854f988c8254ec2123c8ae7d0d0dc","unresolved":false,"context_lines":[{"line_number":372,"context_line":"        except NoMatch as e:"},{"line_number":373,"context_line":"            raise NoMatch(\"\\nFailed to match Template to Response: \\n%s\\n\""},{"line_number":374,"context_line":"                          \"Template: %s\\n\\n\""},{"line_number":375,"context_line":"                          \"Response: %s\\n\\n\" %"},{"line_number":376,"context_line":"                          (e,"},{"line_number":377,"context_line":"                           pp.pformat(template_data),"},{"line_number":378,"context_line":"                           pp.pformat(response_data)))"}],"source_content_type":"text/x-python","patch_set":6,"id":"df140735_035fc9e5","line":375,"updated":"2017-06-07 18:29:01.000000000","message":"unrelated","commit_id":"6455637688030f49f9176761d86a789d448a266c"}],"nova/tests/functional/notification_sample_tests/test_service_update.py":[{"author":{"_account_id":2750,"name":"Sean Dague","email":"sean@dague.net","username":"sdague"},"change_message_id":"a9da9aa201909eebc44d2e61b08e34f38745106b","unresolved":false,"context_lines":[{"line_number":77,"context_line":""},{"line_number":78,"context_line":""},{"line_number":79,"context_line":"class TestServiceUpdateNotificationSampleLatest("},{"line_number":80,"context_line":"        TestServiceUpdateNotificationSamplev2_52):"},{"line_number":81,"context_line":"    \"\"\"Tests the PUT /os-services/{service_id} API notifications.\"\"\""},{"line_number":82,"context_line":""},{"line_number":83,"context_line":"    MAX_MICROVERSION \u003d \u0027latest\u0027"}],"source_content_type":"text/x-python","patch_set":22,"id":"1f1a1f67_5815f847","line":80,"range":{"start_line":80,"start_character":8,"end_line":80,"end_character":48},"updated":"2017-07-19 13:34:41.000000000","message":"follow up: this duplicates all the test methods, inheriting from the other test class instead of from the common base just introduces coupling that we could avoid.","commit_id":"2f7bf29d472d349759ffd8aece23a75f4e27a4f9"},{"author":{"_account_id":6873,"name":"Matt Riedemann","email":"mriedem.os@gmail.com","username":"mriedem"},"change_message_id":"0ca0cab73046dbac1a24e2ffa0fdd1ed50408862","unresolved":false,"context_lines":[{"line_number":77,"context_line":""},{"line_number":78,"context_line":""},{"line_number":79,"context_line":"class TestServiceUpdateNotificationSampleLatest("},{"line_number":80,"context_line":"        TestServiceUpdateNotificationSamplev2_52):"},{"line_number":81,"context_line":"    \"\"\"Tests the PUT /os-services/{service_id} API notifications.\"\"\""},{"line_number":82,"context_line":""},{"line_number":83,"context_line":"    MAX_MICROVERSION \u003d \u0027latest\u0027"}],"source_content_type":"text/x-python","patch_set":22,"id":"1f1a1f67_d179e3c4","line":80,"range":{"start_line":80,"start_character":8,"end_line":80,"end_character":48},"in_reply_to":"1f1a1f67_5815f847","updated":"2017-07-19 14:51:43.000000000","message":"It\u0027s intentional, because I wanted to make sure that the new microversion is also testing the same scenarios in the existing test.","commit_id":"2f7bf29d472d349759ffd8aece23a75f4e27a4f9"}],"nova/tests/unit/api/openstack/compute/test_services.py":[{"author":{"_account_id":6873,"name":"Matt Riedemann","email":"mriedem.os@gmail.com","username":"mriedem"},"change_message_id":"9e485a04e563fb909ddaf64da98a3f32cc146f0b","unresolved":false,"context_lines":[{"line_number":1042,"context_line":"        self.assertNotIn(\u0027uuid\u0027, fields)"},{"line_number":1043,"context_line":""},{"line_number":1044,"context_line":"    def test_delete_takes_uuid_for_id(self):"},{"line_number":1045,"context_line":"        service \u003d self.host_api.db.service_create("},{"line_number":1046,"context_line":"            context.get_admin_context(),"},{"line_number":1047,"context_line":"            {\u0027host\u0027: \u0027fake-compute-host\u0027,"},{"line_number":1048,"context_line":"             \u0027binary\u0027: \u0027nova-compute\u0027,"}],"source_content_type":"text/x-python","patch_set":8,"id":"7f231b9d_3484335e","line":1045,"range":{"start_line":1045,"start_character":18,"end_line":1045,"end_character":49},"updated":"2017-06-12 20:44:19.000000000","message":"Rather than go through the database directly, let\u0027s use self.start_service here.","commit_id":"5e995d57fe22170c4ff3b69581ce387d5efbdbeb"},{"author":{"_account_id":6873,"name":"Matt Riedemann","email":"mriedem.os@gmail.com","username":"mriedem"},"change_message_id":"c0c3f735cf6568664f8156c1400307b9b2b75d1a","unresolved":false,"context_lines":[{"line_number":940,"context_line":""},{"line_number":941,"context_line":"class ServicesTestV248(ServicesTestV211):"},{"line_number":942,"context_line":"    \"\"\"This is a boundary test to ensure that 2.48 behaves the same as 2.11.\"\"\""},{"line_number":943,"context_line":"    wsgi_api_version \u003d \u00272.48\u0027"},{"line_number":944,"context_line":""},{"line_number":945,"context_line":""},{"line_number":946,"context_line":"class FakeServiceGroupAPI(object):"}],"source_content_type":"text/x-python","patch_set":21,"id":"1f1a1f67_54e045cd","line":943,"range":{"start_line":943,"start_character":24,"end_line":943,"end_character":28},"updated":"2017-07-18 18:00:13.000000000","message":"This should be 2.52 now.","commit_id":"f04c39bbf8e23cfbd07db0bb34548b7ea8e62fdb"}]}
