)]}'
{"ironic/common/exception.py":[{"author":{"_account_id":10239,"name":"Dmitry Tantsur","email":"dtantsur@protonmail.com","username":"dtantsur"},"change_message_id":"4933fd3b87f014463d5cad190c5a7c902c864298","unresolved":false,"context_lines":[{"line_number":559,"context_line":""},{"line_number":560,"context_line":""},{"line_number":561,"context_line":"class NodeCleaningTimeout(IronicException):"},{"line_number":562,"context_line":"    pass"},{"line_number":563,"context_line":""},{"line_number":564,"context_line":""},{"line_number":565,"context_line":"class PathNotFound(IronicException):"}],"source_content_type":"text/x-python","patch_set":4,"id":"ba5da102_61b90515","line":562,"updated":"2016-11-02 11:44:17.000000000","message":"let\u0027s add an error message here. even if we don\u0027t expose it to users right now, we might start doing it in the future or by chance","commit_id":"30a1a20ba07b76b36c8b756a86b32e69d0d587d8"},{"author":{"_account_id":13295,"name":"Mario Villaplana","email":"mario.villaplana@gmail.com","username":"mariojv"},"change_message_id":"c4e3cf52e378b6c6c25e49ed0f0801c9da0dd8cd","unresolved":false,"context_lines":[{"line_number":559,"context_line":""},{"line_number":560,"context_line":""},{"line_number":561,"context_line":"class NodeCleaningTimeout(IronicException):"},{"line_number":562,"context_line":"    pass"},{"line_number":563,"context_line":""},{"line_number":564,"context_line":""},{"line_number":565,"context_line":"class PathNotFound(IronicException):"}],"source_content_type":"text/x-python","patch_set":4,"id":"ba5da102_f924d30d","line":562,"in_reply_to":"ba5da102_61b90515","updated":"2016-11-02 20:42:08.000000000","message":"Done","commit_id":"30a1a20ba07b76b36c8b756a86b32e69d0d587d8"}],"ironic/conductor/manager.py":[{"author":{"_account_id":10239,"name":"Dmitry Tantsur","email":"dtantsur@protonmail.com","username":"dtantsur"},"change_message_id":"4933fd3b87f014463d5cad190c5a7c902c864298","unresolved":false,"context_lines":[{"line_number":1368,"context_line":"                                            \u0027provision_updated_at\u0027],"},{"line_number":1369,"context_line":"                                    filters\u003dfilters)"},{"line_number":1370,"context_line":""},{"line_number":1371,"context_line":"        if not node_iter:"},{"line_number":1372,"context_line":"            return"},{"line_number":1373,"context_line":""},{"line_number":1374,"context_line":"        callback_timeout \u003d CONF.conductor.clean_callback_timeout"}],"source_content_type":"text/x-python","patch_set":4,"id":"ba5da102_8138d9a1","line":1371,"updated":"2016-11-02 11:44:17.000000000","message":"node_iter is an iterator, so this check makes no sense","commit_id":"30a1a20ba07b76b36c8b756a86b32e69d0d587d8"},{"author":{"_account_id":13295,"name":"Mario Villaplana","email":"mario.villaplana@gmail.com","username":"mariojv"},"change_message_id":"c4e3cf52e378b6c6c25e49ed0f0801c9da0dd8cd","unresolved":false,"context_lines":[{"line_number":1368,"context_line":"                                            \u0027provision_updated_at\u0027],"},{"line_number":1369,"context_line":"                                    filters\u003dfilters)"},{"line_number":1370,"context_line":""},{"line_number":1371,"context_line":"        if not node_iter:"},{"line_number":1372,"context_line":"            return"},{"line_number":1373,"context_line":""},{"line_number":1374,"context_line":"        callback_timeout \u003d CONF.conductor.clean_callback_timeout"}],"source_content_type":"text/x-python","patch_set":4,"id":"ba5da102_9982f7c6","line":1371,"in_reply_to":"ba5da102_8138d9a1","updated":"2016-11-02 20:42:08.000000000","message":"You\u0027re right, removed","commit_id":"30a1a20ba07b76b36c8b756a86b32e69d0d587d8"},{"author":{"_account_id":7711,"name":"Yuriy Zveryanskyy","email":"yzveryanskyy@mirantis.com","username":"yuriyz"},"change_message_id":"5db97809fbdabb5a54fc48f69a58c590281d3eb0","unresolved":false,"context_lines":[{"line_number":889,"context_line":"                timeout \u003d eventlet.Timeout(step[\u0027timeout\u0027],"},{"line_number":890,"context_line":"                                           exception.NodeCleaningTimeout)"},{"line_number":891,"context_line":"            try:"},{"line_number":892,"context_line":"                result \u003d interface.execute_clean_step(task, step)"},{"line_number":893,"context_line":"            except exception.NodeCleaningTimeout:"},{"line_number":894,"context_line":"                msg \u003d (_(\u0027Node %(node)s timed out on %(step)s: \u0027"},{"line_number":895,"context_line":"                         \u0027failed to complete step within the allotted \u0027"}],"source_content_type":"text/x-python","patch_set":5,"id":"ba5da102_b85ccef1","line":892,"updated":"2016-11-04 12:10:15.000000000","message":"There is a note in eventlet doc: \"If the code block catches and doesn’t re-raise BaseException (for example, with except:), then it will catch the Timeout exception, and might not abort as intended.\"\nI tried this code:\n\n\u003e\u003e\u003e eventlet.Timeout(10)\n\u003cTimeout at 0x7f3fcb5029b0 seconds\u003d10 pending\u003e\n\u003e\u003e\u003e eventlet.sleep(20)\nTraceback (most recent call last):\n  File \"\u003cstdin\u003e\", line 1, in \u003cmodule\u003e\n  File \"/usr/local/lib/python2.7/dist-packages/eventlet/greenthread.py\", line 34, in sleep\n    hub.switch()\n  File \"/usr/local/lib/python2.7/dist-packages/eventlet/hubs/hub.py\", line 294, in switch\n    return self.greenlet.switch()\neventlet.timeout.Timeout: 10 seconds\n\u003e\u003e\u003e class MyException(Exception):\n...     pass\n... \n\u003e\u003e\u003e def f():\n...     try:\n...             eventlet.sleep(20)\n...     except Exception:\n...             pass\n... \n\u003e\u003e\u003e eventlet.Timeout(10, MyException)\n\u003cTimeout at 0x7f3fcb4955a0 seconds\u003d10 exception\u003d\u003cclass \u0027__main__.MyException\u0027\u003e pending\u003e\n\u003e\u003e\u003e f()\n\u003e\u003e\u003e \n^^ no exception here\n\nWe can not know in conductor manager driver\u0027s code detail, timeout will not work in case as example and if driver code catch all exceptions and re-raise as custom exception. Looks like eventlet Timeout exception derived directly from BaseException (it\u0027s system exception) for avoiding mentioned problems.","commit_id":"593a9c9862037ccf2ebfd67b4c4f7e822c9b8008"},{"author":{"_account_id":13295,"name":"Mario Villaplana","email":"mario.villaplana@gmail.com","username":"mariojv"},"change_message_id":"fda7e9d51d1fae9d500615e4d8e9307e576e48b7","unresolved":false,"context_lines":[{"line_number":889,"context_line":"                timeout \u003d eventlet.Timeout(step[\u0027timeout\u0027],"},{"line_number":890,"context_line":"                                           exception.NodeCleaningTimeout)"},{"line_number":891,"context_line":"            try:"},{"line_number":892,"context_line":"                result \u003d interface.execute_clean_step(task, step)"},{"line_number":893,"context_line":"            except exception.NodeCleaningTimeout:"},{"line_number":894,"context_line":"                msg \u003d (_(\u0027Node %(node)s timed out on %(step)s: \u0027"},{"line_number":895,"context_line":"                         \u0027failed to complete step within the allotted \u0027"}],"source_content_type":"text/x-python","patch_set":5,"id":"7a77a97e_24c10c2f","line":892,"in_reply_to":"ba5da102_b85ccef1","updated":"2016-11-16 19:38:29.000000000","message":"It works fine if you have a handler for the custom exception. See what I did in my code:\n\n\u003e\u003e\u003e class MyExc(Exception):\n...     pass\n... \n\u003e\u003e\u003e def f():\n...     t \u003d eventlet.Timeout(5, MyExc)\n...     try:\n...             eventlet.sleep(10)\n...     except MyExc:\n...             print(\"my exception was raised!\")\n...     except Exception:\n...             print(\"some random exception was raised\")\n...     finally:\n...             if t:\n...                     t.cancel()\n... \n\u003e\u003e\u003e f()\nmy exception was raised!\n\u003e\u003e\u003e\n\nThe \"finally\" clause makes sure the timeout gets aborted properly.","commit_id":"593a9c9862037ccf2ebfd67b4c4f7e822c9b8008"},{"author":{"_account_id":14525,"name":"Vasyl Saienko","email":"vsaienko@mirantis.com","username":"vsaienko"},"change_message_id":"ca6efaad763db0cba530da5e715faeaf87c082e1","unresolved":false,"context_lines":[{"line_number":892,"context_line":"                result \u003d interface.execute_clean_step(task, step)"},{"line_number":893,"context_line":"            except exception.NodeCleaningTimeout:"},{"line_number":894,"context_line":"                msg \u003d (_(\u0027Node %(node)s timed out on %(step)s: \u0027"},{"line_number":895,"context_line":"                         \u0027failed to complete step within the allotted \u0027"},{"line_number":896,"context_line":"                         \u0027%(timeout)s seconds.\u0027) %"},{"line_number":897,"context_line":"                       {\u0027node\u0027: node.uuid,"},{"line_number":898,"context_line":"                        \u0027step\u0027: step,"}],"source_content_type":"text/x-python","patch_set":5,"id":"ba5da102_d977bd06","line":895,"range":{"start_line":895,"start_character":61,"end_line":895,"end_character":69},"updated":"2016-11-04 15:39:47.000000000","message":"s/allotted/allocated","commit_id":"593a9c9862037ccf2ebfd67b4c4f7e822c9b8008"},{"author":{"_account_id":13295,"name":"Mario Villaplana","email":"mario.villaplana@gmail.com","username":"mariojv"},"change_message_id":"fda7e9d51d1fae9d500615e4d8e9307e576e48b7","unresolved":false,"context_lines":[{"line_number":892,"context_line":"                result \u003d interface.execute_clean_step(task, step)"},{"line_number":893,"context_line":"            except exception.NodeCleaningTimeout:"},{"line_number":894,"context_line":"                msg \u003d (_(\u0027Node %(node)s timed out on %(step)s: \u0027"},{"line_number":895,"context_line":"                         \u0027failed to complete step within the allotted \u0027"},{"line_number":896,"context_line":"                         \u0027%(timeout)s seconds.\u0027) %"},{"line_number":897,"context_line":"                       {\u0027node\u0027: node.uuid,"},{"line_number":898,"context_line":"                        \u0027step\u0027: step,"}],"source_content_type":"text/x-python","patch_set":5,"id":"7a77a97e_6464e448","line":895,"range":{"start_line":895,"start_character":61,"end_line":895,"end_character":69},"in_reply_to":"ba5da102_d977bd06","updated":"2016-11-16 19:38:29.000000000","message":"Done","commit_id":"593a9c9862037ccf2ebfd67b4c4f7e822c9b8008"},{"author":{"_account_id":14525,"name":"Vasyl Saienko","email":"vsaienko@mirantis.com","username":"vsaienko"},"change_message_id":"ca6efaad763db0cba530da5e715faeaf87c082e1","unresolved":false,"context_lines":[{"line_number":893,"context_line":"            except exception.NodeCleaningTimeout:"},{"line_number":894,"context_line":"                msg \u003d (_(\u0027Node %(node)s timed out on %(step)s: \u0027"},{"line_number":895,"context_line":"                         \u0027failed to complete step within the allotted \u0027"},{"line_number":896,"context_line":"                         \u0027%(timeout)s seconds.\u0027) %"},{"line_number":897,"context_line":"                       {\u0027node\u0027: node.uuid,"},{"line_number":898,"context_line":"                        \u0027step\u0027: step,"},{"line_number":899,"context_line":"                        \u0027timeout\u0027: step[\u0027timeout\u0027]})"}],"source_content_type":"text/x-python","patch_set":5,"id":"ba5da102_991f05b7","line":896,"range":{"start_line":896,"start_character":49,"end_line":896,"end_character":50},"updated":"2016-11-04 15:39:47.000000000","message":"s/%/,\n\nhttp://docs.openstack.org/developer/oslo.i18n/guidelines.html#adding-variables-to-log-messages","commit_id":"593a9c9862037ccf2ebfd67b4c4f7e822c9b8008"},{"author":{"_account_id":13295,"name":"Mario Villaplana","email":"mario.villaplana@gmail.com","username":"mariojv"},"change_message_id":"fda7e9d51d1fae9d500615e4d8e9307e576e48b7","unresolved":false,"context_lines":[{"line_number":893,"context_line":"            except exception.NodeCleaningTimeout:"},{"line_number":894,"context_line":"                msg \u003d (_(\u0027Node %(node)s timed out on %(step)s: \u0027"},{"line_number":895,"context_line":"                         \u0027failed to complete step within the allotted \u0027"},{"line_number":896,"context_line":"                         \u0027%(timeout)s seconds.\u0027) %"},{"line_number":897,"context_line":"                       {\u0027node\u0027: node.uuid,"},{"line_number":898,"context_line":"                        \u0027step\u0027: step,"},{"line_number":899,"context_line":"                        \u0027timeout\u0027: step[\u0027timeout\u0027]})"}],"source_content_type":"text/x-python","patch_set":5,"id":"7a77a97e_64cb041f","line":896,"range":{"start_line":896,"start_character":49,"end_line":896,"end_character":50},"in_reply_to":"ba5da102_991f05b7","updated":"2016-11-16 19:38:29.000000000","message":"Done","commit_id":"593a9c9862037ccf2ebfd67b4c4f7e822c9b8008"},{"author":{"_account_id":14525,"name":"Vasyl Saienko","email":"vsaienko@mirantis.com","username":"vsaienko"},"change_message_id":"ca6efaad763db0cba530da5e715faeaf87c082e1","unresolved":false,"context_lines":[{"line_number":1391,"context_line":"            # Also check provision state update time, and compare to the"},{"line_number":1392,"context_line":"            # more generic clean_callback_timeout, if this clean step"},{"line_number":1393,"context_line":"            # hasn\u0027t timed out yet and that config value is specified"},{"line_number":1394,"context_line":"            if not fail_cleaning and callback_timeout is not None:"},{"line_number":1395,"context_line":"                time_elapsed \u003d (now - provision_updated_at).total_seconds()"},{"line_number":1396,"context_line":"                if time_elapsed \u003e callback_timeout:"},{"line_number":1397,"context_line":"                    fail_cleaning \u003d True"}],"source_content_type":"text/x-python","patch_set":5,"id":"ba5da102_19d055c9","line":1394,"range":{"start_line":1394,"start_character":12,"end_line":1394,"end_character":66},"updated":"2016-11-04 15:39:47.000000000","message":"if fail_cleaning and callback_timeout is None:","commit_id":"593a9c9862037ccf2ebfd67b4c4f7e822c9b8008"},{"author":{"_account_id":13295,"name":"Mario Villaplana","email":"mario.villaplana@gmail.com","username":"mariojv"},"change_message_id":"fda7e9d51d1fae9d500615e4d8e9307e576e48b7","unresolved":false,"context_lines":[{"line_number":1391,"context_line":"            # Also check provision state update time, and compare to the"},{"line_number":1392,"context_line":"            # more generic clean_callback_timeout, if this clean step"},{"line_number":1393,"context_line":"            # hasn\u0027t timed out yet and that config value is specified"},{"line_number":1394,"context_line":"            if not fail_cleaning and callback_timeout is not None:"},{"line_number":1395,"context_line":"                time_elapsed \u003d (now - provision_updated_at).total_seconds()"},{"line_number":1396,"context_line":"                if time_elapsed \u003e callback_timeout:"},{"line_number":1397,"context_line":"                    fail_cleaning \u003d True"}],"source_content_type":"text/x-python","patch_set":5,"id":"7a77a97e_04ac1033","line":1394,"range":{"start_line":1394,"start_character":12,"end_line":1394,"end_character":66},"in_reply_to":"ba5da102_19d055c9","updated":"2016-11-16 19:38:29.000000000","message":"I don\u0027t think so?\n\nI check \"fail_cleaning\" to see if we already know that this node should fail, so we can skip calculating time_elapsed. I check that callback_timeout is not None since it doesn\u0027t make sense to check the elapsed time since provision state change if that config option is not set.","commit_id":"593a9c9862037ccf2ebfd67b4c4f7e822c9b8008"},{"author":{"_account_id":7711,"name":"Yuriy Zveryanskyy","email":"yzveryanskyy@mirantis.com","username":"yuriyz"},"change_message_id":"4afa2d7d65db078c3b5a0ed968aa5941cf809c09","unresolved":false,"context_lines":[{"line_number":889,"context_line":"                timeout \u003d eventlet.Timeout(step[\u0027timeout\u0027],"},{"line_number":890,"context_line":"                                           exception.NodeCleaningTimeout)"},{"line_number":891,"context_line":"            try:"},{"line_number":892,"context_line":"                result \u003d interface.execute_clean_step(task, step)"},{"line_number":893,"context_line":"            except exception.NodeCleaningTimeout:"},{"line_number":894,"context_line":"                msg \u003d (_(\u0027Node %(node)s timed out on %(step)s: \u0027"},{"line_number":895,"context_line":"                         \u0027failed to complete step within the allocated \u0027"}],"source_content_type":"text/x-python","patch_set":7,"id":"7a77a97e_a019f37b","line":892,"updated":"2016-11-21 10:35:52.000000000","message":"It will work with custom exception if we guarantee that driver does not catches all non-system exception. For example execute_clean_step() contains code:\n\n ...\n except Exception:\n     raise IronicDriverException()\n ...\n\nTry this example:\n\u003e\u003e\u003e class DriverException(Exception):\n...     pass\n... \n\u003e\u003e\u003e class TimeoutException(Exception):\n...     pass\n... \n\u003e\u003e\u003e def f():\n...     eventlet.Timeout(5, TimeoutException)\n...     try:\n...             driver()\n...     except TimeoutException:\n...             print \"timeout\"\n...     except Exception as e:\n...             print str(e)\n... \n\u003e\u003e\u003e def driver():\n...     try:\n...             eventlet.sleep(10)\n...     except Exception:\n...             raise DriverException(\"driver error\")\n... \n\u003e\u003e\u003e f()\ndriver error\n\u003e\u003e\u003e\n\nI think we should use eventlet\u0027s Timeout exception here.","commit_id":"71e34e0451fc4e236c4b302440a497f3c6661f2a"},{"author":{"_account_id":12356,"name":"Vladyslav Drok","email":"vdrok@mirantis.com","username":"vdrok"},"change_message_id":"5e5137b4cd82290496367d3e919c23ed7d6b9a66","unresolved":false,"context_lines":[{"line_number":889,"context_line":"                timeout \u003d eventlet.Timeout(step[\u0027timeout\u0027],"},{"line_number":890,"context_line":"                                           exception.NodeCleaningTimeout)"},{"line_number":891,"context_line":"            try:"},{"line_number":892,"context_line":"                result \u003d interface.execute_clean_step(task, step)"},{"line_number":893,"context_line":"            except exception.NodeCleaningTimeout:"},{"line_number":894,"context_line":"                msg \u003d (_(\u0027Node %(node)s timed out on %(step)s: \u0027"},{"line_number":895,"context_line":"                         \u0027failed to complete step within the allocated \u0027"}],"source_content_type":"text/x-python","patch_set":7,"id":"7a77a97e_962b6194","line":892,"in_reply_to":"7a77a97e_a019f37b","updated":"2016-11-21 12:10:44.000000000","message":"++, having read through the docs, it makes sense. Also would be good to ensure that the timeout raised here is is the one we\u0027ve defined on L889 and not something raised inside the execute_clean_step.","commit_id":"71e34e0451fc4e236c4b302440a497f3c6661f2a"},{"author":{"_account_id":12356,"name":"Vladyslav Drok","email":"vdrok@mirantis.com","username":"vdrok"},"change_message_id":"5e5137b4cd82290496367d3e919c23ed7d6b9a66","unresolved":false,"context_lines":[{"line_number":913,"context_line":"                    # Disable timeout immediately after clean step execution"},{"line_number":914,"context_line":"                    # finishes, even if the clean step is async. A separate"},{"line_number":915,"context_line":"                    # periodic task handles the async case."},{"line_number":916,"context_line":"                    timeout.cancel()"},{"line_number":917,"context_line":""},{"line_number":918,"context_line":"            # Check if the step is done or not. The step should return"},{"line_number":919,"context_line":"            # states.CLEANWAIT if the step is still being executed, or"}],"source_content_type":"text/x-python","patch_set":7,"id":"7a77a97e_11c91bad","line":916,"updated":"2016-11-21 12:10:44.000000000","message":"You could use with_timeout function here, that would .cancel by itself. Also, you could always pass the step.get(\u0027timeout\u0027) value as seconds to this function, as if it is None, there will be no timeout.","commit_id":"71e34e0451fc4e236c4b302440a497f3c6661f2a"},{"author":{"_account_id":12356,"name":"Vladyslav Drok","email":"vdrok@mirantis.com","username":"vdrok"},"change_message_id":"5e5137b4cd82290496367d3e919c23ed7d6b9a66","unresolved":false,"context_lines":[{"line_number":1368,"context_line":"                                            \u0027provision_updated_at\u0027],"},{"line_number":1369,"context_line":"                                    filters\u003dfilters)"},{"line_number":1370,"context_line":""},{"line_number":1371,"context_line":"        callback_timeout \u003d CONF.conductor.clean_callback_timeout"},{"line_number":1372,"context_line":"        for (node_uuid, driver, clean_step, driver_internal_info,"},{"line_number":1373,"context_line":"             provision_updated_at) in node_iter:"},{"line_number":1374,"context_line":"            fail_cleaning \u003d False"}],"source_content_type":"text/x-python","patch_set":7,"id":"7a77a97e_312a972d","line":1371,"updated":"2016-11-21 12:10:44.000000000","message":"defined twice","commit_id":"71e34e0451fc4e236c4b302440a497f3c6661f2a"},{"author":{"_account_id":12356,"name":"Vladyslav Drok","email":"vdrok@mirantis.com","username":"vdrok"},"change_message_id":"5e5137b4cd82290496367d3e919c23ed7d6b9a66","unresolved":false,"context_lines":[{"line_number":1398,"context_line":""},{"line_number":1399,"context_line":"            if fail_cleaning:"},{"line_number":1400,"context_line":"                filters \u003d {\u0027uuid\u0027: node_uuid}"},{"line_number":1401,"context_line":"                self._fail_if_in_state("},{"line_number":1402,"context_line":"                    context, filters, states.CLEANWAIT, \u0027provision_updated_at\u0027,"},{"line_number":1403,"context_line":"                    keep_target_state\u003dTrue,"},{"line_number":1404,"context_line":"                    callback_method\u003dutils.cleanup_cleanwait_timeout)"}],"source_content_type":"text/x-python","patch_set":7,"id":"7a77a97e_11b59b7d","line":1401,"updated":"2016-11-21 12:10:44.000000000","message":"This means we\u0027ll be doing a request for each node here, can we accumulate all uuids in a list and pass this list as a filter? Or maybe pass these uuids to the _fail_if_in_state directly as a new argument to avoid calling iter_nodes?","commit_id":"71e34e0451fc4e236c4b302440a497f3c6661f2a"}],"ironic/drivers/base.py":[{"author":{"_account_id":7711,"name":"Yuriy Zveryanskyy","email":"yzveryanskyy@mirantis.com","username":"yuriyz"},"change_message_id":"5db97809fbdabb5a54fc48f69a58c590281d3eb0","unresolved":false,"context_lines":[{"line_number":1160,"context_line":"                {\u0027arg\u0027: arg})"},{"line_number":1161,"context_line":""},{"line_number":1162,"context_line":""},{"line_number":1163,"context_line":"def clean_step(priority, abortable\u003dFalse, argsinfo\u003dNone, timeout\u003d0):"},{"line_number":1164,"context_line":"    \"\"\"Decorator for cleaning steps."},{"line_number":1165,"context_line":""},{"line_number":1166,"context_line":"    Cleaning steps may be used in manual or automated cleaning."}],"source_content_type":"text/x-python","patch_set":5,"id":"ba5da102_9f4a94ab","line":1163,"updated":"2016-11-04 12:10:15.000000000","message":"Set timeout in this decorator is not very good solution because the same step can work with different hardware in different envs.","commit_id":"593a9c9862037ccf2ebfd67b4c4f7e822c9b8008"},{"author":{"_account_id":13295,"name":"Mario Villaplana","email":"mario.villaplana@gmail.com","username":"mariojv"},"change_message_id":"fda7e9d51d1fae9d500615e4d8e9307e576e48b7","unresolved":false,"context_lines":[{"line_number":1160,"context_line":"                {\u0027arg\u0027: arg})"},{"line_number":1161,"context_line":""},{"line_number":1162,"context_line":""},{"line_number":1163,"context_line":"def clean_step(priority, abortable\u003dFalse, argsinfo\u003dNone, timeout\u003d0):"},{"line_number":1164,"context_line":"    \"\"\"Decorator for cleaning steps."},{"line_number":1165,"context_line":""},{"line_number":1166,"context_line":"    Cleaning steps may be used in manual or automated cleaning."}],"source_content_type":"text/x-python","patch_set":5,"id":"7a77a97e_24ee6cec","line":1163,"in_reply_to":"ba5da102_9f4a94ab","updated":"2016-11-16 19:38:29.000000000","message":"I\u0027d like to still allow the option for driver developers, since some drivers are meant to work well with specific hardware types. This will probably be more useful once driver composition reform happens.\n\nAlso, this can be used with an IPA hardware manager as well. The only thing needed for that is to set the value of \"timeout\" in the clean step dict. I will have a follow up patch to add documentation about this to IPA.","commit_id":"593a9c9862037ccf2ebfd67b4c4f7e822c9b8008"}]}
