)]}'
{"sushy/resources/system/system.py":[{"author":{"_account_id":11076,"name":"Shivanand Tendulker","email":"stendulker@gmail.com","username":"stendulker"},"change_message_id":"1391f1d3447dd8cb3e6e58e75ddb24b239807dd9","unresolved":false,"context_lines":[{"line_number":207,"context_line":"                    set(sys_maps.BOOT_SOURCE_TARGET_MAP)."},{"line_number":208,"context_line":"                    intersection(self.boot.allowed_values)])"},{"line_number":209,"context_line":""},{"line_number":210,"context_line":"    def set_system_boot_source(self, target\u003dNone, enabled\u003dNone, mode\u003dNone):"},{"line_number":211,"context_line":"        \"\"\"Set boot source and/or boot frequency and/or boot mode."},{"line_number":212,"context_line":""},{"line_number":213,"context_line":"        Set the boot source and/or boot frequency and/or boot mode to use"}],"source_content_type":"text/x-python","patch_set":1,"id":"1fa4df85_629978c2","line":210,"range":{"start_line":210,"start_character":50,"end_line":210,"end_character":63},"updated":"2020-03-03 09:11:44.000000000","message":"Wont this cause backward in-compatibility as default value is changed?","commit_id":"b8023e34bf4b7a95cbd947f95d9be6293a87acf4"},{"author":{"_account_id":26340,"name":"Ilya Etingof","email":"etingof@gmail.com","username":"etingof"},"change_message_id":"eabcf0691761487a14cbe7c0fd686977b8c4327f","unresolved":false,"context_lines":[{"line_number":207,"context_line":"                    set(sys_maps.BOOT_SOURCE_TARGET_MAP)."},{"line_number":208,"context_line":"                    intersection(self.boot.allowed_values)])"},{"line_number":209,"context_line":""},{"line_number":210,"context_line":"    def set_system_boot_source(self, target\u003dNone, enabled\u003dNone, mode\u003dNone):"},{"line_number":211,"context_line":"        \"\"\"Set boot source and/or boot frequency and/or boot mode."},{"line_number":212,"context_line":""},{"line_number":213,"context_line":"        Set the boot source and/or boot frequency and/or boot mode to use"}],"source_content_type":"text/x-python","patch_set":1,"id":"1fa4df85_cd9bbd63","line":210,"range":{"start_line":210,"start_character":50,"end_line":210,"end_character":63},"in_reply_to":"1fa4df85_629978c2","updated":"2020-03-03 10:38:15.000000000","message":"It will, but may be that\u0027s OK...? I have two thoughts:\n\n* The whole point of this change is to stop touching boot parameters (including boot frequency) unless explicitly asked\n* I have a gut feeling that BMCs are not overly consistent when it comes to boot options - some seem to ignoring boot frequency, some are failing when it\u0027s given...\n\nIf we want to preserve backward compatibility, the only idea that I have is to introduce another variable and eventually deprecate `enabled`.\n\nWDYT?","commit_id":"b8023e34bf4b7a95cbd947f95d9be6293a87acf4"},{"author":{"_account_id":26340,"name":"Ilya Etingof","email":"etingof@gmail.com","username":"etingof"},"change_message_id":"52f4fcb2e343803d96081438ce8e1160a5befdc8","unresolved":false,"context_lines":[{"line_number":207,"context_line":"                    set(sys_maps.BOOT_SOURCE_TARGET_MAP)."},{"line_number":208,"context_line":"                    intersection(self.boot.allowed_values)])"},{"line_number":209,"context_line":""},{"line_number":210,"context_line":"    def set_system_boot_source(self, target\u003dNone, enabled\u003dNone, mode\u003dNone):"},{"line_number":211,"context_line":"        \"\"\"Set boot source and/or boot frequency and/or boot mode."},{"line_number":212,"context_line":""},{"line_number":213,"context_line":"        Set the boot source and/or boot frequency and/or boot mode to use"}],"source_content_type":"text/x-python","patch_set":1,"id":"1fa4df85_5f99ae76","line":210,"range":{"start_line":210,"start_character":50,"end_line":210,"end_character":63},"in_reply_to":"1fa4df85_9ce5f40b","updated":"2020-03-03 13:47:45.000000000","message":"OK, here\u0027s my take on that.","commit_id":"b8023e34bf4b7a95cbd947f95d9be6293a87acf4"},{"author":{"_account_id":11076,"name":"Shivanand Tendulker","email":"stendulker@gmail.com","username":"stendulker"},"change_message_id":"ef7c8f3bffd95525c08a4622106c72c084b724df","unresolved":false,"context_lines":[{"line_number":207,"context_line":"                    set(sys_maps.BOOT_SOURCE_TARGET_MAP)."},{"line_number":208,"context_line":"                    intersection(self.boot.allowed_values)])"},{"line_number":209,"context_line":""},{"line_number":210,"context_line":"    def set_system_boot_source(self, target\u003dNone, enabled\u003dNone, mode\u003dNone):"},{"line_number":211,"context_line":"        \"\"\"Set boot source and/or boot frequency and/or boot mode."},{"line_number":212,"context_line":""},{"line_number":213,"context_line":"        Set the boot source and/or boot frequency and/or boot mode to use"}],"source_content_type":"text/x-python","patch_set":1,"id":"1fa4df85_9ce5f40b","line":210,"range":{"start_line":210,"start_character":50,"end_line":210,"end_character":63},"in_reply_to":"1fa4df85_cd9bbd63","updated":"2020-03-03 12:48:36.000000000","message":"I think we should introduce a new method for this behavior. and mark the method set_system_boot_source() for obsolescence. Change Ironic code to use new method (set_system_boot_attributes). WDYT?\n\ndef _set_system_boot_attributes(self, target\u003dNone, enabled\u003dNone, mode\u003dNone):\n    All code from L211-L261\n\ndef set_system_boot_attributes(self, target\u003dNone, enabled\u003dNone, mode\u003dNone):\n   self._set_system_boot_attributes(target\u003dtarget, enabled\u003denabled, mode\u003dmode)\n\ndef set_system_boot_source(self, target, enabled\u003dsys_cons.BOOT_SOURCE_ENABLED_ONCE, mode\u003dNone):\n    Add a warning that this method is obsoleted and oen should use set_system_boot_attributes() instead.\n    self._set_system_boot_attributes(target\u003dtarget, enabled\u003denabled, mode\u003dmode)","commit_id":"b8023e34bf4b7a95cbd947f95d9be6293a87acf4"},{"author":{"_account_id":23847,"name":"Richard G. Pioso","email":"richard.pioso@gmail.com","username":"richard.pioso"},"change_message_id":"e9ad813f9a6e050a5adf3093bb073fd0e1ad0870","unresolved":false,"context_lines":[{"line_number":226,"context_line":"        \"\"\""},{"line_number":227,"context_line":"        data \u003d collections.defaultdict(dict)"},{"line_number":228,"context_line":""},{"line_number":229,"context_line":"        if target is not None:"},{"line_number":230,"context_line":"            valid_targets \u003d self.get_allowed_system_boot_source_values()"},{"line_number":231,"context_line":"            if target not in valid_targets:"},{"line_number":232,"context_line":"                raise exceptions.InvalidParameterValueError("},{"line_number":233,"context_line":"                    parameter\u003d\u0027target\u0027, value\u003dtarget,"},{"line_number":234,"context_line":"                    valid_values\u003dvalid_targets)"},{"line_number":235,"context_line":""},{"line_number":236,"context_line":"            fishy_target \u003d sys_maps.BOOT_SOURCE_TARGET_MAP_REV[target]"},{"line_number":237,"context_line":""},{"line_number":238,"context_line":"            data[\u0027Boot\u0027][\u0027BootSourceOverrideTarget\u0027] \u003d fishy_target"},{"line_number":239,"context_line":""},{"line_number":240,"context_line":"        if enabled is not None:"},{"line_number":241,"context_line":"            if enabled not in sys_maps.BOOT_SOURCE_ENABLED_MAP_REV:"},{"line_number":242,"context_line":"                raise exceptions.InvalidParameterValueError("},{"line_number":243,"context_line":"                    parameter\u003d\u0027enabled\u0027, value\u003denabled,"},{"line_number":244,"context_line":"                    valid_values\u003dlist(sys_maps.BOOT_SOURCE_ENABLED_MAP_REV))"},{"line_number":245,"context_line":""},{"line_number":246,"context_line":"            fishy_freq \u003d sys_maps.BOOT_SOURCE_ENABLED_MAP_REV[enabled]"},{"line_number":247,"context_line":""},{"line_number":248,"context_line":"            data[\u0027Boot\u0027][\u0027BootSourceOverrideEnabled\u0027] \u003d fishy_freq"},{"line_number":249,"context_line":""},{"line_number":250,"context_line":"        if mode is not None:"},{"line_number":251,"context_line":"            if mode not in sys_maps.BOOT_SOURCE_MODE_MAP_REV:"},{"line_number":252,"context_line":"                raise exceptions.InvalidParameterValueError("},{"line_number":253,"context_line":"                    parameter\u003d\u0027mode\u0027, value\u003dmode,"},{"line_number":254,"context_line":"                    valid_values\u003dlist(sys_maps.BOOT_SOURCE_MODE_MAP_REV))"},{"line_number":255,"context_line":""},{"line_number":256,"context_line":"            fishy_mode \u003d sys_maps.BOOT_SOURCE_MODE_MAP_REV[mode]"},{"line_number":257,"context_line":""},{"line_number":258,"context_line":"            data[\u0027Boot\u0027][\u0027BootSourceOverrideMode\u0027] \u003d fishy_mode"},{"line_number":259,"context_line":""},{"line_number":260,"context_line":"        # TODO(lucasagomes): Check the return code and response body ?"},{"line_number":261,"context_line":"        #                    Probably we should call refresh() as well."},{"line_number":262,"context_line":"        self._conn.patch(self.path, data\u003ddata)"},{"line_number":263,"context_line":""},{"line_number":264,"context_line":"    def set_system_boot_source("},{"line_number":265,"context_line":"            self, target, enabled\u003dsys_cons.BOOT_SOURCE_ENABLED_ONCE,"}],"source_content_type":"text/x-python","patch_set":3,"id":"1fa4df85_16b3010c","line":262,"range":{"start_line":229,"start_character":0,"end_line":262,"end_character":46},"updated":"2020-03-04 23:57:16.000000000","message":"At the midcycle, I believe we described the implementation in set_system_boot_source() this proposed change effectively modifies as passing PUT data in a PATCH request. We seemed to agree the PATCH request is reasonable, but the data should be changed to PATCH data which contains only the parameters which have changed. I believe this does not do that. If the caller passes in arguments which represent no change, they are still provided in the data.\n\nI see an openstack/ironic change which depends on this sushy change, https://review.opendev.org/#/c/711118/, checks if the desired value is different from the current value -- https://review.opendev.org/#/c/711118/2/ironic/drivers/modules/redfish/management.py@135. Might that logic be better placed in this method so callers do not need to concern themselves with that?","commit_id":"25efb92e04ddb4211d6240f2f78fd8769a8dbe0c"},{"author":{"_account_id":26340,"name":"Ilya Etingof","email":"etingof@gmail.com","username":"etingof"},"change_message_id":"c26c3f6e181175906e8bca6e15e8e2253f8d282d","unresolved":false,"context_lines":[{"line_number":226,"context_line":"        \"\"\""},{"line_number":227,"context_line":"        data \u003d collections.defaultdict(dict)"},{"line_number":228,"context_line":""},{"line_number":229,"context_line":"        if target is not None:"},{"line_number":230,"context_line":"            valid_targets \u003d self.get_allowed_system_boot_source_values()"},{"line_number":231,"context_line":"            if target not in valid_targets:"},{"line_number":232,"context_line":"                raise exceptions.InvalidParameterValueError("},{"line_number":233,"context_line":"                    parameter\u003d\u0027target\u0027, value\u003dtarget,"},{"line_number":234,"context_line":"                    valid_values\u003dvalid_targets)"},{"line_number":235,"context_line":""},{"line_number":236,"context_line":"            fishy_target \u003d sys_maps.BOOT_SOURCE_TARGET_MAP_REV[target]"},{"line_number":237,"context_line":""},{"line_number":238,"context_line":"            data[\u0027Boot\u0027][\u0027BootSourceOverrideTarget\u0027] \u003d fishy_target"},{"line_number":239,"context_line":""},{"line_number":240,"context_line":"        if enabled is not None:"},{"line_number":241,"context_line":"            if enabled not in sys_maps.BOOT_SOURCE_ENABLED_MAP_REV:"},{"line_number":242,"context_line":"                raise exceptions.InvalidParameterValueError("},{"line_number":243,"context_line":"                    parameter\u003d\u0027enabled\u0027, value\u003denabled,"},{"line_number":244,"context_line":"                    valid_values\u003dlist(sys_maps.BOOT_SOURCE_ENABLED_MAP_REV))"},{"line_number":245,"context_line":""},{"line_number":246,"context_line":"            fishy_freq \u003d sys_maps.BOOT_SOURCE_ENABLED_MAP_REV[enabled]"},{"line_number":247,"context_line":""},{"line_number":248,"context_line":"            data[\u0027Boot\u0027][\u0027BootSourceOverrideEnabled\u0027] \u003d fishy_freq"},{"line_number":249,"context_line":""},{"line_number":250,"context_line":"        if mode is not None:"},{"line_number":251,"context_line":"            if mode not in sys_maps.BOOT_SOURCE_MODE_MAP_REV:"},{"line_number":252,"context_line":"                raise exceptions.InvalidParameterValueError("},{"line_number":253,"context_line":"                    parameter\u003d\u0027mode\u0027, value\u003dmode,"},{"line_number":254,"context_line":"                    valid_values\u003dlist(sys_maps.BOOT_SOURCE_MODE_MAP_REV))"},{"line_number":255,"context_line":""},{"line_number":256,"context_line":"            fishy_mode \u003d sys_maps.BOOT_SOURCE_MODE_MAP_REV[mode]"},{"line_number":257,"context_line":""},{"line_number":258,"context_line":"            data[\u0027Boot\u0027][\u0027BootSourceOverrideMode\u0027] \u003d fishy_mode"},{"line_number":259,"context_line":""},{"line_number":260,"context_line":"        # TODO(lucasagomes): Check the return code and response body ?"},{"line_number":261,"context_line":"        #                    Probably we should call refresh() as well."},{"line_number":262,"context_line":"        self._conn.patch(self.path, data\u003ddata)"},{"line_number":263,"context_line":""},{"line_number":264,"context_line":"    def set_system_boot_source("},{"line_number":265,"context_line":"            self, target, enabled\u003dsys_cons.BOOT_SOURCE_ENABLED_ONCE,"}],"source_content_type":"text/x-python","patch_set":3,"id":"1fa4df85_bda201ad","line":262,"range":{"start_line":229,"start_character":0,"end_line":262,"end_character":46},"in_reply_to":"1fa4df85_16b3010c","updated":"2020-03-05 14:39:10.000000000","message":"\u003e At the midcycle, I believe we described the implementation in\n \u003e set_system_boot_source() this proposed change effectively modifies\n \u003e as passing PUT data in a PATCH request. We seemed to agree the\n \u003e PATCH request is reasonable, but the data should be changed to\n \u003e PATCH data which contains only the parameters which have changed. I\n \u003e believe this does not do that. If the caller passes in arguments\n \u003e which represent no change, they are still provided in the data.\n\n\nThat\u0027s s very good point! After the conversation we\u0027ve had, I went on to check how it goes with the official fishiness - it appears, that the fishy way of PATCHing is this [1].\n\n \n \u003e I see an openstack/ironic change which depends on this sushy\n \u003e change, https://review.opendev.org/#/c/711118/, checks if the\n \u003e desired value is different from the current value --\n \u003e https://review.opendev.org/#/c/711118/2/ironic/drivers/modules/redfish/management.py@135.\n \u003e Might that logic be better placed in this method so callers do not\n \u003e need to concern themselves with that?\n\n\nI thought about that as well! My problem here is that this conditional update is inherently racy (if more than one client is operating on the same BMC, or BMC changes its state between GET and PATCH). Therefore I am not certain that we (as sushy) should make this risky decision rather than to let the client decide what\u0027s the best approach for it.","commit_id":"25efb92e04ddb4211d6240f2f78fd8769a8dbe0c"},{"author":{"_account_id":23847,"name":"Richard G. Pioso","email":"richard.pioso@gmail.com","username":"richard.pioso"},"change_message_id":"fd3605546cb1f33aeca970f08aaa8aa921f2d742","unresolved":false,"context_lines":[{"line_number":226,"context_line":"        \"\"\""},{"line_number":227,"context_line":"        data \u003d collections.defaultdict(dict)"},{"line_number":228,"context_line":""},{"line_number":229,"context_line":"        if target is not None:"},{"line_number":230,"context_line":"            valid_targets \u003d self.get_allowed_system_boot_source_values()"},{"line_number":231,"context_line":"            if target not in valid_targets:"},{"line_number":232,"context_line":"                raise exceptions.InvalidParameterValueError("},{"line_number":233,"context_line":"                    parameter\u003d\u0027target\u0027, value\u003dtarget,"},{"line_number":234,"context_line":"                    valid_values\u003dvalid_targets)"},{"line_number":235,"context_line":""},{"line_number":236,"context_line":"            fishy_target \u003d sys_maps.BOOT_SOURCE_TARGET_MAP_REV[target]"},{"line_number":237,"context_line":""},{"line_number":238,"context_line":"            data[\u0027Boot\u0027][\u0027BootSourceOverrideTarget\u0027] \u003d fishy_target"},{"line_number":239,"context_line":""},{"line_number":240,"context_line":"        if enabled is not None:"},{"line_number":241,"context_line":"            if enabled not in sys_maps.BOOT_SOURCE_ENABLED_MAP_REV:"},{"line_number":242,"context_line":"                raise exceptions.InvalidParameterValueError("},{"line_number":243,"context_line":"                    parameter\u003d\u0027enabled\u0027, value\u003denabled,"},{"line_number":244,"context_line":"                    valid_values\u003dlist(sys_maps.BOOT_SOURCE_ENABLED_MAP_REV))"},{"line_number":245,"context_line":""},{"line_number":246,"context_line":"            fishy_freq \u003d sys_maps.BOOT_SOURCE_ENABLED_MAP_REV[enabled]"},{"line_number":247,"context_line":""},{"line_number":248,"context_line":"            data[\u0027Boot\u0027][\u0027BootSourceOverrideEnabled\u0027] \u003d fishy_freq"},{"line_number":249,"context_line":""},{"line_number":250,"context_line":"        if mode is not None:"},{"line_number":251,"context_line":"            if mode not in sys_maps.BOOT_SOURCE_MODE_MAP_REV:"},{"line_number":252,"context_line":"                raise exceptions.InvalidParameterValueError("},{"line_number":253,"context_line":"                    parameter\u003d\u0027mode\u0027, value\u003dmode,"},{"line_number":254,"context_line":"                    valid_values\u003dlist(sys_maps.BOOT_SOURCE_MODE_MAP_REV))"},{"line_number":255,"context_line":""},{"line_number":256,"context_line":"            fishy_mode \u003d sys_maps.BOOT_SOURCE_MODE_MAP_REV[mode]"},{"line_number":257,"context_line":""},{"line_number":258,"context_line":"            data[\u0027Boot\u0027][\u0027BootSourceOverrideMode\u0027] \u003d fishy_mode"},{"line_number":259,"context_line":""},{"line_number":260,"context_line":"        # TODO(lucasagomes): Check the return code and response body ?"},{"line_number":261,"context_line":"        #                    Probably we should call refresh() as well."},{"line_number":262,"context_line":"        self._conn.patch(self.path, data\u003ddata)"},{"line_number":263,"context_line":""},{"line_number":264,"context_line":"    def set_system_boot_source("},{"line_number":265,"context_line":"            self, target, enabled\u003dsys_cons.BOOT_SOURCE_ENABLED_ONCE,"}],"source_content_type":"text/x-python","patch_set":3,"id":"1fa4df85_86433113","line":262,"range":{"start_line":229,"start_character":0,"end_line":262,"end_character":46},"in_reply_to":"1fa4df85_18548320","updated":"2020-03-05 22:10:39.000000000","message":"\u003e I forgot to paste the spec [1]:\n \u003e \n \u003e Changes to one or more properties within the resource addressed by\n \u003e the request Uri are sent in the request body. Properties not\n \u003e specified in the request body are not directly changed by the PATCH\n \u003e request.\n \u003e \n \u003e 1. http://redfish.dmtf.org/schemas/DSP0266_1.5.0.html#update-patch-a-id-update-patch-a-\n\n\nTo provide context, I have copied my earlier, context-free response here.\n\nThank you for the reference. My read of it is that the decision we reached at the midcycle, include only the changed properties in the PATCH request\u0027s data, complies with the standard.\n\nDo you agree?","commit_id":"25efb92e04ddb4211d6240f2f78fd8769a8dbe0c"},{"author":{"_account_id":26340,"name":"Ilya Etingof","email":"etingof@gmail.com","username":"etingof"},"change_message_id":"0dbaecbf7cce626b9cf0cc9d91c806115948ec07","unresolved":false,"context_lines":[{"line_number":226,"context_line":"        \"\"\""},{"line_number":227,"context_line":"        data \u003d collections.defaultdict(dict)"},{"line_number":228,"context_line":""},{"line_number":229,"context_line":"        if target is not None:"},{"line_number":230,"context_line":"            valid_targets \u003d self.get_allowed_system_boot_source_values()"},{"line_number":231,"context_line":"            if target not in valid_targets:"},{"line_number":232,"context_line":"                raise exceptions.InvalidParameterValueError("},{"line_number":233,"context_line":"                    parameter\u003d\u0027target\u0027, value\u003dtarget,"},{"line_number":234,"context_line":"                    valid_values\u003dvalid_targets)"},{"line_number":235,"context_line":""},{"line_number":236,"context_line":"            fishy_target \u003d sys_maps.BOOT_SOURCE_TARGET_MAP_REV[target]"},{"line_number":237,"context_line":""},{"line_number":238,"context_line":"            data[\u0027Boot\u0027][\u0027BootSourceOverrideTarget\u0027] \u003d fishy_target"},{"line_number":239,"context_line":""},{"line_number":240,"context_line":"        if enabled is not None:"},{"line_number":241,"context_line":"            if enabled not in sys_maps.BOOT_SOURCE_ENABLED_MAP_REV:"},{"line_number":242,"context_line":"                raise exceptions.InvalidParameterValueError("},{"line_number":243,"context_line":"                    parameter\u003d\u0027enabled\u0027, value\u003denabled,"},{"line_number":244,"context_line":"                    valid_values\u003dlist(sys_maps.BOOT_SOURCE_ENABLED_MAP_REV))"},{"line_number":245,"context_line":""},{"line_number":246,"context_line":"            fishy_freq \u003d sys_maps.BOOT_SOURCE_ENABLED_MAP_REV[enabled]"},{"line_number":247,"context_line":""},{"line_number":248,"context_line":"            data[\u0027Boot\u0027][\u0027BootSourceOverrideEnabled\u0027] \u003d fishy_freq"},{"line_number":249,"context_line":""},{"line_number":250,"context_line":"        if mode is not None:"},{"line_number":251,"context_line":"            if mode not in sys_maps.BOOT_SOURCE_MODE_MAP_REV:"},{"line_number":252,"context_line":"                raise exceptions.InvalidParameterValueError("},{"line_number":253,"context_line":"                    parameter\u003d\u0027mode\u0027, value\u003dmode,"},{"line_number":254,"context_line":"                    valid_values\u003dlist(sys_maps.BOOT_SOURCE_MODE_MAP_REV))"},{"line_number":255,"context_line":""},{"line_number":256,"context_line":"            fishy_mode \u003d sys_maps.BOOT_SOURCE_MODE_MAP_REV[mode]"},{"line_number":257,"context_line":""},{"line_number":258,"context_line":"            data[\u0027Boot\u0027][\u0027BootSourceOverrideMode\u0027] \u003d fishy_mode"},{"line_number":259,"context_line":""},{"line_number":260,"context_line":"        # TODO(lucasagomes): Check the return code and response body ?"},{"line_number":261,"context_line":"        #                    Probably we should call refresh() as well."},{"line_number":262,"context_line":"        self._conn.patch(self.path, data\u003ddata)"},{"line_number":263,"context_line":""},{"line_number":264,"context_line":"    def set_system_boot_source("},{"line_number":265,"context_line":"            self, target, enabled\u003dsys_cons.BOOT_SOURCE_ENABLED_ONCE,"}],"source_content_type":"text/x-python","patch_set":3,"id":"1fa4df85_bda50aa4","line":262,"range":{"start_line":229,"start_character":0,"end_line":262,"end_character":46},"in_reply_to":"1fa4df85_86433113","updated":"2020-03-06 17:52:42.000000000","message":"I think at the mid-cycle we thought we should only include the changes that we want to modify because that would be easier on the BMCs (which are not always  super reliable and support performant). I agree with that, or at least that is what I gathered from that discussion.\n\nAt that time we thought we should do in RFC6902 way, because that\u0027s how REST APIs tend to work. Later on it turned out that Redfish spec does not suggest to use RFC6902.\n\nThis patch implements non-RFC6902 way of including only modified attributes in PATCH.","commit_id":"25efb92e04ddb4211d6240f2f78fd8769a8dbe0c"},{"author":{"_account_id":23847,"name":"Richard G. Pioso","email":"richard.pioso@gmail.com","username":"richard.pioso"},"change_message_id":"fd3605546cb1f33aeca970f08aaa8aa921f2d742","unresolved":false,"context_lines":[{"line_number":226,"context_line":"        \"\"\""},{"line_number":227,"context_line":"        data \u003d collections.defaultdict(dict)"},{"line_number":228,"context_line":""},{"line_number":229,"context_line":"        if target is not None:"},{"line_number":230,"context_line":"            valid_targets \u003d self.get_allowed_system_boot_source_values()"},{"line_number":231,"context_line":"            if target not in valid_targets:"},{"line_number":232,"context_line":"                raise exceptions.InvalidParameterValueError("},{"line_number":233,"context_line":"                    parameter\u003d\u0027target\u0027, value\u003dtarget,"},{"line_number":234,"context_line":"                    valid_values\u003dvalid_targets)"},{"line_number":235,"context_line":""},{"line_number":236,"context_line":"            fishy_target \u003d sys_maps.BOOT_SOURCE_TARGET_MAP_REV[target]"},{"line_number":237,"context_line":""},{"line_number":238,"context_line":"            data[\u0027Boot\u0027][\u0027BootSourceOverrideTarget\u0027] \u003d fishy_target"},{"line_number":239,"context_line":""},{"line_number":240,"context_line":"        if enabled is not None:"},{"line_number":241,"context_line":"            if enabled not in sys_maps.BOOT_SOURCE_ENABLED_MAP_REV:"},{"line_number":242,"context_line":"                raise exceptions.InvalidParameterValueError("},{"line_number":243,"context_line":"                    parameter\u003d\u0027enabled\u0027, value\u003denabled,"},{"line_number":244,"context_line":"                    valid_values\u003dlist(sys_maps.BOOT_SOURCE_ENABLED_MAP_REV))"},{"line_number":245,"context_line":""},{"line_number":246,"context_line":"            fishy_freq \u003d sys_maps.BOOT_SOURCE_ENABLED_MAP_REV[enabled]"},{"line_number":247,"context_line":""},{"line_number":248,"context_line":"            data[\u0027Boot\u0027][\u0027BootSourceOverrideEnabled\u0027] \u003d fishy_freq"},{"line_number":249,"context_line":""},{"line_number":250,"context_line":"        if mode is not None:"},{"line_number":251,"context_line":"            if mode not in sys_maps.BOOT_SOURCE_MODE_MAP_REV:"},{"line_number":252,"context_line":"                raise exceptions.InvalidParameterValueError("},{"line_number":253,"context_line":"                    parameter\u003d\u0027mode\u0027, value\u003dmode,"},{"line_number":254,"context_line":"                    valid_values\u003dlist(sys_maps.BOOT_SOURCE_MODE_MAP_REV))"},{"line_number":255,"context_line":""},{"line_number":256,"context_line":"            fishy_mode \u003d sys_maps.BOOT_SOURCE_MODE_MAP_REV[mode]"},{"line_number":257,"context_line":""},{"line_number":258,"context_line":"            data[\u0027Boot\u0027][\u0027BootSourceOverrideMode\u0027] \u003d fishy_mode"},{"line_number":259,"context_line":""},{"line_number":260,"context_line":"        # TODO(lucasagomes): Check the return code and response body ?"},{"line_number":261,"context_line":"        #                    Probably we should call refresh() as well."},{"line_number":262,"context_line":"        self._conn.patch(self.path, data\u003ddata)"},{"line_number":263,"context_line":""},{"line_number":264,"context_line":"    def set_system_boot_source("},{"line_number":265,"context_line":"            self, target, enabled\u003dsys_cons.BOOT_SOURCE_ENABLED_ONCE,"}],"source_content_type":"text/x-python","patch_set":3,"id":"1fa4df85_c63da98f","line":262,"range":{"start_line":229,"start_character":0,"end_line":262,"end_character":46},"in_reply_to":"1fa4df85_bda201ad","updated":"2020-03-05 22:10:39.000000000","message":"\u003e I thought about that as well! My problem here is that this\n \u003e conditional update is inherently racy (if more than one client is\n \u003e operating on the same BMC, or BMC changes its state between GET and\n \u003e PATCH). Therefore I am not certain that we (as sushy) should make\n \u003e this risky decision rather than to let the client decide what\u0027s the\n \u003e best approach for it.\n\n\nI do not see any risk here. AFAIU, the system boot options aspect of the Redfish RESTful API is inherently racy. Immediately after Client One PATCHes it, Client Two could overwrite those settings with a PATCH of its own. There is no way to atomically set the system boot options and boot the system with them.\n\nSince there are no management roles and every client has access to everything, one could say that two clients managing a server at the same time is fundamentally broken. I am not sure we should concern ourselves about that possibility.\n\nA parameter could be added to set_system_boot_options() which indicates whether or not to include unchanged properties. Just a thought.","commit_id":"25efb92e04ddb4211d6240f2f78fd8769a8dbe0c"},{"author":{"_account_id":26340,"name":"Ilya Etingof","email":"etingof@gmail.com","username":"etingof"},"change_message_id":"fbf57ef61231530ba8fcfab4965cefc435ff70ab","unresolved":false,"context_lines":[{"line_number":226,"context_line":"        \"\"\""},{"line_number":227,"context_line":"        data \u003d collections.defaultdict(dict)"},{"line_number":228,"context_line":""},{"line_number":229,"context_line":"        if target is not None:"},{"line_number":230,"context_line":"            valid_targets \u003d self.get_allowed_system_boot_source_values()"},{"line_number":231,"context_line":"            if target not in valid_targets:"},{"line_number":232,"context_line":"                raise exceptions.InvalidParameterValueError("},{"line_number":233,"context_line":"                    parameter\u003d\u0027target\u0027, value\u003dtarget,"},{"line_number":234,"context_line":"                    valid_values\u003dvalid_targets)"},{"line_number":235,"context_line":""},{"line_number":236,"context_line":"            fishy_target \u003d sys_maps.BOOT_SOURCE_TARGET_MAP_REV[target]"},{"line_number":237,"context_line":""},{"line_number":238,"context_line":"            data[\u0027Boot\u0027][\u0027BootSourceOverrideTarget\u0027] \u003d fishy_target"},{"line_number":239,"context_line":""},{"line_number":240,"context_line":"        if enabled is not None:"},{"line_number":241,"context_line":"            if enabled not in sys_maps.BOOT_SOURCE_ENABLED_MAP_REV:"},{"line_number":242,"context_line":"                raise exceptions.InvalidParameterValueError("},{"line_number":243,"context_line":"                    parameter\u003d\u0027enabled\u0027, value\u003denabled,"},{"line_number":244,"context_line":"                    valid_values\u003dlist(sys_maps.BOOT_SOURCE_ENABLED_MAP_REV))"},{"line_number":245,"context_line":""},{"line_number":246,"context_line":"            fishy_freq \u003d sys_maps.BOOT_SOURCE_ENABLED_MAP_REV[enabled]"},{"line_number":247,"context_line":""},{"line_number":248,"context_line":"            data[\u0027Boot\u0027][\u0027BootSourceOverrideEnabled\u0027] \u003d fishy_freq"},{"line_number":249,"context_line":""},{"line_number":250,"context_line":"        if mode is not None:"},{"line_number":251,"context_line":"            if mode not in sys_maps.BOOT_SOURCE_MODE_MAP_REV:"},{"line_number":252,"context_line":"                raise exceptions.InvalidParameterValueError("},{"line_number":253,"context_line":"                    parameter\u003d\u0027mode\u0027, value\u003dmode,"},{"line_number":254,"context_line":"                    valid_values\u003dlist(sys_maps.BOOT_SOURCE_MODE_MAP_REV))"},{"line_number":255,"context_line":""},{"line_number":256,"context_line":"            fishy_mode \u003d sys_maps.BOOT_SOURCE_MODE_MAP_REV[mode]"},{"line_number":257,"context_line":""},{"line_number":258,"context_line":"            data[\u0027Boot\u0027][\u0027BootSourceOverrideMode\u0027] \u003d fishy_mode"},{"line_number":259,"context_line":""},{"line_number":260,"context_line":"        # TODO(lucasagomes): Check the return code and response body ?"},{"line_number":261,"context_line":"        #                    Probably we should call refresh() as well."},{"line_number":262,"context_line":"        self._conn.patch(self.path, data\u003ddata)"},{"line_number":263,"context_line":""},{"line_number":264,"context_line":"    def set_system_boot_source("},{"line_number":265,"context_line":"            self, target, enabled\u003dsys_cons.BOOT_SOURCE_ENABLED_ONCE,"}],"source_content_type":"text/x-python","patch_set":3,"id":"1fa4df85_18548320","line":262,"range":{"start_line":229,"start_character":0,"end_line":262,"end_character":46},"in_reply_to":"1fa4df85_bda201ad","updated":"2020-03-05 15:37:16.000000000","message":"I forgot to paste the spec [1]:\n\n    Changes to one or more properties within the resource addressed by the request Uri are sent in the request body. Properties not specified in the request body are not directly changed by the PATCH request. \n\n1. http://redfish.dmtf.org/schemas/DSP0266_1.5.0.html#update-patch-a-id-update-patch-a-","commit_id":"25efb92e04ddb4211d6240f2f78fd8769a8dbe0c"},{"author":{"_account_id":26340,"name":"Ilya Etingof","email":"etingof@gmail.com","username":"etingof"},"change_message_id":"0dbaecbf7cce626b9cf0cc9d91c806115948ec07","unresolved":false,"context_lines":[{"line_number":226,"context_line":"        \"\"\""},{"line_number":227,"context_line":"        data \u003d collections.defaultdict(dict)"},{"line_number":228,"context_line":""},{"line_number":229,"context_line":"        if target is not None:"},{"line_number":230,"context_line":"            valid_targets \u003d self.get_allowed_system_boot_source_values()"},{"line_number":231,"context_line":"            if target not in valid_targets:"},{"line_number":232,"context_line":"                raise exceptions.InvalidParameterValueError("},{"line_number":233,"context_line":"                    parameter\u003d\u0027target\u0027, value\u003dtarget,"},{"line_number":234,"context_line":"                    valid_values\u003dvalid_targets)"},{"line_number":235,"context_line":""},{"line_number":236,"context_line":"            fishy_target \u003d sys_maps.BOOT_SOURCE_TARGET_MAP_REV[target]"},{"line_number":237,"context_line":""},{"line_number":238,"context_line":"            data[\u0027Boot\u0027][\u0027BootSourceOverrideTarget\u0027] \u003d fishy_target"},{"line_number":239,"context_line":""},{"line_number":240,"context_line":"        if enabled is not None:"},{"line_number":241,"context_line":"            if enabled not in sys_maps.BOOT_SOURCE_ENABLED_MAP_REV:"},{"line_number":242,"context_line":"                raise exceptions.InvalidParameterValueError("},{"line_number":243,"context_line":"                    parameter\u003d\u0027enabled\u0027, value\u003denabled,"},{"line_number":244,"context_line":"                    valid_values\u003dlist(sys_maps.BOOT_SOURCE_ENABLED_MAP_REV))"},{"line_number":245,"context_line":""},{"line_number":246,"context_line":"            fishy_freq \u003d sys_maps.BOOT_SOURCE_ENABLED_MAP_REV[enabled]"},{"line_number":247,"context_line":""},{"line_number":248,"context_line":"            data[\u0027Boot\u0027][\u0027BootSourceOverrideEnabled\u0027] \u003d fishy_freq"},{"line_number":249,"context_line":""},{"line_number":250,"context_line":"        if mode is not None:"},{"line_number":251,"context_line":"            if mode not in sys_maps.BOOT_SOURCE_MODE_MAP_REV:"},{"line_number":252,"context_line":"                raise exceptions.InvalidParameterValueError("},{"line_number":253,"context_line":"                    parameter\u003d\u0027mode\u0027, value\u003dmode,"},{"line_number":254,"context_line":"                    valid_values\u003dlist(sys_maps.BOOT_SOURCE_MODE_MAP_REV))"},{"line_number":255,"context_line":""},{"line_number":256,"context_line":"            fishy_mode \u003d sys_maps.BOOT_SOURCE_MODE_MAP_REV[mode]"},{"line_number":257,"context_line":""},{"line_number":258,"context_line":"            data[\u0027Boot\u0027][\u0027BootSourceOverrideMode\u0027] \u003d fishy_mode"},{"line_number":259,"context_line":""},{"line_number":260,"context_line":"        # TODO(lucasagomes): Check the return code and response body ?"},{"line_number":261,"context_line":"        #                    Probably we should call refresh() as well."},{"line_number":262,"context_line":"        self._conn.patch(self.path, data\u003ddata)"},{"line_number":263,"context_line":""},{"line_number":264,"context_line":"    def set_system_boot_source("},{"line_number":265,"context_line":"            self, target, enabled\u003dsys_cons.BOOT_SOURCE_ENABLED_ONCE,"}],"source_content_type":"text/x-python","patch_set":3,"id":"1fa4df85_f8c39087","line":262,"range":{"start_line":229,"start_character":0,"end_line":262,"end_character":46},"in_reply_to":"1fa4df85_c63da98f","updated":"2020-03-06 17:52:42.000000000","message":"\u003e \u003e I thought about that as well! My problem here is that this\n \u003e \u003e conditional update is inherently racy (if more than one client is\n \u003e \u003e operating on the same BMC, or BMC changes its state between GET\n \u003e and\n \u003e \u003e PATCH). Therefore I am not certain that we (as sushy) should make\n \u003e \u003e this risky decision rather than to let the client decide what\u0027s\n \u003e the\n \u003e \u003e best approach for it.\n \u003e \n \u003e \n \u003e I do not see any risk here. AFAIU, the system boot options aspect\n \u003e of the Redfish RESTful API is inherently racy. Immediately after\n \u003e Client One PATCHes it, Client Two could overwrite those settings\n \u003e with a PATCH of its own. There is no way to atomically set the\n \u003e system boot options and boot the system with them.\n\nYes, this is exactly the risk I am worrying about. I do agree that there seems to be no clear solution to avoid this racing.\n\nOn the other hand, may be many clients - one BMC is a legitimate case? If it was not, may be we\u0027d have a word in the spec or some kind of locking mechanism built in?\n\n \u003e Since there are no management roles and every client has access to\n \u003e everything, one could say that two clients managing a server at the\n \u003e same time is fundamentally broken. I am not sure we should concern\n \u003e ourselves about that possibility.\n\nMay be that depends on the site...?  Some installations may somehow ensure one client - one BMC relationship, others may allow one-to-many. In the latter case  sushy should not invoke this read-check-write logic, but do just unconditional write.\n\n \u003e A parameter could be added to set_system_boot_options() which\n \u003e indicates whether or not to include unchanged properties. Just a\n \u003e thought.\n\nWell, that\u0027s a way, but I am still not sure it\u0027s justified given our murky understanding of the use-cases...\n\nAlso, we have 3 distinct parameters in that method, will that new parameter control all three options at once or each individually?","commit_id":"25efb92e04ddb4211d6240f2f78fd8769a8dbe0c"},{"author":{"_account_id":11655,"name":"Julia Kreger","email":"juliaashleykreger@gmail.com","username":"jkreger","status":"Flying to the moon with a Jetpack!"},"change_message_id":"a0dcd282bb3cda65050ebf97c9b7e7d768faa82c","unresolved":false,"context_lines":[{"line_number":226,"context_line":"        \"\"\""},{"line_number":227,"context_line":"        data \u003d collections.defaultdict(dict)"},{"line_number":228,"context_line":""},{"line_number":229,"context_line":"        if target is not None:"},{"line_number":230,"context_line":"            valid_targets \u003d self.get_allowed_system_boot_source_values()"},{"line_number":231,"context_line":"            if target not in valid_targets:"},{"line_number":232,"context_line":"                raise exceptions.InvalidParameterValueError("},{"line_number":233,"context_line":"                    parameter\u003d\u0027target\u0027, value\u003dtarget,"},{"line_number":234,"context_line":"                    valid_values\u003dvalid_targets)"},{"line_number":235,"context_line":""},{"line_number":236,"context_line":"            fishy_target \u003d sys_maps.BOOT_SOURCE_TARGET_MAP_REV[target]"},{"line_number":237,"context_line":""},{"line_number":238,"context_line":"            data[\u0027Boot\u0027][\u0027BootSourceOverrideTarget\u0027] \u003d fishy_target"},{"line_number":239,"context_line":""},{"line_number":240,"context_line":"        if enabled is not None:"},{"line_number":241,"context_line":"            if enabled not in sys_maps.BOOT_SOURCE_ENABLED_MAP_REV:"},{"line_number":242,"context_line":"                raise exceptions.InvalidParameterValueError("},{"line_number":243,"context_line":"                    parameter\u003d\u0027enabled\u0027, value\u003denabled,"},{"line_number":244,"context_line":"                    valid_values\u003dlist(sys_maps.BOOT_SOURCE_ENABLED_MAP_REV))"},{"line_number":245,"context_line":""},{"line_number":246,"context_line":"            fishy_freq \u003d sys_maps.BOOT_SOURCE_ENABLED_MAP_REV[enabled]"},{"line_number":247,"context_line":""},{"line_number":248,"context_line":"            data[\u0027Boot\u0027][\u0027BootSourceOverrideEnabled\u0027] \u003d fishy_freq"},{"line_number":249,"context_line":""},{"line_number":250,"context_line":"        if mode is not None:"},{"line_number":251,"context_line":"            if mode not in sys_maps.BOOT_SOURCE_MODE_MAP_REV:"},{"line_number":252,"context_line":"                raise exceptions.InvalidParameterValueError("},{"line_number":253,"context_line":"                    parameter\u003d\u0027mode\u0027, value\u003dmode,"},{"line_number":254,"context_line":"                    valid_values\u003dlist(sys_maps.BOOT_SOURCE_MODE_MAP_REV))"},{"line_number":255,"context_line":""},{"line_number":256,"context_line":"            fishy_mode \u003d sys_maps.BOOT_SOURCE_MODE_MAP_REV[mode]"},{"line_number":257,"context_line":""},{"line_number":258,"context_line":"            data[\u0027Boot\u0027][\u0027BootSourceOverrideMode\u0027] \u003d fishy_mode"},{"line_number":259,"context_line":""},{"line_number":260,"context_line":"        # TODO(lucasagomes): Check the return code and response body ?"},{"line_number":261,"context_line":"        #                    Probably we should call refresh() as well."},{"line_number":262,"context_line":"        self._conn.patch(self.path, data\u003ddata)"},{"line_number":263,"context_line":""},{"line_number":264,"context_line":"    def set_system_boot_source("},{"line_number":265,"context_line":"            self, target, enabled\u003dsys_cons.BOOT_SOURCE_ENABLED_ONCE,"}],"source_content_type":"text/x-python","patch_set":3,"id":"df33271e_3d73d3e9","line":262,"range":{"start_line":229,"start_character":0,"end_line":262,"end_character":46},"in_reply_to":"1fa4df85_f8c39087","updated":"2020-03-23 20:39:19.000000000","message":"\u003e \u003e \u003e I thought about that as well! My problem here is that this\n \u003e \u003e \u003e conditional update is inherently racy (if more than one client\n \u003e is\n \u003e \u003e \u003e operating on the same BMC, or BMC changes its state between GET\n \u003e \u003e and\n \u003e \u003e \u003e PATCH). Therefore I am not certain that we (as sushy) should\n \u003e make\n \u003e \u003e \u003e this risky decision rather than to let the client decide what\u0027s\n \u003e \u003e the\n \u003e \u003e \u003e best approach for it.\n \u003e \u003e\n\nObviously it is likely best for the client to try and decide that and also assert that as needed. I see this potentially being problematic if there is wholesale behavior differences, but the key is really trying to get the BMC to honor the setting changes.\n\n \u003e \u003e\n \u003e \u003e I do not see any risk here. AFAIU, the system boot options aspect\n \u003e \u003e of the Redfish RESTful API is inherently racy. Immediately after\n \u003e \u003e Client One PATCHes it, Client Two could overwrite those settings\n \u003e \u003e with a PATCH of its own. There is no way to atomically set the\n \u003e \u003e system boot options and boot the system with them.\n \u003e \n \u003e Yes, this is exactly the risk I am worrying about. I do agree that\n \u003e there seems to be no clear solution to avoid this racing.\n \u003e \n \u003e On the other hand, may be many clients - one BMC is a legitimate\n \u003e case? If it was not, may be we\u0027d have a word in the spec or some\n \u003e kind of locking mechanism built in?\n \u003e \n \u003e \u003e Since there are no management roles and every client has access\n \u003e to\n \u003e \u003e everything, one could say that two clients managing a server at\n \u003e the\n \u003e \u003e same time is fundamentally broken. I am not sure we should\n \u003e concern\n \u003e \u003e ourselves about that possibility.\n \u003e \n \u003e May be that depends on the site...?  Some installations may somehow\n \u003e ensure one client - one BMC relationship, others may allow\n \u003e one-to-many. In the latter case  sushy should not invoke this\n \u003e read-check-write logic, but do just unconditional write.\n \u003e \n\nI am +1000 with Richard on that it is invalid configuration to to manage the same distinct system with two separate management platforms concurrently. We simply cannot support that operation and the operating model which ironic an support is as it is basically the sole authoritative source of truth.\n\nSo trying to build library internal locking doesn\u0027t seem to apply nor would actually fix this issue because the race would still be achievable. Basically, this sort of race exists with most APIs anyway, all we can do is try to cope our best with the caller of the library (ironic, or any other program.)\n\nAlso likely worth stressing that some vendors have explicitly stated their redfish BMC address is a proxy frontend to the backend API which doesn\u0027t update for 30-60 seconds. That is logic we can\u0027t represent handling for and is a huge potential race. There really is no defending against that and trying to prevent an operator from misusing the APIs.\n\n \u003e \u003e A parameter could be added to set_system_boot_options() which\n \u003e \u003e indicates whether or not to include unchanged properties. Just a\n \u003e \u003e thought.\n \u003e \n \u003e Well, that\u0027s a way, but I am still not sure it\u0027s justified given\n \u003e our murky understanding of the use-cases...\n \u003e \n \u003e Also, we have 3 distinct parameters in that method, will that new\n \u003e parameter control all three options at once or each individually?\n\nI\u0027m not exactly a fan of different parameters and sending blank updates, but maybe it is warranted except only by BMC design/behavior.  Perhaps the thing is the caller of the library should be knowing when to do things one at a time?","commit_id":"25efb92e04ddb4211d6240f2f78fd8769a8dbe0c"},{"author":{"_account_id":23851,"name":"Riccardo Pittau","email":"elfosardo@gmail.com","username":"elfosardo"},"change_message_id":"97d07b554ec5ba54db0756520a6107f18f284fc2","unresolved":false,"context_lines":[{"line_number":261,"context_line":"        #                    Probably we should call refresh() as well."},{"line_number":262,"context_line":"        self._conn.patch(self.path, data\u003ddata)"},{"line_number":263,"context_line":""},{"line_number":264,"context_line":"    def set_system_boot_source("},{"line_number":265,"context_line":"            self, target, enabled\u003dsys_cons.BOOT_SOURCE_ENABLED_ONCE,"},{"line_number":266,"context_line":"            mode\u003dNone):"},{"line_number":267,"context_line":"        \"\"\"Set boot source and/or boot frequency and/or boot mode."}],"source_content_type":"text/x-python","patch_set":3,"id":"1fa4df85_47c9d723","line":264,"updated":"2020-03-04 10:28:15.000000000","message":"let\u0027s add a note to remove this at some point\nMaybe after next release?","commit_id":"25efb92e04ddb4211d6240f2f78fd8769a8dbe0c"},{"author":{"_account_id":26340,"name":"Ilya Etingof","email":"etingof@gmail.com","username":"etingof"},"change_message_id":"c26c3f6e181175906e8bca6e15e8e2253f8d282d","unresolved":false,"context_lines":[{"line_number":261,"context_line":"        #                    Probably we should call refresh() as well."},{"line_number":262,"context_line":"        self._conn.patch(self.path, data\u003ddata)"},{"line_number":263,"context_line":""},{"line_number":264,"context_line":"    def set_system_boot_source("},{"line_number":265,"context_line":"            self, target, enabled\u003dsys_cons.BOOT_SOURCE_ENABLED_ONCE,"},{"line_number":266,"context_line":"            mode\u003dNone):"},{"line_number":267,"context_line":"        \"\"\"Set boot source and/or boot frequency and/or boot mode."}],"source_content_type":"text/x-python","patch_set":3,"id":"1fa4df85_ddd81d7c","line":264,"in_reply_to":"1fa4df85_47c9d723","updated":"2020-03-05 14:39:10.000000000","message":"Done","commit_id":"25efb92e04ddb4211d6240f2f78fd8769a8dbe0c"}]}
