)]}'
{"ironic/api/controllers/v1/node.py":[{"author":{"_account_id":22724,"name":"Galyna Zholtkevych","email":"galynazholtkevych1991@gmail.com","username":"gzholtkevych"},"change_message_id":"7307f9ffdd7715948b6485bba0522583d7db6d99","unresolved":false,"context_lines":[{"line_number":1333,"context_line":"        return pecan.request.rpcapi.validate_driver_interfaces("},{"line_number":1334,"context_line":"            pecan.request.context, rpc_node.uuid, topic)"},{"line_number":1335,"context_line":""},{"line_number":1336,"context_line":"    @METRICS.timer(\u0027NodesController.get_etag\u0027)"},{"line_number":1337,"context_line":"    def get_etag(self, node_ident):"},{"line_number":1338,"context_line":"        \"\"\"Retrieve etag from memcache"},{"line_number":1339,"context_line":""},{"line_number":1340,"context_line":"        :param node_ident: UUID or logical name of a node."},{"line_number":1341,"context_line":"        \"\"\""},{"line_number":1342,"context_line":"        cdict \u003d pecan.request.context.to_dict()"},{"line_number":1343,"context_line":"        policy.authorize(\u0027baremetal:node:get\u0027, cdict, cdict)"},{"line_number":1344,"context_line":""},{"line_number":1345,"context_line":"        if self.from_chassis:"},{"line_number":1346,"context_line":"            raise exception.OperationNotPermitted()"},{"line_number":1347,"context_line":""},{"line_number":1348,"context_line":"        headers \u003d pecan.response.headers"},{"line_number":1349,"context_line":"        # TODO: to be implemented getting etag somehow"},{"line_number":1350,"context_line":"        # (if decided to use cache)"},{"line_number":1351,"context_line":"        headers[\u0027ETag\u0027] \u003d api_utils.get_etag(node_ident)"},{"line_number":1352,"context_line":"        pecan.response.headers \u003d headers"},{"line_number":1353,"context_line":""},{"line_number":1354,"context_line":"    @METRICS.timer(\u0027NodesController.get_one\u0027)"},{"line_number":1355,"context_line":"    @expose.expose(Node, types.uuid_or_name, types.listtype)"}],"source_content_type":"text/x-python","patch_set":3,"id":"ba5da102_56fbd3c0","line":1352,"range":{"start_line":1336,"start_character":4,"end_line":1352,"end_character":40},"updated":"2016-11-02 17:08:36.000000000","message":"To be strongly discussed. \nIt makes sence to do it when we send response for update request and we only need etag in the response and do not need the full node and we avoid going to the database in this case. But it also has some disadvantages","commit_id":"0b217b130b57d3cad606ae7d5fb8adf1ba52b91c"},{"author":{"_account_id":19072,"name":"Xavier","email":"marcusrafael@lsd.ufcg.edu.br","username":"marcusrafael"},"change_message_id":"7ef3628b9f834d3523519915a1f1d7c00ece44fa","unresolved":false,"context_lines":[{"line_number":1346,"context_line":"            raise exception.OperationNotPermitted()"},{"line_number":1347,"context_line":""},{"line_number":1348,"context_line":"        headers \u003d pecan.response.headers"},{"line_number":1349,"context_line":"        # TODO(galyna): here it makes sence to use separate endpoint"},{"line_number":1350,"context_line":"        # for the case only if the cache is used instead of db requests"},{"line_number":1351,"context_line":"        # If db api is used, this code will be erased and common endpoint"},{"line_number":1352,"context_line":"        # will be used to get etag (because there in any case the db requests"}],"source_content_type":"text/x-python","patch_set":4,"id":"ba5da102_7e8f9b74","line":1349,"range":{"start_line":1349,"start_character":38,"end_line":1349,"end_character":43},"updated":"2016-11-03 18:21:18.000000000","message":"s/sence/sense/","commit_id":"aab7b5d461f18150a355b74dc32e05cdf8184e79"},{"author":{"_account_id":19213,"name":"Szymon Borkowski","email":"szymon.borkowski@intel.com","username":"sborkows"},"change_message_id":"cc905861c4964db07c5511ee482664ed1d1bdb00","unresolved":false,"context_lines":[{"line_number":141,"context_line":"    if not api_utils.allow_resource_class():"},{"line_number":142,"context_line":"        obj.resource_class \u003d wsme.Unset"},{"line_number":143,"context_line":""},{"line_number":144,"context_line":"    obj.etag \u003d wsme.Unset"},{"line_number":145,"context_line":""},{"line_number":146,"context_line":""},{"line_number":147,"context_line":"def update_state_in_older_versions(obj):"}],"source_content_type":"text/x-python","patch_set":24,"id":"da4df55a_6616ef56","line":144,"range":{"start_line":144,"start_character":4,"end_line":144,"end_character":25},"updated":"2016-12-23 10:12:16.000000000","message":"Can you explain me why we always unset this? Is it associated with calling api_utils.allow_etag() in e.g. L485? If not, then IMO this method should be called here in order to unset this field properly.","commit_id":"49f568c374e1b19a1a0335611cff77ce3971e0cb"},{"author":{"_account_id":19213,"name":"Szymon Borkowski","email":"szymon.borkowski@intel.com","username":"sborkows"},"change_message_id":"cc905861c4964db07c5511ee482664ed1d1bdb00","unresolved":false,"context_lines":[{"line_number":467,"context_line":"        #                    target state from the current one"},{"line_number":468,"context_line":"        rpc_node \u003d api_utils.get_rpc_node(node_ident)"},{"line_number":469,"context_line":"        topic \u003d pecan.request.rpcapi.get_topic_for(rpc_node)"},{"line_number":470,"context_line":"        request_etag \u003d pecan.request.headers.get(\u0027If-Match\u0027)"},{"line_number":471,"context_line":""},{"line_number":472,"context_line":"        if target not in [ir_states.POWER_ON,"},{"line_number":473,"context_line":"                          ir_states.POWER_OFF,"}],"source_content_type":"text/x-python","patch_set":24,"id":"da4df55a_615b392f","line":470,"range":{"start_line":470,"start_character":8,"end_line":470,"end_character":60},"updated":"2016-12-23 10:12:16.000000000","message":"nit: this line can be moved to L484 to keep this consistent with L485-490 (like in other methods).","commit_id":"49f568c374e1b19a1a0335611cff77ce3971e0cb"}],"ironic/api/controllers/v1/utils.py":[{"author":{"_account_id":22724,"name":"Galyna Zholtkevych","email":"galynazholtkevych1991@gmail.com","username":"gzholtkevych"},"change_message_id":"47e4ebd92066cf1ef1e475cdd0bbd3913826eafc","unresolved":false,"context_lines":[{"line_number":440,"context_line":"    :param resource_obj: resource object to be based on while generating"},{"line_number":441,"context_line":"    \"\"\""},{"line_number":442,"context_line":"    etag \u003d generate_etag(resource_obj)"},{"line_number":443,"context_line":"    # set somehow to memcache, using resource identity"},{"line_number":444,"context_line":""},{"line_number":445,"context_line":""},{"line_number":446,"context_line":"def get_cached_etag(resource_ident):"}],"source_content_type":"text/x-python","patch_set":3,"id":"ba5da102_f695c732","line":443,"range":{"start_line":443,"start_character":3,"end_line":443,"end_character":54},"updated":"2016-11-02 17:13:13.000000000","message":"To be strongly discussed and investigated. It is not in the spec.\nIt helps to avoid extra db api calls in the case if we have separate endpoint for update requests.","commit_id":"0b217b130b57d3cad606ae7d5fb8adf1ba52b91c"},{"author":{"_account_id":19072,"name":"Xavier","email":"marcusrafael@lsd.ufcg.edu.br","username":"marcusrafael"},"change_message_id":"7ef3628b9f834d3523519915a1f1d7c00ece44fa","unresolved":false,"context_lines":[{"line_number":392,"context_line":""},{"line_number":393,"context_line":""},{"line_number":394,"context_line":"def allow_etag():"},{"line_number":395,"context_line":"    \"\"\"Check if heartbeat and lookup endpoints are allowed."},{"line_number":396,"context_line":""},{"line_number":397,"context_line":"        Version 1.22 of the API introduced them."},{"line_number":398,"context_line":"        \"\"\""}],"source_content_type":"text/x-python","patch_set":4,"id":"ba5da102_debfc7cd","line":395,"range":{"start_line":395,"start_character":7,"end_line":395,"end_character":59},"updated":"2016-11-03 18:21:18.000000000","message":"s/Check if heartbeat and lookup endpoints are allowed./Check etags support./","commit_id":"aab7b5d461f18150a355b74dc32e05cdf8184e79"},{"author":{"_account_id":19072,"name":"Xavier","email":"marcusrafael@lsd.ufcg.edu.br","username":"marcusrafael"},"change_message_id":"7ef3628b9f834d3523519915a1f1d7c00ece44fa","unresolved":false,"context_lines":[{"line_number":394,"context_line":"def allow_etag():"},{"line_number":395,"context_line":"    \"\"\"Check if heartbeat and lookup endpoints are allowed."},{"line_number":396,"context_line":""},{"line_number":397,"context_line":"        Version 1.22 of the API introduced them."},{"line_number":398,"context_line":"        \"\"\""},{"line_number":399,"context_line":"    return pecan.request.version.minor \u003e\u003d versions.MINOR_23_ETAGS"},{"line_number":400,"context_line":""}],"source_content_type":"text/x-python","patch_set":4,"id":"ba5da102_fe0d6be8","line":397,"range":{"start_line":397,"start_character":16,"end_line":397,"end_character":20},"updated":"2016-11-03 18:21:18.000000000","message":"s/1.22/1.23/ ?","commit_id":"aab7b5d461f18150a355b74dc32e05cdf8184e79"},{"author":{"_account_id":19213,"name":"Szymon Borkowski","email":"szymon.borkowski@intel.com","username":"sborkows"},"change_message_id":"a1a730e405707e8844a6e0bff93756662a595088","unresolved":false,"context_lines":[{"line_number":550,"context_line":""},{"line_number":551,"context_line":""},{"line_number":552,"context_line":"def allow_etag():"},{"line_number":553,"context_line":"    \"\"\"Check if heartbeat and lookup endpoints are allowed."},{"line_number":554,"context_line":""},{"line_number":555,"context_line":"        Version 1.22 of the API introduced them."},{"line_number":556,"context_line":"        \"\"\""},{"line_number":557,"context_line":"    return pecan.request.version.minor \u003e\u003d versions.MINOR_32_ETAGS"},{"line_number":558,"context_line":""}],"source_content_type":"text/x-python","patch_set":42,"id":"1a430d35_7a778ed4","line":555,"range":{"start_line":553,"start_character":4,"end_line":555,"end_character":48},"updated":"2017-02-03 16:37:53.000000000","message":"I think this comment is not valid for that method :)","commit_id":"a6e48eb1a6cef842b7584c9387ffcaa26807af35"},{"author":{"_account_id":22724,"name":"Galyna Zholtkevych","email":"galynazholtkevych1991@gmail.com","username":"gzholtkevych"},"change_message_id":"bfe9ac08646799dff126a25a1341be5d91c2dc29","unresolved":false,"context_lines":[{"line_number":550,"context_line":""},{"line_number":551,"context_line":""},{"line_number":552,"context_line":"def allow_etag():"},{"line_number":553,"context_line":"    \"\"\"Check if heartbeat and lookup endpoints are allowed."},{"line_number":554,"context_line":""},{"line_number":555,"context_line":"        Version 1.22 of the API introduced them."},{"line_number":556,"context_line":"        \"\"\""},{"line_number":557,"context_line":"    return pecan.request.version.minor \u003e\u003d versions.MINOR_32_ETAGS"},{"line_number":558,"context_line":""}],"source_content_type":"text/x-python","patch_set":42,"id":"1a430d35_4a9c7f69","line":555,"range":{"start_line":553,"start_character":4,"end_line":555,"end_character":48},"in_reply_to":"1a430d35_7a778ed4","updated":"2017-02-06 14:20:25.000000000","message":"The point is the syntax sugar is the last thing to do and until I have -2 on this patch, untitests, pep8 and stuff like that may be remained for now only important notes about changing behaviour in the project have the value for now :) \nAnyway thank you, there is some work that can be done right now! I will concern you notes","commit_id":"a6e48eb1a6cef842b7584c9387ffcaa26807af35"}],"ironic/api/controllers/v1/versions.py":[{"author":{"_account_id":19213,"name":"Szymon Borkowski","email":"szymon.borkowski@intel.com","username":"sborkows"},"change_message_id":"8cc52344e22a3e7811755a6a9a1c321c0f012283","unresolved":false,"context_lines":[{"line_number":56,"context_line":"# v1.24: Add subcontrollers: node.portgroup, portgroup.ports."},{"line_number":57,"context_line":"#        Add port.portgroup_uuid field."},{"line_number":58,"context_line":"# v1.25: Add possibility to unset chassis_uuid from node."},{"line_number":59,"context_line":"# v1.25: Add possibility to unset chassis_uuid from node."},{"line_number":60,"context_line":""},{"line_number":61,"context_line":"MINOR_0_JUNO \u003d 0"},{"line_number":62,"context_line":"MINOR_1_INITIAL_VERSION \u003d 1"}],"source_content_type":"text/x-python","patch_set":20,"id":"1a6eadb0_5cf4ba59","line":59,"updated":"2016-12-16 13:28:28.000000000","message":"I think you wanted to add here v1.26 which supports ETAGs.","commit_id":"af8609dba0ecba4d7a30c79a243295ded5d11b9c"},{"author":{"_account_id":19213,"name":"Szymon Borkowski","email":"szymon.borkowski@intel.com","username":"sborkows"},"change_message_id":"8cc52344e22a3e7811755a6a9a1c321c0f012283","unresolved":false,"context_lines":[{"line_number":90,"context_line":"# doc/source/dev/webapi-version-history.rst with a detailed explanation of"},{"line_number":91,"context_line":"# what the version has changed."},{"line_number":92,"context_line":"MINOR_MAX_VERSION \u003d MINOR_25_UNSET_CHASSIS_UUID"},{"line_number":93,"context_line":"MINOR_MAX_VERSION \u003d MINOR_26_ETAGS"},{"line_number":94,"context_line":""},{"line_number":95,"context_line":"# String representations of the minor and maximum versions"},{"line_number":96,"context_line":"MIN_VERSION_STRING \u003d \u0027{}.{}\u0027.format(BASE_VERSION, MINOR_1_INITIAL_VERSION)"}],"source_content_type":"text/x-python","patch_set":20,"id":"1a6eadb0_5cc2fae9","line":93,"updated":"2016-12-16 13:28:28.000000000","message":"Why are you overwriting here MINOR_MAX_VERSION instead of changing its value in L92?","commit_id":"af8609dba0ecba4d7a30c79a243295ded5d11b9c"}],"ironic/common/exception.py":[{"author":{"_account_id":19072,"name":"Xavier","email":"marcusrafael@lsd.ufcg.edu.br","username":"marcusrafael"},"change_message_id":"7ef3628b9f834d3523519915a1f1d7c00ece44fa","unresolved":false,"context_lines":[{"line_number":106,"context_line":""},{"line_number":107,"context_line":""},{"line_number":108,"context_line":"class PreconditionFailed(IronicException):"},{"line_number":109,"context_line":"    _msq_fmt \u003d _(\u0027The precondition given in the request headers failed\u0027)"},{"line_number":110,"context_line":"    code \u003d http_client.PRECONDITION_FAILED"},{"line_number":111,"context_line":""},{"line_number":112,"context_line":""}],"source_content_type":"text/x-python","patch_set":4,"id":"ba5da102_5ea1f792","line":109,"range":{"start_line":109,"start_character":56,"end_line":109,"end_character":70},"updated":"2016-11-03 18:21:18.000000000","message":"s/headers failed/headers has failed./","commit_id":"aab7b5d461f18150a355b74dc32e05cdf8184e79"}],"ironic/conductor/manager.py":[{"author":{"_account_id":18893,"name":"Miles Gould","email":"mgould@redhat.com","username":"pozorvlak"},"change_message_id":"a464f8c97d94675143fa2b893e61b78d21d6c6ac","unresolved":false,"context_lines":[{"line_number":102,"context_line":"        \"\"\""},{"line_number":103,"context_line":"        # NOTE (gzholtkevych): this method should be somewhere at low level"},{"line_number":104,"context_line":"        # of the project because hash calculate may take time and the resource"},{"line_number":105,"context_line":"        # should be locked while hash is being calculated. It makes"},{"line_number":106,"context_line":"        # sense, decreasing the probability of inconsistency, if someone would"},{"line_number":107,"context_line":"        # be faster to update. Moreover, if someone updated earlier, user will"},{"line_number":108,"context_line":"        # go to retry or fail and new etag will be generated again"}],"source_content_type":"text/x-python","patch_set":1,"id":"ba5da102_deae4ae5","line":105,"updated":"2016-11-01 16:26:53.000000000","message":"I don\u0027t see why you need locking here.\n\n - Alice requests node ABC\n - it\u0027s loaded into memory from the DB\n - the API server starts calculating its hash\n - Bob updates the node\n - The hash calculation finishes\n - Alice gets data about the node, not realising it\u0027s already out of date\n - She tries to update it\n - Her proposed update is rejected because her ETag is out of date.\n\nThe above is correct behaviour, isn\u0027t it?","commit_id":"d7f9359fac0ed31a87f55ab1a57201ed2dc675c0"},{"author":{"_account_id":18893,"name":"Miles Gould","email":"mgould@redhat.com","username":"pozorvlak"},"change_message_id":"a464f8c97d94675143fa2b893e61b78d21d6c6ac","unresolved":false,"context_lines":[{"line_number":108,"context_line":"        # go to retry or fail and new etag will be generated again"},{"line_number":109,"context_line":""},{"line_number":110,"context_line":"        # NOTE (gzholtkevych): Json way is a draft. May be a way of the string"},{"line_number":111,"context_line":"        # convertion will be changed"},{"line_number":112,"context_line":"        converted \u003d json.dumps(delta)"},{"line_number":113,"context_line":"        return hashlib.sha1(converted)"},{"line_number":114,"context_line":""}],"source_content_type":"text/x-python","patch_set":1,"id":"ba5da102_03578d26","line":111,"updated":"2016-11-01 16:26:53.000000000","message":"Nit: \"conversion\"","commit_id":"d7f9359fac0ed31a87f55ab1a57201ed2dc675c0"},{"author":{"_account_id":19213,"name":"Szymon Borkowski","email":"szymon.borkowski@intel.com","username":"sborkows"},"change_message_id":"8cc52344e22a3e7811755a6a9a1c321c0f012283","unresolved":false,"context_lines":[{"line_number":317,"context_line":"                                   exception.UnsupportedDriverExtension,"},{"line_number":318,"context_line":"                                   exception.DriverNotFound)"},{"line_number":319,"context_line":"    def driver_vendor_passthru(self, context, driver_name, driver_method,"},{"line_number":320,"context_line":"                               http_method, info, request_etag\u003dNone):"},{"line_number":321,"context_line":"        \"\"\"Handle top-level vendor actions."},{"line_number":322,"context_line":""},{"line_number":323,"context_line":"        RPC method which handles driver-level vendor passthru calls. These"}],"source_content_type":"text/x-python","patch_set":20,"id":"1a6eadb0_9c14924d","line":320,"range":{"start_line":320,"start_character":50,"end_line":320,"end_character":67},"updated":"2016-12-16 13:28:28.000000000","message":"It seems that this parameter is not used in this method at all? Is it not completed?","commit_id":"af8609dba0ecba4d7a30c79a243295ded5d11b9c"}],"ironic/conductor/rpcapi.py":[{"author":{"_account_id":19213,"name":"Szymon Borkowski","email":"szymon.borkowski@intel.com","username":"sborkows"},"change_message_id":"8cc52344e22a3e7811755a6a9a1c321c0f012283","unresolved":false,"context_lines":[{"line_number":589,"context_line":"        :param context: request context."},{"line_number":590,"context_line":"        :param node_id: node id or uuid."},{"line_number":591,"context_line":"        :param topic: RPC topic. Defaults to self.topic."},{"line_number":592,"context_line":"        :param request_etag: Optional parameter that allows to check if"},{"line_number":593,"context_line":"               the resource is up-to-date and fail if not."},{"line_number":594,"context_line":"        :raises: NodeLocked if node is locked by another conductor."},{"line_number":595,"context_line":"        :raises: HardwareInspectionFailure"},{"line_number":596,"context_line":"        :raises: NoFreeConductorWorker when there is no free worker to start"}],"source_content_type":"text/x-python","patch_set":20,"id":"1a6eadb0_ff4ad853","line":593,"range":{"start_line":592,"start_character":8,"end_line":593,"end_character":58},"updated":"2016-12-16 13:28:28.000000000","message":"Should we add this parameter to docstring of every method affected by this patch?","commit_id":"af8609dba0ecba4d7a30c79a243295ded5d11b9c"},{"author":{"_account_id":22724,"name":"Galyna Zholtkevych","email":"galynazholtkevych1991@gmail.com","username":"gzholtkevych"},"change_message_id":"92510eeb9717ac408fc97e66da82f37f12aa4a9a","unresolved":false,"context_lines":[{"line_number":589,"context_line":"        :param context: request context."},{"line_number":590,"context_line":"        :param node_id: node id or uuid."},{"line_number":591,"context_line":"        :param topic: RPC topic. Defaults to self.topic."},{"line_number":592,"context_line":"        :param request_etag: Optional parameter that allows to check if"},{"line_number":593,"context_line":"               the resource is up-to-date and fail if not."},{"line_number":594,"context_line":"        :raises: NodeLocked if node is locked by another conductor."},{"line_number":595,"context_line":"        :raises: HardwareInspectionFailure"},{"line_number":596,"context_line":"        :raises: NoFreeConductorWorker when there is no free worker to start"}],"source_content_type":"text/x-python","patch_set":20,"id":"1a6eadb0_8416f049","line":593,"range":{"start_line":592,"start_character":8,"end_line":593,"end_character":58},"in_reply_to":"1a6eadb0_ff4ad853","updated":"2016-12-16 16:15:41.000000000","message":"Yes, for sure. Will be done","commit_id":"af8609dba0ecba4d7a30c79a243295ded5d11b9c"},{"author":{"_account_id":19213,"name":"Szymon Borkowski","email":"szymon.borkowski@intel.com","username":"sborkows"},"change_message_id":"cc905861c4964db07c5511ee482664ed1d1bdb00","unresolved":false,"context_lines":[{"line_number":589,"context_line":"        :param context: request context."},{"line_number":590,"context_line":"        :param node_id: node id or uuid."},{"line_number":591,"context_line":"        :param topic: RPC topic. Defaults to self.topic."},{"line_number":592,"context_line":"        :param request_etag: Optional parameter that allows to check if"},{"line_number":593,"context_line":"               the resource is up-to-date and fail if not."},{"line_number":594,"context_line":"        :raises: NodeLocked if node is locked by another conductor."},{"line_number":595,"context_line":"        :raises: HardwareInspectionFailure"},{"line_number":596,"context_line":"        :raises: NoFreeConductorWorker when there is no free worker to start"}],"source_content_type":"text/x-python","patch_set":24,"id":"da4df55a_a1d7e1bd","line":593,"range":{"start_line":592,"start_character":8,"end_line":593,"end_character":58},"updated":"2016-12-23 10:12:16.000000000","message":"I did not understand your last comment about this param description. Will you add this in other methods, or remove it? IMO, we should be consequent -\u003e add this description to every rpc method containing this param (like the other params).","commit_id":"49f568c374e1b19a1a0335611cff77ce3971e0cb"}],"ironic/db/sqlalchemy/alembic/versions/d29d2974a28_add_etags.py":[{"author":{"_account_id":18893,"name":"Miles Gould","email":"mgould@redhat.com","username":"pozorvlak"},"change_message_id":"a464f8c97d94675143fa2b893e61b78d21d6c6ac","unresolved":false,"context_lines":[{"line_number":30,"context_line":"    # Note(gzholtkevych): This is a question about chassis: should etag be"},{"line_number":31,"context_line":"    # necessary for chassis case, as chassis update actions is not really"},{"line_number":32,"context_line":"    # used for now"},{"line_number":33,"context_line":"    op.add_column(\u0027chassis\u0027, sa.Column(\u0027etag\u0027, sa.Text(), nullable\u003dTrue))"},{"line_number":34,"context_line":"    op.add_column(\u0027nodes\u0027, sa.Column(\u0027etag\u0027, sa.Text(), nullable\u003dFalse))"},{"line_number":35,"context_line":"    op.add_column(\u0027ports\u0027, sa.Column(\u0027etag\u0027, sa.Text(), nullable\u003dFalse))"},{"line_number":36,"context_line":"    op.add_column(\u0027portgroups\u0027, sa.Column(\u0027etag\u0027, sa.Text(), nullable\u003dFalse))"}],"source_content_type":"text/x-python","patch_set":1,"id":"ba5da102_83b47d82","line":33,"updated":"2016-11-01 16:26:53.000000000","message":"I haven\u0027t seen ETags being stored in the database before - django.utils.cache generates them on-demand, for instance: https://github.com/django/django/blob/master/django/utils/cache.py#L107. How are you going to ensure your cached ETags are invalidated correctly?\n\nActually, are you even using these columns?","commit_id":"d7f9359fac0ed31a87f55ab1a57201ed2dc675c0"},{"author":{"_account_id":22724,"name":"Galyna Zholtkevych","email":"galynazholtkevych1991@gmail.com","username":"gzholtkevych"},"change_message_id":"d90f60157a1da16861ba1fd6f7c72cfab89df077","unresolved":false,"context_lines":[{"line_number":30,"context_line":"    # Note(gzholtkevych): This is a question about chassis: should etag be"},{"line_number":31,"context_line":"    # necessary for chassis case, as chassis update actions is not really"},{"line_number":32,"context_line":"    # used for now"},{"line_number":33,"context_line":"    op.add_column(\u0027chassis\u0027, sa.Column(\u0027etag\u0027, sa.Text(), nullable\u003dTrue))"},{"line_number":34,"context_line":"    op.add_column(\u0027nodes\u0027, sa.Column(\u0027etag\u0027, sa.Text(), nullable\u003dFalse))"},{"line_number":35,"context_line":"    op.add_column(\u0027ports\u0027, sa.Column(\u0027etag\u0027, sa.Text(), nullable\u003dFalse))"},{"line_number":36,"context_line":"    op.add_column(\u0027portgroups\u0027, sa.Column(\u0027etag\u0027, sa.Text(), nullable\u003dFalse))"}],"source_content_type":"text/x-python","patch_set":1,"id":"ba5da102_581f9907","line":33,"in_reply_to":"ba5da102_3a458fb2","updated":"2016-11-02 09:29:52.000000000","message":"I investigated this thing and realized that we are going to the database in any case when updating the resource (see https://github.com/openstack/ironic/blob/master/ironic/objects/node.py#L190).\nAnd as we are having several API endpoints, how the cache would work? Is there a sence to make it distributed?\n\nMoreover while presence of the etags is in the data model in spec, I would follow it and if somehow etags cached are approved, I will change the implementation, but for now I am leaving this as a draft.\n\nThank you for kind review","commit_id":"d7f9359fac0ed31a87f55ab1a57201ed2dc675c0"},{"author":{"_account_id":18893,"name":"Miles Gould","email":"mgould@redhat.com","username":"pozorvlak"},"change_message_id":"d385dd918e2b833033d313bee4a7383dc0efc9fd","unresolved":false,"context_lines":[{"line_number":30,"context_line":"    # Note(gzholtkevych): This is a question about chassis: should etag be"},{"line_number":31,"context_line":"    # necessary for chassis case, as chassis update actions is not really"},{"line_number":32,"context_line":"    # used for now"},{"line_number":33,"context_line":"    op.add_column(\u0027chassis\u0027, sa.Column(\u0027etag\u0027, sa.Text(), nullable\u003dTrue))"},{"line_number":34,"context_line":"    op.add_column(\u0027nodes\u0027, sa.Column(\u0027etag\u0027, sa.Text(), nullable\u003dFalse))"},{"line_number":35,"context_line":"    op.add_column(\u0027ports\u0027, sa.Column(\u0027etag\u0027, sa.Text(), nullable\u003dFalse))"},{"line_number":36,"context_line":"    op.add_column(\u0027portgroups\u0027, sa.Column(\u0027etag\u0027, sa.Text(), nullable\u003dFalse))"}],"source_content_type":"text/x-python","patch_set":1,"id":"ba5da102_e40e038b","line":33,"in_reply_to":"ba5da102_581f9907","updated":"2016-11-02 12:21:10.000000000","message":"Ah, I\u0027d missed that. I\u0027ve left a comment on the spec to say that we should consider *not* storing the generated ETags :-)\n\n\"We built a distributed system to cache the cache-invalidation tokens for our distributed system\" sounds like the start of a horror story to me...","commit_id":"d7f9359fac0ed31a87f55ab1a57201ed2dc675c0"},{"author":{"_account_id":18893,"name":"Miles Gould","email":"mgould@redhat.com","username":"pozorvlak"},"change_message_id":"5e1cdb8874ab2d0985d0b347edae5c57a8ebfd1d","unresolved":false,"context_lines":[{"line_number":30,"context_line":"    # Note(gzholtkevych): This is a question about chassis: should etag be"},{"line_number":31,"context_line":"    # necessary for chassis case, as chassis update actions is not really"},{"line_number":32,"context_line":"    # used for now"},{"line_number":33,"context_line":"    op.add_column(\u0027chassis\u0027, sa.Column(\u0027etag\u0027, sa.Text(), nullable\u003dTrue))"},{"line_number":34,"context_line":"    op.add_column(\u0027nodes\u0027, sa.Column(\u0027etag\u0027, sa.Text(), nullable\u003dFalse))"},{"line_number":35,"context_line":"    op.add_column(\u0027ports\u0027, sa.Column(\u0027etag\u0027, sa.Text(), nullable\u003dFalse))"},{"line_number":36,"context_line":"    op.add_column(\u0027portgroups\u0027, sa.Column(\u0027etag\u0027, sa.Text(), nullable\u003dFalse))"}],"source_content_type":"text/x-python","patch_set":1,"id":"ba5da102_3a458fb2","line":33,"in_reply_to":"ba5da102_7a89c774","updated":"2016-11-01 18:02:47.000000000","message":"Yeah, I think the web framework is the right layer at which to support this.","commit_id":"d7f9359fac0ed31a87f55ab1a57201ed2dc675c0"},{"author":{"_account_id":22724,"name":"Galyna Zholtkevych","email":"galynazholtkevych1991@gmail.com","username":"gzholtkevych"},"change_message_id":"9ec3c5a9534669e5acd8c2cd9168fb03e7040713","unresolved":false,"context_lines":[{"line_number":30,"context_line":"    # Note(gzholtkevych): This is a question about chassis: should etag be"},{"line_number":31,"context_line":"    # necessary for chassis case, as chassis update actions is not really"},{"line_number":32,"context_line":"    # used for now"},{"line_number":33,"context_line":"    op.add_column(\u0027chassis\u0027, sa.Column(\u0027etag\u0027, sa.Text(), nullable\u003dTrue))"},{"line_number":34,"context_line":"    op.add_column(\u0027nodes\u0027, sa.Column(\u0027etag\u0027, sa.Text(), nullable\u003dFalse))"},{"line_number":35,"context_line":"    op.add_column(\u0027ports\u0027, sa.Column(\u0027etag\u0027, sa.Text(), nullable\u003dFalse))"},{"line_number":36,"context_line":"    op.add_column(\u0027portgroups\u0027, sa.Column(\u0027etag\u0027, sa.Text(), nullable\u003dFalse))"}],"source_content_type":"text/x-python","patch_set":1,"id":"ba5da102_7a89c774","line":33,"in_reply_to":"ba5da102_83b47d82","updated":"2016-11-01 17:45:54.000000000","message":"Moreover, if we are using pecan, I will think if it is possible to implement memcache, etags there  (if it is still not) and, may be, propose it..","commit_id":"d7f9359fac0ed31a87f55ab1a57201ed2dc675c0"},{"author":{"_account_id":22724,"name":"Galyna Zholtkevych","email":"galynazholtkevych1991@gmail.com","username":"gzholtkevych"},"change_message_id":"81e9984260b3b74fd35e2aa356b1bc88abe32053","unresolved":false,"context_lines":[{"line_number":30,"context_line":"    # Note(gzholtkevych): This is a question about chassis: should etag be"},{"line_number":31,"context_line":"    # necessary for chassis case, as chassis update actions is not really"},{"line_number":32,"context_line":"    # used for now"},{"line_number":33,"context_line":"    op.add_column(\u0027chassis\u0027, sa.Column(\u0027etag\u0027, sa.Text(), nullable\u003dTrue))"},{"line_number":34,"context_line":"    op.add_column(\u0027nodes\u0027, sa.Column(\u0027etag\u0027, sa.Text(), nullable\u003dFalse))"},{"line_number":35,"context_line":"    op.add_column(\u0027ports\u0027, sa.Column(\u0027etag\u0027, sa.Text(), nullable\u003dFalse))"},{"line_number":36,"context_line":"    op.add_column(\u0027portgroups\u0027, sa.Column(\u0027etag\u0027, sa.Text(), nullable\u003dFalse))"}],"source_content_type":"text/x-python","patch_set":1,"id":"ba5da102_74b47d81","line":33,"in_reply_to":"ba5da102_83b47d82","updated":"2016-11-01 17:40:38.000000000","message":"Thank you! It seems, now I found better solution for remembering current ETag to validate client request.\nSo I will correct the code","commit_id":"d7f9359fac0ed31a87f55ab1a57201ed2dc675c0"},{"author":{"_account_id":22724,"name":"Galyna Zholtkevych","email":"galynazholtkevych1991@gmail.com","username":"gzholtkevych"},"change_message_id":"01ff978ecb69fe06f16de9798b60bfb638c31c97","unresolved":false,"context_lines":[{"line_number":30,"context_line":"    # Note(gzholtkevych): This is a question about chassis: should etag be"},{"line_number":31,"context_line":"    # necessary for chassis case, as chassis update actions is not really"},{"line_number":32,"context_line":"    # used for now"},{"line_number":33,"context_line":"    op.add_column(\u0027chassis\u0027, sa.Column(\u0027etag\u0027, sa.Text(), nullable\u003dTrue))"},{"line_number":34,"context_line":"    op.add_column(\u0027nodes\u0027, sa.Column(\u0027etag\u0027, sa.Text(), nullable\u003dFalse))"},{"line_number":35,"context_line":"    op.add_column(\u0027ports\u0027, sa.Column(\u0027etag\u0027, sa.Text(), nullable\u003dFalse))"},{"line_number":36,"context_line":"    op.add_column(\u0027portgroups\u0027, sa.Column(\u0027etag\u0027, sa.Text(), nullable\u003dFalse))"}],"source_content_type":"text/x-python","patch_set":1,"id":"ba5da102_90649d22","line":33,"in_reply_to":"ba5da102_e40e038b","updated":"2016-11-02 13:46:59.000000000","message":"Thank you :-)","commit_id":"d7f9359fac0ed31a87f55ab1a57201ed2dc675c0"}],"ironic/db/sqlalchemy/api.py":[{"author":{"_account_id":19213,"name":"Szymon Borkowski","email":"szymon.borkowski@intel.com","username":"sborkows"},"change_message_id":"8cc52344e22a3e7811755a6a9a1c321c0f012283","unresolved":false,"context_lines":[{"line_number":195,"context_line":"    \"\"\""},{"line_number":196,"context_line":"    valuable_resource_fields \u003d {k: v for k, v in resource_obj.items()"},{"line_number":197,"context_line":"                                if k not in ETAG_EXCLUDED_NODE_FIELDS and"},{"line_number":198,"context_line":"                                resource_obj[k] is not None}"},{"line_number":199,"context_line":"    # NOTE(galyna): avoid etag generation if no valuable resources were changed"},{"line_number":200,"context_line":"    if not valuable_resource_fields:"},{"line_number":201,"context_line":"        return"}],"source_content_type":"text/x-python","patch_set":20,"id":"1a6eadb0_d5525d66","line":198,"range":{"start_line":198,"start_character":32,"end_line":198,"end_character":47},"updated":"2016-12-16 13:28:28.000000000","message":"s/resource_obj[k]/v","commit_id":"af8609dba0ecba4d7a30c79a243295ded5d11b9c"},{"author":{"_account_id":22724,"name":"Galyna Zholtkevych","email":"galynazholtkevych1991@gmail.com","username":"gzholtkevych"},"change_message_id":"92510eeb9717ac408fc97e66da82f37f12aa4a9a","unresolved":false,"context_lines":[{"line_number":195,"context_line":"    \"\"\""},{"line_number":196,"context_line":"    valuable_resource_fields \u003d {k: v for k, v in resource_obj.items()"},{"line_number":197,"context_line":"                                if k not in ETAG_EXCLUDED_NODE_FIELDS and"},{"line_number":198,"context_line":"                                resource_obj[k] is not None}"},{"line_number":199,"context_line":"    # NOTE(galyna): avoid etag generation if no valuable resources were changed"},{"line_number":200,"context_line":"    if not valuable_resource_fields:"},{"line_number":201,"context_line":"        return"}],"source_content_type":"text/x-python","patch_set":20,"id":"1a6eadb0_44c938ab","line":198,"range":{"start_line":198,"start_character":32,"end_line":198,"end_character":47},"in_reply_to":"1a6eadb0_d5525d66","updated":"2016-12-16 16:15:41.000000000","message":"Done","commit_id":"af8609dba0ecba4d7a30c79a243295ded5d11b9c"},{"author":{"_account_id":19213,"name":"Szymon Borkowski","email":"szymon.borkowski@intel.com","username":"sborkows"},"change_message_id":"a1a730e405707e8844a6e0bff93756662a595088","unresolved":false,"context_lines":[{"line_number":47,"context_line":""},{"line_number":48,"context_line":""},{"line_number":49,"context_line":"_CONTEXT \u003d threading.local()"},{"line_number":50,"context_line":"ETAG_EXCLUDED_NODE_FIELDS \u003d [\u0027id\u0027,\u0027driver_internal_info\u0027, \u0027created_at\u0027,"},{"line_number":51,"context_line":"                             \u0027updated_at\u0027, \u0027inspection_started_at\u0027,"},{"line_number":52,"context_line":"                             \u0027inspection_finished_at\u0027, \u0027provision_updated_at\u0027]"},{"line_number":53,"context_line":"ETAG_EXCLUDED_CHASSSIS_FIELDS \u003d []"},{"line_number":54,"context_line":"ETAG_EXCLUDED_PORT_FIELDS \u003d []"},{"line_number":55,"context_line":"ETAG_EXCLUDED_PORTGROUP_FIELDS \u003d []"}],"source_content_type":"text/x-python","patch_set":42,"id":"1a430d35_90097b34","line":52,"range":{"start_line":50,"start_character":0,"end_line":52,"end_character":78},"updated":"2017-02-03 16:37:53.000000000","message":"What about \u0027etag\u0027 field, as it is mentioned in spec as excluded field too?","commit_id":"a6e48eb1a6cef842b7584c9387ffcaa26807af35"}],"ironic/objects/base.py":[{"author":{"_account_id":19213,"name":"Szymon Borkowski","email":"szymon.borkowski@intel.com","username":"sborkows"},"change_message_id":"d99043fcc3c017c14e005ac959e2709e9b976bf5","unresolved":false,"context_lines":[{"line_number":125,"context_line":"        # NOTE(galyna): avoid etag generation if no valuable resources were"},{"line_number":126,"context_line":"        # changed"},{"line_number":127,"context_line":"        if not valuable_resource_fields:"},{"line_number":128,"context_line":"            return self.etag"},{"line_number":129,"context_line":""},{"line_number":130,"context_line":"        converted \u003d json.dumps(valuable_resource_fields)"},{"line_number":131,"context_line":"        if isinstance(converted, six.text_type):"}],"source_content_type":"text/x-python","patch_set":25,"id":"da4df55a_1b445048","line":128,"range":{"start_line":128,"start_character":11,"end_line":128,"end_character":28},"updated":"2016-12-27 10:07:23.000000000","message":"Is it possible to have this field not set? E.g. in create() method in objects/node.py (L320) ?","commit_id":"f42d7b02f24ebe95ea02f80d2c0725f96fcb8a60"},{"author":{"_account_id":19213,"name":"Szymon Borkowski","email":"szymon.borkowski@intel.com","username":"sborkows"},"change_message_id":"a1a730e405707e8844a6e0bff93756662a595088","unresolved":false,"context_lines":[{"line_number":14,"context_line":""},{"line_number":15,"context_line":"\"\"\"Ironic common internal object model\"\"\""},{"line_number":16,"context_line":""},{"line_number":17,"context_line":"import json"},{"line_number":18,"context_line":""},{"line_number":19,"context_line":"import hashlib"},{"line_number":20,"context_line":"from oslo_utils import versionutils"},{"line_number":21,"context_line":"from oslo_versionedobjects import base as object_base"},{"line_number":22,"context_line":"import six"}],"source_content_type":"text/x-python","patch_set":42,"id":"1a430d35_eb3652b3","line":19,"range":{"start_line":17,"start_character":0,"end_line":19,"end_character":14},"updated":"2017-02-03 16:37:53.000000000","message":"pep8 fails because of unused imports here.","commit_id":"a6e48eb1a6cef842b7584c9387ffcaa26807af35"},{"author":{"_account_id":19213,"name":"Szymon Borkowski","email":"szymon.borkowski@intel.com","username":"sborkows"},"change_message_id":"a1a730e405707e8844a6e0bff93756662a595088","unresolved":false,"context_lines":[{"line_number":19,"context_line":"import hashlib"},{"line_number":20,"context_line":"from oslo_utils import versionutils"},{"line_number":21,"context_line":"from oslo_versionedobjects import base as object_base"},{"line_number":22,"context_line":"import six"},{"line_number":23,"context_line":""},{"line_number":24,"context_line":"from ironic import objects"},{"line_number":25,"context_line":"from ironic.objects import fields as object_fields"}],"source_content_type":"text/x-python","patch_set":42,"id":"1a430d35_6b4b422c","line":22,"range":{"start_line":22,"start_character":0,"end_line":22,"end_character":10},"updated":"2017-02-03 16:37:53.000000000","message":"ditto","commit_id":"a6e48eb1a6cef842b7584c9387ffcaa26807af35"}],"ironic/objects/node.py":[{"author":{"_account_id":19213,"name":"Szymon Borkowski","email":"szymon.borkowski@intel.com","username":"sborkows"},"change_message_id":"d99043fcc3c017c14e005ac959e2709e9b976bf5","unresolved":false,"context_lines":[{"line_number":25,"context_line":"from ironic.objects import notification"},{"line_number":26,"context_line":""},{"line_number":27,"context_line":"REQUIRED_INT_PROPERTIES \u003d [\u0027local_gb\u0027, \u0027cpus\u0027, \u0027memory_mb\u0027]"},{"line_number":28,"context_line":"ETAG_EXCLUDED_NODE_FIELDS \u003d [\u0027driver_internal_info\u0027, \u0027created_at\u0027,"},{"line_number":29,"context_line":"                             \u0027updated_at\u0027, \u0027inspection_started_at\u0027,"},{"line_number":30,"context_line":"                             \u0027inspection_finished_at\u0027, \u0027provision_updated_at\u0027]"},{"line_number":31,"context_line":""},{"line_number":32,"context_line":""},{"line_number":33,"context_line":"@base.IronicObjectRegistry.register"}],"source_content_type":"text/x-python","patch_set":25,"id":"da4df55a_a4424666","line":30,"range":{"start_line":28,"start_character":0,"end_line":30,"end_character":78},"updated":"2016-12-27 10:07:23.000000000","message":"What about port and portgroup objects\u0027 excluded fields you mentioned in spec (L70)?\nI think we should rename it to ETAG_EXCLUDED_FIELDS and move it to base, then in each object extend it when needed.","commit_id":"f42d7b02f24ebe95ea02f80d2c0725f96fcb8a60"}],"ironic/tests/unit/api/v1/test_nodes.py":[{"author":{"_account_id":19213,"name":"Szymon Borkowski","email":"szymon.borkowski@intel.com","username":"sborkows"},"change_message_id":"8cc52344e22a3e7811755a6a9a1c321c0f012283","unresolved":false,"context_lines":[{"line_number":2753,"context_line":"                                         states.VERBS[\u0027provide\u0027],"},{"line_number":2754,"context_line":"                                         \u0027test-topic\u0027, None)"},{"line_number":2755,"context_line":""},{"line_number":2756,"context_line":"    @mock.patch.object(rpcapi.ConductorAPI, \u0027do_provisioning_action\u0027)"},{"line_number":2757,"context_line":"    def test_provide_from_manage_with_etag(self, mock_dpa):"},{"line_number":2758,"context_line":"        self.node.provision_state \u003d states.MANAGEABLE"},{"line_number":2759,"context_line":"        self.node.save()"},{"line_number":2760,"context_line":""},{"line_number":2761,"context_line":"        ret \u003d self.put_json(\u0027/nodes/%s/states/provision\u0027 % self.node.uuid,"},{"line_number":2762,"context_line":"                            {\u0027target\u0027: states.VERBS[\u0027provide\u0027]},"},{"line_number":2763,"context_line":"                            headers\u003d{api_base.Version.string: \"1.26\","},{"line_number":2764,"context_line":"                                     \u0027If-Match\u0027: \u0027fake-etag\u0027})"},{"line_number":2765,"context_line":"        self.assertEqual(http_client.ACCEPTED, ret.status_code)"},{"line_number":2766,"context_line":"        self.assertEqual(b\u0027\u0027, ret.body)"},{"line_number":2767,"context_line":"        mock_dpa.assert_called_once_with(mock.ANY, self.node.uuid,"},{"line_number":2768,"context_line":"                                         states.VERBS[\u0027provide\u0027],"},{"line_number":2769,"context_line":"                                         \u0027test-topic\u0027, \u0027fake-etag\u0027)"},{"line_number":2770,"context_line":""},{"line_number":2771,"context_line":"    def test_inspect_already_in_progress(self):"},{"line_number":2772,"context_line":"        node \u003d self.node"}],"source_content_type":"text/x-python","patch_set":20,"id":"1a6eadb0_2bb972cc","line":2769,"range":{"start_line":2756,"start_character":3,"end_line":2769,"end_character":67},"updated":"2016-12-16 13:28:28.000000000","message":"Is it the duplicated test_provide_from_manage_etag() from L2728 ?","commit_id":"af8609dba0ecba4d7a30c79a243295ded5d11b9c"},{"author":{"_account_id":22724,"name":"Galyna Zholtkevych","email":"galynazholtkevych1991@gmail.com","username":"gzholtkevych"},"change_message_id":"92510eeb9717ac408fc97e66da82f37f12aa4a9a","unresolved":false,"context_lines":[{"line_number":2753,"context_line":"                                         states.VERBS[\u0027provide\u0027],"},{"line_number":2754,"context_line":"                                         \u0027test-topic\u0027, None)"},{"line_number":2755,"context_line":""},{"line_number":2756,"context_line":"    @mock.patch.object(rpcapi.ConductorAPI, \u0027do_provisioning_action\u0027)"},{"line_number":2757,"context_line":"    def test_provide_from_manage_with_etag(self, mock_dpa):"},{"line_number":2758,"context_line":"        self.node.provision_state \u003d states.MANAGEABLE"},{"line_number":2759,"context_line":"        self.node.save()"},{"line_number":2760,"context_line":""},{"line_number":2761,"context_line":"        ret \u003d self.put_json(\u0027/nodes/%s/states/provision\u0027 % self.node.uuid,"},{"line_number":2762,"context_line":"                            {\u0027target\u0027: states.VERBS[\u0027provide\u0027]},"},{"line_number":2763,"context_line":"                            headers\u003d{api_base.Version.string: \"1.26\","},{"line_number":2764,"context_line":"                                     \u0027If-Match\u0027: \u0027fake-etag\u0027})"},{"line_number":2765,"context_line":"        self.assertEqual(http_client.ACCEPTED, ret.status_code)"},{"line_number":2766,"context_line":"        self.assertEqual(b\u0027\u0027, ret.body)"},{"line_number":2767,"context_line":"        mock_dpa.assert_called_once_with(mock.ANY, self.node.uuid,"},{"line_number":2768,"context_line":"                                         states.VERBS[\u0027provide\u0027],"},{"line_number":2769,"context_line":"                                         \u0027test-topic\u0027, \u0027fake-etag\u0027)"},{"line_number":2770,"context_line":""},{"line_number":2771,"context_line":"    def test_inspect_already_in_progress(self):"},{"line_number":2772,"context_line":"        node \u003d self.node"}],"source_content_type":"text/x-python","patch_set":20,"id":"1a6eadb0_24643cb7","line":2769,"range":{"start_line":2756,"start_character":3,"end_line":2769,"end_character":67},"in_reply_to":"1a6eadb0_2bb972cc","updated":"2016-12-16 16:15:41.000000000","message":"Yes, it is indeed :) thanks","commit_id":"af8609dba0ecba4d7a30c79a243295ded5d11b9c"}]}
