)]}'
{"/COMMIT_MSG":[{"author":{"_account_id":7882,"name":"Yuiko Takada Mori","email":"yuiko-mori@nec.com","username":"YuikoTakada"},"change_message_id":"061c256240d47576f470b12325fb9756e84c73b8","unresolved":false,"context_lines":[{"line_number":9,"context_line":"- set node tags"},{"line_number":10,"context_line":"- get a list of tags of a node"},{"line_number":11,"context_line":"- remove all tags from a node"},{"line_number":12,"context_line":"- node list tags/tags_any/not_tags/not_tags_any"},{"line_number":13,"context_line":"  filter support"},{"line_number":14,"context_line":"- include tags in node details"},{"line_number":15,"context_line":""}],"source_content_type":"text/x-gerrit-commit-message","patch_set":22,"id":"9abb7d3a_a1bf0aa9","line":12,"range":{"start_line":12,"start_character":12,"end_line":12,"end_character":47},"updated":"2016-06-03 08:02:19.000000000","message":"According to the spec, these filters have not got consensus from community guys...How to set tags_any and not_tags_any to API? like GET /v1/nodes/nodes/tags/tags_any\u003d{tag_a}\u0026tags_any\u003d{tag_b} ?\n\nin spec, written like GET /v1/nodes?tag\u003d{tag_a}\u0026tag\u003d{tag_b} . which is correct?","commit_id":"48de97232d6cad5e4c1badfa329b198ebe75fdba"}],"doc/source/webapi/v1.rst":[{"author":{"_account_id":7882,"name":"Yuiko Takada Mori","email":"yuiko-mori@nec.com","username":"YuikoTakada"},"change_message_id":"061c256240d47576f470b12325fb9756e84c73b8","unresolved":false,"context_lines":[{"line_number":242,"context_line":""},{"line_number":243,"context_line":".. autotype:: ironic.api.controllers.v1.node.NodeStates"},{"line_number":244,"context_line":"   :members:"},{"line_number":245,"context_line":""},{"line_number":246,"context_line":""},{"line_number":247,"context_line":"Ports"},{"line_number":248,"context_line":"\u003d\u003d\u003d\u003d\u003d"}],"source_content_type":"text/x-rst","patch_set":22,"id":"9abb7d3a_e184725e","line":245,"updated":"2016-06-03 08:02:19.000000000","message":"need to add here also","commit_id":"48de97232d6cad5e4c1badfa329b198ebe75fdba"}],"ironic/api/controllers/v1/node.py":[{"author":{"_account_id":2889,"name":"Aeva Black","email":"aeva.online@gmail.com","username":"tenbrae"},"change_message_id":"62153bfb2e6252dc6250c23b55e447656728671b","unresolved":false,"context_lines":[{"line_number":94,"context_line":""},{"line_number":95,"context_line":"    if pecan.request.version.minor \u003c versions.MINOR_12_RAID_CONFIG:"},{"line_number":96,"context_line":"        obj.raid_config \u003d wsme.Unset"},{"line_number":97,"context_line":"        obj.target_raid_config \u003d wsme.Unset"},{"line_number":98,"context_line":""},{"line_number":99,"context_line":""},{"line_number":100,"context_line":"def assert_juno_provision_state_name(obj):"}],"source_content_type":"text/x-python","patch_set":5,"id":"9a8ffd7b_fdd6e04d","line":97,"updated":"2015-12-02 17:18:02.000000000","message":"you should hide tags from older clients here","commit_id":"ba383e261b0f4fefc72f33a02b6b6d5e252f89c8"},{"author":{"_account_id":2889,"name":"Aeva Black","email":"aeva.online@gmail.com","username":"tenbrae"},"change_message_id":"62153bfb2e6252dc6250c23b55e447656728671b","unresolved":false,"context_lines":[{"line_number":111,"context_line":""},{"line_number":112,"context_line":""},{"line_number":113,"context_line":"def _get_tags_names(tags):"},{"line_number":114,"context_line":"    return [t.tag for t in tags]"},{"line_number":115,"context_line":""},{"line_number":116,"context_line":""},{"line_number":117,"context_line":"class BootDeviceController(rest.RestController):"}],"source_content_type":"text/x-python","patch_set":5,"id":"9a8ffd7b_9dc79497","line":114,"updated":"2015-12-02 17:18:02.000000000","message":"this line generates an error:\n\n2015-12-02 09:03:08.006 21693 ERROR wsme.api [req-56038bd1-fef5-46f7-bd6b-6ca5cd7e7630 - - - - -] Server-side error: \"\u0027NoneType\u0027 object is not iterable\". Detail: \nTraceback (most recent call last):\n\n  File \"/opt/source/openstack/ironic/local/lib/python2.7/site-packages/wsmeext/pecan.py\", line 84, in callfunction\n    result \u003d f(self, *args, **kwargs)\n\n  File \"/opt/source/openstack/ironic/ironic/api/controllers/v1/node.py\", line 516, in get\n    return Tags(tags\u003d_get_tags_names(tags))\n\n  File \"/opt/source/openstack/ironic/ironic/api/controllers/v1/node.py\", line 114, in _get_tags_names\n    return [t.tag for t in tags]\n\nTypeError: \u0027NoneType\u0027 object is not iterable","commit_id":"ba383e261b0f4fefc72f33a02b6b6d5e252f89c8"},{"author":{"_account_id":2889,"name":"Aeva Black","email":"aeva.online@gmail.com","username":"tenbrae"},"change_message_id":"62153bfb2e6252dc6250c23b55e447656728671b","unresolved":false,"context_lines":[{"line_number":915,"context_line":"    maintenance \u003d NodeMaintenanceController()"},{"line_number":916,"context_line":"    \"\"\"Expose maintenance as a sub-element of nodes\"\"\""},{"line_number":917,"context_line":""},{"line_number":918,"context_line":"    tags \u003d NodeTagsController()"},{"line_number":919,"context_line":"    \"\"\"Expose tags as a sub-element of nodes\"\"\""},{"line_number":920,"context_line":""},{"line_number":921,"context_line":"    # Set the flag to indicate that the requests to this resource are"}],"source_content_type":"text/x-python","patch_set":5,"id":"9a8ffd7b_bdccd8bb","line":918,"updated":"2015-12-02 17:18:02.000000000","message":"This is only creating the subresource /v1/nodes/\u003cNNN\u003e/tags -- but not providing any link to it. Such a link from the parent resource is necessary so that clients traversing the RESTful interface can discover the \u0027tags\u0027. Eg,\n  GET /v1/nodes/\u003cNNN\u003e\nshould return a link to the \"tags\" resource, or should embed it in the parent. For example:\n\n  curl -H \u0027X-OpenStack-Ironic-API-Version: latest\u0027 http://localhost:6385/v1/nodes/foo 2\u003e/dev/null | json_pp | grep ports || echo \u0027not found\u0027\n   \"ports\" : [\n         \"href\" : \"http://localhost:6385/v1/nodes/75f21c83-e6a0-43ab-9e81-9942737b87c1/ports\",\n\nCompare that to:\n\n  curl -H \u0027X-OpenStack-Ironic-API-Version: latest\u0027 http://localhost:6385/v1/nodes/foo 2\u003e/dev/null | json_pp | grep tag || echo \u0027not found\u0027                                       \n  not found","commit_id":"ba383e261b0f4fefc72f33a02b6b6d5e252f89c8"},{"author":{"_account_id":12356,"name":"Vladyslav Drok","email":"vdrok@mirantis.com","username":"vdrok"},"change_message_id":"21a5b79dbcaa30d06b06480e1b3d426d6e90e686","unresolved":false,"context_lines":[{"line_number":502,"context_line":""},{"line_number":503,"context_line":"    @classmethod"},{"line_number":504,"context_line":"    def sample(cls):"},{"line_number":505,"context_line":"        tags \u003d {\u0027tags\u0027: [\"tag1\", \"tag2\"]}"},{"line_number":506,"context_line":"        return cls(tags\u003dtags)"},{"line_number":507,"context_line":""},{"line_number":508,"context_line":""}],"source_content_type":"text/x-python","patch_set":11,"id":"7a5de9d1_f13ac497","line":505,"updated":"2016-01-28 17:13:32.000000000","message":"This is not an array as is mentioned on L496.","commit_id":"d110391d9581bca37a055d296ec64fff5e76c908"},{"author":{"_account_id":6610,"name":"Zhenguo Niu","email":"Niu.ZGlinux@gmail.com","username":"niu-zglinux"},"change_message_id":"ec4e569537b6053ea8ba971fad8760d34647bb8e","unresolved":false,"context_lines":[{"line_number":502,"context_line":""},{"line_number":503,"context_line":"    @classmethod"},{"line_number":504,"context_line":"    def sample(cls):"},{"line_number":505,"context_line":"        tags \u003d {\u0027tags\u0027: [\"tag1\", \"tag2\"]}"},{"line_number":506,"context_line":"        return cls(tags\u003dtags)"},{"line_number":507,"context_line":""},{"line_number":508,"context_line":""}],"source_content_type":"text/x-python","patch_set":11,"id":"7a5de9d1_d49bda70","line":505,"in_reply_to":"7a5de9d1_f13ac497","updated":"2016-01-29 06:50:11.000000000","message":"Done","commit_id":"d110391d9581bca37a055d296ec64fff5e76c908"},{"author":{"_account_id":12356,"name":"Vladyslav Drok","email":"vdrok@mirantis.com","username":"vdrok"},"change_message_id":"7e80effbf411b79a1a6e4fd638d10fac5f067790","unresolved":false,"context_lines":[{"line_number":506,"context_line":"        return cls(tags\u003dtags)"},{"line_number":507,"context_line":""},{"line_number":508,"context_line":""},{"line_number":509,"context_line":"class NodeTagsController(rest.RestController):"},{"line_number":510,"context_line":""},{"line_number":511,"context_line":"    @expose.expose(Tags, types.uuid_or_name)"},{"line_number":512,"context_line":"    def get(self, node_ident):"}],"source_content_type":"text/x-python","patch_set":11,"id":"7a5de9d1_4c83d656","line":509,"updated":"2016-01-29 10:26:30.000000000","message":"Also, there is no way to add a tag in the API, only replace all of them.","commit_id":"d110391d9581bca37a055d296ec64fff5e76c908"},{"author":{"_account_id":12356,"name":"Vladyslav Drok","email":"vdrok@mirantis.com","username":"vdrok"},"change_message_id":"f3e36fadbe6da6d3b1c00078c5becde72180b7a7","unresolved":false,"context_lines":[{"line_number":508,"context_line":""},{"line_number":509,"context_line":"class NodeTagsController(rest.RestController):"},{"line_number":510,"context_line":""},{"line_number":511,"context_line":"    @expose.expose(Tags, types.uuid_or_name)"},{"line_number":512,"context_line":"    def get(self, node_ident):"},{"line_number":513,"context_line":"        \"\"\"List the tags of a node."},{"line_number":514,"context_line":""}],"source_content_type":"text/x-python","patch_set":11,"id":"7a5de9d1_d103e140","line":511,"updated":"2016-01-29 10:23:42.000000000","message":"In this controller methods you should also check for API version.","commit_id":"d110391d9581bca37a055d296ec64fff5e76c908"},{"author":{"_account_id":12356,"name":"Vladyslav Drok","email":"vdrok@mirantis.com","username":"vdrok"},"change_message_id":"f3e36fadbe6da6d3b1c00078c5becde72180b7a7","unresolved":false,"context_lines":[{"line_number":520,"context_line":"        return Tags(tags\u003d_get_tags_names(tags))"},{"line_number":521,"context_line":""},{"line_number":522,"context_line":"    @expose.expose(Tags, types.uuid_or_name, wtypes.ArrayType(str),"},{"line_number":523,"context_line":"                   status_code\u003dhttp_client.ACCEPTED)"},{"line_number":524,"context_line":"    def put(self, node_ident, tags):"},{"line_number":525,"context_line":"        \"\"\"Modify the tag list of a node."},{"line_number":526,"context_line":""}],"source_content_type":"text/x-python","patch_set":11,"id":"7a5de9d1_f185bdac","line":523,"updated":"2016-01-29 10:23:42.000000000","message":"Also I\u0027m wondering should it be 200 OK instead?","commit_id":"d110391d9581bca37a055d296ec64fff5e76c908"},{"author":{"_account_id":12356,"name":"Vladyslav Drok","email":"vdrok@mirantis.com","username":"vdrok"},"change_message_id":"21a5b79dbcaa30d06b06480e1b3d426d6e90e686","unresolved":false,"context_lines":[{"line_number":521,"context_line":""},{"line_number":522,"context_line":"    @expose.expose(Tags, types.uuid_or_name, wtypes.ArrayType(str),"},{"line_number":523,"context_line":"                   status_code\u003dhttp_client.ACCEPTED)"},{"line_number":524,"context_line":"    def put(self, node_ident, tags):"},{"line_number":525,"context_line":"        \"\"\"Modify the tag list of a node."},{"line_number":526,"context_line":""},{"line_number":527,"context_line":"        :param node_ident: UUID or logical name of a node."}],"source_content_type":"text/x-python","patch_set":11,"id":"7a5de9d1_5196384d","line":524,"updated":"2016-01-28 17:13:32.000000000","message":"I\u0027m not able to do the put neither with [\u0027tag1\u0027, \u0027tag2\u0027], nor with {\u0027tags\u0027: [\u0027tag1\u0027, \u0027tag2\u0027]}. Although I may be doing something wrong:\n\n $ curl -i -X PUT http://127.0.0.1:6385/v1/nodes/node-0/tags -H \"X-OpenStack-Ironic-API-Version: 1.15\" -d \u0027[\"tag1\", \"tag10\"]\u0027\n HTTP/1.1 400 Bad Request\n X-Openstack-Ironic-Api-Minimum-Version: 1.1\n X-Openstack-Ironic-Api-Maximum-Version: 1.15\n X-Openstack-Ironic-Api-Version: 1.15\n Content-Type: application/json\n Content-Length: 147\n Date: Thu, 28 Jan 2016 17:10:24 GMT\n\n {\"error_message\": \"{\\\"debuginfo\\\": null, \\\"faultcode\\\": \\\"Client\\\", \\\"faultstring\\\": \\\"Unknown argument: \\\\\\\"[\\\\\\\"tag1\\\\\\\", \\\\\\\"tag10\\\\\\\"]\\\\\\\"\\\"}\"}\n\n $ curl -i -X PUT http://127.0.0.1:6385/v1/nodes/node-0/tags -H \"X-OpenStack-Ironic-API-Version: 1.15\" -d \u0027{\"tags\": [\"tag1\", \"tag10\"]}\u0027\n HTTP/1.1 400 Bad Request\n X-Openstack-Ironic-Api-Minimum-Version: 1.1\n X-Openstack-Ironic-Api-Maximum-Version: 1.15\n X-Openstack-Ironic-Api-Version: 1.15\n Content-Type: application/json\n Content-Length: 163\n Date: Thu, 28 Jan 2016 16:56:42 GMT\n\n {\"error_message\": \"{\\\"debuginfo\\\": null, \\\"faultcode\\\": \\\"Client\\\", \\\"faultstring\\\": \\\"Unknown argument: \\\\\\\"{\\\\\\\"tags\\\\\\\": [\\\\\\\"tag1\\\\\\\", \\\\\\\"tag10\\\\\\\"]}\\\\\\\"\\\"}\"}","commit_id":"d110391d9581bca37a055d296ec64fff5e76c908"},{"author":{"_account_id":6610,"name":"Zhenguo Niu","email":"Niu.ZGlinux@gmail.com","username":"niu-zglinux"},"change_message_id":"ec4e569537b6053ea8ba971fad8760d34647bb8e","unresolved":false,"context_lines":[{"line_number":521,"context_line":""},{"line_number":522,"context_line":"    @expose.expose(Tags, types.uuid_or_name, wtypes.ArrayType(str),"},{"line_number":523,"context_line":"                   status_code\u003dhttp_client.ACCEPTED)"},{"line_number":524,"context_line":"    def put(self, node_ident, tags):"},{"line_number":525,"context_line":"        \"\"\"Modify the tag list of a node."},{"line_number":526,"context_line":""},{"line_number":527,"context_line":"        :param node_ident: UUID or logical name of a node."}],"source_content_type":"text/x-python","patch_set":11,"id":"7a5de9d1_e9c4ff5f","line":524,"in_reply_to":"7a5de9d1_5196384d","updated":"2016-01-29 06:50:11.000000000","message":"hi vdrok, you should specify \"Content-Type: application/json\" in the curl request, to recognize the json body \u0027{\"tags\": [\"tag1\", \"tag2\"]}\u0027.","commit_id":"d110391d9581bca37a055d296ec64fff5e76c908"},{"author":{"_account_id":12356,"name":"Vladyslav Drok","email":"vdrok@mirantis.com","username":"vdrok"},"change_message_id":"f3e36fadbe6da6d3b1c00078c5becde72180b7a7","unresolved":false,"context_lines":[{"line_number":521,"context_line":""},{"line_number":522,"context_line":"    @expose.expose(Tags, types.uuid_or_name, wtypes.ArrayType(str),"},{"line_number":523,"context_line":"                   status_code\u003dhttp_client.ACCEPTED)"},{"line_number":524,"context_line":"    def put(self, node_ident, tags):"},{"line_number":525,"context_line":"        \"\"\"Modify the tag list of a node."},{"line_number":526,"context_line":""},{"line_number":527,"context_line":"        :param node_ident: UUID or logical name of a node."}],"source_content_type":"text/x-python","patch_set":11,"id":"7a5de9d1_d16e812e","line":524,"in_reply_to":"7a5de9d1_e9c4ff5f","updated":"2016-01-29 10:23:42.000000000","message":"Yep, thanks, forgot to add it :)","commit_id":"d110391d9581bca37a055d296ec64fff5e76c908"},{"author":{"_account_id":12356,"name":"Vladyslav Drok","email":"vdrok@mirantis.com","username":"vdrok"},"change_message_id":"21a5b79dbcaa30d06b06480e1b3d426d6e90e686","unresolved":false,"context_lines":[{"line_number":531,"context_line":"        tags \u003d objects.NodeTagList.set(pecan.request.context, node.id, tags)"},{"line_number":532,"context_line":"        return Tags(tags\u003d_get_tags_names(tags))"},{"line_number":533,"context_line":""},{"line_number":534,"context_line":"    @expose.expose(None, types.uuid_or_name, status_code\u003dhttp_client.ACCEPTED)"},{"line_number":535,"context_line":"    def delete(self, node_ident):"},{"line_number":536,"context_line":"        \"\"\"Remove the tags of a node."},{"line_number":537,"context_line":""}],"source_content_type":"text/x-python","patch_set":11,"id":"7a5de9d1_165676d2","line":534,"updated":"2016-01-28 17:13:32.000000000","message":"it should be NO_CONTENT here?","commit_id":"d110391d9581bca37a055d296ec64fff5e76c908"},{"author":{"_account_id":6610,"name":"Zhenguo Niu","email":"Niu.ZGlinux@gmail.com","username":"niu-zglinux"},"change_message_id":"ec4e569537b6053ea8ba971fad8760d34647bb8e","unresolved":false,"context_lines":[{"line_number":531,"context_line":"        tags \u003d objects.NodeTagList.set(pecan.request.context, node.id, tags)"},{"line_number":532,"context_line":"        return Tags(tags\u003d_get_tags_names(tags))"},{"line_number":533,"context_line":""},{"line_number":534,"context_line":"    @expose.expose(None, types.uuid_or_name, status_code\u003dhttp_client.ACCEPTED)"},{"line_number":535,"context_line":"    def delete(self, node_ident):"},{"line_number":536,"context_line":"        \"\"\"Remove the tags of a node."},{"line_number":537,"context_line":""}],"source_content_type":"text/x-python","patch_set":11,"id":"7a5de9d1_94ba42bf","line":534,"in_reply_to":"7a5de9d1_165676d2","updated":"2016-01-29 06:50:11.000000000","message":"Done","commit_id":"d110391d9581bca37a055d296ec64fff5e76c908"},{"author":{"_account_id":12356,"name":"Vladyslav Drok","email":"vdrok@mirantis.com","username":"vdrok"},"change_message_id":"21a5b79dbcaa30d06b06480e1b3d426d6e90e686","unresolved":false,"context_lines":[{"line_number":661,"context_line":"    ports \u003d wsme.wsattr([link.Link], readonly\u003dTrue)"},{"line_number":662,"context_line":"    \"\"\"Links to the collection of ports on this node\"\"\""},{"line_number":663,"context_line":""},{"line_number":664,"context_line":"    states \u003d wsme.wsattr([link.Link], readonly\u003dTrue)"},{"line_number":665,"context_line":"    \"\"\"Links to endpoint for retrieving and setting node states\"\"\""},{"line_number":666,"context_line":""},{"line_number":667,"context_line":"    tags \u003d wtypes.ArrayType(str)"}],"source_content_type":"text/x-python","patch_set":11,"id":"7a5de9d1_abb93b7b","line":664,"updated":"2016-01-28 17:13:32.000000000","message":"Also, what about the link to /tags controller as Devananda commented in PS5?","commit_id":"d110391d9581bca37a055d296ec64fff5e76c908"},{"author":{"_account_id":12356,"name":"Vladyslav Drok","email":"vdrok@mirantis.com","username":"vdrok"},"change_message_id":"f3e36fadbe6da6d3b1c00078c5becde72180b7a7","unresolved":false,"context_lines":[{"line_number":661,"context_line":"    ports \u003d wsme.wsattr([link.Link], readonly\u003dTrue)"},{"line_number":662,"context_line":"    \"\"\"Links to the collection of ports on this node\"\"\""},{"line_number":663,"context_line":""},{"line_number":664,"context_line":"    states \u003d wsme.wsattr([link.Link], readonly\u003dTrue)"},{"line_number":665,"context_line":"    \"\"\"Links to endpoint for retrieving and setting node states\"\"\""},{"line_number":666,"context_line":""},{"line_number":667,"context_line":"    tags \u003d wtypes.ArrayType(str)"}],"source_content_type":"text/x-python","patch_set":11,"id":"7a5de9d1_f1505d60","line":664,"in_reply_to":"7a5de9d1_6fd1ef56","updated":"2016-01-29 10:23:42.000000000","message":"Correct, but the user still needs to discover endpoint where to do delete or put.","commit_id":"d110391d9581bca37a055d296ec64fff5e76c908"},{"author":{"_account_id":6610,"name":"Zhenguo Niu","email":"Niu.ZGlinux@gmail.com","username":"niu-zglinux"},"change_message_id":"ec4e569537b6053ea8ba971fad8760d34647bb8e","unresolved":false,"context_lines":[{"line_number":661,"context_line":"    ports \u003d wsme.wsattr([link.Link], readonly\u003dTrue)"},{"line_number":662,"context_line":"    \"\"\"Links to the collection of ports on this node\"\"\""},{"line_number":663,"context_line":""},{"line_number":664,"context_line":"    states \u003d wsme.wsattr([link.Link], readonly\u003dTrue)"},{"line_number":665,"context_line":"    \"\"\"Links to endpoint for retrieving and setting node states\"\"\""},{"line_number":666,"context_line":""},{"line_number":667,"context_line":"    tags \u003d wtypes.ArrayType(str)"}],"source_content_type":"text/x-python","patch_set":11,"id":"7a5de9d1_6fd1ef56","line":664,"in_reply_to":"7a5de9d1_abb93b7b","updated":"2016-01-29 06:50:11.000000000","message":"instead of returning a link to the tags resources, I embed it in the node.","commit_id":"d110391d9581bca37a055d296ec64fff5e76c908"},{"author":{"_account_id":12356,"name":"Vladyslav Drok","email":"vdrok@mirantis.com","username":"vdrok"},"change_message_id":"21a5b79dbcaa30d06b06480e1b3d426d6e90e686","unresolved":false,"context_lines":[{"line_number":681,"context_line":"            if hasattr(self, k):"},{"line_number":682,"context_line":"                self.fields.append(k)"},{"line_number":683,"context_line":"                if k \u003d\u003d \u0027tags\u0027:"},{"line_number":684,"context_line":"                    tags \u003d kwargs.get(k)"},{"line_number":685,"context_line":"                    setattr(self, k,"},{"line_number":686,"context_line":"                            _get_tags_names(tags)"},{"line_number":687,"context_line":"                            if tags is not None else wtypes.Unset)"}],"source_content_type":"text/x-python","patch_set":11,"id":"7a5de9d1_a2e8807d","line":684,"updated":"2016-01-28 17:13:32.000000000","message":"Is it possible for tags to be None here? If so, things may fail on L118","commit_id":"d110391d9581bca37a055d296ec64fff5e76c908"},{"author":{"_account_id":6610,"name":"Zhenguo Niu","email":"Niu.ZGlinux@gmail.com","username":"niu-zglinux"},"change_message_id":"ec4e569537b6053ea8ba971fad8760d34647bb8e","unresolved":false,"context_lines":[{"line_number":681,"context_line":"            if hasattr(self, k):"},{"line_number":682,"context_line":"                self.fields.append(k)"},{"line_number":683,"context_line":"                if k \u003d\u003d \u0027tags\u0027:"},{"line_number":684,"context_line":"                    tags \u003d kwargs.get(k)"},{"line_number":685,"context_line":"                    setattr(self, k,"},{"line_number":686,"context_line":"                            _get_tags_names(tags)"},{"line_number":687,"context_line":"                            if tags is not None else wtypes.Unset)"}],"source_content_type":"text/x-python","patch_set":11,"id":"7a5de9d1_afc9277a","line":684,"in_reply_to":"7a5de9d1_a2e8807d","updated":"2016-01-29 06:50:11.000000000","message":"I only call _get_tags_names() if tags is not None, see L687.","commit_id":"d110391d9581bca37a055d296ec64fff5e76c908"},{"author":{"_account_id":12356,"name":"Vladyslav Drok","email":"vdrok@mirantis.com","username":"vdrok"},"change_message_id":"f3e36fadbe6da6d3b1c00078c5becde72180b7a7","unresolved":false,"context_lines":[{"line_number":681,"context_line":"            if hasattr(self, k):"},{"line_number":682,"context_line":"                self.fields.append(k)"},{"line_number":683,"context_line":"                if k \u003d\u003d \u0027tags\u0027:"},{"line_number":684,"context_line":"                    tags \u003d kwargs.get(k)"},{"line_number":685,"context_line":"                    setattr(self, k,"},{"line_number":686,"context_line":"                            _get_tags_names(tags)"},{"line_number":687,"context_line":"                            if tags is not None else wtypes.Unset)"}],"source_content_type":"text/x-python","patch_set":11,"id":"7a5de9d1_31483587","line":684,"in_reply_to":"7a5de9d1_afc9277a","updated":"2016-01-29 10:23:42.000000000","message":"Oh, right, sorry for confusion.","commit_id":"d110391d9581bca37a055d296ec64fff5e76c908"},{"author":{"_account_id":12356,"name":"Vladyslav Drok","email":"vdrok@mirantis.com","username":"vdrok"},"change_message_id":"21a5b79dbcaa30d06b06480e1b3d426d6e90e686","unresolved":false,"context_lines":[{"line_number":1034,"context_line":""},{"line_number":1035,"context_line":"        \"\"\""},{"line_number":1036,"context_line":"        for field in objects.Node.fields:"},{"line_number":1037,"context_line":"            if field \u003d\u003d \u0027tags\u0027:"},{"line_number":1038,"context_line":"                continue"},{"line_number":1039,"context_line":"            try:"},{"line_number":1040,"context_line":"                patch_val \u003d getattr(node, field)"}],"source_content_type":"text/x-python","patch_set":11,"id":"7a5de9d1_422bcc94","line":1037,"updated":"2016-01-28 17:13:32.000000000","message":"Please add a comment that it is handled by a different endpoint.","commit_id":"d110391d9581bca37a055d296ec64fff5e76c908"},{"author":{"_account_id":6610,"name":"Zhenguo Niu","email":"Niu.ZGlinux@gmail.com","username":"niu-zglinux"},"change_message_id":"ec4e569537b6053ea8ba971fad8760d34647bb8e","unresolved":false,"context_lines":[{"line_number":1034,"context_line":""},{"line_number":1035,"context_line":"        \"\"\""},{"line_number":1036,"context_line":"        for field in objects.Node.fields:"},{"line_number":1037,"context_line":"            if field \u003d\u003d \u0027tags\u0027:"},{"line_number":1038,"context_line":"                continue"},{"line_number":1039,"context_line":"            try:"},{"line_number":1040,"context_line":"                patch_val \u003d getattr(node, field)"}],"source_content_type":"text/x-python","patch_set":11,"id":"7a5de9d1_cf9b4371","line":1037,"in_reply_to":"7a5de9d1_422bcc94","updated":"2016-01-29 06:50:11.000000000","message":"Done","commit_id":"d110391d9581bca37a055d296ec64fff5e76c908"},{"author":{"_account_id":10206,"name":"Madhuri Kumari","email":"madhuri.kumari@intel.com","username":"Madhuri"},"change_message_id":"d02bb4ffa8b169806a0e07cc0c51d2949ac51622","unresolved":false,"context_lines":[{"line_number":669,"context_line":"        if not api_utils.allow_tags():"},{"line_number":670,"context_line":"            raise exception.NotFound()"},{"line_number":671,"context_line":"        node \u003d api_utils.get_rpc_node(node_ident)"},{"line_number":672,"context_line":"        tags \u003d objects.NodeTagList.create(pecan.request.context, node.id, tags)"},{"line_number":673,"context_line":"        return Tags(tags\u003d_get_tags_names(tags))"},{"line_number":674,"context_line":""},{"line_number":675,"context_line":"    @expose.expose(None, types.uuid_or_name,"}],"source_content_type":"text/x-python","patch_set":25,"id":"1a6eadb0_58c54b59","line":672,"range":{"start_line":672,"start_character":15,"end_line":672,"end_character":79},"updated":"2016-12-19 18:17:21.000000000","message":"I might be wrong here. But is it good to write to db from api service. IMO the conductor service is meant to read/write to db whereas api service should only have read permission to the db.\nThoughts?","commit_id":"1dfa1122a82861bf8c86a329a2ef4a5340769a5a"},{"author":{"_account_id":12356,"name":"Vladyslav Drok","email":"vdrok@mirantis.com","username":"vdrok"},"change_message_id":"5c6611922bb159fd2cb274f862de5daf7ef5a111","unresolved":false,"context_lines":[{"line_number":1366,"context_line":"                _(\"The sort_key value %(key)s is an invalid field for \""},{"line_number":1367,"context_line":"                  \"sorting\") % {\u0027key\u0027: sort_key})"},{"line_number":1368,"context_line":""},{"line_number":1369,"context_line":"        # TODO(vdrok): refactor this bit, too many ifs"},{"line_number":1370,"context_line":"        filters \u003d {}"},{"line_number":1371,"context_line":"        parameters \u003d {\u0027sort_key\u0027: sort_key, \u0027sort_dir\u0027: sort_dir}"},{"line_number":1372,"context_line":"        link_params_not_none \u003d [\u0027associated\u0027, \u0027maintenance\u0027]"}],"source_content_type":"text/x-python","patch_set":31,"id":"ffe62b97_90188075","line":1369,"updated":"2017-03-27 11:29:35.000000000","message":"This was changed, as if let this be as-is, with addition of various tag filters, pep8 starts to complain about code complexity.","commit_id":"71ba3bf9e98ae00ff68eb0ceb7c2ec100405676e"},{"author":{"_account_id":6618,"name":"Ruby Loo","email":"opensrloo@gmail.com","username":"rloo"},"change_message_id":"a23ca9098e516e3d6bfb1b6c8204de03e9a7004c","unresolved":false,"context_lines":[{"line_number":735,"context_line":"        :param tags: List value; tags of a node."},{"line_number":736,"context_line":"        \"\"\""},{"line_number":737,"context_line":"        cdict \u003d pecan.request.context.to_policy_values()"},{"line_number":738,"context_line":"        policy.authorize(\u0027baremetal:node:tag:put\u0027, cdict, cdict)"},{"line_number":739,"context_line":"        if not api_utils.allow_tags():"},{"line_number":740,"context_line":"            raise exception.NotFound()"},{"line_number":741,"context_line":"        node \u003d api_utils.get_rpc_node(node_ident)"}],"source_content_type":"text/x-python","patch_set":34,"id":"1f1a1f67_d5285487","line":738,"updated":"2017-07-14 02:11:14.000000000","message":"wondering if we should use something other than \u0027put\u0027. Is it clear what \u0027put\u0027 means? I see \u0027baremetal:node:inject_nmi\u0027, \u0027..:node:set_console_state\u0027, \u0027:set_maintenance\u0027, \u0027:set_boot_device\u0027.","commit_id":"7acd80647669b22acce6e49dab6510c003af5095"},{"author":{"_account_id":12356,"name":"Vladyslav Drok","email":"vdrok@mirantis.com","username":"vdrok"},"change_message_id":"41a5d32109658b1e4b9dce159349a52379a206ed","unresolved":false,"context_lines":[{"line_number":735,"context_line":"        :param tags: List value; tags of a node."},{"line_number":736,"context_line":"        \"\"\""},{"line_number":737,"context_line":"        cdict \u003d pecan.request.context.to_policy_values()"},{"line_number":738,"context_line":"        policy.authorize(\u0027baremetal:node:tag:put\u0027, cdict, cdict)"},{"line_number":739,"context_line":"        if not api_utils.allow_tags():"},{"line_number":740,"context_line":"            raise exception.NotFound()"},{"line_number":741,"context_line":"        node \u003d api_utils.get_rpc_node(node_ident)"}],"source_content_type":"text/x-python","patch_set":34,"id":"1f1a1f67_4877eaa1","line":738,"in_reply_to":"1f1a1f67_d5285487","updated":"2017-07-14 16:30:36.000000000","message":"Yeah, set might make more sense.","commit_id":"7acd80647669b22acce6e49dab6510c003af5095"},{"author":{"_account_id":6618,"name":"Ruby Loo","email":"opensrloo@gmail.com","username":"rloo"},"change_message_id":"a23ca9098e516e3d6bfb1b6c8204de03e9a7004c","unresolved":false,"context_lines":[{"line_number":740,"context_line":"            raise exception.NotFound()"},{"line_number":741,"context_line":"        node \u003d api_utils.get_rpc_node(node_ident)"},{"line_number":742,"context_line":"        tags \u003d objects.NodeTagList.create(pecan.request.context, node.id, tags)"},{"line_number":743,"context_line":"        return Tags(tags\u003d_get_tags_names(tags))"},{"line_number":744,"context_line":""},{"line_number":745,"context_line":"    @expose.expose(None, types.uuid_or_name,"},{"line_number":746,"context_line":"                   status_code\u003dhttp_client.NO_CONTENT)"}],"source_content_type":"text/x-python","patch_set":34,"id":"1f1a1f67_75f620fc","line":743,"updated":"2017-07-14 02:11:14.000000000","message":"Does this replace the list of tags for the node, with this new list of tags? I\u0027m guessing yes (and it addresses [1]). But we don\u0027t have anything (yet) for Addressing Individual Tags [2]\n\n[1] http://specs.openstack.org/openstack/api-wg/guidelines/tags.html#modifying-the-tag-list\n[2] http://specs.openstack.org/openstack/api-wg/guidelines/tags.html#addressing-individual-tags","commit_id":"7acd80647669b22acce6e49dab6510c003af5095"},{"author":{"_account_id":12356,"name":"Vladyslav Drok","email":"vdrok@mirantis.com","username":"vdrok"},"change_message_id":"41a5d32109658b1e4b9dce159349a52379a206ed","unresolved":false,"context_lines":[{"line_number":740,"context_line":"            raise exception.NotFound()"},{"line_number":741,"context_line":"        node \u003d api_utils.get_rpc_node(node_ident)"},{"line_number":742,"context_line":"        tags \u003d objects.NodeTagList.create(pecan.request.context, node.id, tags)"},{"line_number":743,"context_line":"        return Tags(tags\u003d_get_tags_names(tags))"},{"line_number":744,"context_line":""},{"line_number":745,"context_line":"    @expose.expose(None, types.uuid_or_name,"},{"line_number":746,"context_line":"                   status_code\u003dhttp_client.NO_CONTENT)"}],"source_content_type":"text/x-python","patch_set":34,"id":"1f1a1f67_a83c3ebf","line":743,"in_reply_to":"1f1a1f67_75f620fc","updated":"2017-07-14 16:30:36.000000000","message":"Yup, may add the individual operations.","commit_id":"7acd80647669b22acce6e49dab6510c003af5095"},{"author":{"_account_id":6618,"name":"Ruby Loo","email":"opensrloo@gmail.com","username":"rloo"},"change_message_id":"03e69aa0fc27df5f47e78c7465378bb3e1761142","unresolved":false,"context_lines":[{"line_number":740,"context_line":"            raise exception.NotFound()"},{"line_number":741,"context_line":"        node \u003d api_utils.get_rpc_node(node_ident)"},{"line_number":742,"context_line":"        tags \u003d objects.NodeTagList.create(pecan.request.context, node.id, tags)"},{"line_number":743,"context_line":"        return Tags(tags\u003d_get_tags_names(tags))"},{"line_number":744,"context_line":""},{"line_number":745,"context_line":"    @expose.expose(None, types.uuid_or_name,"},{"line_number":746,"context_line":"                   status_code\u003dhttp_client.NO_CONTENT)"}],"source_content_type":"text/x-python","patch_set":34,"id":"1f1a1f67_cc2f3886","line":743,"in_reply_to":"1f1a1f67_a83c3ebf","updated":"2017-07-18 14:03:00.000000000","message":"Ok, if we don\u0027t end up adding the individual tags, we should note it somewhere, maybe in the spec?","commit_id":"7acd80647669b22acce6e49dab6510c003af5095"},{"author":{"_account_id":12356,"name":"Vladyslav Drok","email":"vdrok@mirantis.com","username":"vdrok"},"change_message_id":"589a14eb0cf24ab93467dc1f8fab12b9b6911cfe","unresolved":false,"context_lines":[{"line_number":740,"context_line":"            raise exception.NotFound()"},{"line_number":741,"context_line":"        node \u003d api_utils.get_rpc_node(node_ident)"},{"line_number":742,"context_line":"        tags \u003d objects.NodeTagList.create(pecan.request.context, node.id, tags)"},{"line_number":743,"context_line":"        return Tags(tags\u003d_get_tags_names(tags))"},{"line_number":744,"context_line":""},{"line_number":745,"context_line":"    @expose.expose(None, types.uuid_or_name,"},{"line_number":746,"context_line":"                   status_code\u003dhttp_client.NO_CONTENT)"}],"source_content_type":"text/x-python","patch_set":34,"id":"ff346bd7_c8713aaa","line":743,"in_reply_to":"1f1a1f67_cc2f3886","updated":"2017-07-28 16:21:35.000000000","message":"I guess I\u0027ll add that to a subsequent patch.","commit_id":"7acd80647669b22acce6e49dab6510c003af5095"},{"author":{"_account_id":6618,"name":"Ruby Loo","email":"opensrloo@gmail.com","username":"rloo"},"change_message_id":"a23ca9098e516e3d6bfb1b6c8204de03e9a7004c","unresolved":false,"context_lines":[{"line_number":741,"context_line":"        node \u003d api_utils.get_rpc_node(node_ident)"},{"line_number":742,"context_line":"        tags \u003d objects.NodeTagList.create(pecan.request.context, node.id, tags)"},{"line_number":743,"context_line":"        return Tags(tags\u003d_get_tags_names(tags))"},{"line_number":744,"context_line":""},{"line_number":745,"context_line":"    @expose.expose(None, types.uuid_or_name,"},{"line_number":746,"context_line":"                   status_code\u003dhttp_client.NO_CONTENT)"},{"line_number":747,"context_line":"    def delete(self, node_ident):"}],"source_content_type":"text/x-python","patch_set":34,"id":"1f1a1f67_75e060fb","line":744,"updated":"2017-07-14 02:11:14.000000000","message":"I\u0027ve got a small concern here, wrt this and rolling upgrades. Although maybe it can be addressed when/if it is needed. Most of the other resources are modified via RPC request to the conductor. (The exceptions are chassis-create\u0026update, portgroup-create.) We just changed master so that port is created-via-conductor, so I suppose we could do a similar thing for tags if we need to.","commit_id":"7acd80647669b22acce6e49dab6510c003af5095"},{"author":{"_account_id":12356,"name":"Vladyslav Drok","email":"vdrok@mirantis.com","username":"vdrok"},"change_message_id":"41a5d32109658b1e4b9dce159349a52379a206ed","unresolved":false,"context_lines":[{"line_number":741,"context_line":"        node \u003d api_utils.get_rpc_node(node_ident)"},{"line_number":742,"context_line":"        tags \u003d objects.NodeTagList.create(pecan.request.context, node.id, tags)"},{"line_number":743,"context_line":"        return Tags(tags\u003d_get_tags_names(tags))"},{"line_number":744,"context_line":""},{"line_number":745,"context_line":"    @expose.expose(None, types.uuid_or_name,"},{"line_number":746,"context_line":"                   status_code\u003dhttp_client.NO_CONTENT)"},{"line_number":747,"context_line":"    def delete(self, node_ident):"}],"source_content_type":"text/x-python","patch_set":34,"id":"1f1a1f67_afbe9262","line":744,"in_reply_to":"1f1a1f67_75e060fb","updated":"2017-07-14 16:30:36.000000000","message":"I don\u0027t think there is a reason to do it on the conductor-side yet, and may never be, as these are just strings to save into DB, there should be no additional logic involved, otherwise they wouldn\u0027t be tags :)","commit_id":"7acd80647669b22acce6e49dab6510c003af5095"},{"author":{"_account_id":6618,"name":"Ruby Loo","email":"opensrloo@gmail.com","username":"rloo"},"change_message_id":"03e69aa0fc27df5f47e78c7465378bb3e1761142","unresolved":false,"context_lines":[{"line_number":741,"context_line":"        node \u003d api_utils.get_rpc_node(node_ident)"},{"line_number":742,"context_line":"        tags \u003d objects.NodeTagList.create(pecan.request.context, node.id, tags)"},{"line_number":743,"context_line":"        return Tags(tags\u003d_get_tags_names(tags))"},{"line_number":744,"context_line":""},{"line_number":745,"context_line":"    @expose.expose(None, types.uuid_or_name,"},{"line_number":746,"context_line":"                   status_code\u003dhttp_client.NO_CONTENT)"},{"line_number":747,"context_line":"    def delete(self, node_ident):"}],"source_content_type":"text/x-python","patch_set":34,"id":"1f1a1f67_4c7208af","line":744,"in_reply_to":"1f1a1f67_afbe9262","updated":"2017-07-18 14:03:00.000000000","message":"Yeah, my thinking too. Just wanted to \u0027record\u0027 the thinking here cuz I\u0027m sure I will forget in a week :)","commit_id":"7acd80647669b22acce6e49dab6510c003af5095"},{"author":{"_account_id":6618,"name":"Ruby Loo","email":"opensrloo@gmail.com","username":"rloo"},"change_message_id":"a23ca9098e516e3d6bfb1b6c8204de03e9a7004c","unresolved":false,"context_lines":[{"line_number":1528,"context_line":"                            in maintenance mode (\"False\")."},{"line_number":1529,"context_line":"        :param provision_state: Optional string value to get only nodes in"},{"line_number":1530,"context_line":"                                that provision state."},{"line_number":1531,"context_line":"        :param tags: Optional, a list with a sepcified set of string values to"},{"line_number":1532,"context_line":"                     get only nodes with all tags."},{"line_number":1533,"context_line":"        :param tags_any: Optional, a list with a sepcified set of string values"},{"line_number":1534,"context_line":"                         to get only nodes with any of the tags."}],"source_content_type":"text/x-python","patch_set":34,"id":"1f1a1f67_8a5cfb7e","line":1531,"updated":"2017-07-14 02:11:14.000000000","message":"nit s/sepcified/specified/\n\nsame issue below","commit_id":"7acd80647669b22acce6e49dab6510c003af5095"},{"author":{"_account_id":12356,"name":"Vladyslav Drok","email":"vdrok@mirantis.com","username":"vdrok"},"change_message_id":"589a14eb0cf24ab93467dc1f8fab12b9b6911cfe","unresolved":false,"context_lines":[{"line_number":1528,"context_line":"                            in maintenance mode (\"False\")."},{"line_number":1529,"context_line":"        :param provision_state: Optional string value to get only nodes in"},{"line_number":1530,"context_line":"                                that provision state."},{"line_number":1531,"context_line":"        :param tags: Optional, a list with a sepcified set of string values to"},{"line_number":1532,"context_line":"                     get only nodes with all tags."},{"line_number":1533,"context_line":"        :param tags_any: Optional, a list with a sepcified set of string values"},{"line_number":1534,"context_line":"                         to get only nodes with any of the tags."}],"source_content_type":"text/x-python","patch_set":34,"id":"ff346bd7_c87ffa63","line":1531,"in_reply_to":"1f1a1f67_8a5cfb7e","updated":"2017-07-28 16:21:35.000000000","message":"Done","commit_id":"7acd80647669b22acce6e49dab6510c003af5095"}],"ironic/api/controllers/v1/versions.py":[{"author":{"_account_id":7882,"name":"Yuiko Takada Mori","email":"yuiko-mori@nec.com","username":"YuikoTakada"},"change_message_id":"061c256240d47576f470b12325fb9756e84c73b8","unresolved":false,"context_lines":[{"line_number":45,"context_line":"#        1. \u0027/v1/nodes/\u003cuuid\u003e/states\u0027"},{"line_number":46,"context_line":"#        2. \u0027/v1/drivers/\u003cdriver-name\u003e/properties\u0027"},{"line_number":47,"context_line":"# v1.15: Add ability to do manual cleaning of nodes"},{"line_number":48,"context_line":"# v1.16: Add ability to filter nodes by driver."},{"line_number":49,"context_line":""},{"line_number":50,"context_line":"MINOR_0_JUNO \u003d 0"},{"line_number":51,"context_line":"MINOR_1_INITIAL_VERSION \u003d 1"}],"source_content_type":"text/x-python","patch_set":22,"id":"9abb7d3a_b6810e92","line":48,"range":{"start_line":48,"start_character":0,"end_line":48,"end_character":47},"updated":"2016-06-03 08:02:19.000000000","message":"Please add explanation under here also.","commit_id":"48de97232d6cad5e4c1badfa329b198ebe75fdba"}],"ironic/db/sqlalchemy/api.py":[{"author":{"_account_id":12356,"name":"Vladyslav Drok","email":"vdrok@mirantis.com","username":"vdrok"},"change_message_id":"21a5b79dbcaa30d06b06480e1b3d426d6e90e686","unresolved":false,"context_lines":[{"line_number":360,"context_line":"            port_query \u003d add_port_filter_by_node(port_query, node_id)"},{"line_number":361,"context_line":"            port_query.delete()"},{"line_number":362,"context_line":""},{"line_number":363,"context_line":"            tag_query \u003d model_query(models.NodeTag).filter_by(node_id\u003dnode_id)"},{"line_number":364,"context_line":"            tag_query.delete()"},{"line_number":365,"context_line":""},{"line_number":366,"context_line":"            query.delete()"}],"source_content_type":"text/x-python","patch_set":11,"id":"7a5de9d1_d004667f","line":363,"updated":"2016-01-28 17:13:32.000000000","message":"This should be done in previous patches as this one claims to be an API only :) Also this is not tested anywhere.","commit_id":"d110391d9581bca37a055d296ec64fff5e76c908"}],"releasenotes/notes/add-node-tags-1812f453c0cfba8c.yaml":[{"author":{"_account_id":6618,"name":"Ruby Loo","email":"opensrloo@gmail.com","username":"rloo"},"change_message_id":"de20aa149e347b497f9f54583c09d9f899c52497","unresolved":false,"context_lines":[{"line_number":1,"context_line":"---"},{"line_number":2,"context_line":"features:"},{"line_number":3,"context_line":"  - Adds support for node tags. This feature is available starting"},{"line_number":4,"context_line":"    with API version 1.32."}],"source_content_type":"text/x-yaml","patch_set":33,"id":"5f201791_730120af","line":4,"updated":"2017-06-27 12:29:42.000000000","message":"I wonder if we should explicitly mention the REST APIs that are available to support this. What is a \u0027tag\u0027 anyway, a string of max chars (I don\u0027t remember now)? And maybe how to specify it, the new filter strings that are available?\n\nAlso reminds me that we need to update the api-ref.","commit_id":"c9036a3c1db68e976e84d0be85ecdf19e9e0b53e"}]}
