)]}'
{"/COMMIT_MSG":[{"author":{"_account_id":6873,"name":"Matt Riedemann","email":"mriedem.os@gmail.com","username":"mriedem"},"change_message_id":"18a40d188b39b5a210f70fcdd7e7268483727b50","unresolved":false,"context_lines":[{"line_number":8,"context_line":""},{"line_number":9,"context_line":"When shelving a server and saving its new SHELVING task state, we"},{"line_number":10,"context_line":"expect the current the task state to be None and do not handle any"},{"line_number":11,"context_line":"UnexpectedTaskStateError exceptions that the database layer may throw"},{"line_number":12,"context_line":"at us. In those cases, we return an error 500 to the user, when in"},{"line_number":13,"context_line":"actuality an error 409 conflict would be more appropriate. This"},{"line_number":14,"context_line":"patches makes the API layer handle UnexpectedTaskStateError exceptions"}],"source_content_type":"text/x-gerrit-commit-message","patch_set":1,"id":"3fa7e38b_e2ef6a1a","line":11,"updated":"2019-10-30 18:34:05.000000000","message":"So you\u0027re asserting that between this check:\n\nhttps://github.com/openstack/nova/blob/f33f8c2ba21dec59a460c4cce19559cd2996c791/nova/compute/api.py#L3666\n\nWhere task_state must be None:\n\nhttps://github.com/openstack/nova/blob/f33f8c2ba21dec59a460c4cce19559cd2996c791/nova/compute/api.py#L115\n\nAnd this call to update the task_state:\n\nhttps://github.com/openstack/nova/blob/f33f8c2ba21dec59a460c4cce19559cd2996c791/nova/compute/api.py#L3675\n\nThe task_state is changing? It\u0027s possible, but a super tight window. Also, it would be extremely pervasive in all of our APIs - and some are a lot worse, meaning they set save the instance task_state after doing other stuff, e.g.:\n\nhttps://github.com/openstack/nova/blob/f33f8c2ba21dec59a460c4cce19559cd2996c791/nova/compute/api.py#L3695\n\nhttps://github.com/openstack/nova/blob/f33f8c2ba21dec59a460c4cce19559cd2996c791/nova/compute/api.py#L3634\n\nhttps://github.com/openstack/nova/blob/f33f8c2ba21dec59a460c4cce19559cd2996c791/nova/compute/api.py#L3348","commit_id":"0c0ef6801027b909c78b75e0eeddcf57d6158589"},{"author":{"_account_id":8864,"name":"Artom Lifshitz","email":"notartom@gmail.com","username":"artom"},"change_message_id":"fbf5604685c86eaf0c35e5da37e64c8619a27690","unresolved":false,"context_lines":[{"line_number":8,"context_line":""},{"line_number":9,"context_line":"When shelving a server and saving its new SHELVING task state, we"},{"line_number":10,"context_line":"expect the current the task state to be None and do not handle any"},{"line_number":11,"context_line":"UnexpectedTaskStateError exceptions that the database layer may throw"},{"line_number":12,"context_line":"at us. In those cases, we return an error 500 to the user, when in"},{"line_number":13,"context_line":"actuality an error 409 conflict would be more appropriate. This"},{"line_number":14,"context_line":"patches makes the API layer handle UnexpectedTaskStateError exceptions"}],"source_content_type":"text/x-gerrit-commit-message","patch_set":1,"id":"3fa7e38b_42099eda","line":11,"in_reply_to":"3fa7e38b_e2ef6a1a","updated":"2019-10-30 18:41:37.000000000","message":"\u003e So you\u0027re asserting that between this check:\n \u003e \n \u003e https://github.com/openstack/nova/blob/f33f8c2ba21dec59a460c4cce19559cd2996c791/nova/compute/api.py#L3666\n \u003e \n \u003e Where task_state must be None:\n \u003e \n \u003e https://github.com/openstack/nova/blob/f33f8c2ba21dec59a460c4cce19559cd2996c791/nova/compute/api.py#L115\n \u003e \n \u003e And this call to update the task_state:\n \u003e \n \u003e https://github.com/openstack/nova/blob/f33f8c2ba21dec59a460c4cce19559cd2996c791/nova/compute/api.py#L3675\n \u003e \n \u003e The task_state is changing? It\u0027s possible, but a super tight\n \u003e window.\n\nI hadn\u0027t actually paid attention to the details of check_instance_state, I thought it was just checking VM states, not task states. And yeah, I agree with everything you said. The customer who reported this was doing artificial testing for another bug (https://bugs.launchpad.net/nova/+bug/1821373), so they were hammering the shelve API pretty intensely from multiple clients.\n\n \u003e Also, it would be extremely pervasive in all of our APIs -\n \u003e and some are a lot worse, meaning they set save the instance\n \u003e task_state after doing other stuff, e.g.:\n \u003e \n \u003e https://github.com/openstack/nova/blob/f33f8c2ba21dec59a460c4cce19559cd2996c791/nova/compute/api.py#L3695\n \u003e \n \u003e https://github.com/openstack/nova/blob/f33f8c2ba21dec59a460c4cce19559cd2996c791/nova/compute/api.py#L3634\n \u003e \n \u003e https://github.com/openstack/nova/blob/f33f8c2ba21dec59a460c4cce19559cd2996c791/nova/compute/api.py#L3348\n\nI guess if no one is complaining, no one is hitting that? As you said, pretty small window, and as I said, artificial testing for a related thing.","commit_id":"0c0ef6801027b909c78b75e0eeddcf57d6158589"},{"author":{"_account_id":6873,"name":"Matt Riedemann","email":"mriedem.os@gmail.com","username":"mriedem"},"change_message_id":"d79a24425527ef7cf33bb6464f77476d9f251ddd","unresolved":false,"context_lines":[{"line_number":7,"context_line":"Avoid error 500 on shelve task_state race"},{"line_number":8,"context_line":""},{"line_number":9,"context_line":"When shelving a server and saving its new SHELVING task state, we"},{"line_number":10,"context_line":"expect the current the task state to be None and do not handle any"},{"line_number":11,"context_line":"UnexpectedTaskStateError exceptions that the database layer may throw"},{"line_number":12,"context_line":"at us. In those cases, we return an error 500 to the user, when in"},{"line_number":13,"context_line":"actuality an error 409 conflict would be more appropriate. This"}],"source_content_type":"text/x-gerrit-commit-message","patch_set":2,"id":"3fa7e38b_c59358a2","line":10,"range":{"start_line":10,"start_character":19,"end_line":10,"end_character":22},"updated":"2019-10-30 19:49:09.000000000","message":"nix","commit_id":"6ccf65c74d5a0f4b51ff2b14ab8274ff582c3258"},{"author":{"_account_id":6873,"name":"Matt Riedemann","email":"mriedem.os@gmail.com","username":"mriedem"},"change_message_id":"64fa428ba6672d348a18c062842ccabcce993300","unresolved":false,"context_lines":[{"line_number":7,"context_line":"Avoid error 500 on shelve task_state race"},{"line_number":8,"context_line":""},{"line_number":9,"context_line":"When shelving a server and saving its new SHELVING task state, we"},{"line_number":10,"context_line":"expect the current the task state to be None and do not handle any"},{"line_number":11,"context_line":"UnexpectedTaskStateError exceptions that the database layer may throw"},{"line_number":12,"context_line":"at us. In those cases, we return an error 500 to the user, when in"},{"line_number":13,"context_line":"actuality an error 409 conflict would be more appropriate. This"}],"source_content_type":"text/x-gerrit-commit-message","patch_set":2,"id":"3fa7e38b_85fa40b7","line":10,"range":{"start_line":10,"start_character":19,"end_line":10,"end_character":22},"in_reply_to":"3fa7e38b_c59358a2","updated":"2019-10-30 19:57:40.000000000","message":"Done","commit_id":"6ccf65c74d5a0f4b51ff2b14ab8274ff582c3258"},{"author":{"_account_id":6873,"name":"Matt Riedemann","email":"mriedem.os@gmail.com","username":"mriedem"},"change_message_id":"d79a24425527ef7cf33bb6464f77476d9f251ddd","unresolved":false,"context_lines":[{"line_number":11,"context_line":"UnexpectedTaskStateError exceptions that the database layer may throw"},{"line_number":12,"context_line":"at us. In those cases, we return an error 500 to the user, when in"},{"line_number":13,"context_line":"actuality an error 409 conflict would be more appropriate. This"},{"line_number":14,"context_line":"patches makes the API layer handle UnexpectedTaskStateError exceptions"},{"line_number":15,"context_line":"and return a 409 to the user."},{"line_number":16,"context_line":""},{"line_number":17,"context_line":"Closes-bug: 1850694"}],"source_content_type":"text/x-gerrit-commit-message","patch_set":2,"id":"3fa7e38b_658e247a","line":14,"range":{"start_line":14,"start_character":0,"end_line":14,"end_character":7},"updated":"2019-10-30 19:49:09.000000000","message":"patch","commit_id":"6ccf65c74d5a0f4b51ff2b14ab8274ff582c3258"},{"author":{"_account_id":6873,"name":"Matt Riedemann","email":"mriedem.os@gmail.com","username":"mriedem"},"change_message_id":"64fa428ba6672d348a18c062842ccabcce993300","unresolved":false,"context_lines":[{"line_number":11,"context_line":"UnexpectedTaskStateError exceptions that the database layer may throw"},{"line_number":12,"context_line":"at us. In those cases, we return an error 500 to the user, when in"},{"line_number":13,"context_line":"actuality an error 409 conflict would be more appropriate. This"},{"line_number":14,"context_line":"patches makes the API layer handle UnexpectedTaskStateError exceptions"},{"line_number":15,"context_line":"and return a 409 to the user."},{"line_number":16,"context_line":""},{"line_number":17,"context_line":"Closes-bug: 1850694"}],"source_content_type":"text/x-gerrit-commit-message","patch_set":2,"id":"3fa7e38b_252fcc3f","line":14,"range":{"start_line":14,"start_character":0,"end_line":14,"end_character":7},"in_reply_to":"3fa7e38b_658e247a","updated":"2019-10-30 19:57:40.000000000","message":"Done","commit_id":"6ccf65c74d5a0f4b51ff2b14ab8274ff582c3258"}],"nova/api/openstack/compute/shelve.py":[{"author":{"_account_id":6873,"name":"Matt Riedemann","email":"mriedem.os@gmail.com","username":"mriedem"},"change_message_id":"225c62742607e532a989ce23045a0b33914191e7","unresolved":false,"context_lines":[{"line_number":42,"context_line":"        \"\"\"Move an instance into shelved mode.\"\"\""},{"line_number":43,"context_line":"        context \u003d req.environ[\"nova.context\"]"},{"line_number":44,"context_line":""},{"line_number":45,"context_line":"        instance \u003d common.get_instance(self.compute_api, context, id)"},{"line_number":46,"context_line":"        context.can(shelve_policies.POLICY_ROOT % \u0027shelve\u0027,"},{"line_number":47,"context_line":"                    target\u003d{\u0027user_id\u0027: instance.user_id,"},{"line_number":48,"context_line":"                            \u0027project_id\u0027: instance.project_id})"}],"source_content_type":"text/x-python","patch_set":1,"id":"3fa7e38b_c246ee21","line":45,"updated":"2019-10-30 18:37:48.000000000","message":"Considering the race window, it\u0027s possible that task_state is None when we fetch the instance here but concurrently shelved and changed the task_state before calling self.compute_api.shelve, check_instance_state would be checking a stale copy of the instance from the DB.","commit_id":"0c0ef6801027b909c78b75e0eeddcf57d6158589"},{"author":{"_account_id":6873,"name":"Matt Riedemann","email":"mriedem.os@gmail.com","username":"mriedem"},"change_message_id":"d0f9511d7f09ccb2f82a4945224c546eae6224cd","unresolved":false,"context_lines":[{"line_number":51,"context_line":"        except (exception.InstanceIsLocked,"},{"line_number":52,"context_line":"                exception.UnexpectedTaskStateError) as e:"},{"line_number":53,"context_line":"            raise exc.HTTPConflict(explanation\u003de.format_message())"},{"line_number":54,"context_line":"        except exception.InstanceInvalidState as state_error:"},{"line_number":55,"context_line":"            common.raise_http_conflict_for_instance_invalid_state(state_error,"},{"line_number":56,"context_line":"                                                                  \u0027shelve\u0027, id)"},{"line_number":57,"context_line":""}],"source_content_type":"text/x-python","patch_set":1,"id":"3fa7e38b_42643eb9","line":54,"updated":"2019-10-30 18:38:37.000000000","message":"Your test is probably hitting this because your fake instance object isn\u0027t using a valid vm_state or task_state\u003dNone value for the shelve action.","commit_id":"0c0ef6801027b909c78b75e0eeddcf57d6158589"},{"author":{"_account_id":8864,"name":"Artom Lifshitz","email":"notartom@gmail.com","username":"artom"},"change_message_id":"c81e75fd4fa8160418c4bfad6eed516922789e12","unresolved":false,"context_lines":[{"line_number":51,"context_line":"        except (exception.InstanceIsLocked,"},{"line_number":52,"context_line":"                exception.UnexpectedTaskStateError) as e:"},{"line_number":53,"context_line":"            raise exc.HTTPConflict(explanation\u003de.format_message())"},{"line_number":54,"context_line":"        except exception.InstanceInvalidState as state_error:"},{"line_number":55,"context_line":"            common.raise_http_conflict_for_instance_invalid_state(state_error,"},{"line_number":56,"context_line":"                                                                  \u0027shelve\u0027, id)"},{"line_number":57,"context_line":""}],"source_content_type":"text/x-python","patch_set":1,"id":"3fa7e38b_828a36b9","line":54,"in_reply_to":"3fa7e38b_42643eb9","updated":"2019-10-30 19:19:59.000000000","message":"Yep, and launched_at needs to be set as well. Fixed.","commit_id":"0c0ef6801027b909c78b75e0eeddcf57d6158589"},{"author":{"_account_id":11604,"name":"sean mooney","email":"smooney@redhat.com","username":"sean-k-mooney"},"change_message_id":"21796a11ac585111814f03614fb4b83d7e0c1af3","unresolved":false,"context_lines":[{"line_number":49,"context_line":"        try:"},{"line_number":50,"context_line":"            self.compute_api.shelve(context, instance)"},{"line_number":51,"context_line":"        except (exception.InstanceIsLocked,"},{"line_number":52,"context_line":"                exception.UnexpectedTaskStateError) as e:"},{"line_number":53,"context_line":"            raise exc.HTTPConflict(explanation\u003de.format_message())"},{"line_number":54,"context_line":"        except exception.InstanceInvalidState as state_error:"},{"line_number":55,"context_line":"            common.raise_http_conflict_for_instance_invalid_state(state_error,"}],"source_content_type":"text/x-python","patch_set":3,"id":"3fa7e38b_0bb661fa","line":52,"range":{"start_line":52,"start_character":26,"end_line":52,"end_character":50},"updated":"2019-10-30 23:13:25.000000000","message":"we could also  set\n code \u003d 409\nhere https://github.com/openstack/nova/blob/50223cae9e6bf5dcac32bcbc83d31afb61f1bbcd/nova/exception.py#L1593\n\nwhich will prevent the  @wsgi.expected_errors((404, 409))\ndecorator converting it to a 500\n\nhttps://github.com/openstack/nova/blob/27e88f6a66e544060492d008c27bc8e1f5949dba/nova/api/openstack/wsgi.py#L660-L707\n\nim not sure if that would be all that would be required but i think it would have the same effect and just work in any other case where we dont catch exception.UnexpectedTaskStateError","commit_id":"a423d8b27785623550f401a200b68ca926c0a119"},{"author":{"_account_id":8864,"name":"Artom Lifshitz","email":"notartom@gmail.com","username":"artom"},"change_message_id":"d2bd04b1472576b216f7ddbd24fdcb80dc889f8f","unresolved":false,"context_lines":[{"line_number":49,"context_line":"        try:"},{"line_number":50,"context_line":"            self.compute_api.shelve(context, instance)"},{"line_number":51,"context_line":"        except (exception.InstanceIsLocked,"},{"line_number":52,"context_line":"                exception.UnexpectedTaskStateError) as e:"},{"line_number":53,"context_line":"            raise exc.HTTPConflict(explanation\u003de.format_message())"},{"line_number":54,"context_line":"        except exception.InstanceInvalidState as state_error:"},{"line_number":55,"context_line":"            common.raise_http_conflict_for_instance_invalid_state(state_error,"}],"source_content_type":"text/x-python","patch_set":3,"id":"3fa7e38b_abd14dfd","line":52,"range":{"start_line":52,"start_character":26,"end_line":52,"end_character":50},"in_reply_to":"3fa7e38b_0bb661fa","updated":"2019-10-30 23:32:09.000000000","message":"I like this, but I\u0027m also slightly (perhaps needlessly) afraid of such a sweeping change.","commit_id":"a423d8b27785623550f401a200b68ca926c0a119"},{"author":{"_account_id":6873,"name":"Matt Riedemann","email":"mriedem.os@gmail.com","username":"mriedem"},"change_message_id":"f6b588168a3baabf72ff42e7a7f3c2566a4d518d","unresolved":false,"context_lines":[{"line_number":49,"context_line":"        try:"},{"line_number":50,"context_line":"            self.compute_api.shelve(context, instance)"},{"line_number":51,"context_line":"        except (exception.InstanceIsLocked,"},{"line_number":52,"context_line":"                exception.UnexpectedTaskStateError) as e:"},{"line_number":53,"context_line":"            raise exc.HTTPConflict(explanation\u003de.format_message())"},{"line_number":54,"context_line":"        except exception.InstanceInvalidState as state_error:"},{"line_number":55,"context_line":"            common.raise_http_conflict_for_instance_invalid_state(state_error,"}],"source_content_type":"text/x-python","patch_set":3,"id":"3fa7e38b_d2f9d1c7","line":52,"range":{"start_line":52,"start_character":26,"end_line":52,"end_character":50},"in_reply_to":"3fa7e38b_1900f465","updated":"2019-10-31 13:38:18.000000000","message":"UnexpectedTaskStateError doesn\u0027t extend WSGIHTTPException so you won\u0027t get here:\n\nhttps://github.com/openstack/nova/blob/27e88f6a66e544060492d008c27bc8e1f5949dba/nova/api/openstack/wsgi.py#L678","commit_id":"a423d8b27785623550f401a200b68ca926c0a119"},{"author":{"_account_id":7166,"name":"Sylvain Bauza","email":"sbauza@redhat.com","username":"sbauza"},"change_message_id":"4bc1db8f3a960cdba9eb2814fd40c2b63140bddf","unresolved":false,"context_lines":[{"line_number":49,"context_line":"        try:"},{"line_number":50,"context_line":"            self.compute_api.shelve(context, instance)"},{"line_number":51,"context_line":"        except (exception.InstanceIsLocked,"},{"line_number":52,"context_line":"                exception.UnexpectedTaskStateError) as e:"},{"line_number":53,"context_line":"            raise exc.HTTPConflict(explanation\u003de.format_message())"},{"line_number":54,"context_line":"        except exception.InstanceInvalidState as state_error:"},{"line_number":55,"context_line":"            common.raise_http_conflict_for_instance_invalid_state(state_error,"}],"source_content_type":"text/x-python","patch_set":3,"id":"3fa7e38b_1900f465","line":52,"range":{"start_line":52,"start_character":26,"end_line":52,"end_character":50},"in_reply_to":"3fa7e38b_abd14dfd","updated":"2019-10-31 10:32:10.000000000","message":"I tend to prefer this simpliest solution.","commit_id":"a423d8b27785623550f401a200b68ca926c0a119"}],"nova/tests/unit/api/openstack/compute/test_shelve.py":[{"author":{"_account_id":6873,"name":"Matt Riedemann","email":"mriedem.os@gmail.com","username":"mriedem"},"change_message_id":"d79a24425527ef7cf33bb6464f77476d9f251ddd","unresolved":false,"context_lines":[{"line_number":51,"context_line":"    @mock.patch(\u0027nova.objects.instance.Instance.save\u0027)"},{"line_number":52,"context_line":"    def test_shelve_task_state_race(self, mock_save, get_instance_mock):"},{"line_number":53,"context_line":"        instance \u003d fake_instance.fake_instance_obj("},{"line_number":54,"context_line":"            self.req.environ[\u0027nova.context\u0027], launch\u003dTrue,"},{"line_number":55,"context_line":"            vm_state\u003dvm_states.ACTIVE, task_state\u003dNone)"},{"line_number":56,"context_line":"        get_instance_mock.return_value \u003d instance"},{"line_number":57,"context_line":"        mock_save.side_effect \u003d exception.UnexpectedTaskStateError("}],"source_content_type":"text/x-python","patch_set":2,"id":"3fa7e38b_45ed2823","line":54,"range":{"start_line":54,"start_character":46,"end_line":54,"end_character":52},"updated":"2019-10-30 19:49:09.000000000","message":"This isn\u0027t a real field on Instance, I think you mean launched_at.","commit_id":"6ccf65c74d5a0f4b51ff2b14ab8274ff582c3258"},{"author":{"_account_id":6873,"name":"Matt Riedemann","email":"mriedem.os@gmail.com","username":"mriedem"},"change_message_id":"64fa428ba6672d348a18c062842ccabcce993300","unresolved":false,"context_lines":[{"line_number":51,"context_line":"    @mock.patch(\u0027nova.objects.instance.Instance.save\u0027)"},{"line_number":52,"context_line":"    def test_shelve_task_state_race(self, mock_save, get_instance_mock):"},{"line_number":53,"context_line":"        instance \u003d fake_instance.fake_instance_obj("},{"line_number":54,"context_line":"            self.req.environ[\u0027nova.context\u0027], launch\u003dTrue,"},{"line_number":55,"context_line":"            vm_state\u003dvm_states.ACTIVE, task_state\u003dNone)"},{"line_number":56,"context_line":"        get_instance_mock.return_value \u003d instance"},{"line_number":57,"context_line":"        mock_save.side_effect \u003d exception.UnexpectedTaskStateError("}],"source_content_type":"text/x-python","patch_set":2,"id":"3fa7e38b_453208a9","line":54,"range":{"start_line":54,"start_character":46,"end_line":54,"end_character":52},"in_reply_to":"3fa7e38b_45ed2823","updated":"2019-10-30 19:57:40.000000000","message":"Done","commit_id":"6ccf65c74d5a0f4b51ff2b14ab8274ff582c3258"},{"author":{"_account_id":6873,"name":"Matt Riedemann","email":"mriedem.os@gmail.com","username":"mriedem"},"change_message_id":"3660ec71b3cc15a64d42a61b49541b90cabcec14","unresolved":false,"context_lines":[{"line_number":57,"context_line":"        mock_save.side_effect \u003d exception.UnexpectedTaskStateError("},{"line_number":58,"context_line":"            instance_uuid\u003dinstance.uuid, expected\u003dNone,"},{"line_number":59,"context_line":"            actual\u003dtask_states.SHELVING)"},{"line_number":60,"context_line":"        self.assertRaises(webob.exc.HTTPConflict, self.controller._shelve,"},{"line_number":61,"context_line":"                          self.req, uuidsentinel.fake, body\u003d{\u0027shelve\u0027: {}})"},{"line_number":62,"context_line":"        mock_save.assert_called_once_with(expected_task_state\u003d[None])"},{"line_number":63,"context_line":""}],"source_content_type":"text/x-python","patch_set":2,"id":"3fa7e38b_c546f821","line":60,"updated":"2019-10-30 19:54:27.000000000","message":"You could avoid the issues you had before in this test by asserting the error message is what you\u0027d expect from UnexpectedTaskStateError.","commit_id":"6ccf65c74d5a0f4b51ff2b14ab8274ff582c3258"},{"author":{"_account_id":6873,"name":"Matt Riedemann","email":"mriedem.os@gmail.com","username":"mriedem"},"change_message_id":"64fa428ba6672d348a18c062842ccabcce993300","unresolved":false,"context_lines":[{"line_number":57,"context_line":"        mock_save.side_effect \u003d exception.UnexpectedTaskStateError("},{"line_number":58,"context_line":"            instance_uuid\u003dinstance.uuid, expected\u003dNone,"},{"line_number":59,"context_line":"            actual\u003dtask_states.SHELVING)"},{"line_number":60,"context_line":"        self.assertRaises(webob.exc.HTTPConflict, self.controller._shelve,"},{"line_number":61,"context_line":"                          self.req, uuidsentinel.fake, body\u003d{\u0027shelve\u0027: {}})"},{"line_number":62,"context_line":"        mock_save.assert_called_once_with(expected_task_state\u003d[None])"},{"line_number":63,"context_line":""}],"source_content_type":"text/x-python","patch_set":2,"id":"3fa7e38b_05289030","line":60,"in_reply_to":"3fa7e38b_c546f821","updated":"2019-10-30 19:57:40.000000000","message":"Done","commit_id":"6ccf65c74d5a0f4b51ff2b14ab8274ff582c3258"}],"nova/tests/unit/fake_instance.py":[{"author":{"_account_id":6873,"name":"Matt Riedemann","email":"mriedem.os@gmail.com","username":"mriedem"},"change_message_id":"6a16ee55daf703aafe86bbc72cf44fdec50eb97d","unresolved":false,"context_lines":[{"line_number":103,"context_line":"    return db_instance"},{"line_number":104,"context_line":""},{"line_number":105,"context_line":""},{"line_number":106,"context_line":"def fake_instance_obj(context, obj_instance_class\u003dNone, launch\u003dFalse,"},{"line_number":107,"context_line":"                      **updates):"},{"line_number":108,"context_line":"    if obj_instance_class is None:"},{"line_number":109,"context_line":"        obj_instance_class \u003d objects.Instance"}],"source_content_type":"text/x-python","patch_set":2,"id":"3fa7e38b_85dec067","line":106,"range":{"start_line":106,"start_character":56,"end_line":106,"end_character":69},"updated":"2019-10-30 19:49:42.000000000","message":"We don\u0027t need this, you can just specify launched_at in **updates.","commit_id":"6ccf65c74d5a0f4b51ff2b14ab8274ff582c3258"},{"author":{"_account_id":6873,"name":"Matt Riedemann","email":"mriedem.os@gmail.com","username":"mriedem"},"change_message_id":"64fa428ba6672d348a18c062842ccabcce993300","unresolved":false,"context_lines":[{"line_number":103,"context_line":"    return db_instance"},{"line_number":104,"context_line":""},{"line_number":105,"context_line":""},{"line_number":106,"context_line":"def fake_instance_obj(context, obj_instance_class\u003dNone, launch\u003dFalse,"},{"line_number":107,"context_line":"                      **updates):"},{"line_number":108,"context_line":"    if obj_instance_class is None:"},{"line_number":109,"context_line":"        obj_instance_class \u003d objects.Instance"}],"source_content_type":"text/x-python","patch_set":2,"id":"3fa7e38b_c51d980f","line":106,"range":{"start_line":106,"start_character":56,"end_line":106,"end_character":69},"in_reply_to":"3fa7e38b_85dec067","updated":"2019-10-30 19:57:40.000000000","message":"Done","commit_id":"6ccf65c74d5a0f4b51ff2b14ab8274ff582c3258"},{"author":{"_account_id":8864,"name":"Artom Lifshitz","email":"notartom@gmail.com","username":"artom"},"change_message_id":"b0d9582456f843a1d0b2ccb69d6352eba3989fac","unresolved":false,"context_lines":[{"line_number":103,"context_line":"    return db_instance"},{"line_number":104,"context_line":""},{"line_number":105,"context_line":""},{"line_number":106,"context_line":"def fake_instance_obj(context, obj_instance_class\u003dNone, launch\u003dFalse,"},{"line_number":107,"context_line":"                      **updates):"},{"line_number":108,"context_line":"    if obj_instance_class is None:"},{"line_number":109,"context_line":"        obj_instance_class \u003d objects.Instance"}],"source_content_type":"text/x-python","patch_set":2,"id":"3fa7e38b_0584100a","line":106,"in_reply_to":"3fa7e38b_c51d980f","updated":"2019-10-30 20:03:02.000000000","message":"Yeah, I thought I\u0027d do an extra bit of abstraction to avoid the datetime import. Clearly I was overthinking this.","commit_id":"6ccf65c74d5a0f4b51ff2b14ab8274ff582c3258"}]}
