)]}'
{"nova/exception.py":[{"author":{"_account_id":6873,"name":"Matt Riedemann","email":"mriedem.os@gmail.com","username":"mriedem"},"change_message_id":"333f19281f098a41b48c7ccecd6736d18636d7c1","unresolved":false,"context_lines":[{"line_number":2096,"context_line":""},{"line_number":2097,"context_line":""},{"line_number":2098,"context_line":"class BuildRequestNotFound(NotFound):"},{"line_number":2099,"context_line":"    msg_fmt \u003d _(\"BuildRequest not found for %(uuid)s\")"}],"source_content_type":"text/x-python","patch_set":11,"id":"9aed3d3a_831f1007","line":2099,"range":{"start_line":2099,"start_character":17,"end_line":2099,"end_character":52},"updated":"2016-02-29 19:11:10.000000000","message":"If this can only happen for an instance uuid (which right now is the case), then I think it\u0027d be good to have \u0027instance\u0027 in there for context, i.e.:\n\n\"BuildRequest not found for instance %(uuid)s\"","commit_id":"a60c999a03e646ee27664cbddcf7f2021ba42487"},{"author":{"_account_id":5441,"name":"Andrew Laski","email":"andrew@lascii.com","username":"alaski"},"change_message_id":"6c2606acb9b1d3ea36989757cca43d75aa759570","unresolved":false,"context_lines":[{"line_number":2096,"context_line":""},{"line_number":2097,"context_line":""},{"line_number":2098,"context_line":"class BuildRequestNotFound(NotFound):"},{"line_number":2099,"context_line":"    msg_fmt \u003d _(\"BuildRequest not found for %(uuid)s\")"}],"source_content_type":"text/x-python","patch_set":11,"id":"9aed3d3a_2314449e","line":2099,"range":{"start_line":2099,"start_character":17,"end_line":2099,"end_character":52},"in_reply_to":"9aed3d3a_831f1007","updated":"2016-02-29 19:34:10.000000000","message":"Sure.","commit_id":"a60c999a03e646ee27664cbddcf7f2021ba42487"}],"nova/objects/build_request.py":[{"author":{"_account_id":18247,"name":"Mark Doffman","email":"mdoffman@linux.vnet.ibm.com","username":"doffm"},"change_message_id":"7b2ff7b8e8954cf72ecd11db53c67e78d2b470a8","unresolved":false,"context_lines":[{"line_number":55,"context_line":"        # mixin, however these are not metadata about the BuildRequest object"},{"line_number":56,"context_line":"        # but data about the instance to be booted.  So we explicitly add them"},{"line_number":57,"context_line":"        # here, and leave out the deleted/deleted_at fields because if this was"},{"line_number":58,"context_line":"        # deleted we would not show it."},{"line_number":59,"context_line":"        \u0027created_at\u0027: fields.DateTimeField(nullable\u003dTrue),"},{"line_number":60,"context_line":"        \u0027updated_at\u0027: fields.DateTimeField(nullable\u003dTrue),"},{"line_number":61,"context_line":"    }"}],"source_content_type":"text/x-python","patch_set":2,"id":"3a57f1b5_f320979d","line":58,"updated":"2016-02-10 20:44:07.000000000","message":"To make this completely clear shouldn\u0027t the field names be renamed to something like \u0027instance_created_at\u0027 and \u0027instance_updated_at\u0027.","commit_id":"ba8dabcf3dc4c5c90f07adffdf0206292dd96578"},{"author":{"_account_id":5441,"name":"Andrew Laski","email":"andrew@lascii.com","username":"alaski"},"change_message_id":"29425d29e301a5130cec856cd3bd941e1e1eadfa","unresolved":false,"context_lines":[{"line_number":55,"context_line":"        # mixin, however these are not metadata about the BuildRequest object"},{"line_number":56,"context_line":"        # but data about the instance to be booted.  So we explicitly add them"},{"line_number":57,"context_line":"        # here, and leave out the deleted/deleted_at fields because if this was"},{"line_number":58,"context_line":"        # deleted we would not show it."},{"line_number":59,"context_line":"        \u0027created_at\u0027: fields.DateTimeField(nullable\u003dTrue),"},{"line_number":60,"context_line":"        \u0027updated_at\u0027: fields.DateTimeField(nullable\u003dTrue),"},{"line_number":61,"context_line":"    }"}],"source_content_type":"text/x-python","patch_set":2,"id":"3a57f1b5_003d93c3","line":58,"in_reply_to":"3a57f1b5_7e9d0ebb","updated":"2016-02-11 22:06:11.000000000","message":"After making the change and thinking about this more I am leaning towards leaving these as created_at/updated_at and modifying the comment. I would like to move in the direction of a pre-instance object being an important thing in its own right and not just this thing we need to do because cells forces it. We\u0027ll probably always need to be able to synthesize this into an instance for the API, but I don\u0027t think I want to tie this to an instance representation too much.","commit_id":"ba8dabcf3dc4c5c90f07adffdf0206292dd96578"},{"author":{"_account_id":5441,"name":"Andrew Laski","email":"andrew@lascii.com","username":"alaski"},"change_message_id":"bba4138f2797b7beea4c176fcd3fce37a019005d","unresolved":false,"context_lines":[{"line_number":55,"context_line":"        # mixin, however these are not metadata about the BuildRequest object"},{"line_number":56,"context_line":"        # but data about the instance to be booted.  So we explicitly add them"},{"line_number":57,"context_line":"        # here, and leave out the deleted/deleted_at fields because if this was"},{"line_number":58,"context_line":"        # deleted we would not show it."},{"line_number":59,"context_line":"        \u0027created_at\u0027: fields.DateTimeField(nullable\u003dTrue),"},{"line_number":60,"context_line":"        \u0027updated_at\u0027: fields.DateTimeField(nullable\u003dTrue),"},{"line_number":61,"context_line":"    }"}],"source_content_type":"text/x-python","patch_set":2,"id":"3a57f1b5_7e9d0ebb","line":58,"in_reply_to":"3a57f1b5_f320979d","updated":"2016-02-11 19:18:11.000000000","message":"Yeah, that\u0027s a great idea.","commit_id":"ba8dabcf3dc4c5c90f07adffdf0206292dd96578"},{"author":{"_account_id":18247,"name":"Mark Doffman","email":"mdoffman@linux.vnet.ibm.com","username":"doffm"},"change_message_id":"7b2ff7b8e8954cf72ecd11db53c67e78d2b470a8","unresolved":false,"context_lines":[{"line_number":115,"context_line":"        db_req.save(context.session)"},{"line_number":116,"context_line":"        # NOTE: There should be a better way to do this.  This is done because"},{"line_number":117,"context_line":"        # a later access will trigger a lazy load outside of the db session"},{"line_number":118,"context_line":"        # so it will fail."},{"line_number":119,"context_line":"        db_req.request_spec"},{"line_number":120,"context_line":"        return db_req"},{"line_number":121,"context_line":""}],"source_content_type":"text/x-python","patch_set":2,"id":"3a57f1b5_764a55c7","line":118,"updated":"2016-02-10 20:44:07.000000000","message":"There probably is a better way. Do an eager load on the db object. I have put a possible fix in comments in the db object patch.","commit_id":"ba8dabcf3dc4c5c90f07adffdf0206292dd96578"},{"author":{"_account_id":5441,"name":"Andrew Laski","email":"andrew@lascii.com","username":"alaski"},"change_message_id":"bba4138f2797b7beea4c176fcd3fce37a019005d","unresolved":false,"context_lines":[{"line_number":115,"context_line":"        db_req.save(context.session)"},{"line_number":116,"context_line":"        # NOTE: There should be a better way to do this.  This is done because"},{"line_number":117,"context_line":"        # a later access will trigger a lazy load outside of the db session"},{"line_number":118,"context_line":"        # so it will fail."},{"line_number":119,"context_line":"        db_req.request_spec"},{"line_number":120,"context_line":"        return db_req"},{"line_number":121,"context_line":""}],"source_content_type":"text/x-python","patch_set":2,"id":"3a57f1b5_1eaf3ae3","line":118,"in_reply_to":"3a57f1b5_764a55c7","updated":"2016-02-11 19:18:11.000000000","message":"Interesting, I\u0027ll give that a shot. Thanks.","commit_id":"ba8dabcf3dc4c5c90f07adffdf0206292dd96578"},{"author":{"_account_id":11803,"name":"Ryan Rossiter","email":"rlrossit@us.ibm.com","username":"rlrossiter"},"change_message_id":"832daec8b09acdcd001b78ec0a9f4bb52933357d","unresolved":false,"context_lines":[{"line_number":159,"context_line":"    def from_components(cls, context, instance_uuid, request_spec,"},{"line_number":160,"context_line":"            display_name, metadata, progress, vm_state, task_state,"},{"line_number":161,"context_line":"            access_ip_v4, access_ip_v6, info_cache, security_groups,"},{"line_number":162,"context_line":"            config_drive, key_name, locked_by):"},{"line_number":163,"context_line":"        \"\"\"Returns a new BuildRequest object hydrated by various components."},{"line_number":164,"context_line":""},{"line_number":165,"context_line":"        This helper is useful in creating the BuildRequest from various objects"}],"source_content_type":"text/x-python","patch_set":4,"id":"3a57f1b5_39d530e7","line":162,"updated":"2016-02-12 21:31:54.000000000","message":"You can just do the same thing by calling __init__() with these args, so I\u0027m confused as to why this function needs to be here. Are you trying to assert that it\u0027s created with exactly these arguments? But still nothing would stop me from calling __init__ with whatever I want...\n\nSome thoughts. Do we want to override init to ONLY take a context? So if someone wants to set some fields, we don\u0027t let them, the only way to do it is via this factory method? (Kinda like making a private constructor)","commit_id":"a61159b026a49f666caeb3a574005fdbee736d16"},{"author":{"_account_id":18247,"name":"Mark Doffman","email":"mdoffman@linux.vnet.ibm.com","username":"doffm"},"change_message_id":"6ed2e27465aaf3888726fd94281523cdad6f2ff0","unresolved":false,"context_lines":[{"line_number":159,"context_line":"    def from_components(cls, context, instance_uuid, request_spec,"},{"line_number":160,"context_line":"            display_name, metadata, progress, vm_state, task_state,"},{"line_number":161,"context_line":"            access_ip_v4, access_ip_v6, info_cache, security_groups,"},{"line_number":162,"context_line":"            config_drive, key_name, locked_by):"},{"line_number":163,"context_line":"        \"\"\"Returns a new BuildRequest object hydrated by various components."},{"line_number":164,"context_line":""},{"line_number":165,"context_line":"        This helper is useful in creating the BuildRequest from various objects"}],"source_content_type":"text/x-python","patch_set":4,"id":"3a57f1b5_5cc9fa57","line":162,"in_reply_to":"3a57f1b5_39d530e7","updated":"2016-02-12 21:42:41.000000000","message":"Even if we don\u0027t JUST want to call the constructor with \u0027context\u0027 this method could still be a constructor override.\n\nIs this the only way a build request should be created? If so then overriding the constructor makes more sense.\n\nThis might not be true for the RequestSpec object as I can see there are two different ways it is created. (from_primitives and from_components).","commit_id":"a61159b026a49f666caeb3a574005fdbee736d16"},{"author":{"_account_id":5441,"name":"Andrew Laski","email":"andrew@lascii.com","username":"alaski"},"change_message_id":"3e3673bd1f5a7d71b48017785aade3178e64db77","unresolved":false,"context_lines":[{"line_number":159,"context_line":"    def from_components(cls, context, instance_uuid, request_spec,"},{"line_number":160,"context_line":"            display_name, metadata, progress, vm_state, task_state,"},{"line_number":161,"context_line":"            access_ip_v4, access_ip_v6, info_cache, security_groups,"},{"line_number":162,"context_line":"            config_drive, key_name, locked_by):"},{"line_number":163,"context_line":"        \"\"\"Returns a new BuildRequest object hydrated by various components."},{"line_number":164,"context_line":""},{"line_number":165,"context_line":"        This helper is useful in creating the BuildRequest from various objects"}],"source_content_type":"text/x-python","patch_set":4,"id":"3a57f1b5_77c3af89","line":162,"in_reply_to":"3a57f1b5_5cc9fa57","updated":"2016-02-12 21:54:06.000000000","message":"This was me just copying RequestSpec because that\u0027s what I had just done before this. Moving this to __init__ would be the right thing to do here. The one benefit this does provide is that the use of this method ensures the object is fully populated. I could require that of __init__ but I\u0027m not sure that constraint makes sense there. I\u0027ll remove this method though.","commit_id":"a61159b026a49f666caeb3a574005fdbee736d16"},{"author":{"_account_id":782,"name":"John Garbutt","email":"john@johngarbutt.com","username":"johngarbutt"},"change_message_id":"c837301553ccb35acfd7fe7895f0a1a99a7ad19b","unresolved":false,"context_lines":[{"line_number":46,"context_line":"        \u0027access_ip_v6\u0027: fields.IPV6AddressField(nullable\u003dTrue),"},{"line_number":47,"context_line":"        \u0027info_cache\u0027: fields.ObjectField(\u0027InstanceInfoCache\u0027, nullable\u003dTrue),"},{"line_number":48,"context_line":"        \u0027security_groups\u0027: fields.ObjectField(\u0027SecurityGroupList\u0027),"},{"line_number":49,"context_line":"        \u0027config_drive\u0027: fields.StringField(nullable\u003dTrue),"},{"line_number":50,"context_line":"        \u0027key_name\u0027: fields.StringField(nullable\u003dTrue),"},{"line_number":51,"context_line":"        \u0027locked_by\u0027: fields.EnumField([\u0027owner\u0027, \u0027admin\u0027], nullable\u003dTrue),"},{"line_number":52,"context_line":"        \u0027request_spec\u0027: fields.ObjectField(\u0027RequestSpec\u0027),"}],"source_content_type":"text/x-python","patch_set":5,"id":"bae84128_e56dd033","line":49,"updated":"2016-02-19 18:52:08.000000000","message":"Can we be more specific here, and be a nullable enum?\n\nActually, can\u0027t this just be a boolean?","commit_id":"4cb1e24ea8fc4d255fd933564a532e303305f031"},{"author":{"_account_id":782,"name":"John Garbutt","email":"john@johngarbutt.com","username":"johngarbutt"},"change_message_id":"1859815b034483e5b2f6efa8ebbeb7f46b793e66","unresolved":false,"context_lines":[{"line_number":46,"context_line":"        \u0027access_ip_v6\u0027: fields.IPV6AddressField(nullable\u003dTrue),"},{"line_number":47,"context_line":"        \u0027info_cache\u0027: fields.ObjectField(\u0027InstanceInfoCache\u0027, nullable\u003dTrue),"},{"line_number":48,"context_line":"        \u0027security_groups\u0027: fields.ObjectField(\u0027SecurityGroupList\u0027),"},{"line_number":49,"context_line":"        \u0027config_drive\u0027: fields.StringField(nullable\u003dTrue),"},{"line_number":50,"context_line":"        \u0027key_name\u0027: fields.StringField(nullable\u003dTrue),"},{"line_number":51,"context_line":"        \u0027locked_by\u0027: fields.EnumField([\u0027owner\u0027, \u0027admin\u0027], nullable\u003dTrue),"},{"line_number":52,"context_line":"        \u0027request_spec\u0027: fields.ObjectField(\u0027RequestSpec\u0027),"}],"source_content_type":"text/x-python","patch_set":5,"id":"bae84128_bbe9e482","line":49,"in_reply_to":"bae84128_d0ce8859","updated":"2016-02-22 11:28:05.000000000","message":"Oh wow, you are totally right. Thats a mess :(","commit_id":"4cb1e24ea8fc4d255fd933564a532e303305f031"},{"author":{"_account_id":5441,"name":"Andrew Laski","email":"andrew@lascii.com","username":"alaski"},"change_message_id":"901ec12b9e3b8e68bab5a12c86dcf97539f03999","unresolved":false,"context_lines":[{"line_number":46,"context_line":"        \u0027access_ip_v6\u0027: fields.IPV6AddressField(nullable\u003dTrue),"},{"line_number":47,"context_line":"        \u0027info_cache\u0027: fields.ObjectField(\u0027InstanceInfoCache\u0027, nullable\u003dTrue),"},{"line_number":48,"context_line":"        \u0027security_groups\u0027: fields.ObjectField(\u0027SecurityGroupList\u0027),"},{"line_number":49,"context_line":"        \u0027config_drive\u0027: fields.StringField(nullable\u003dTrue),"},{"line_number":50,"context_line":"        \u0027key_name\u0027: fields.StringField(nullable\u003dTrue),"},{"line_number":51,"context_line":"        \u0027locked_by\u0027: fields.EnumField([\u0027owner\u0027, \u0027admin\u0027], nullable\u003dTrue),"},{"line_number":52,"context_line":"        \u0027request_spec\u0027: fields.ObjectField(\u0027RequestSpec\u0027),"}],"source_content_type":"text/x-python","patch_set":5,"id":"bae84128_d0ce8859","line":49,"in_reply_to":"bae84128_e56dd033","updated":"2016-02-19 19:00:57.000000000","message":"It could be, but that diverges from the Instance object which this is emulating. I would have to add some compatibility code since it appears that this is actually passed in as a string from the API.","commit_id":"4cb1e24ea8fc4d255fd933564a532e303305f031"},{"author":{"_account_id":6873,"name":"Matt Riedemann","email":"mriedem.os@gmail.com","username":"mriedem"},"change_message_id":"333f19281f098a41b48c7ccecd6736d18636d7c1","unresolved":false,"context_lines":[{"line_number":37,"context_line":"        \u0027project_id\u0027: fields.StringField(),"},{"line_number":38,"context_line":"        \u0027user_id\u0027: fields.StringField(),"},{"line_number":39,"context_line":"        \u0027display_name\u0027: fields.StringField(nullable\u003dTrue),"},{"line_number":40,"context_line":"        \u0027instance_metadata\u0027: fields.DictOfStringsField(),"},{"line_number":41,"context_line":"        \u0027progress\u0027: fields.IntegerField(),"},{"line_number":42,"context_line":"        \u0027vm_state\u0027: fields.StringField(),"},{"line_number":43,"context_line":"        \u0027task_state\u0027: fields.StringField(),"},{"line_number":44,"context_line":"        \u0027image_ref\u0027: fields.StringField(nullable\u003dTrue),"},{"line_number":45,"context_line":"        \u0027access_ip_v4\u0027: fields.IPV4AddressField(nullable\u003dTrue),"},{"line_number":46,"context_line":"        \u0027access_ip_v6\u0027: fields.IPV6AddressField(nullable\u003dTrue),"}],"source_content_type":"text/x-python","patch_set":11,"id":"9aed3d3a_a0ccca6a","line":43,"range":{"start_line":40,"start_character":8,"end_line":43,"end_character":43},"updated":"2016-02-29 19:11:10.000000000","message":"Shouldn\u0027t these all be nullable\u003dTrue given the model?\n\nhttps://github.com/openstack/nova/blob/d411d60587e54dd364b7a329035726f2e281a9f7/nova/db/sqlalchemy/api_models.py#L162-L165\n\nOr are you just copying these from the Instance object?","commit_id":"a60c999a03e646ee27664cbddcf7f2021ba42487"},{"author":{"_account_id":5441,"name":"Andrew Laski","email":"andrew@lascii.com","username":"alaski"},"change_message_id":"6c2606acb9b1d3ea36989757cca43d75aa759570","unresolved":false,"context_lines":[{"line_number":37,"context_line":"        \u0027project_id\u0027: fields.StringField(),"},{"line_number":38,"context_line":"        \u0027user_id\u0027: fields.StringField(),"},{"line_number":39,"context_line":"        \u0027display_name\u0027: fields.StringField(nullable\u003dTrue),"},{"line_number":40,"context_line":"        \u0027instance_metadata\u0027: fields.DictOfStringsField(),"},{"line_number":41,"context_line":"        \u0027progress\u0027: fields.IntegerField(),"},{"line_number":42,"context_line":"        \u0027vm_state\u0027: fields.StringField(),"},{"line_number":43,"context_line":"        \u0027task_state\u0027: fields.StringField(),"},{"line_number":44,"context_line":"        \u0027image_ref\u0027: fields.StringField(nullable\u003dTrue),"},{"line_number":45,"context_line":"        \u0027access_ip_v4\u0027: fields.IPV4AddressField(nullable\u003dTrue),"},{"line_number":46,"context_line":"        \u0027access_ip_v6\u0027: fields.IPV6AddressField(nullable\u003dTrue),"}],"source_content_type":"text/x-python","patch_set":11,"id":"9aed3d3a_c3f75857","line":43,"range":{"start_line":40,"start_character":8,"end_line":43,"end_character":43},"in_reply_to":"9aed3d3a_a0ccca6a","updated":"2016-02-29 19:34:10.000000000","message":"task_state should definitely be nullable. The others are never null in practice afaict but I will update them to match the model.","commit_id":"a60c999a03e646ee27664cbddcf7f2021ba42487"},{"author":{"_account_id":6873,"name":"Matt Riedemann","email":"mriedem.os@gmail.com","username":"mriedem"},"change_message_id":"333f19281f098a41b48c7ccecd6736d18636d7c1","unresolved":false,"context_lines":[{"line_number":50,"context_line":"        \u0027key_name\u0027: fields.StringField(nullable\u003dTrue),"},{"line_number":51,"context_line":"        \u0027locked_by\u0027: fields.EnumField([\u0027owner\u0027, \u0027admin\u0027], nullable\u003dTrue),"},{"line_number":52,"context_line":"        \u0027request_spec\u0027: fields.ObjectField(\u0027RequestSpec\u0027),"},{"line_number":53,"context_line":"        # NOTE(alaski): Normally these would come from the NovaPersistentObject"},{"line_number":54,"context_line":"        # mixin, however these are not metadata about the BuildRequest object"},{"line_number":55,"context_line":"        # but data about the instance to be booted.  So we explicitly add them"},{"line_number":56,"context_line":"        # here, and leave out the deleted/deleted_at fields because if this was"},{"line_number":57,"context_line":"        # deleted we would not show it."},{"line_number":58,"context_line":"        \u0027created_at\u0027: fields.DateTimeField(nullable\u003dTrue),"},{"line_number":59,"context_line":"        \u0027updated_at\u0027: fields.DateTimeField(nullable\u003dTrue),"},{"line_number":60,"context_line":"    }"},{"line_number":61,"context_line":""},{"line_number":62,"context_line":"    def _load_request_spec(self, db_spec):"}],"source_content_type":"text/x-python","patch_set":11,"id":"9aed3d3a_20627a3e","line":59,"range":{"start_line":53,"start_character":8,"end_line":59,"end_character":58},"updated":"2016-02-29 19:11:10.000000000","message":"I\u0027m not really understanding this, since we\u0027re inserting rows into the build_requests table, shouldn\u0027t we have created_at in there? Or does oslo.db/sqlalchemy just default it on insert?","commit_id":"a60c999a03e646ee27664cbddcf7f2021ba42487"},{"author":{"_account_id":5441,"name":"Andrew Laski","email":"andrew@lascii.com","username":"alaski"},"change_message_id":"6c2606acb9b1d3ea36989757cca43d75aa759570","unresolved":false,"context_lines":[{"line_number":50,"context_line":"        \u0027key_name\u0027: fields.StringField(nullable\u003dTrue),"},{"line_number":51,"context_line":"        \u0027locked_by\u0027: fields.EnumField([\u0027owner\u0027, \u0027admin\u0027], nullable\u003dTrue),"},{"line_number":52,"context_line":"        \u0027request_spec\u0027: fields.ObjectField(\u0027RequestSpec\u0027),"},{"line_number":53,"context_line":"        # NOTE(alaski): Normally these would come from the NovaPersistentObject"},{"line_number":54,"context_line":"        # mixin, however these are not metadata about the BuildRequest object"},{"line_number":55,"context_line":"        # but data about the instance to be booted.  So we explicitly add them"},{"line_number":56,"context_line":"        # here, and leave out the deleted/deleted_at fields because if this was"},{"line_number":57,"context_line":"        # deleted we would not show it."},{"line_number":58,"context_line":"        \u0027created_at\u0027: fields.DateTimeField(nullable\u003dTrue),"},{"line_number":59,"context_line":"        \u0027updated_at\u0027: fields.DateTimeField(nullable\u003dTrue),"},{"line_number":60,"context_line":"    }"},{"line_number":61,"context_line":""},{"line_number":62,"context_line":"    def _load_request_spec(self, db_spec):"}],"source_content_type":"text/x-python","patch_set":11,"id":"9aed3d3a_63392cf2","line":59,"range":{"start_line":53,"start_character":8,"end_line":59,"end_character":58},"in_reply_to":"9aed3d3a_20627a3e","updated":"2016-02-29 19:34:10.000000000","message":"It happens through the TimestampMixin http://git.openstack.org/cgit/openstack/oslo.db/tree/oslo_db/sqlalchemy/models.py#n135 which is included in the db model.","commit_id":"a60c999a03e646ee27664cbddcf7f2021ba42487"},{"author":{"_account_id":6873,"name":"Matt Riedemann","email":"mriedem.os@gmail.com","username":"mriedem"},"change_message_id":"cb512c3fadfe81bc24aa7b1b58b1aee68ebbb662","unresolved":false,"context_lines":[{"line_number":50,"context_line":"        \u0027key_name\u0027: fields.StringField(nullable\u003dTrue),"},{"line_number":51,"context_line":"        \u0027locked_by\u0027: fields.EnumField([\u0027owner\u0027, \u0027admin\u0027], nullable\u003dTrue),"},{"line_number":52,"context_line":"        \u0027request_spec\u0027: fields.ObjectField(\u0027RequestSpec\u0027),"},{"line_number":53,"context_line":"        # NOTE(alaski): Normally these would come from the NovaPersistentObject"},{"line_number":54,"context_line":"        # mixin, however these are not metadata about the BuildRequest object"},{"line_number":55,"context_line":"        # but data about the instance to be booted.  So we explicitly add them"},{"line_number":56,"context_line":"        # here, and leave out the deleted/deleted_at fields because if this was"},{"line_number":57,"context_line":"        # deleted we would not show it."},{"line_number":58,"context_line":"        \u0027created_at\u0027: fields.DateTimeField(nullable\u003dTrue),"},{"line_number":59,"context_line":"        \u0027updated_at\u0027: fields.DateTimeField(nullable\u003dTrue),"},{"line_number":60,"context_line":"    }"},{"line_number":61,"context_line":""},{"line_number":62,"context_line":"    def _load_request_spec(self, db_spec):"}],"source_content_type":"text/x-python","patch_set":11,"id":"9aed3d3a_6c7639d8","line":59,"range":{"start_line":53,"start_character":8,"end_line":59,"end_character":58},"in_reply_to":"9aed3d3a_63392cf2","updated":"2016-02-29 20:54:16.000000000","message":"So where do we ever set these based on the instance\u0027s values? Because wouldn\u0027t _from_db_object just set these from the values in the build_requests row that we fetch from the DB?","commit_id":"a60c999a03e646ee27664cbddcf7f2021ba42487"},{"author":{"_account_id":5441,"name":"Andrew Laski","email":"andrew@lascii.com","username":"alaski"},"change_message_id":"24b3ff7592a1e5c5fb968fbcace2be3e8d55bd01","unresolved":false,"context_lines":[{"line_number":50,"context_line":"        \u0027key_name\u0027: fields.StringField(nullable\u003dTrue),"},{"line_number":51,"context_line":"        \u0027locked_by\u0027: fields.EnumField([\u0027owner\u0027, \u0027admin\u0027], nullable\u003dTrue),"},{"line_number":52,"context_line":"        \u0027request_spec\u0027: fields.ObjectField(\u0027RequestSpec\u0027),"},{"line_number":53,"context_line":"        # NOTE(alaski): Normally these would come from the NovaPersistentObject"},{"line_number":54,"context_line":"        # mixin, however these are not metadata about the BuildRequest object"},{"line_number":55,"context_line":"        # but data about the instance to be booted.  So we explicitly add them"},{"line_number":56,"context_line":"        # here, and leave out the deleted/deleted_at fields because if this was"},{"line_number":57,"context_line":"        # deleted we would not show it."},{"line_number":58,"context_line":"        \u0027created_at\u0027: fields.DateTimeField(nullable\u003dTrue),"},{"line_number":59,"context_line":"        \u0027updated_at\u0027: fields.DateTimeField(nullable\u003dTrue),"},{"line_number":60,"context_line":"    }"},{"line_number":61,"context_line":""},{"line_number":62,"context_line":"    def _load_request_spec(self, db_spec):"}],"source_content_type":"text/x-python","patch_set":11,"id":"9aed3d3a_553931d6","line":59,"range":{"start_line":53,"start_character":8,"end_line":59,"end_character":58},"in_reply_to":"9aed3d3a_6c7639d8","updated":"2016-02-29 22:50:45.000000000","message":"I think I need to update the comment. They\u0027re not set based on the instance values, the become the instance values when that is created. I left the comment because typically these fields are left out of the object as they\u0027re really just db metadata. In this case they\u0027re explicitly part of the object because we\u0027ll carry them over to the instance.","commit_id":"a60c999a03e646ee27664cbddcf7f2021ba42487"},{"author":{"_account_id":6873,"name":"Matt Riedemann","email":"mriedem.os@gmail.com","username":"mriedem"},"change_message_id":"333f19281f098a41b48c7ccecd6736d18636d7c1","unresolved":false,"context_lines":[{"line_number":59,"context_line":"        \u0027updated_at\u0027: fields.DateTimeField(nullable\u003dTrue),"},{"line_number":60,"context_line":"    }"},{"line_number":61,"context_line":""},{"line_number":62,"context_line":"    def _load_request_spec(self, db_spec):"},{"line_number":63,"context_line":"        self.request_spec \u003d objects.RequestSpec._from_db_object(self._context,"},{"line_number":64,"context_line":"                objects.RequestSpec(), db_spec)"},{"line_number":65,"context_line":""},{"line_number":66,"context_line":"    def _load_info_cache(self, db_info_cache):"},{"line_number":67,"context_line":"        self.info_cache \u003d objects.InstanceInfoCache.obj_from_primitive("},{"line_number":68,"context_line":"                jsonutils.loads(db_info_cache))"},{"line_number":69,"context_line":""},{"line_number":70,"context_line":"    def _load_security_groups(self, db_sec_group):"},{"line_number":71,"context_line":"        self.security_groups \u003d objects.SecurityGroupList.obj_from_primitive("},{"line_number":72,"context_line":"                jsonutils.loads(db_sec_group))"},{"line_number":73,"context_line":""},{"line_number":74,"context_line":"    @staticmethod"},{"line_number":75,"context_line":"    def _from_db_object(context, req, db_req):"}],"source_content_type":"text/x-python","patch_set":11,"id":"9aed3d3a_83943043","line":72,"range":{"start_line":62,"start_character":4,"end_line":72,"end_character":46},"updated":"2016-02-29 19:11:10.000000000","message":"Did you mean to use these for lazy-loading in obj_load_attr?","commit_id":"a60c999a03e646ee27664cbddcf7f2021ba42487"},{"author":{"_account_id":6873,"name":"Matt Riedemann","email":"mriedem.os@gmail.com","username":"mriedem"},"change_message_id":"cb512c3fadfe81bc24aa7b1b58b1aee68ebbb662","unresolved":false,"context_lines":[{"line_number":59,"context_line":"        \u0027updated_at\u0027: fields.DateTimeField(nullable\u003dTrue),"},{"line_number":60,"context_line":"    }"},{"line_number":61,"context_line":""},{"line_number":62,"context_line":"    def _load_request_spec(self, db_spec):"},{"line_number":63,"context_line":"        self.request_spec \u003d objects.RequestSpec._from_db_object(self._context,"},{"line_number":64,"context_line":"                objects.RequestSpec(), db_spec)"},{"line_number":65,"context_line":""},{"line_number":66,"context_line":"    def _load_info_cache(self, db_info_cache):"},{"line_number":67,"context_line":"        self.info_cache \u003d objects.InstanceInfoCache.obj_from_primitive("},{"line_number":68,"context_line":"                jsonutils.loads(db_info_cache))"},{"line_number":69,"context_line":""},{"line_number":70,"context_line":"    def _load_security_groups(self, db_sec_group):"},{"line_number":71,"context_line":"        self.security_groups \u003d objects.SecurityGroupList.obj_from_primitive("},{"line_number":72,"context_line":"                jsonutils.loads(db_sec_group))"},{"line_number":73,"context_line":""},{"line_number":74,"context_line":"    @staticmethod"},{"line_number":75,"context_line":"    def _from_db_object(context, req, db_req):"}],"source_content_type":"text/x-python","patch_set":11,"id":"9aed3d3a_2c471178","line":72,"range":{"start_line":62,"start_character":4,"end_line":72,"end_character":46},"in_reply_to":"9aed3d3a_63100c5a","updated":"2016-02-29 20:54:16.000000000","message":"Oh I see...magic.","commit_id":"a60c999a03e646ee27664cbddcf7f2021ba42487"},{"author":{"_account_id":5441,"name":"Andrew Laski","email":"andrew@lascii.com","username":"alaski"},"change_message_id":"6c2606acb9b1d3ea36989757cca43d75aa759570","unresolved":false,"context_lines":[{"line_number":59,"context_line":"        \u0027updated_at\u0027: fields.DateTimeField(nullable\u003dTrue),"},{"line_number":60,"context_line":"    }"},{"line_number":61,"context_line":""},{"line_number":62,"context_line":"    def _load_request_spec(self, db_spec):"},{"line_number":63,"context_line":"        self.request_spec \u003d objects.RequestSpec._from_db_object(self._context,"},{"line_number":64,"context_line":"                objects.RequestSpec(), db_spec)"},{"line_number":65,"context_line":""},{"line_number":66,"context_line":"    def _load_info_cache(self, db_info_cache):"},{"line_number":67,"context_line":"        self.info_cache \u003d objects.InstanceInfoCache.obj_from_primitive("},{"line_number":68,"context_line":"                jsonutils.loads(db_info_cache))"},{"line_number":69,"context_line":""},{"line_number":70,"context_line":"    def _load_security_groups(self, db_sec_group):"},{"line_number":71,"context_line":"        self.security_groups \u003d objects.SecurityGroupList.obj_from_primitive("},{"line_number":72,"context_line":"                jsonutils.loads(db_sec_group))"},{"line_number":73,"context_line":""},{"line_number":74,"context_line":"    @staticmethod"},{"line_number":75,"context_line":"    def _from_db_object(context, req, db_req):"}],"source_content_type":"text/x-python","patch_set":11,"id":"9aed3d3a_63100c5a","line":72,"range":{"start_line":62,"start_character":4,"end_line":72,"end_character":46},"in_reply_to":"9aed3d3a_83943043","updated":"2016-02-29 19:34:10.000000000","message":"These are called on line 80 when loading from the db.","commit_id":"a60c999a03e646ee27664cbddcf7f2021ba42487"},{"author":{"_account_id":6873,"name":"Matt Riedemann","email":"mriedem.os@gmail.com","username":"mriedem"},"change_message_id":"333f19281f098a41b48c7ccecd6736d18636d7c1","unresolved":false,"context_lines":[{"line_number":91,"context_line":"    @staticmethod"},{"line_number":92,"context_line":"    @db.api_context_manager.reader"},{"line_number":93,"context_line":"    def _get_by_instance_uuid_from_db(context, instance_uuid):"},{"line_number":94,"context_line":"        db_req \u003d (context.session.query(api_models.BuildRequest)"},{"line_number":95,"context_line":"                .join(api_models.RequestSpec)"},{"line_number":96,"context_line":"                .filter("},{"line_number":97,"context_line":"                    api_models.RequestSpec.instance_uuid \u003d\u003d instance_uuid)"},{"line_number":98,"context_line":"                ).first()"},{"line_number":99,"context_line":"        if not db_req:"},{"line_number":100,"context_line":"            raise exception.BuildRequestNotFound(uuid\u003dinstance_uuid)"},{"line_number":101,"context_line":"        db_req.request_spec"}],"source_content_type":"text/x-python","patch_set":11,"id":"9aed3d3a_8371d078","line":98,"range":{"start_line":94,"start_character":8,"end_line":98,"end_character":25},"updated":"2016-02-29 19:11:10.000000000","message":"I must have missed the memo here, but I guess we\u0027re doing straight sqlalchemy stuff in the API DB objects now rather than in an API DB sqlalchemy api?","commit_id":"a60c999a03e646ee27664cbddcf7f2021ba42487"},{"author":{"_account_id":5441,"name":"Andrew Laski","email":"andrew@lascii.com","username":"alaski"},"change_message_id":"6c2606acb9b1d3ea36989757cca43d75aa759570","unresolved":false,"context_lines":[{"line_number":91,"context_line":"    @staticmethod"},{"line_number":92,"context_line":"    @db.api_context_manager.reader"},{"line_number":93,"context_line":"    def _get_by_instance_uuid_from_db(context, instance_uuid):"},{"line_number":94,"context_line":"        db_req \u003d (context.session.query(api_models.BuildRequest)"},{"line_number":95,"context_line":"                .join(api_models.RequestSpec)"},{"line_number":96,"context_line":"                .filter("},{"line_number":97,"context_line":"                    api_models.RequestSpec.instance_uuid \u003d\u003d instance_uuid)"},{"line_number":98,"context_line":"                ).first()"},{"line_number":99,"context_line":"        if not db_req:"},{"line_number":100,"context_line":"            raise exception.BuildRequestNotFound(uuid\u003dinstance_uuid)"},{"line_number":101,"context_line":"        db_req.request_spec"}],"source_content_type":"text/x-python","patch_set":11,"id":"9aed3d3a_0654aefc","line":98,"range":{"start_line":94,"start_character":8,"end_line":98,"end_character":25},"in_reply_to":"9aed3d3a_8371d078","updated":"2016-02-29 19:34:10.000000000","message":"Yes. Not just the api db objects, but all around now. The db queries all correspond to a particular object and should be bundled rather than having the giant api.py file which is just a mess.","commit_id":"a60c999a03e646ee27664cbddcf7f2021ba42487"},{"author":{"_account_id":6873,"name":"Matt Riedemann","email":"mriedem.os@gmail.com","username":"mriedem"},"change_message_id":"333f19281f098a41b48c7ccecd6736d18636d7c1","unresolved":false,"context_lines":[{"line_number":112,"context_line":"        db_req \u003d api_models.BuildRequest()"},{"line_number":113,"context_line":"        db_req.update(updates)"},{"line_number":114,"context_line":"        db_req.save(context.session)"},{"line_number":115,"context_line":"        # NOTE: There should be a better way to do this.  This is done because"},{"line_number":116,"context_line":"        # a later access will trigger a lazy load outside of the db session"},{"line_number":117,"context_line":"        # so it will fail."},{"line_number":118,"context_line":"        db_req.request_spec"},{"line_number":119,"context_line":"        return db_req"},{"line_number":120,"context_line":""},{"line_number":121,"context_line":"    def _get_update_primitives(self):"}],"source_content_type":"text/x-python","patch_set":11,"id":"9aed3d3a_00dad64b","line":118,"range":{"start_line":115,"start_character":8,"end_line":118,"end_character":27},"updated":"2016-02-29 19:11:10.000000000","message":"Why don\u0027t we just override obj_load_attr in here and if request_spec is the attribute, we load it up based on the request_spec_id?","commit_id":"a60c999a03e646ee27664cbddcf7f2021ba42487"},{"author":{"_account_id":5441,"name":"Andrew Laski","email":"andrew@lascii.com","username":"alaski"},"change_message_id":"6c2606acb9b1d3ea36989757cca43d75aa759570","unresolved":false,"context_lines":[{"line_number":112,"context_line":"        db_req \u003d api_models.BuildRequest()"},{"line_number":113,"context_line":"        db_req.update(updates)"},{"line_number":114,"context_line":"        db_req.save(context.session)"},{"line_number":115,"context_line":"        # NOTE: There should be a better way to do this.  This is done because"},{"line_number":116,"context_line":"        # a later access will trigger a lazy load outside of the db session"},{"line_number":117,"context_line":"        # so it will fail."},{"line_number":118,"context_line":"        db_req.request_spec"},{"line_number":119,"context_line":"        return db_req"},{"line_number":120,"context_line":""},{"line_number":121,"context_line":"    def _get_update_primitives(self):"}],"source_content_type":"text/x-python","patch_set":11,"id":"9aed3d3a_a6dfc267","line":118,"range":{"start_line":115,"start_character":8,"end_line":118,"end_character":27},"in_reply_to":"9aed3d3a_00dad64b","updated":"2016-02-29 19:34:10.000000000","message":"We will always need the request_spec with the BuildRequest object so it\u0027ll be better to load it while we\u0027re in the db session rather than pull it later.","commit_id":"a60c999a03e646ee27664cbddcf7f2021ba42487"},{"author":{"_account_id":6873,"name":"Matt Riedemann","email":"mriedem.os@gmail.com","username":"mriedem"},"change_message_id":"1eb2b026035e205b53aea1251a7f663a345f7595","unresolved":false,"context_lines":[{"line_number":50,"context_line":"        \u0027key_name\u0027: fields.StringField(nullable\u003dTrue),"},{"line_number":51,"context_line":"        \u0027locked_by\u0027: fields.EnumField([\u0027owner\u0027, \u0027admin\u0027], nullable\u003dTrue),"},{"line_number":52,"context_line":"        \u0027request_spec\u0027: fields.ObjectField(\u0027RequestSpec\u0027),"},{"line_number":53,"context_line":"        # NOTE(alaski): Normally these would come from the NovaPersistentObject"},{"line_number":54,"context_line":"        # mixin but they\u0027re being set explicitly because we only need"},{"line_number":55,"context_line":"        # created_at/updated_at. There is no soft delete for this object."},{"line_number":56,"context_line":"        # These fields should be carried over to the instance when it is"},{"line_number":57,"context_line":"        # scheduled and created in a cell database."},{"line_number":58,"context_line":"        \u0027created_at\u0027: fields.DateTimeField(nullable\u003dTrue),"},{"line_number":59,"context_line":"        \u0027updated_at\u0027: fields.DateTimeField(nullable\u003dTrue),"},{"line_number":60,"context_line":"    }"}],"source_content_type":"text/x-python","patch_set":12,"id":"7af24918_89d4a147","line":57,"range":{"start_line":53,"start_character":8,"end_line":57,"end_character":51},"updated":"2016-03-02 15:54:19.000000000","message":"This still seems odd to me, but this comment makes more sense than the previous one anyway. I think it just means, we have this build request created at time x, maybe updated at time y, and when this build request is used to create an instance, we use the created/updated values from this build request to set on the instance that gets created.\n\nIt still seems a bit wonky to me, like the fact that the build request is actually separated from the instance in the data model via the request spec, so I could actually see this stored in the request spec, or just set when the instance is created, but I guess the build request and request spec are separate in that regard.","commit_id":"a90378735c29b6022442958934f5b6210a0f2a87"},{"author":{"_account_id":782,"name":"John Garbutt","email":"john@johngarbutt.com","username":"johngarbutt"},"change_message_id":"2de76b4c1af10b489fa492f14c6c8abba394aadc","unresolved":false,"context_lines":[{"line_number":50,"context_line":"        \u0027key_name\u0027: fields.StringField(nullable\u003dTrue),"},{"line_number":51,"context_line":"        \u0027locked_by\u0027: fields.EnumField([\u0027owner\u0027, \u0027admin\u0027], nullable\u003dTrue),"},{"line_number":52,"context_line":"        \u0027request_spec\u0027: fields.ObjectField(\u0027RequestSpec\u0027),"},{"line_number":53,"context_line":"        # NOTE(alaski): Normally these would come from the NovaPersistentObject"},{"line_number":54,"context_line":"        # mixin but they\u0027re being set explicitly because we only need"},{"line_number":55,"context_line":"        # created_at/updated_at. There is no soft delete for this object."},{"line_number":56,"context_line":"        # These fields should be carried over to the instance when it is"},{"line_number":57,"context_line":"        # scheduled and created in a cell database."},{"line_number":58,"context_line":"        \u0027created_at\u0027: fields.DateTimeField(nullable\u003dTrue),"},{"line_number":59,"context_line":"        \u0027updated_at\u0027: fields.DateTimeField(nullable\u003dTrue),"},{"line_number":60,"context_line":"    }"}],"source_content_type":"text/x-python","patch_set":12,"id":"7af24918_8f0941e0","line":57,"range":{"start_line":53,"start_character":8,"end_line":57,"end_character":51},"in_reply_to":"7af24918_89d4a147","updated":"2016-03-02 16:20:29.000000000","message":"So the build request gets deleted once the instance is created, I think, so no soft delete.\n\nThe request spec stays around until the instance is deleted, I guess? so we know what the request was.\n\nHmm, its a bit odd we do need both still, I am missing something here. Maybe its API updates why the instance is having its cell picked for it?","commit_id":"a90378735c29b6022442958934f5b6210a0f2a87"},{"author":{"_account_id":5441,"name":"Andrew Laski","email":"andrew@lascii.com","username":"alaski"},"change_message_id":"c3cb5f92b8b1478bae7b48e83c648afae6bfa9bf","unresolved":false,"context_lines":[{"line_number":50,"context_line":"        \u0027key_name\u0027: fields.StringField(nullable\u003dTrue),"},{"line_number":51,"context_line":"        \u0027locked_by\u0027: fields.EnumField([\u0027owner\u0027, \u0027admin\u0027], nullable\u003dTrue),"},{"line_number":52,"context_line":"        \u0027request_spec\u0027: fields.ObjectField(\u0027RequestSpec\u0027),"},{"line_number":53,"context_line":"        # NOTE(alaski): Normally these would come from the NovaPersistentObject"},{"line_number":54,"context_line":"        # mixin but they\u0027re being set explicitly because we only need"},{"line_number":55,"context_line":"        # created_at/updated_at. There is no soft delete for this object."},{"line_number":56,"context_line":"        # These fields should be carried over to the instance when it is"},{"line_number":57,"context_line":"        # scheduled and created in a cell database."},{"line_number":58,"context_line":"        \u0027created_at\u0027: fields.DateTimeField(nullable\u003dTrue),"},{"line_number":59,"context_line":"        \u0027updated_at\u0027: fields.DateTimeField(nullable\u003dTrue),"},{"line_number":60,"context_line":"    }"}],"source_content_type":"text/x-python","patch_set":12,"id":"7af24918_a1aff192","line":57,"range":{"start_line":53,"start_character":8,"end_line":57,"end_character":51},"in_reply_to":"7af24918_89d4a147","updated":"2016-03-02 16:16:16.000000000","message":"The request_spec is purely a scheduling construct. I don\u0027t love that it\u0027s being used here to fill out the build_request, and would rather just have this match the instance object as much as possible, but there were concerns about this object duplicating info that we already had in the database. All that being said, I think it makes more sense to pull these fields from this object rather than the request_spec.","commit_id":"a90378735c29b6022442958934f5b6210a0f2a87"},{"author":{"_account_id":5441,"name":"Andrew Laski","email":"andrew@lascii.com","username":"alaski"},"change_message_id":"9bf26e55f43266c7c9bd6d285a4bc561074f4111","unresolved":false,"context_lines":[{"line_number":50,"context_line":"        \u0027key_name\u0027: fields.StringField(nullable\u003dTrue),"},{"line_number":51,"context_line":"        \u0027locked_by\u0027: fields.EnumField([\u0027owner\u0027, \u0027admin\u0027], nullable\u003dTrue),"},{"line_number":52,"context_line":"        \u0027request_spec\u0027: fields.ObjectField(\u0027RequestSpec\u0027),"},{"line_number":53,"context_line":"        # NOTE(alaski): Normally these would come from the NovaPersistentObject"},{"line_number":54,"context_line":"        # mixin but they\u0027re being set explicitly because we only need"},{"line_number":55,"context_line":"        # created_at/updated_at. There is no soft delete for this object."},{"line_number":56,"context_line":"        # These fields should be carried over to the instance when it is"},{"line_number":57,"context_line":"        # scheduled and created in a cell database."},{"line_number":58,"context_line":"        \u0027created_at\u0027: fields.DateTimeField(nullable\u003dTrue),"},{"line_number":59,"context_line":"        \u0027updated_at\u0027: fields.DateTimeField(nullable\u003dTrue),"},{"line_number":60,"context_line":"    }"}],"source_content_type":"text/x-python","patch_set":12,"id":"7af24918_172c27aa","line":57,"range":{"start_line":53,"start_character":8,"end_line":57,"end_character":51},"in_reply_to":"7af24918_8f0941e0","updated":"2016-03-02 16:37:54.000000000","message":"We need the BuildRequest because the request_spec does not contain the other fields here which are necessary for displaying an instance in the API.\n\nHonestly I would rather not pull in the request_spec here, as these objects are really not at all related. But it would be duplicating data to repopulate those fields in here.","commit_id":"a90378735c29b6022442958934f5b6210a0f2a87"},{"author":{"_account_id":6873,"name":"Matt Riedemann","email":"mriedem.os@gmail.com","username":"mriedem"},"change_message_id":"1eb2b026035e205b53aea1251a7f663a345f7595","unresolved":false,"context_lines":[{"line_number":98,"context_line":"                ).first()"},{"line_number":99,"context_line":"        if not db_req:"},{"line_number":100,"context_line":"            raise exception.BuildRequestNotFound(uuid\u003dinstance_uuid)"},{"line_number":101,"context_line":"        db_req.request_spec"},{"line_number":102,"context_line":"        return db_req"},{"line_number":103,"context_line":""},{"line_number":104,"context_line":"    @base.remotable_classmethod"}],"source_content_type":"text/x-python","patch_set":12,"id":"7af24918_49ef39b0","line":101,"range":{"start_line":101,"start_character":8,"end_line":101,"end_character":27},"updated":"2016-03-02 15:54:19.000000000","message":"You might want to put a comment around this explaining that this is loading the request_spec attribute. I\u0027m still a bit confused honestly in how this works - why isn\u0027t this on the db_req object already so that when you eventually get to _from_db_object it\u0027s there and gets loaded via _load_request_spec?","commit_id":"a90378735c29b6022442958934f5b6210a0f2a87"},{"author":{"_account_id":782,"name":"John Garbutt","email":"john@johngarbutt.com","username":"johngarbutt"},"change_message_id":"2de76b4c1af10b489fa492f14c6c8abba394aadc","unresolved":false,"context_lines":[{"line_number":98,"context_line":"                ).first()"},{"line_number":99,"context_line":"        if not db_req:"},{"line_number":100,"context_line":"            raise exception.BuildRequestNotFound(uuid\u003dinstance_uuid)"},{"line_number":101,"context_line":"        db_req.request_spec"},{"line_number":102,"context_line":"        return db_req"},{"line_number":103,"context_line":""},{"line_number":104,"context_line":"    @base.remotable_classmethod"}],"source_content_type":"text/x-python","patch_set":12,"id":"7af24918_4f7459fc","line":101,"range":{"start_line":101,"start_character":8,"end_line":101,"end_character":27},"in_reply_to":"7af24918_49ef39b0","updated":"2016-03-02 16:20:29.000000000","message":"+1 for another comment here, if we can\u0027t get rid of this.","commit_id":"a90378735c29b6022442958934f5b6210a0f2a87"},{"author":{"_account_id":5441,"name":"Andrew Laski","email":"andrew@lascii.com","username":"alaski"},"change_message_id":"c3cb5f92b8b1478bae7b48e83c648afae6bfa9bf","unresolved":false,"context_lines":[{"line_number":98,"context_line":"                ).first()"},{"line_number":99,"context_line":"        if not db_req:"},{"line_number":100,"context_line":"            raise exception.BuildRequestNotFound(uuid\u003dinstance_uuid)"},{"line_number":101,"context_line":"        db_req.request_spec"},{"line_number":102,"context_line":"        return db_req"},{"line_number":103,"context_line":""},{"line_number":104,"context_line":"    @base.remotable_classmethod"}],"source_content_type":"text/x-python","patch_set":12,"id":"7af24918_8f994122","line":101,"range":{"start_line":101,"start_character":8,"end_line":101,"end_character":27},"in_reply_to":"7af24918_49ef39b0","updated":"2016-03-02 16:16:16.000000000","message":"I can remove this and use .with_entities on the query. It\u0027s just the save() that needs this.","commit_id":"a90378735c29b6022442958934f5b6210a0f2a87"},{"author":{"_account_id":6873,"name":"Matt Riedemann","email":"mriedem.os@gmail.com","username":"mriedem"},"change_message_id":"1eb2b026035e205b53aea1251a7f663a345f7595","unresolved":false,"context_lines":[{"line_number":112,"context_line":"        db_req \u003d api_models.BuildRequest()"},{"line_number":113,"context_line":"        db_req.update(updates)"},{"line_number":114,"context_line":"        db_req.save(context.session)"},{"line_number":115,"context_line":"        # NOTE: There should be a better way to do this.  This is done because"},{"line_number":116,"context_line":"        # a later access will trigger a lazy load outside of the db session"},{"line_number":117,"context_line":"        # so it will fail."},{"line_number":118,"context_line":"        db_req.request_spec"},{"line_number":119,"context_line":"        return db_req"},{"line_number":120,"context_line":""}],"source_content_type":"text/x-python","patch_set":12,"id":"7af24918_297e2d19","line":117,"range":{"start_line":115,"start_character":8,"end_line":117,"end_character":26},"updated":"2016-03-02 15:54:19.000000000","message":"I still think we could implement obj_load_attr to load this up in a lazy fashion if necessary, and use something like expected_attrs to get it on initial query from the database. But I could just be missing how this is used later.","commit_id":"a90378735c29b6022442958934f5b6210a0f2a87"},{"author":{"_account_id":5441,"name":"Andrew Laski","email":"andrew@lascii.com","username":"alaski"},"change_message_id":"c3cb5f92b8b1478bae7b48e83c648afae6bfa9bf","unresolved":false,"context_lines":[{"line_number":112,"context_line":"        db_req \u003d api_models.BuildRequest()"},{"line_number":113,"context_line":"        db_req.update(updates)"},{"line_number":114,"context_line":"        db_req.save(context.session)"},{"line_number":115,"context_line":"        # NOTE: There should be a better way to do this.  This is done because"},{"line_number":116,"context_line":"        # a later access will trigger a lazy load outside of the db session"},{"line_number":117,"context_line":"        # so it will fail."},{"line_number":118,"context_line":"        db_req.request_spec"},{"line_number":119,"context_line":"        return db_req"},{"line_number":120,"context_line":""}],"source_content_type":"text/x-python","patch_set":12,"id":"7af24918_c1583d35","line":117,"range":{"start_line":115,"start_character":8,"end_line":117,"end_character":26},"in_reply_to":"7af24918_297e2d19","updated":"2016-03-02 16:16:16.000000000","message":"I can add the lazy load, but honestly the request_spec needs to be here so it should just always be loaded when pulling the build_request from the db.","commit_id":"a90378735c29b6022442958934f5b6210a0f2a87"},{"author":{"_account_id":782,"name":"John Garbutt","email":"john@johngarbutt.com","username":"johngarbutt"},"change_message_id":"2de76b4c1af10b489fa492f14c6c8abba394aadc","unresolved":false,"context_lines":[{"line_number":112,"context_line":"        db_req \u003d api_models.BuildRequest()"},{"line_number":113,"context_line":"        db_req.update(updates)"},{"line_number":114,"context_line":"        db_req.save(context.session)"},{"line_number":115,"context_line":"        # NOTE: There should be a better way to do this.  This is done because"},{"line_number":116,"context_line":"        # a later access will trigger a lazy load outside of the db session"},{"line_number":117,"context_line":"        # so it will fail."},{"line_number":118,"context_line":"        db_req.request_spec"},{"line_number":119,"context_line":"        return db_req"},{"line_number":120,"context_line":""}],"source_content_type":"text/x-python","patch_set":12,"id":"7af24918_cfb4e9d2","line":117,"range":{"start_line":115,"start_character":8,"end_line":117,"end_character":26},"in_reply_to":"7af24918_297e2d19","updated":"2016-03-02 16:20:29.000000000","message":"so this is needed to populate the object correctly after its created, I think. maybe we should make that clearer?","commit_id":"a90378735c29b6022442958934f5b6210a0f2a87"},{"author":{"_account_id":6873,"name":"Matt Riedemann","email":"mriedem.os@gmail.com","username":"mriedem"},"change_message_id":"1eb2b026035e205b53aea1251a7f663a345f7595","unresolved":false,"context_lines":[{"line_number":121,"context_line":"    def _get_update_primitives(self):"},{"line_number":122,"context_line":"        updates \u003d self.obj_get_changes()"},{"line_number":123,"context_line":"        object_fields \u003d [\u0027info_cache\u0027, \u0027security_groups\u0027]"},{"line_number":124,"context_line":"        json_fields \u003d [\u0027instance_metadata\u0027]"},{"line_number":125,"context_line":"        ip_fields \u003d [\u0027access_ip_v4\u0027, \u0027access_ip_v6\u0027]"},{"line_number":126,"context_line":"        for key, value in six.iteritems(updates):"},{"line_number":127,"context_line":"            if key in object_fields and value is not None:"}],"source_content_type":"text/x-python","patch_set":12,"id":"7af24918_092251b9","line":124,"range":{"start_line":124,"start_character":8,"end_line":124,"end_character":43},"updated":"2016-03-02 15:54:19.000000000","message":"nit: we could make this a more global constant since it\u0027s used in a couple of places.","commit_id":"a90378735c29b6022442958934f5b6210a0f2a87"},{"author":{"_account_id":782,"name":"John Garbutt","email":"john@johngarbutt.com","username":"johngarbutt"},"change_message_id":"2de76b4c1af10b489fa492f14c6c8abba394aadc","unresolved":false,"context_lines":[{"line_number":121,"context_line":"    def _get_update_primitives(self):"},{"line_number":122,"context_line":"        updates \u003d self.obj_get_changes()"},{"line_number":123,"context_line":"        object_fields \u003d [\u0027info_cache\u0027, \u0027security_groups\u0027]"},{"line_number":124,"context_line":"        json_fields \u003d [\u0027instance_metadata\u0027]"},{"line_number":125,"context_line":"        ip_fields \u003d [\u0027access_ip_v4\u0027, \u0027access_ip_v6\u0027]"},{"line_number":126,"context_line":"        for key, value in six.iteritems(updates):"},{"line_number":127,"context_line":"            if key in object_fields and value is not None:"}],"source_content_type":"text/x-python","patch_set":12,"id":"7af24918_4f90d9ec","line":124,"range":{"start_line":124,"start_character":8,"end_line":124,"end_character":43},"in_reply_to":"7af24918_092251b9","updated":"2016-03-02 16:20:29.000000000","message":"hmm, because its in ln 76 as well, yeah, this should be a constant shared between those two places.","commit_id":"a90378735c29b6022442958934f5b6210a0f2a87"},{"author":{"_account_id":6873,"name":"Matt Riedemann","email":"mriedem.os@gmail.com","username":"mriedem"},"change_message_id":"b1355a82a711647c089164c1aa6cdd06cf2d9924","unresolved":false,"context_lines":[{"line_number":121,"context_line":"    def _get_update_primitives(self):"},{"line_number":122,"context_line":"        updates \u003d self.obj_get_changes()"},{"line_number":123,"context_line":"        object_fields \u003d [\u0027info_cache\u0027, \u0027security_groups\u0027]"},{"line_number":124,"context_line":"        json_fields \u003d [\u0027instance_metadata\u0027]"},{"line_number":125,"context_line":"        ip_fields \u003d [\u0027access_ip_v4\u0027, \u0027access_ip_v6\u0027]"},{"line_number":126,"context_line":"        for key, value in six.iteritems(updates):"},{"line_number":127,"context_line":"            if key in object_fields and value is not None:"}],"source_content_type":"text/x-python","patch_set":12,"id":"7af24918_04b23394","line":124,"range":{"start_line":124,"start_character":8,"end_line":124,"end_character":43},"in_reply_to":"7af24918_4f90d9ec","updated":"2016-03-02 16:28:08.000000000","message":"And the unit tests.","commit_id":"a90378735c29b6022442958934f5b6210a0f2a87"},{"author":{"_account_id":782,"name":"John Garbutt","email":"john@johngarbutt.com","username":"johngarbutt"},"change_message_id":"2de76b4c1af10b489fa492f14c6c8abba394aadc","unresolved":false,"context_lines":[{"line_number":133,"context_line":"                updates[key] \u003d str(value)"},{"line_number":134,"context_line":"        req_spec_obj \u003d updates.pop(\u0027request_spec\u0027, None)"},{"line_number":135,"context_line":"        if req_spec_obj:"},{"line_number":136,"context_line":"            updates[\u0027request_spec_id\u0027] \u003d req_spec_obj.id"},{"line_number":137,"context_line":"        return updates"},{"line_number":138,"context_line":""},{"line_number":139,"context_line":"    @base.remotable"}],"source_content_type":"text/x-python","patch_set":12,"id":"7af24918_c1a67d0f","line":136,"updated":"2016-03-02 16:20:29.000000000","message":"I wonder if we should really double check to see if the id has changed, before adding it in the changes? Although I guess thats not really the point, it was set, so it should be updated.","commit_id":"a90378735c29b6022442958934f5b6210a0f2a87"},{"author":{"_account_id":5441,"name":"Andrew Laski","email":"andrew@lascii.com","username":"alaski"},"change_message_id":"3dec225e9aa02b68e93bcb0a5567dc5caa82eb77","unresolved":false,"context_lines":[{"line_number":133,"context_line":"                updates[key] \u003d str(value)"},{"line_number":134,"context_line":"        req_spec_obj \u003d updates.pop(\u0027request_spec\u0027, None)"},{"line_number":135,"context_line":"        if req_spec_obj:"},{"line_number":136,"context_line":"            updates[\u0027request_spec_id\u0027] \u003d req_spec_obj.id"},{"line_number":137,"context_line":"        return updates"},{"line_number":138,"context_line":""},{"line_number":139,"context_line":"    @base.remotable"}],"source_content_type":"text/x-python","patch_set":12,"id":"7af24918_1a8d6e7b","line":136,"in_reply_to":"7af24918_c1a67d0f","updated":"2016-03-02 16:58:48.000000000","message":"Right. And req_spec_obj is pulled out of self.obj_get_changes() so if we get here we know there\u0027s been a change in this area.","commit_id":"a90378735c29b6022442958934f5b6210a0f2a87"},{"author":{"_account_id":6873,"name":"Matt Riedemann","email":"mriedem.os@gmail.com","username":"mriedem"},"change_message_id":"52ff7392bcc46d15778a99d934cf5faa238c2bf9","unresolved":false,"context_lines":[{"line_number":139,"context_line":"    @base.remotable"},{"line_number":140,"context_line":"    def create(self):"},{"line_number":141,"context_line":"        if self.obj_attr_is_set(\u0027id\u0027):"},{"line_number":142,"context_line":"            raise exception.ObjectActionError(action\u003d\u0027create\u0027,"},{"line_number":143,"context_line":"                                              reason\u003d\u0027already created\u0027)"},{"line_number":144,"context_line":""},{"line_number":145,"context_line":"        updates \u003d self._get_update_primitives()"},{"line_number":146,"context_line":"        db_req \u003d self._create_in_db(self._context, updates)"}],"source_content_type":"text/x-python","patch_set":12,"id":"7af24918_f4841cd5","line":143,"range":{"start_line":142,"start_character":46,"end_line":143,"end_character":70},"updated":"2016-03-02 16:13:38.000000000","message":"Something tells me these should be marked for translation, but this is a pattern that\u0027s used in a bunch of objects so it would have to be dealt with separately.","commit_id":"a90378735c29b6022442958934f5b6210a0f2a87"},{"author":{"_account_id":6873,"name":"Matt Riedemann","email":"mriedem.os@gmail.com","username":"mriedem"},"change_message_id":"5377a465cfb3991c9b0e6599d2d29407382e4218","unresolved":false,"context_lines":[{"line_number":139,"context_line":"    @base.remotable"},{"line_number":140,"context_line":"    def create(self):"},{"line_number":141,"context_line":"        if self.obj_attr_is_set(\u0027id\u0027):"},{"line_number":142,"context_line":"            raise exception.ObjectActionError(action\u003d\u0027create\u0027,"},{"line_number":143,"context_line":"                                              reason\u003d\u0027already created\u0027)"},{"line_number":144,"context_line":""},{"line_number":145,"context_line":"        updates \u003d self._get_update_primitives()"},{"line_number":146,"context_line":"        db_req \u003d self._create_in_db(self._context, updates)"}],"source_content_type":"text/x-python","patch_set":12,"id":"7af24918_3783239a","line":143,"range":{"start_line":142,"start_character":46,"end_line":143,"end_character":70},"in_reply_to":"7af24918_17d8a71c","updated":"2016-03-02 16:37:17.000000000","message":"Right, but someone using es would get something like:\n\n\u0027spanish spanish spanish create spanish already created\u0027\n\nWe\u0027ve had similar issues in other exception messages that take kwargs like this for operations that are hard-coded in English.","commit_id":"a90378735c29b6022442958934f5b6210a0f2a87"},{"author":{"_account_id":5441,"name":"Andrew Laski","email":"andrew@lascii.com","username":"alaski"},"change_message_id":"d8f1556a6b357ea82b44283ada6b1465d558b5b0","unresolved":false,"context_lines":[{"line_number":139,"context_line":"    @base.remotable"},{"line_number":140,"context_line":"    def create(self):"},{"line_number":141,"context_line":"        if self.obj_attr_is_set(\u0027id\u0027):"},{"line_number":142,"context_line":"            raise exception.ObjectActionError(action\u003d\u0027create\u0027,"},{"line_number":143,"context_line":"                                              reason\u003d\u0027already created\u0027)"},{"line_number":144,"context_line":""},{"line_number":145,"context_line":"        updates \u003d self._get_update_primitives()"},{"line_number":146,"context_line":"        db_req \u003d self._create_in_db(self._context, updates)"}],"source_content_type":"text/x-python","patch_set":12,"id":"7af24918_17d8a71c","line":143,"range":{"start_line":142,"start_character":46,"end_line":143,"end_character":70},"in_reply_to":"7af24918_f4841cd5","updated":"2016-03-02 16:34:49.000000000","message":"The exception message is marked for translation, so these are put into a string marked for translation.","commit_id":"a90378735c29b6022442958934f5b6210a0f2a87"},{"author":{"_account_id":6873,"name":"Matt Riedemann","email":"mriedem.os@gmail.com","username":"mriedem"},"change_message_id":"b2666e58a586591a3b934bd070d0779288a83c3e","unresolved":false,"context_lines":[{"line_number":96,"context_line":"    def _get_by_instance_uuid_from_db(context, instance_uuid):"},{"line_number":97,"context_line":"        db_req \u003d (context.session.query(api_models.BuildRequest)"},{"line_number":98,"context_line":"                .join(api_models.RequestSpec)"},{"line_number":99,"context_line":"                .with_entities(api_models.BuildRequest,"},{"line_number":100,"context_line":"                               api_models.RequestSpec)"},{"line_number":101,"context_line":"                .filter("},{"line_number":102,"context_line":"                    api_models.RequestSpec.instance_uuid \u003d\u003d instance_uuid)"},{"line_number":103,"context_line":"                ).first()"}],"source_content_type":"text/x-python","patch_set":13,"id":"7af24918_451387b8","line":100,"range":{"start_line":99,"start_character":16,"end_line":100,"end_character":54},"updated":"2016-03-02 19:53:05.000000000","message":"I think I\u0027d prefer a backref in the API model just because I\u0027m used to that with the other models we have in the nova database, but we could always change that later if we wanted.","commit_id":"3dd185e37bd0abeeb960dbfbbc8cb6e249a6f18d"},{"author":{"_account_id":782,"name":"John Garbutt","email":"john@johngarbutt.com","username":"johngarbutt"},"change_message_id":"28c8ad7b216859337c1408ca1a28804aac3faf89","unresolved":false,"context_lines":[{"line_number":96,"context_line":"    def _get_by_instance_uuid_from_db(context, instance_uuid):"},{"line_number":97,"context_line":"        db_req \u003d (context.session.query(api_models.BuildRequest)"},{"line_number":98,"context_line":"                .join(api_models.RequestSpec)"},{"line_number":99,"context_line":"                .with_entities(api_models.BuildRequest,"},{"line_number":100,"context_line":"                               api_models.RequestSpec)"},{"line_number":101,"context_line":"                .filter("},{"line_number":102,"context_line":"                    api_models.RequestSpec.instance_uuid \u003d\u003d instance_uuid)"},{"line_number":103,"context_line":"                ).first()"}],"source_content_type":"text/x-python","patch_set":13,"id":"7af24918_b701c16c","line":100,"range":{"start_line":99,"start_character":16,"end_line":100,"end_character":54},"in_reply_to":"7af24918_451387b8","updated":"2016-03-03 09:15:18.000000000","message":"I am the same actually, later on in the series, but yeah, its a clean up thing.","commit_id":"3dd185e37bd0abeeb960dbfbbc8cb6e249a6f18d"}],"nova/tests/functional/db/test_build_request.py":[{"author":{"_account_id":6873,"name":"Matt Riedemann","email":"mriedem.os@gmail.com","username":"mriedem"},"change_message_id":"05328f53a79997e9d08d7e6d53fbb0f8ebd72580","unresolved":false,"context_lines":[{"line_number":26,"context_line":"class BuildRequestTestCase(test.NoDBTestCase):"},{"line_number":27,"context_line":"    def setUp(self):"},{"line_number":28,"context_line":"        super(BuildRequestTestCase, self).setUp()"},{"line_number":29,"context_line":"        # NOTE: This means that we\u0027re using a database for this test suite"},{"line_number":30,"context_line":"        # despite inheriting from NoDBTestCase"},{"line_number":31,"context_line":"        self.useFixture(fixtures.Database(database\u003d\u0027api\u0027))"},{"line_number":32,"context_line":"        self.context \u003d context.RequestContext(\u0027fake-user\u0027, \u0027fake-project\u0027)"},{"line_number":33,"context_line":"        self.build_req_obj \u003d build_request.BuildRequest()"}],"source_content_type":"text/x-python","patch_set":12,"id":"7af24918_41af0d81","line":30,"range":{"start_line":29,"start_character":8,"end_line":30,"end_character":46},"updated":"2016-03-02 16:19:15.000000000","message":"I guess this is because TestCase assumes you\u0027re using the nova database, but we aren\u0027t.","commit_id":"a90378735c29b6022442958934f5b6210a0f2a87"},{"author":{"_account_id":5441,"name":"Andrew Laski","email":"andrew@lascii.com","username":"alaski"},"change_message_id":"3dec225e9aa02b68e93bcb0a5567dc5caa82eb77","unresolved":false,"context_lines":[{"line_number":26,"context_line":"class BuildRequestTestCase(test.NoDBTestCase):"},{"line_number":27,"context_line":"    def setUp(self):"},{"line_number":28,"context_line":"        super(BuildRequestTestCase, self).setUp()"},{"line_number":29,"context_line":"        # NOTE: This means that we\u0027re using a database for this test suite"},{"line_number":30,"context_line":"        # despite inheriting from NoDBTestCase"},{"line_number":31,"context_line":"        self.useFixture(fixtures.Database(database\u003d\u0027api\u0027))"},{"line_number":32,"context_line":"        self.context \u003d context.RequestContext(\u0027fake-user\u0027, \u0027fake-project\u0027)"},{"line_number":33,"context_line":"        self.build_req_obj \u003d build_request.BuildRequest()"}],"source_content_type":"text/x-python","patch_set":12,"id":"7af24918_7a0632cf","line":30,"range":{"start_line":29,"start_character":8,"end_line":30,"end_character":46},"in_reply_to":"7af24918_41af0d81","updated":"2016-03-02 16:58:48.000000000","message":"Right. Ultimately we could probably use a test.APIDBTestCase rather than doing this.","commit_id":"a90378735c29b6022442958934f5b6210a0f2a87"},{"author":{"_account_id":6873,"name":"Matt Riedemann","email":"mriedem.os@gmail.com","username":"mriedem"},"change_message_id":"05328f53a79997e9d08d7e6d53fbb0f8ebd72580","unresolved":false,"context_lines":[{"line_number":56,"context_line":"        req \u003d self._create_req()"},{"line_number":57,"context_line":"        db_req \u003d self.build_req_obj._get_by_instance_uuid_from_db(self.context,"},{"line_number":58,"context_line":"                self.instance_uuid)"},{"line_number":59,"context_line":"        object_fields \u003d [\u0027info_cache\u0027, \u0027security_groups\u0027]"},{"line_number":60,"context_line":"        json_fields \u003d [\u0027instance_metadata\u0027]"},{"line_number":61,"context_line":"        ip_fields \u003d [\u0027access_ip_v4\u0027, \u0027access_ip_v6\u0027]"},{"line_number":62,"context_line":"        for key in self.build_req_obj.fields.keys():"},{"line_number":63,"context_line":"            expected \u003d getattr(req, key)"},{"line_number":64,"context_line":"            db_value \u003d db_req[key]"}],"source_content_type":"text/x-python","patch_set":12,"id":"7af24918_4179cdf5","line":61,"range":{"start_line":59,"start_character":8,"end_line":61,"end_character":52},"updated":"2016-03-02 16:19:15.000000000","message":"We should maybe make these constants in the BuildRequest object module so we don\u0027t have to copy/paste this around.","commit_id":"a90378735c29b6022442958934f5b6210a0f2a87"},{"author":{"_account_id":6873,"name":"Matt Riedemann","email":"mriedem.os@gmail.com","username":"mriedem"},"change_message_id":"05328f53a79997e9d08d7e6d53fbb0f8ebd72580","unresolved":false,"context_lines":[{"line_number":75,"context_line":"                expected \u003d jsonutils.dumps(expected)"},{"line_number":76,"context_line":"            elif key in ip_fields:"},{"line_number":77,"context_line":"                expected \u003d str(expected)"},{"line_number":78,"context_line":"            elif key in [\u0027created_at\u0027, \u0027updated_at\u0027]:"},{"line_number":79,"context_line":"                # Objects store tz aware datetimes but the db does not."},{"line_number":80,"context_line":"                expected \u003d expected.replace(tzinfo\u003dNone)"},{"line_number":81,"context_line":"            self.assertEqual(expected, db_value)"}],"source_content_type":"text/x-python","patch_set":12,"id":"7af24918_6167a925","line":78,"range":{"start_line":78,"start_character":24,"end_line":78,"end_character":52},"updated":"2016-03-02 16:19:15.000000000","message":"nit: there is probably a way to determine the type from the field and if it\u0027s a DateTimeField then do the tz stuff, but meh.","commit_id":"a90378735c29b6022442958934f5b6210a0f2a87"}],"nova/tests/unit/fake_build_request.py":[{"author":{"_account_id":6873,"name":"Matt Riedemann","email":"mriedem.os@gmail.com","username":"mriedem"},"change_message_id":"5a4cd1184fb48e742701d46f4b21261872f8bcb7","unresolved":false,"context_lines":[{"line_number":89,"context_line":"        # create() can\u0027t be called if this is set"},{"line_number":90,"context_line":"        if field \u003d\u003d \u0027id\u0027:"},{"line_number":91,"context_line":"            continue"},{"line_number":92,"context_line":"        if isinstance(req_obj.fields[field], fields.ObjectField):"},{"line_number":93,"context_line":"            value \u003d value"},{"line_number":94,"context_line":"            if field \u003d\u003d \u0027request_spec\u0027:"},{"line_number":95,"context_line":"                req_spec \u003d objects.RequestSpec._from_db_object(context,"},{"line_number":96,"context_line":"                        objects.RequestSpec(), value)"},{"line_number":97,"context_line":"                req_obj.request_spec \u003d req_spec"},{"line_number":98,"context_line":"            elif field \u003d\u003d \u0027info_cache\u0027:"},{"line_number":99,"context_line":"                setattr(req_obj, field,"},{"line_number":100,"context_line":"                        objects.InstanceInfoCache.obj_from_primitive("},{"line_number":101,"context_line":"                            jsonutils.loads(value)))"},{"line_number":102,"context_line":"            elif field \u003d\u003d \u0027security_groups\u0027:"},{"line_number":103,"context_line":"                setattr(req_obj, field,"},{"line_number":104,"context_line":"                        objects.SecurityGroupList.obj_from_primitive("},{"line_number":105,"context_line":"                            jsonutils.loads(value)))"},{"line_number":106,"context_line":"        elif field \u003d\u003d \u0027instance_metadata\u0027:"},{"line_number":107,"context_line":"            setattr(req_obj, field, jsonutils.loads(value))"},{"line_number":108,"context_line":"        else:"},{"line_number":109,"context_line":"            setattr(req_obj, field, value)"},{"line_number":110,"context_line":"    # This should never be a changed field"},{"line_number":111,"context_line":"    req_obj.obj_reset_changes([\u0027id\u0027])"},{"line_number":112,"context_line":"    return req_obj"}],"source_content_type":"text/x-python","patch_set":12,"id":"7af24918_b759f300","line":109,"range":{"start_line":92,"start_character":8,"end_line":109,"end_character":42},"updated":"2016-03-02 16:32:47.000000000","message":"Can\u0027t we re-use BuildRequest._from_db_object for a lot of this since the logic is duplicated?","commit_id":"a90378735c29b6022442958934f5b6210a0f2a87"},{"author":{"_account_id":6873,"name":"Matt Riedemann","email":"mriedem.os@gmail.com","username":"mriedem"},"change_message_id":"05ff8664d779f061703a82b26916261db0f1c2c8","unresolved":false,"context_lines":[{"line_number":89,"context_line":"        # create() can\u0027t be called if this is set"},{"line_number":90,"context_line":"        if field \u003d\u003d \u0027id\u0027:"},{"line_number":91,"context_line":"            continue"},{"line_number":92,"context_line":"        if isinstance(req_obj.fields[field], fields.ObjectField):"},{"line_number":93,"context_line":"            value \u003d value"},{"line_number":94,"context_line":"            if field \u003d\u003d \u0027request_spec\u0027:"},{"line_number":95,"context_line":"                req_spec \u003d objects.RequestSpec._from_db_object(context,"},{"line_number":96,"context_line":"                        objects.RequestSpec(), value)"},{"line_number":97,"context_line":"                req_obj.request_spec \u003d req_spec"},{"line_number":98,"context_line":"            elif field \u003d\u003d \u0027info_cache\u0027:"},{"line_number":99,"context_line":"                setattr(req_obj, field,"},{"line_number":100,"context_line":"                        objects.InstanceInfoCache.obj_from_primitive("},{"line_number":101,"context_line":"                            jsonutils.loads(value)))"},{"line_number":102,"context_line":"            elif field \u003d\u003d \u0027security_groups\u0027:"},{"line_number":103,"context_line":"                setattr(req_obj, field,"},{"line_number":104,"context_line":"                        objects.SecurityGroupList.obj_from_primitive("},{"line_number":105,"context_line":"                            jsonutils.loads(value)))"},{"line_number":106,"context_line":"        elif field \u003d\u003d \u0027instance_metadata\u0027:"},{"line_number":107,"context_line":"            setattr(req_obj, field, jsonutils.loads(value))"},{"line_number":108,"context_line":"        else:"},{"line_number":109,"context_line":"            setattr(req_obj, field, value)"},{"line_number":110,"context_line":"    # This should never be a changed field"},{"line_number":111,"context_line":"    req_obj.obj_reset_changes([\u0027id\u0027])"},{"line_number":112,"context_line":"    return req_obj"}],"source_content_type":"text/x-python","patch_set":12,"id":"7af24918_c2f4b088","line":109,"range":{"start_line":92,"start_character":8,"end_line":109,"end_character":42},"in_reply_to":"7af24918_9aeb3eb0","updated":"2016-03-02 18:41:45.000000000","message":"OK, I figured it was something like that. Maybe Dan has ideas, but it\u0027s not the end of the world if we can\u0027t pretty it up - and that could always come later too.","commit_id":"a90378735c29b6022442958934f5b6210a0f2a87"},{"author":{"_account_id":5441,"name":"Andrew Laski","email":"andrew@lascii.com","username":"alaski"},"change_message_id":"3dec225e9aa02b68e93bcb0a5567dc5caa82eb77","unresolved":false,"context_lines":[{"line_number":89,"context_line":"        # create() can\u0027t be called if this is set"},{"line_number":90,"context_line":"        if field \u003d\u003d \u0027id\u0027:"},{"line_number":91,"context_line":"            continue"},{"line_number":92,"context_line":"        if isinstance(req_obj.fields[field], fields.ObjectField):"},{"line_number":93,"context_line":"            value \u003d value"},{"line_number":94,"context_line":"            if field \u003d\u003d \u0027request_spec\u0027:"},{"line_number":95,"context_line":"                req_spec \u003d objects.RequestSpec._from_db_object(context,"},{"line_number":96,"context_line":"                        objects.RequestSpec(), value)"},{"line_number":97,"context_line":"                req_obj.request_spec \u003d req_spec"},{"line_number":98,"context_line":"            elif field \u003d\u003d \u0027info_cache\u0027:"},{"line_number":99,"context_line":"                setattr(req_obj, field,"},{"line_number":100,"context_line":"                        objects.InstanceInfoCache.obj_from_primitive("},{"line_number":101,"context_line":"                            jsonutils.loads(value)))"},{"line_number":102,"context_line":"            elif field \u003d\u003d \u0027security_groups\u0027:"},{"line_number":103,"context_line":"                setattr(req_obj, field,"},{"line_number":104,"context_line":"                        objects.SecurityGroupList.obj_from_primitive("},{"line_number":105,"context_line":"                            jsonutils.loads(value)))"},{"line_number":106,"context_line":"        elif field \u003d\u003d \u0027instance_metadata\u0027:"},{"line_number":107,"context_line":"            setattr(req_obj, field, jsonutils.loads(value))"},{"line_number":108,"context_line":"        else:"},{"line_number":109,"context_line":"            setattr(req_obj, field, value)"},{"line_number":110,"context_line":"    # This should never be a changed field"},{"line_number":111,"context_line":"    req_obj.obj_reset_changes([\u0027id\u0027])"},{"line_number":112,"context_line":"    return req_obj"}],"source_content_type":"text/x-python","patch_set":12,"id":"7af24918_9aeb3eb0","line":109,"range":{"start_line":92,"start_character":8,"end_line":109,"end_character":42},"in_reply_to":"7af24918_b759f300","updated":"2016-03-02 16:58:48.000000000","message":"I attempted that. We can\u0027t because _from_db_object assumes \u0027id\u0027 is being set and we specifically need to not set it in some cases here. If I modify _from_db_object to not require \u0027id\u0027 we lose the protection there that we should have which requires it to be set on a model from the db. And there is no mechanism for unsetting a field on an object. It can be nulled but not unset.","commit_id":"a90378735c29b6022442958934f5b6210a0f2a87"}],"nova/tests/unit/objects/test_build_request.py":[{"author":{"_account_id":6873,"name":"Matt Riedemann","email":"mriedem.os@gmail.com","username":"mriedem"},"change_message_id":"97cac155e7dca1927e6ae20c14fe28f4f370fe2e","unresolved":false,"context_lines":[{"line_number":45,"context_line":"        req_obj \u003d fake_build_request.fake_req_obj(self.context, fake_req)"},{"line_number":46,"context_line":""},{"line_number":47,"context_line":"        def _test_create_args(self2, context, changes):"},{"line_number":48,"context_line":"            # This is being tested this way because the json strings for the"},{"line_number":49,"context_line":"            # object fields don\u0027t always match even when the object primitives"},{"line_number":50,"context_line":"            # do."},{"line_number":51,"context_line":""},{"line_number":52,"context_line":"            # primitive fields"},{"line_number":53,"context_line":"            for field in [\u0027project_id\u0027, \u0027user_id\u0027, \u0027display_name\u0027, \u0027progress\u0027,"}],"source_content_type":"text/x-python","patch_set":12,"id":"7af24918_f7f9bb81","line":50,"range":{"start_line":48,"start_character":12,"end_line":50,"end_character":17},"updated":"2016-03-02 16:35:56.000000000","message":"Doesn\u0027t the StableObjectJsonFixture handle this for us?\n\nhttps://github.com/openstack/nova/blob/master/nova/tests/fixtures.py#L454\n\nYou might have written this test before that was a thing.","commit_id":"a90378735c29b6022442958934f5b6210a0f2a87"},{"author":{"_account_id":5441,"name":"Andrew Laski","email":"andrew@lascii.com","username":"alaski"},"change_message_id":"3dec225e9aa02b68e93bcb0a5567dc5caa82eb77","unresolved":false,"context_lines":[{"line_number":45,"context_line":"        req_obj \u003d fake_build_request.fake_req_obj(self.context, fake_req)"},{"line_number":46,"context_line":""},{"line_number":47,"context_line":"        def _test_create_args(self2, context, changes):"},{"line_number":48,"context_line":"            # This is being tested this way because the json strings for the"},{"line_number":49,"context_line":"            # object fields don\u0027t always match even when the object primitives"},{"line_number":50,"context_line":"            # do."},{"line_number":51,"context_line":""},{"line_number":52,"context_line":"            # primitive fields"},{"line_number":53,"context_line":"            for field in [\u0027project_id\u0027, \u0027user_id\u0027, \u0027display_name\u0027, \u0027progress\u0027,"}],"source_content_type":"text/x-python","patch_set":12,"id":"7af24918_7a611239","line":50,"range":{"start_line":48,"start_character":12,"end_line":50,"end_character":17},"in_reply_to":"7af24918_f7f9bb81","updated":"2016-03-02 16:58:48.000000000","message":"It may. I don\u0027t think it was a thing when I started on this, but I\u0027ll try it out.","commit_id":"a90378735c29b6022442958934f5b6210a0f2a87"}]}
