)]}'
{"/COMMIT_MSG":[{"author":{"_account_id":9303,"name":"Abhishek Kekane","email":"akekane@redhat.com","username":"abhishekkekane"},"change_message_id":"8eb4e8a598a5beff662f11b624df9a02d9d03744","unresolved":false,"context_lines":[{"line_number":9,"context_line":"Cinder API.create_snapshot command was reimplemented to"},{"line_number":10,"context_line":"work with TaskFlow 0.1."},{"line_number":11,"context_line":""},{"line_number":12,"context_line":"Change-Id: I86c173cb9c406c876011707eed0e00b5e9a387a9"}],"source_content_type":"text/x-gerrit-commit-message","patch_set":6,"id":"AAAATn%2F%2FB40%3D","line":12,"updated":"2013-11-15 13:03:11.000000000","message":"Could you please add blueprint or bug reference in commit message.","commit_id":"f4124881fc91075662d20be44bbe4d3c662504c1"}],"cinder/volume/flows/create_snapshot.py":[{"author":{"_account_id":7349,"name":"Anastasia Karpinska","email":"akarpinska@griddynamics.com","username":"anastasia-karpinska"},"change_message_id":"e18d9b4bc79851f310293a554da829153e22f3f4","unresolved":false,"context_lines":[{"line_number":134,"context_line":"        return snapshot"},{"line_number":135,"context_line":""},{"line_number":136,"context_line":"    def revert(self, context, volume, **kwargs):"},{"line_number":137,"context_line":"        self.db.snapshot_destroy(context, volume[\u0027id\u0027])"},{"line_number":138,"context_line":""},{"line_number":139,"context_line":""},{"line_number":140,"context_line":"class VolumeCreateSnapshotTask(flow_base.CinderTask):"}],"source_content_type":"text/x-python","patch_set":1,"id":"AAAATn%2F%2Ff9E%3D","line":137,"updated":"2013-11-04 11:07:20.000000000","message":"self._db","commit_id":"43a112fbaf3df4ea37369fdc58e66f46540d02a4"},{"author":{"_account_id":7366,"name":"Ivan Melnikov","email":"imelnikov@griddynamics.com","username":"imelnikov"},"change_message_id":"788a3ea4d5c3356dc4baddd820d663f0f9e5548c","unresolved":false,"context_lines":[{"line_number":61,"context_line":"            provides\u003d(\u0027volume_id\u0027, \u0027volume_type_id\u0027, \u0027size\u0027),"},{"line_number":62,"context_line":"            **kwargs)"},{"line_number":63,"context_line":""},{"line_number":64,"context_line":"    def execute(self, volume):"},{"line_number":65,"context_line":"        return volume[\u0027id\u0027], volume[\u0027volume_type_id\u0027], volume[\u0027size\u0027]"},{"line_number":66,"context_line":""},{"line_number":67,"context_line":""}],"source_content_type":"text/x-python","patch_set":2,"id":"AAAATn%2F%2Ffz8%3D","line":64,"updated":"2013-11-04 13:53:10.000000000","message":"Do we really need this task? Can\u0027t we just use volume[\u0027id\u0027] later? Or extract values from volume in flow factory function?\n\nBTW, as far as I can see, you don\u0027t use this task results anywhere in the flow.","commit_id":"ef61064a8df106ad21df23f52e663fef25454573"},{"author":{"_account_id":8895,"name":"Stanislav Kudriashev","email":"stas.kudriashev@gmail.com","username":"skudriashev"},"change_message_id":"a14482a5e25ac56091c029e17c5c5a4a71ec76b1","unresolved":false,"context_lines":[{"line_number":61,"context_line":"            provides\u003d(\u0027volume_id\u0027, \u0027volume_type_id\u0027, \u0027size\u0027),"},{"line_number":62,"context_line":"            **kwargs)"},{"line_number":63,"context_line":""},{"line_number":64,"context_line":"    def execute(self, volume):"},{"line_number":65,"context_line":"        return volume[\u0027id\u0027], volume[\u0027volume_type_id\u0027], volume[\u0027size\u0027]"},{"line_number":66,"context_line":""},{"line_number":67,"context_line":""}],"source_content_type":"text/x-python","patch_set":2,"id":"AAAATn%2F%2FflU%3D","line":64,"in_reply_to":"AAAATn%2F%2Ffxs%3D","updated":"2013-11-04 15:58:39.000000000","message":"Done","commit_id":"ef61064a8df106ad21df23f52e663fef25454573"},{"author":{"_account_id":8895,"name":"Stanislav Kudriashev","email":"stas.kudriashev@gmail.com","username":"skudriashev"},"change_message_id":"061d2b6d18a12ffe48dd49a38373527abfbfb13d","unresolved":false,"context_lines":[{"line_number":61,"context_line":"            provides\u003d(\u0027volume_id\u0027, \u0027volume_type_id\u0027, \u0027size\u0027),"},{"line_number":62,"context_line":"            **kwargs)"},{"line_number":63,"context_line":""},{"line_number":64,"context_line":"    def execute(self, volume):"},{"line_number":65,"context_line":"        return volume[\u0027id\u0027], volume[\u0027volume_type_id\u0027], volume[\u0027size\u0027]"},{"line_number":66,"context_line":""},{"line_number":67,"context_line":""}],"source_content_type":"text/x-python","patch_set":2,"id":"AAAATn%2F%2Ffxs%3D","line":64,"in_reply_to":"AAAATn%2F%2Ffz8%3D","updated":"2013-11-04 14:19:19.000000000","message":"This task is needed for common.QuotaReserveTask and common.QuotaCommitTask tasks that don\u0027t accept volume, but only these separate parameters.","commit_id":"ef61064a8df106ad21df23f52e663fef25454573"},{"author":{"_account_id":7366,"name":"Ivan Melnikov","email":"imelnikov@griddynamics.com","username":"imelnikov"},"change_message_id":"788a3ea4d5c3356dc4baddd820d663f0f9e5548c","unresolved":false,"context_lines":[{"line_number":68,"context_line":"class QuotaReserveOptsTask(flow_base.CinderTask):"},{"line_number":69,"context_line":""},{"line_number":70,"context_line":"    def __init__(self, **kwargs):"},{"line_number":71,"context_line":"        super(QuotaReserveOptsTask, self).__init__(provides\u003d\"reserve_opts\","},{"line_number":72,"context_line":"                                                   **kwargs)"},{"line_number":73,"context_line":""},{"line_number":74,"context_line":"    def execute(self, volume):"}],"source_content_type":"text/x-python","patch_set":2,"id":"AAAATn%2F%2Ffzk%3D","line":71,"updated":"2013-11-04 13:53:10.000000000","message":"I think it\u0027s better to use default_provides here and in similar situations. Redefining provides this way prevents flow author to change provides of the task. Worse, code like\n\n  QuotaReserveOptsTask(provides\u003d\"renamed_reserve_opts\")\n\nwill fail with TypeError.","commit_id":"ef61064a8df106ad21df23f52e663fef25454573"},{"author":{"_account_id":8895,"name":"Stanislav Kudriashev","email":"stas.kudriashev@gmail.com","username":"skudriashev"},"change_message_id":"a14482a5e25ac56091c029e17c5c5a4a71ec76b1","unresolved":false,"context_lines":[{"line_number":68,"context_line":"class QuotaReserveOptsTask(flow_base.CinderTask):"},{"line_number":69,"context_line":""},{"line_number":70,"context_line":"    def __init__(self, **kwargs):"},{"line_number":71,"context_line":"        super(QuotaReserveOptsTask, self).__init__(provides\u003d\"reserve_opts\","},{"line_number":72,"context_line":"                                                   **kwargs)"},{"line_number":73,"context_line":""},{"line_number":74,"context_line":"    def execute(self, volume):"}],"source_content_type":"text/x-python","patch_set":2,"id":"AAAATn%2F%2Ffk0%3D","line":71,"in_reply_to":"AAAATn%2F%2Ffzk%3D","updated":"2013-11-04 15:58:39.000000000","message":"Done","commit_id":"ef61064a8df106ad21df23f52e663fef25454573"},{"author":{"_account_id":7366,"name":"Ivan Melnikov","email":"imelnikov@griddynamics.com","username":"imelnikov"},"change_message_id":"788a3ea4d5c3356dc4baddd820d663f0f9e5548c","unresolved":false,"context_lines":[{"line_number":71,"context_line":"        super(QuotaReserveOptsTask, self).__init__(provides\u003d\"reserve_opts\","},{"line_number":72,"context_line":"                                                   **kwargs)"},{"line_number":73,"context_line":""},{"line_number":74,"context_line":"    def execute(self, volume):"},{"line_number":75,"context_line":"        reserve_opts \u003d {\u0027snapshots\u0027: 1}"},{"line_number":76,"context_line":"        if not CONF.no_snapshot_gb_quota:"},{"line_number":77,"context_line":"            reserve_opts.update({\u0027gigabytes\u0027: volume[\u0027size\u0027]})"}],"source_content_type":"text/x-python","patch_set":2,"id":"AAAATn%2F%2FfzE%3D","line":74,"updated":"2013-11-04 13:53:10.000000000","message":"Same question as with ExtractVolumeTask above: should this *really* be a separate task?","commit_id":"ef61064a8df106ad21df23f52e663fef25454573"},{"author":{"_account_id":8895,"name":"Stanislav Kudriashev","email":"stas.kudriashev@gmail.com","username":"skudriashev"},"change_message_id":"a14482a5e25ac56091c029e17c5c5a4a71ec76b1","unresolved":false,"context_lines":[{"line_number":71,"context_line":"        super(QuotaReserveOptsTask, self).__init__(provides\u003d\"reserve_opts\","},{"line_number":72,"context_line":"                                                   **kwargs)"},{"line_number":73,"context_line":""},{"line_number":74,"context_line":"    def execute(self, volume):"},{"line_number":75,"context_line":"        reserve_opts \u003d {\u0027snapshots\u0027: 1}"},{"line_number":76,"context_line":"        if not CONF.no_snapshot_gb_quota:"},{"line_number":77,"context_line":"            reserve_opts.update({\u0027gigabytes\u0027: volume[\u0027size\u0027]})"}],"source_content_type":"text/x-python","patch_set":2,"id":"AAAATn%2F%2Ffmc%3D","line":74,"in_reply_to":"AAAATn%2F%2Ffxc%3D","updated":"2013-11-04 15:58:39.000000000","message":"Done","commit_id":"ef61064a8df106ad21df23f52e663fef25454573"},{"author":{"_account_id":7366,"name":"Ivan Melnikov","email":"imelnikov@griddynamics.com","username":"imelnikov"},"change_message_id":"132f8bdb461cd7ee548a67be2884c95bb90b92e9","unresolved":false,"context_lines":[{"line_number":71,"context_line":"        super(QuotaReserveOptsTask, self).__init__(provides\u003d\"reserve_opts\","},{"line_number":72,"context_line":"                                                   **kwargs)"},{"line_number":73,"context_line":""},{"line_number":74,"context_line":"    def execute(self, volume):"},{"line_number":75,"context_line":"        reserve_opts \u003d {\u0027snapshots\u0027: 1}"},{"line_number":76,"context_line":"        if not CONF.no_snapshot_gb_quota:"},{"line_number":77,"context_line":"            reserve_opts.update({\u0027gigabytes\u0027: volume[\u0027size\u0027]})"}],"source_content_type":"text/x-python","patch_set":2,"id":"AAAATn%2F%2Ffxc%3D","line":74,"in_reply_to":"AAAATn%2F%2Ffyo%3D","updated":"2013-11-04 14:09:22.000000000","message":"That\u0027s understandable, and code re-use is definitely a good thing. But I\u0027d like to consider other ways of doing it, like injecting reservation options into storage on flow creation or using inheritance instead of composition for code reuse? For this particular case the latter looks like a cleaner option to me.","commit_id":"ef61064a8df106ad21df23f52e663fef25454573"},{"author":{"_account_id":7349,"name":"Anastasia Karpinska","email":"akarpinska@griddynamics.com","username":"anastasia-karpinska"},"change_message_id":"6f1b3e01cd153790fac8ca80523dfb1bf1236b55","unresolved":false,"context_lines":[{"line_number":71,"context_line":"        super(QuotaReserveOptsTask, self).__init__(provides\u003d\"reserve_opts\","},{"line_number":72,"context_line":"                                                   **kwargs)"},{"line_number":73,"context_line":""},{"line_number":74,"context_line":"    def execute(self, volume):"},{"line_number":75,"context_line":"        reserve_opts \u003d {\u0027snapshots\u0027: 1}"},{"line_number":76,"context_line":"        if not CONF.no_snapshot_gb_quota:"},{"line_number":77,"context_line":"            reserve_opts.update({\u0027gigabytes\u0027: volume[\u0027size\u0027]})"}],"source_content_type":"text/x-python","patch_set":2,"id":"AAAATn%2F%2Ffyo%3D","line":74,"in_reply_to":"AAAATn%2F%2FfzE%3D","updated":"2013-11-04 13:57:47.000000000","message":"Different commands reserves quotas with different options. If we want to use common ReserverQuotaTask for all commands, we should create tasks for browsing reservation options.","commit_id":"ef61064a8df106ad21df23f52e663fef25454573"},{"author":{"_account_id":7366,"name":"Ivan Melnikov","email":"imelnikov@griddynamics.com","username":"imelnikov"},"change_message_id":"788a3ea4d5c3356dc4baddd820d663f0f9e5548c","unresolved":false,"context_lines":[{"line_number":78,"context_line":"        return reserve_opts"},{"line_number":79,"context_line":""},{"line_number":80,"context_line":""},{"line_number":81,"context_line":"def handle_quota_reserve_exception(e, context, size):"},{"line_number":82,"context_line":"    overs \u003d e.kwargs[\u0027overs\u0027]"},{"line_number":83,"context_line":"    usages \u003d e.kwargs[\u0027usages\u0027]"},{"line_number":84,"context_line":"    quotas \u003d e.kwargs[\u0027quotas\u0027]"}],"source_content_type":"text/x-python","patch_set":2,"id":"AAAATn%2F%2Ffzg%3D","line":81,"updated":"2013-11-04 13:53:10.000000000","message":"For this I\u0027d prefer inheritance over functional composition. Our tasks are classes, so it seems more consistent to employ object-oriented way for code reuse here.","commit_id":"ef61064a8df106ad21df23f52e663fef25454573"},{"author":{"_account_id":8895,"name":"Stanislav Kudriashev","email":"stas.kudriashev@gmail.com","username":"skudriashev"},"change_message_id":"a14482a5e25ac56091c029e17c5c5a4a71ec76b1","unresolved":false,"context_lines":[{"line_number":78,"context_line":"        return reserve_opts"},{"line_number":79,"context_line":""},{"line_number":80,"context_line":""},{"line_number":81,"context_line":"def handle_quota_reserve_exception(e, context, size):"},{"line_number":82,"context_line":"    overs \u003d e.kwargs[\u0027overs\u0027]"},{"line_number":83,"context_line":"    usages \u003d e.kwargs[\u0027usages\u0027]"},{"line_number":84,"context_line":"    quotas \u003d e.kwargs[\u0027quotas\u0027]"}],"source_content_type":"text/x-python","patch_set":2,"id":"AAAATn%2F%2FfmY%3D","line":81,"in_reply_to":"AAAATn%2F%2Ffzg%3D","updated":"2013-11-04 15:58:39.000000000","message":"Done","commit_id":"ef61064a8df106ad21df23f52e663fef25454573"}]}
