)]}'
{"nova/db/sqlalchemy/resource_class_cache.py":[{"author":{"_account_id":11564,"name":"Chris Dent","email":"cdent@anticdent.org","username":"chdent"},"change_message_id":"83091f6dd2fc547976f311cd8aad1982d2666d78","unresolved":false,"context_lines":[{"line_number":44,"context_line":""},{"line_number":45,"context_line":"    :param cache: ResourceClassCache object to refresh."},{"line_number":46,"context_line":"    \"\"\""},{"line_number":47,"context_line":"    conn \u003d ctx.session.connection()"},{"line_number":48,"context_line":"    sel \u003d sa.select([_RC_TBL.c.id, _RC_TBL.c.name])"},{"line_number":49,"context_line":"    res \u003d conn.execute(sel).fetchall()"},{"line_number":50,"context_line":"    cache.id_cache \u003d {r[1]: r[0] for r in res}"}],"source_content_type":"text/x-python","patch_set":1,"id":"ba5da102_ffd79aea","line":47,"updated":"2016-11-01 10:53:08.000000000","message":"I\u0027m not entirely clear, even with your note in the commit quite what\u0027s going on here.\n\nIs this connection is being allowed to be left open, always? If so, does it make sense to remove the context manager decorator so that it is clear that the caller is supposed to be a context manager of some kind?\n\nOr is it instead that the \u0027with\u0027 statement was redundant because of the decorator and this is cleaning that up?","commit_id":"7f0ff54adf50a8d64dbc25094f4aef68c0ef4111"},{"author":{"_account_id":6849,"name":"Roman Podoliaka","email":"roman.podoliaka@gmail.com","username":"rpodolyaka"},"change_message_id":"b32c342bde1958e68fa507e4d156c5dacb77cdd1","unresolved":false,"context_lines":[{"line_number":44,"context_line":""},{"line_number":45,"context_line":"    :param cache: ResourceClassCache object to refresh."},{"line_number":46,"context_line":"    \"\"\""},{"line_number":47,"context_line":"    conn \u003d ctx.session.connection()"},{"line_number":48,"context_line":"    sel \u003d sa.select([_RC_TBL.c.id, _RC_TBL.c.name])"},{"line_number":49,"context_line":"    res \u003d conn.execute(sel).fetchall()"},{"line_number":50,"context_line":"    cache.id_cache \u003d {r[1]: r[0] for r in res}"}],"source_content_type":"text/x-python","patch_set":1,"id":"ba5da102_f256e528","line":47,"in_reply_to":"ba5da102_b28b8dc2","updated":"2016-11-01 15:12:05.000000000","message":"I haven\u0027t checked the code up the stack yet, but just in case if you need a totally independent connection/transaction, you could do it like: https://github.com/openstack/nova/blob/master/nova/db/sqlalchemy/api.py#L4438","commit_id":"7f0ff54adf50a8d64dbc25094f4aef68c0ef4111"},{"author":{"_account_id":11816,"name":"mike bayer","display_name":"Mike Bayer","email":"mike_mp@zzzcomputing.com","username":"zzzeek","status":"Red Hat"},"change_message_id":"7a9454ea881a07dbf7ee9bcba58da4d8a1d81f5e","unresolved":false,"context_lines":[{"line_number":44,"context_line":""},{"line_number":45,"context_line":"    :param cache: ResourceClassCache object to refresh."},{"line_number":46,"context_line":"    \"\"\""},{"line_number":47,"context_line":"    conn \u003d ctx.session.connection()"},{"line_number":48,"context_line":"    sel \u003d sa.select([_RC_TBL.c.id, _RC_TBL.c.name])"},{"line_number":49,"context_line":"    res \u003d conn.execute(sel).fetchall()"},{"line_number":50,"context_line":"    cache.id_cache \u003d {r[1]: r[0] for r in res}"}],"source_content_type":"text/x-python","patch_set":1,"id":"ba5da102_b28b8dc2","line":47,"in_reply_to":"ba5da102_f2efc5e6","updated":"2016-11-01 15:09:57.000000000","message":"so yeah, there\u0027s a bunch of ways the \"with: \" can still be used here, but if it\u0027s \"session.connection() as conn\", that would close() the connection that\u0027s possibly already in use by the session for an enclosing transaction.   The enginefacade is likely the most appropriate:\n\n    with db_api.api_context_manager.reader.connection.using(ctx) as conn:\n        \u003c do stuff\u003e\n\nThe context manager there will make sure to use the connection owned by the Session, so you\u0027re in the same transaction, and it will make sure the scope of that connection stays appropriate to the calling context.","commit_id":"7f0ff54adf50a8d64dbc25094f4aef68c0ef4111"},{"author":{"_account_id":7,"name":"Jay Pipes","email":"jaypipes@gmail.com","username":"jaypipes"},"change_message_id":"54256a35aff222ac211ef99241061a4adecd027c","unresolved":false,"context_lines":[{"line_number":44,"context_line":""},{"line_number":45,"context_line":"    :param cache: ResourceClassCache object to refresh."},{"line_number":46,"context_line":"    \"\"\""},{"line_number":47,"context_line":"    conn \u003d ctx.session.connection()"},{"line_number":48,"context_line":"    sel \u003d sa.select([_RC_TBL.c.id, _RC_TBL.c.name])"},{"line_number":49,"context_line":"    res \u003d conn.execute(sel).fetchall()"},{"line_number":50,"context_line":"    cache.id_cache \u003d {r[1]: r[0] for r in res}"}],"source_content_type":"text/x-python","patch_set":1,"id":"ba5da102_f2efc5e6","line":47,"in_reply_to":"ba5da102_ffd79aea","updated":"2016-11-01 14:59:44.000000000","message":"This is kind of the issue with the way that the enginefacade stuff works. You can\u0027t really ever close() a connection that is either implicitly (via the enginefacade\u0027s transaction context decorators) or explicitly (like here with the with session.connection() ... context manager) managed.\n\nYou can\u0027t close() the connection because something that, for instance, creates or operates against multiple objects each instantiated with the same Context object will try to use a close()d SQLAlchemy connection to do some work and then everything goes boom!\n\nThe alternative to this is to have the SQLAlchemy enginefacade or Session.connection() stuff auto-reopen closed connections somehow, but I\u0027m unsure how to do something like that. :(","commit_id":"7f0ff54adf50a8d64dbc25094f4aef68c0ef4111"},{"author":{"_account_id":6849,"name":"Roman Podoliaka","email":"roman.podoliaka@gmail.com","username":"rpodolyaka"},"change_message_id":"937e4c9e9f0fbf2d878768dad2b345e29eff9750","unresolved":false,"context_lines":[{"line_number":38,"context_line":"            raise ValueError"},{"line_number":39,"context_line":""},{"line_number":40,"context_line":""},{"line_number":41,"context_line":"@db_api.api_context_manager.reader"},{"line_number":42,"context_line":"def _refresh_from_db(ctx, cache):"},{"line_number":43,"context_line":"    \"\"\"Grabs all custom resource classes from the DB table and populates the"},{"line_number":44,"context_line":"    supplied cache object\u0027s internal integer and string identifier dicts."}],"source_content_type":"text/x-python","patch_set":7,"id":"ba5da102_f143f8ac","line":41,"updated":"2016-11-03 10:15:50.000000000","message":"An alternative a bit more concise way to write the very same thing would be:\n\n@db_api.api_context_manager.reader.connection\n   def _refresh_from_db(ctx, cache):\n       \"\"\"Grabs all custom resource classes from the DB table and populates the\n       supplied cache object\u0027s internal integer and string identifier dicts.\n \n       :param cache: ResourceClassCache object to refresh.\n       \"\"\"\n      sel \u003d sa.select([_RC_TBL.c.id, _RC_TBL.c.name])\n      res \u003d ctx.connection.execute(sel).fetchall()\n      cache.id_cache \u003d {r[1]: r[0] for r in res}\n      cache.str_cache \u003d {r[0]: r[1] for r in res}\n\nbut functionally they are equivalent.\n\nProposed an addition to oslo.db docs: https://review.openstack.org/393213","commit_id":"a518660fff0fd2bb1e0863212806aaaf828366a7"},{"author":{"_account_id":6873,"name":"Matt Riedemann","email":"mriedem.os@gmail.com","username":"mriedem"},"change_message_id":"b35d0090f778017dd89cce79a0f1923cc579b278","unresolved":false,"context_lines":[{"line_number":65,"context_line":"        self.id_cache \u003d {}"},{"line_number":66,"context_line":"        self.str_cache \u003d {}"},{"line_number":67,"context_line":""},{"line_number":68,"context_line":"    def clear(self):"},{"line_number":69,"context_line":"        self.id_cache \u003d {}"},{"line_number":70,"context_line":"        self.str_cache \u003d {}"},{"line_number":71,"context_line":""}],"source_content_type":"text/x-python","patch_set":13,"id":"7a77a97e_9a01a63c","line":68,"updated":"2016-11-22 01:03:11.000000000","message":"Should we lock this with a shared lock that\u0027s also used with _refresh_from_db? Seems we wouldn\u0027t want those happening at the same time.","commit_id":"b2d70546717df7f9a72b8477a8c6573e75cecfc7"},{"author":{"_account_id":7,"name":"Jay Pipes","email":"jaypipes@gmail.com","username":"jaypipes"},"change_message_id":"5ab440a794f6539ce2f481ebbbda2b9ebec42316","unresolved":false,"context_lines":[{"line_number":65,"context_line":"        self.id_cache \u003d {}"},{"line_number":66,"context_line":"        self.str_cache \u003d {}"},{"line_number":67,"context_line":""},{"line_number":68,"context_line":"    def clear(self):"},{"line_number":69,"context_line":"        self.id_cache \u003d {}"},{"line_number":70,"context_line":"        self.str_cache \u003d {}"},{"line_number":71,"context_line":""}],"source_content_type":"text/x-python","patch_set":13,"id":"5a74a57a_a9bac56f","line":68,"in_reply_to":"5a74a57a_2aaf83e4","updated":"2016-11-29 17:05:29.000000000","message":"OK, updated to use a threading.Lock. I reworked the str_from_id() and id_from_string() methods to short-circuit the standard resource classes (constant lookup into an enum) before ever looking at or modifying the custom resource class cache values (while being protected by the lock). This should at least provide us with near zero performance impact for the majority of calls (which are against standard resource classes...)","commit_id":"b2d70546717df7f9a72b8477a8c6573e75cecfc7"},{"author":{"_account_id":6873,"name":"Matt Riedemann","email":"mriedem.os@gmail.com","username":"mriedem"},"change_message_id":"6f6fff32ba155f8e21bdd0546040fd1e6d463bd0","unresolved":false,"context_lines":[{"line_number":65,"context_line":"        self.id_cache \u003d {}"},{"line_number":66,"context_line":"        self.str_cache \u003d {}"},{"line_number":67,"context_line":""},{"line_number":68,"context_line":"    def clear(self):"},{"line_number":69,"context_line":"        self.id_cache \u003d {}"},{"line_number":70,"context_line":"        self.str_cache \u003d {}"},{"line_number":71,"context_line":""}],"source_content_type":"text/x-python","patch_set":13,"id":"5a74a57a_2aaf83e4","line":68,"in_reply_to":"7a77a97e_95a87079","updated":"2016-11-23 02:15:35.000000000","message":"Locking on _refresh_from_db probably wouldn\u0027t be good enough. For example, we could be in string_from_id and call _refresh_from_db which populates str_cache, but before we access self.str_cache[rc_id], clear() runs and wipes str_cache out, so we get a KeyError in string_from_id. So if we lock on clear(), we also need to use the same lock on string_from_id and id_from_string, at least in the sections of those methods that use _refresh_from_db. They are small blocks but they could help us avoid a KeyError slipping through up to the REST API which is going to leak as a 500 error.","commit_id":"b2d70546717df7f9a72b8477a8c6573e75cecfc7"},{"author":{"_account_id":7,"name":"Jay Pipes","email":"jaypipes@gmail.com","username":"jaypipes"},"change_message_id":"d85e27cdecb092ec96ff1733ff74a5420fd052cf","unresolved":false,"context_lines":[{"line_number":65,"context_line":"        self.id_cache \u003d {}"},{"line_number":66,"context_line":"        self.str_cache \u003d {}"},{"line_number":67,"context_line":""},{"line_number":68,"context_line":"    def clear(self):"},{"line_number":69,"context_line":"        self.id_cache \u003d {}"},{"line_number":70,"context_line":"        self.str_cache \u003d {}"},{"line_number":71,"context_line":""}],"source_content_type":"text/x-python","patch_set":13,"id":"7a77a97e_95a87079","line":68,"in_reply_to":"7a77a97e_9a01a63c","updated":"2016-11-22 16:00:14.000000000","message":"yeah, I considered doing that. wasn\u0027t sure it was necessary to care about it really but I suppose I can do it if you think so.","commit_id":"b2d70546717df7f9a72b8477a8c6573e75cecfc7"},{"author":{"_account_id":782,"name":"John Garbutt","email":"john@johngarbutt.com","username":"johngarbutt"},"change_message_id":"982d4ddc72350065be913a999a8c9f6879b46814","unresolved":false,"context_lines":[{"line_number":63,"context_line":"                    `SQLAlchemy.Connection` object to use for any DB lookups."},{"line_number":64,"context_line":"        \"\"\""},{"line_number":65,"context_line":"        self.ctx \u003d ctx"},{"line_number":66,"context_line":"        self.lock \u003d threading.Lock()"},{"line_number":67,"context_line":"        self.id_cache \u003d {}"},{"line_number":68,"context_line":"        self.str_cache \u003d {}"},{"line_number":69,"context_line":""}],"source_content_type":"text/x-python","patch_set":15,"id":"5a74a57a_b625945d","line":66,"updated":"2016-11-30 14:29:32.000000000","message":"Nit: I was kinda expecting us to use the oslo concurrency synchronized thingy.","commit_id":"7963db0641897710ce3dc3616e8a6e523e251011"},{"author":{"_account_id":7,"name":"Jay Pipes","email":"jaypipes@gmail.com","username":"jaypipes"},"change_message_id":"7a6fb56963ff5af7f37a966997cbbbcf26b89c51","unresolved":false,"context_lines":[{"line_number":63,"context_line":"                    `SQLAlchemy.Connection` object to use for any DB lookups."},{"line_number":64,"context_line":"        \"\"\""},{"line_number":65,"context_line":"        self.ctx \u003d ctx"},{"line_number":66,"context_line":"        self.lock \u003d threading.Lock()"},{"line_number":67,"context_line":"        self.id_cache \u003d {}"},{"line_number":68,"context_line":"        self.str_cache \u003d {}"},{"line_number":69,"context_line":""}],"source_content_type":"text/x-python","patch_set":15,"id":"5a74a57a_c61099ab","line":66,"in_reply_to":"5a74a57a_b625945d","updated":"2016-11-30 15:46:34.000000000","message":"done.","commit_id":"7963db0641897710ce3dc3616e8a6e523e251011"},{"author":{"_account_id":782,"name":"John Garbutt","email":"john@johngarbutt.com","username":"johngarbutt"},"change_message_id":"982d4ddc72350065be913a999a8c9f6879b46814","unresolved":false,"context_lines":[{"line_number":98,"context_line":"        \"\"\""},{"line_number":99,"context_line":"        # First check the standard resource classes"},{"line_number":100,"context_line":"        if rc_str in fields.ResourceClass.STANDARD:"},{"line_number":101,"context_line":"            return fields.ResourceClass.STANDARD.index(rc_str)"},{"line_number":102,"context_line":""},{"line_number":103,"context_line":"        with self.lock:"},{"line_number":104,"context_line":"            if rc_str in self.id_cache:"}],"source_content_type":"text/x-python","patch_set":15,"id":"5a74a57a_96bed8d2","line":101,"updated":"2016-11-30 14:29:32.000000000","message":"loving the short circuit","commit_id":"7963db0641897710ce3dc3616e8a6e523e251011"},{"author":{"_account_id":782,"name":"John Garbutt","email":"john@johngarbutt.com","username":"johngarbutt"},"change_message_id":"982d4ddc72350065be913a999a8c9f6879b46814","unresolved":false,"context_lines":[{"line_number":104,"context_line":"            if rc_str in self.id_cache:"},{"line_number":105,"context_line":"                return self.id_cache[rc_str]"},{"line_number":106,"context_line":"            # Otherwise, check the database table"},{"line_number":107,"context_line":"            _refresh_from_db(self.ctx, self)"},{"line_number":108,"context_line":"            if rc_str in self.id_cache:"},{"line_number":109,"context_line":"                return self.id_cache[rc_str]"},{"line_number":110,"context_line":"            raise exception.ResourceClassNotFound(resource_class\u003drc_str)"},{"line_number":111,"context_line":""},{"line_number":112,"context_line":"    def string_from_id(self, rc_id):"}],"source_content_type":"text/x-python","patch_set":15,"id":"5a74a57a_7673fcb4","line":109,"range":{"start_line":107,"start_character":0,"end_line":109,"end_character":44},"updated":"2016-11-30 14:29:32.000000000","message":"Don\u0027t we have a similar issue here, clear could be called right after fetching things from the DB? Then we end up incorrectly raising an exception even though its in the DB?\n\nSomething tells me eventlet doesn\u0027t have a yield point after we get info back from the DB, although there could be one triggered in the context manager exit, I guess.","commit_id":"7963db0641897710ce3dc3616e8a6e523e251011"},{"author":{"_account_id":7,"name":"Jay Pipes","email":"jaypipes@gmail.com","username":"jaypipes"},"change_message_id":"7a6fb56963ff5af7f37a966997cbbbcf26b89c51","unresolved":false,"context_lines":[{"line_number":104,"context_line":"            if rc_str in self.id_cache:"},{"line_number":105,"context_line":"                return self.id_cache[rc_str]"},{"line_number":106,"context_line":"            # Otherwise, check the database table"},{"line_number":107,"context_line":"            _refresh_from_db(self.ctx, self)"},{"line_number":108,"context_line":"            if rc_str in self.id_cache:"},{"line_number":109,"context_line":"                return self.id_cache[rc_str]"},{"line_number":110,"context_line":"            raise exception.ResourceClassNotFound(resource_class\u003drc_str)"},{"line_number":111,"context_line":""},{"line_number":112,"context_line":"    def string_from_id(self, rc_id):"}],"source_content_type":"text/x-python","patch_set":15,"id":"5a74a57a_46ee49ed","line":109,"range":{"start_line":107,"start_character":0,"end_line":109,"end_character":44},"in_reply_to":"5a74a57a_7673fcb4","updated":"2016-11-30 15:46:34.000000000","message":"The lock will prevent changes to the self.id_cache and self.str_cache attributes by different threads, and we\u0027re not reading or writing from those attributes unless we have acquired the lock. I don\u0027t think this has anything to do with DB yields?","commit_id":"7963db0641897710ce3dc3616e8a6e523e251011"},{"author":{"_account_id":782,"name":"John Garbutt","email":"john@johngarbutt.com","username":"johngarbutt"},"change_message_id":"982d4ddc72350065be913a999a8c9f6879b46814","unresolved":false,"context_lines":[{"line_number":138,"context_line":"            _refresh_from_db(self.ctx, self)"},{"line_number":139,"context_line":"            if rc_id in self.str_cache:"},{"line_number":140,"context_line":"                return self.str_cache[rc_id]"},{"line_number":141,"context_line":"            raise exception.ResourceClassNotFound(resource_class\u003drc_id)"}],"source_content_type":"text/x-python","patch_set":15,"id":"5a74a57a_1693a8a4","line":141,"updated":"2016-11-30 14:29:32.000000000","message":"similar worries as above.","commit_id":"7963db0641897710ce3dc3616e8a6e523e251011"},{"author":{"_account_id":6873,"name":"Matt Riedemann","email":"mriedem.os@gmail.com","username":"mriedem"},"change_message_id":"f407b1fd213fd888f4ff22db12df9af99f1cee50","unresolved":false,"context_lines":[{"line_number":73,"context_line":"            self.str_cache \u003d {}"},{"line_number":74,"context_line":""},{"line_number":75,"context_line":"    def get_standards(self):"},{"line_number":76,"context_line":"        \"\"\"Return a list of {\u0027id\u0027: \u003cID\u003e, \u0027name\u0027: \u003cNAME\u003e for all standard"},{"line_number":77,"context_line":"        resource classes."},{"line_number":78,"context_line":"        \"\"\""},{"line_number":79,"context_line":"        return [{\u0027id\u0027: fields.ResourceClass.STANDARD.index(s), \u0027name\u0027: s}"}],"source_content_type":"text/x-python","patch_set":17,"id":"5a74a57a_2e3f4d26","line":76,"range":{"start_line":76,"start_character":55,"end_line":76,"end_character":56},"updated":"2016-12-01 00:21:33.000000000","message":"oops, unrelated, but missing closing } here.","commit_id":"d1c75df6793274fbbca92acbbde821c436a36c76"},{"author":{"_account_id":7,"name":"Jay Pipes","email":"jaypipes@gmail.com","username":"jaypipes"},"change_message_id":"ef022b17c9e56428dc345468106cc69fb3a85c74","unresolved":false,"context_lines":[{"line_number":73,"context_line":"            self.str_cache \u003d {}"},{"line_number":74,"context_line":""},{"line_number":75,"context_line":"    def get_standards(self):"},{"line_number":76,"context_line":"        \"\"\"Return a list of {\u0027id\u0027: \u003cID\u003e, \u0027name\u0027: \u003cNAME\u003e for all standard"},{"line_number":77,"context_line":"        resource classes."},{"line_number":78,"context_line":"        \"\"\""},{"line_number":79,"context_line":"        return [{\u0027id\u0027: fields.ResourceClass.STANDARD.index(s), \u0027name\u0027: s}"}],"source_content_type":"text/x-python","patch_set":17,"id":"5a74a57a_119c765c","line":76,"range":{"start_line":76,"start_character":55,"end_line":76,"end_character":56},"in_reply_to":"5a74a57a_2e3f4d26","updated":"2016-12-01 00:48:08.000000000","message":"Sure, will fix in a later patch :)","commit_id":"d1c75df6793274fbbca92acbbde821c436a36c76"},{"author":{"_account_id":6873,"name":"Matt Riedemann","email":"mriedem.os@gmail.com","username":"mriedem"},"change_message_id":"f407b1fd213fd888f4ff22db12df9af99f1cee50","unresolved":false,"context_lines":[{"line_number":76,"context_line":"        \"\"\"Return a list of {\u0027id\u0027: \u003cID\u003e, \u0027name\u0027: \u003cNAME\u003e for all standard"},{"line_number":77,"context_line":"        resource classes."},{"line_number":78,"context_line":"        \"\"\""},{"line_number":79,"context_line":"        return [{\u0027id\u0027: fields.ResourceClass.STANDARD.index(s), \u0027name\u0027: s}"},{"line_number":80,"context_line":"                for s in fields.ResourceClass.STANDARD]"},{"line_number":81,"context_line":""},{"line_number":82,"context_line":"    def id_from_string(self, rc_str):"},{"line_number":83,"context_line":"        \"\"\"Given a string representation of a resource class -- e.g. \"DISK_GB\""}],"source_content_type":"text/x-python","patch_set":17,"id":"5a74a57a_2ef82d7c","line":80,"range":{"start_line":79,"start_character":15,"end_line":80,"end_character":55},"updated":"2016-12-01 00:21:33.000000000","message":"Seems like at some point we might want to make this a singleton so we don\u0027t have to build this list every time we destroy a resource class.","commit_id":"d1c75df6793274fbbca92acbbde821c436a36c76"},{"author":{"_account_id":7,"name":"Jay Pipes","email":"jaypipes@gmail.com","username":"jaypipes"},"change_message_id":"fd983b211438d80e8c940b04c3344dc1c08d5564","unresolved":false,"context_lines":[{"line_number":76,"context_line":"        \"\"\"Return a list of {\u0027id\u0027: \u003cID\u003e, \u0027name\u0027: \u003cNAME\u003e for all standard"},{"line_number":77,"context_line":"        resource classes."},{"line_number":78,"context_line":"        \"\"\""},{"line_number":79,"context_line":"        return [{\u0027id\u0027: fields.ResourceClass.STANDARD.index(s), \u0027name\u0027: s}"},{"line_number":80,"context_line":"                for s in fields.ResourceClass.STANDARD]"},{"line_number":81,"context_line":""},{"line_number":82,"context_line":"    def id_from_string(self, rc_str):"},{"line_number":83,"context_line":"        \"\"\"Given a string representation of a resource class -- e.g. \"DISK_GB\""}],"source_content_type":"text/x-python","patch_set":17,"id":"3a71b18c_43b01bde","line":80,"range":{"start_line":79,"start_character":15,"end_line":80,"end_character":55},"in_reply_to":"3a71b18c_1a13fd5d","updated":"2016-12-01 15:29:27.000000000","message":"yeah, I suppose that\u0027s an optimization it would be cool to make. Want to push up a patch that does that? (separate from this one...)","commit_id":"d1c75df6793274fbbca92acbbde821c436a36c76"},{"author":{"_account_id":13692,"name":"Roman Dobosz","email":"gryf73@gmail.com","username":"gryf"},"change_message_id":"71bdd5696e6c6ac8a003fb0b8c2579756f54c7d5","unresolved":false,"context_lines":[{"line_number":76,"context_line":"        \"\"\"Return a list of {\u0027id\u0027: \u003cID\u003e, \u0027name\u0027: \u003cNAME\u003e for all standard"},{"line_number":77,"context_line":"        resource classes."},{"line_number":78,"context_line":"        \"\"\""},{"line_number":79,"context_line":"        return [{\u0027id\u0027: fields.ResourceClass.STANDARD.index(s), \u0027name\u0027: s}"},{"line_number":80,"context_line":"                for s in fields.ResourceClass.STANDARD]"},{"line_number":81,"context_line":""},{"line_number":82,"context_line":"    def id_from_string(self, rc_str):"},{"line_number":83,"context_line":"        \"\"\"Given a string representation of a resource class -- e.g. \"DISK_GB\""}],"source_content_type":"text/x-python","patch_set":17,"id":"3a71b18c_e7920857","line":80,"range":{"start_line":79,"start_character":15,"end_line":80,"end_character":55},"in_reply_to":"3a71b18c_43b01bde","updated":"2016-12-01 18:28:44.000000000","message":"Sure. Patch is on the way.","commit_id":"d1c75df6793274fbbca92acbbde821c436a36c76"},{"author":{"_account_id":7,"name":"Jay Pipes","email":"jaypipes@gmail.com","username":"jaypipes"},"change_message_id":"ef022b17c9e56428dc345468106cc69fb3a85c74","unresolved":false,"context_lines":[{"line_number":76,"context_line":"        \"\"\"Return a list of {\u0027id\u0027: \u003cID\u003e, \u0027name\u0027: \u003cNAME\u003e for all standard"},{"line_number":77,"context_line":"        resource classes."},{"line_number":78,"context_line":"        \"\"\""},{"line_number":79,"context_line":"        return [{\u0027id\u0027: fields.ResourceClass.STANDARD.index(s), \u0027name\u0027: s}"},{"line_number":80,"context_line":"                for s in fields.ResourceClass.STANDARD]"},{"line_number":81,"context_line":""},{"line_number":82,"context_line":"    def id_from_string(self, rc_str):"},{"line_number":83,"context_line":"        \"\"\"Given a string representation of a resource class -- e.g. \"DISK_GB\""}],"source_content_type":"text/x-python","patch_set":17,"id":"5a74a57a_91716647","line":80,"range":{"start_line":79,"start_character":15,"end_line":80,"end_character":55},"in_reply_to":"5a74a57a_2ef82d7c","updated":"2016-12-01 00:48:08.000000000","message":"these are just the standard resource classes, built from the enumerated constants in fields.ResourceClass.STANDARD, so there\u0027s nothing that gets rebuilt.","commit_id":"d1c75df6793274fbbca92acbbde821c436a36c76"},{"author":{"_account_id":13692,"name":"Roman Dobosz","email":"gryf73@gmail.com","username":"gryf"},"change_message_id":"fd70835589bb006f3d05015d32d966cc8518570e","unresolved":false,"context_lines":[{"line_number":76,"context_line":"        \"\"\"Return a list of {\u0027id\u0027: \u003cID\u003e, \u0027name\u0027: \u003cNAME\u003e for all standard"},{"line_number":77,"context_line":"        resource classes."},{"line_number":78,"context_line":"        \"\"\""},{"line_number":79,"context_line":"        return [{\u0027id\u0027: fields.ResourceClass.STANDARD.index(s), \u0027name\u0027: s}"},{"line_number":80,"context_line":"                for s in fields.ResourceClass.STANDARD]"},{"line_number":81,"context_line":""},{"line_number":82,"context_line":"    def id_from_string(self, rc_str):"},{"line_number":83,"context_line":"        \"\"\"Given a string representation of a resource class -- e.g. \"DISK_GB\""}],"source_content_type":"text/x-python","patch_set":17,"id":"3a71b18c_1a13fd5d","line":80,"range":{"start_line":79,"start_character":15,"end_line":80,"end_character":55},"in_reply_to":"5a74a57a_91716647","updated":"2016-12-01 08:19:02.000000000","message":"In that case, that could be either constant or class attribute so that list would be built once.","commit_id":"d1c75df6793274fbbca92acbbde821c436a36c76"},{"author":{"_account_id":7166,"name":"Sylvain Bauza","email":"sbauza@redhat.com","username":"sbauza"},"change_message_id":"9d23afca92c0d93f38764122a075c00097b0cf2b","unresolved":false,"context_lines":[{"line_number":98,"context_line":"        \"\"\""},{"line_number":99,"context_line":"        # First check the standard resource classes"},{"line_number":100,"context_line":"        if rc_str in fields.ResourceClass.STANDARD:"},{"line_number":101,"context_line":"            return fields.ResourceClass.STANDARD.index(rc_str)"},{"line_number":102,"context_line":""},{"line_number":103,"context_line":"        with lockutils.lock(_LOCKNAME):"},{"line_number":104,"context_line":"            if rc_str in self.id_cache:"}],"source_content_type":"text/x-python","patch_set":17,"id":"3a71b18c_9891809c","line":101,"updated":"2016-12-02 15:26:04.000000000","message":"So, now you prefer to no longer use the cache for standard classes, fine by me.","commit_id":"d1c75df6793274fbbca92acbbde821c436a36c76"},{"author":{"_account_id":7166,"name":"Sylvain Bauza","email":"sbauza@redhat.com","username":"sbauza"},"change_message_id":"9d23afca92c0d93f38764122a075c00097b0cf2b","unresolved":false,"context_lines":[{"line_number":100,"context_line":"        if rc_str in fields.ResourceClass.STANDARD:"},{"line_number":101,"context_line":"            return fields.ResourceClass.STANDARD.index(rc_str)"},{"line_number":102,"context_line":""},{"line_number":103,"context_line":"        with lockutils.lock(_LOCKNAME):"},{"line_number":104,"context_line":"            if rc_str in self.id_cache:"},{"line_number":105,"context_line":"                return self.id_cache[rc_str]"},{"line_number":106,"context_line":"            # Otherwise, check the database table"}],"source_content_type":"text/x-python","patch_set":17,"id":"3a71b18c_d863f818","line":103,"updated":"2016-12-02 15:26:04.000000000","message":"I\u0027m bit struggling with the performance impact of that semaphore, but okay...","commit_id":"d1c75df6793274fbbca92acbbde821c436a36c76"}],"nova/exception.py":[{"author":{"_account_id":6873,"name":"Matt Riedemann","email":"mriedem.os@gmail.com","username":"mriedem"},"change_message_id":"b35d0090f778017dd89cce79a0f1923cc579b278","unresolved":false,"context_lines":[{"line_number":2130,"context_line":"    msg_fmt \u003d _(\"Resource class %(resource_class)s already exists.\")"},{"line_number":2131,"context_line":""},{"line_number":2132,"context_line":""},{"line_number":2133,"context_line":"class ResourceClassInUse(Invalid):"},{"line_number":2134,"context_line":"    msg_fmt \u003d _(\"Cannot delete resource class. Class is in use in inventory.\")"},{"line_number":2135,"context_line":""},{"line_number":2136,"context_line":""}],"source_content_type":"text/x-python","patch_set":13,"id":"7a77a97e_5ab54e7c","line":2133,"range":{"start_line":2133,"start_character":25,"end_line":2133,"end_character":32},"updated":"2016-11-22 01:03:11.000000000","message":"nit: the spec says this case is a 409, so we could use NovaException and set code \u003d 409 in this type if we wanted. This isn\u0027t a must have since this will be handled in the REST API and converted to an HTTPConflict.","commit_id":"b2d70546717df7f9a72b8477a8c6573e75cecfc7"},{"author":{"_account_id":6873,"name":"Matt Riedemann","email":"mriedem.os@gmail.com","username":"mriedem"},"change_message_id":"b35d0090f778017dd89cce79a0f1923cc579b278","unresolved":false,"context_lines":[{"line_number":2131,"context_line":""},{"line_number":2132,"context_line":""},{"line_number":2133,"context_line":"class ResourceClassInUse(Invalid):"},{"line_number":2134,"context_line":"    msg_fmt \u003d _(\"Cannot delete resource class. Class is in use in inventory.\")"},{"line_number":2135,"context_line":""},{"line_number":2136,"context_line":""},{"line_number":2137,"context_line":"class ResourceClassCannotDeleteStandard(Invalid):"}],"source_content_type":"text/x-python","patch_set":13,"id":"7a77a97e_faa61a52","line":2134,"range":{"start_line":2134,"start_character":17,"end_line":2134,"end_character":45},"updated":"2016-11-22 01:03:11.000000000","message":"nit: add the resource class name to the error message for context.","commit_id":"b2d70546717df7f9a72b8477a8c6573e75cecfc7"},{"author":{"_account_id":7,"name":"Jay Pipes","email":"jaypipes@gmail.com","username":"jaypipes"},"change_message_id":"d85e27cdecb092ec96ff1733ff74a5420fd052cf","unresolved":false,"context_lines":[{"line_number":2131,"context_line":""},{"line_number":2132,"context_line":""},{"line_number":2133,"context_line":"class ResourceClassInUse(Invalid):"},{"line_number":2134,"context_line":"    msg_fmt \u003d _(\"Cannot delete resource class. Class is in use in inventory.\")"},{"line_number":2135,"context_line":""},{"line_number":2136,"context_line":""},{"line_number":2137,"context_line":"class ResourceClassCannotDeleteStandard(Invalid):"}],"source_content_type":"text/x-python","patch_set":13,"id":"7a77a97e_35023c3f","line":2134,"range":{"start_line":2134,"start_character":17,"end_line":2134,"end_character":45},"in_reply_to":"7a77a97e_faa61a52","updated":"2016-11-22 16:00:14.000000000","message":"will do.","commit_id":"b2d70546717df7f9a72b8477a8c6573e75cecfc7"},{"author":{"_account_id":6873,"name":"Matt Riedemann","email":"mriedem.os@gmail.com","username":"mriedem"},"change_message_id":"f407b1fd213fd888f4ff22db12df9af99f1cee50","unresolved":false,"context_lines":[{"line_number":2131,"context_line":""},{"line_number":2132,"context_line":""},{"line_number":2133,"context_line":"class ResourceClassInUse(Invalid):"},{"line_number":2134,"context_line":"    msg_fmt \u003d _(\"Cannot delete resource class. Class is in use in inventory.\")"},{"line_number":2135,"context_line":""},{"line_number":2136,"context_line":""},{"line_number":2137,"context_line":"class ResourceClassCannotDeleteStandard(Invalid):"}],"source_content_type":"text/x-python","patch_set":17,"id":"5a74a57a_aeb51dd1","line":2134,"updated":"2016-12-01 00:21:33.000000000","message":"nit: could add the resource class name in here for context.","commit_id":"d1c75df6793274fbbca92acbbde821c436a36c76"},{"author":{"_account_id":1063,"name":"Ed Leafe","email":"ed@leafe.com","username":"ed-leafe"},"change_message_id":"89d2e942211f6fd0dab9a66d9246cfd02c86003b","unresolved":false,"context_lines":[{"line_number":2131,"context_line":""},{"line_number":2132,"context_line":""},{"line_number":2133,"context_line":"class ResourceClassInUse(Invalid):"},{"line_number":2134,"context_line":"    msg_fmt \u003d _(\"Cannot delete resource class. Class is in use in inventory.\")"},{"line_number":2135,"context_line":""},{"line_number":2136,"context_line":""},{"line_number":2137,"context_line":"class ResourceClassCannotDeleteStandard(Invalid):"}],"source_content_type":"text/x-python","patch_set":17,"id":"3a71b18c_43d7febe","line":2134,"in_reply_to":"5a74a57a_519eee54","updated":"2016-12-02 14:46:53.000000000","message":"I added it in https://review.openstack.org/#/c/406149/","commit_id":"d1c75df6793274fbbca92acbbde821c436a36c76"},{"author":{"_account_id":7,"name":"Jay Pipes","email":"jaypipes@gmail.com","username":"jaypipes"},"change_message_id":"ef022b17c9e56428dc345468106cc69fb3a85c74","unresolved":false,"context_lines":[{"line_number":2131,"context_line":""},{"line_number":2132,"context_line":""},{"line_number":2133,"context_line":"class ResourceClassInUse(Invalid):"},{"line_number":2134,"context_line":"    msg_fmt \u003d _(\"Cannot delete resource class. Class is in use in inventory.\")"},{"line_number":2135,"context_line":""},{"line_number":2136,"context_line":""},{"line_number":2137,"context_line":"class ResourceClassCannotDeleteStandard(Invalid):"}],"source_content_type":"text/x-python","patch_set":17,"id":"5a74a57a_519eee54","line":2134,"in_reply_to":"5a74a57a_aeb51dd1","updated":"2016-12-01 00:48:08.000000000","message":"yeah, will add in followup","commit_id":"d1c75df6793274fbbca92acbbde821c436a36c76"}],"nova/objects/resource_provider.py":[{"author":{"_account_id":6873,"name":"Matt Riedemann","email":"mriedem.os@gmail.com","username":"mriedem"},"change_message_id":"b35d0090f778017dd89cce79a0f1923cc579b278","unresolved":false,"context_lines":[{"line_number":1135,"context_line":"                                              reason\u003d\u0027ID attribute not found\u0027)"},{"line_number":1136,"context_line":"        # Never delete any standard resource class, since the standard resource"},{"line_number":1137,"context_line":"        # classes don\u0027t even exist in the database table anyway."},{"line_number":1138,"context_line":"        _ensure_rc_cache(self._context)"},{"line_number":1139,"context_line":"        standards \u003d _RC_CACHE.get_standards()"},{"line_number":1140,"context_line":"        if self.id in (rc[\u0027id\u0027] for rc in standards):"},{"line_number":1141,"context_line":"            raise exception.ResourceClassCannotDeleteStandard("}],"source_content_type":"text/x-python","patch_set":13,"id":"7a77a97e_9a5d264b","line":1138,"range":{"start_line":1138,"start_character":25,"end_line":1138,"end_character":38},"updated":"2016-11-22 01:03:11.000000000","message":"Do we have to check if this also exists? If not set, isn\u0027t there an OrphanedObjectError we should raise?","commit_id":"b2d70546717df7f9a72b8477a8c6573e75cecfc7"},{"author":{"_account_id":7,"name":"Jay Pipes","email":"jaypipes@gmail.com","username":"jaypipes"},"change_message_id":"d85e27cdecb092ec96ff1733ff74a5420fd052cf","unresolved":false,"context_lines":[{"line_number":1135,"context_line":"                                              reason\u003d\u0027ID attribute not found\u0027)"},{"line_number":1136,"context_line":"        # Never delete any standard resource class, since the standard resource"},{"line_number":1137,"context_line":"        # classes don\u0027t even exist in the database table anyway."},{"line_number":1138,"context_line":"        _ensure_rc_cache(self._context)"},{"line_number":1139,"context_line":"        standards \u003d _RC_CACHE.get_standards()"},{"line_number":1140,"context_line":"        if self.id in (rc[\u0027id\u0027] for rc in standards):"},{"line_number":1141,"context_line":"            raise exception.ResourceClassCannotDeleteStandard("}],"source_content_type":"text/x-python","patch_set":13,"id":"7a77a97e_9544f0b7","line":1138,"range":{"start_line":1138,"start_character":25,"end_line":1138,"end_character":38},"in_reply_to":"7a77a97e_9a5d264b","updated":"2016-11-22 16:00:14.000000000","message":"_ensure_rc_cache() is decorated with the enginefacade transaction context assurance:\n\nhttps://github.com/openstack/nova/blob/master/nova/objects/resource_provider.py#L39","commit_id":"b2d70546717df7f9a72b8477a8c6573e75cecfc7"},{"author":{"_account_id":6873,"name":"Matt Riedemann","email":"mriedem.os@gmail.com","username":"mriedem"},"change_message_id":"b35d0090f778017dd89cce79a0f1923cc579b278","unresolved":false,"context_lines":[{"line_number":1150,"context_line":"        # Don\u0027t delete the resource class if it is referred to in the"},{"line_number":1151,"context_line":"        # inventories table."},{"line_number":1152,"context_line":"        num_inv \u003d context.session.query(models.Inventory).filter("},{"line_number":1153,"context_line":"                models.Inventory.resource_class_id \u003d\u003d _id).count()"},{"line_number":1154,"context_line":"        if num_inv:"},{"line_number":1155,"context_line":"            raise exception.ResourceClassInUse()"},{"line_number":1156,"context_line":""}],"source_content_type":"text/x-python","patch_set":13,"id":"7a77a97e_b512f356","line":1153,"range":{"start_line":1153,"start_character":23,"end_line":1153,"end_character":32},"updated":"2016-11-22 01:03:11.000000000","message":"What about the allocations table? It\u0027s also in there.\n\nAt first I thought why don\u0027t we just use foreign keys for these and let the DB handle it, but that won\u0027t work for inventories/allocations against the standard resource classes which aren\u0027t in the DB.","commit_id":"b2d70546717df7f9a72b8477a8c6573e75cecfc7"},{"author":{"_account_id":7,"name":"Jay Pipes","email":"jaypipes@gmail.com","username":"jaypipes"},"change_message_id":"d85e27cdecb092ec96ff1733ff74a5420fd052cf","unresolved":false,"context_lines":[{"line_number":1150,"context_line":"        # Don\u0027t delete the resource class if it is referred to in the"},{"line_number":1151,"context_line":"        # inventories table."},{"line_number":1152,"context_line":"        num_inv \u003d context.session.query(models.Inventory).filter("},{"line_number":1153,"context_line":"                models.Inventory.resource_class_id \u003d\u003d _id).count()"},{"line_number":1154,"context_line":"        if num_inv:"},{"line_number":1155,"context_line":"            raise exception.ResourceClassInUse()"},{"line_number":1156,"context_line":""}],"source_content_type":"text/x-python","patch_set":13,"id":"7a77a97e_f5d0c4cb","line":1153,"range":{"start_line":1153,"start_character":23,"end_line":1153,"end_character":32},"in_reply_to":"7a77a97e_b512f356","updated":"2016-11-22 16:00:14.000000000","message":"It is not possible to add an allocation record for a resource class that does not have a corresponding inventory for the provider. Likewise, it is not possible to delete an inventory record if there are allocations for that resource class outstanding.\n\nTherefore, we only need to check the Inventory table to see if there are any records that exist referencing that resource class in order to be guaranteed that there are also no allocations referencing that resource class.","commit_id":"b2d70546717df7f9a72b8477a8c6573e75cecfc7"},{"author":{"_account_id":6873,"name":"Matt Riedemann","email":"mriedem.os@gmail.com","username":"mriedem"},"change_message_id":"b35d0090f778017dd89cce79a0f1923cc579b278","unresolved":false,"context_lines":[{"line_number":1157,"context_line":"        res \u003d context.session.query(models.ResourceClass).filter("},{"line_number":1158,"context_line":"                models.ResourceClass.id \u003d\u003d _id).delete()"},{"line_number":1159,"context_line":"        if not res:"},{"line_number":1160,"context_line":"            raise exception.NotFound()"},{"line_number":1161,"context_line":""},{"line_number":1162,"context_line":""},{"line_number":1163,"context_line":"@base.NovaObjectRegistry.register"}],"source_content_type":"text/x-python","patch_set":13,"id":"7a77a97e_55519f0d","line":1160,"range":{"start_line":1160,"start_character":28,"end_line":1160,"end_character":36},"updated":"2016-11-22 01:03:11.000000000","message":"Use ResourceClassNotFound?","commit_id":"b2d70546717df7f9a72b8477a8c6573e75cecfc7"},{"author":{"_account_id":7,"name":"Jay Pipes","email":"jaypipes@gmail.com","username":"jaypipes"},"change_message_id":"d85e27cdecb092ec96ff1733ff74a5420fd052cf","unresolved":false,"context_lines":[{"line_number":1157,"context_line":"        res \u003d context.session.query(models.ResourceClass).filter("},{"line_number":1158,"context_line":"                models.ResourceClass.id \u003d\u003d _id).delete()"},{"line_number":1159,"context_line":"        if not res:"},{"line_number":1160,"context_line":"            raise exception.NotFound()"},{"line_number":1161,"context_line":""},{"line_number":1162,"context_line":""},{"line_number":1163,"context_line":"@base.NovaObjectRegistry.register"}],"source_content_type":"text/x-python","patch_set":13,"id":"7a77a97e_95e07098","line":1160,"range":{"start_line":1160,"start_character":28,"end_line":1160,"end_character":36},"in_reply_to":"7a77a97e_55519f0d","updated":"2016-11-22 16:00:14.000000000","message":"thx, will fix up.","commit_id":"b2d70546717df7f9a72b8477a8c6573e75cecfc7"},{"author":{"_account_id":6873,"name":"Matt Riedemann","email":"mriedem.os@gmail.com","username":"mriedem"},"change_message_id":"f407b1fd213fd888f4ff22db12df9af99f1cee50","unresolved":false,"context_lines":[{"line_number":1218,"context_line":"    def destroy(self):"},{"line_number":1219,"context_line":"        if \u0027id\u0027 not in self:"},{"line_number":1220,"context_line":"            raise exception.ObjectActionError(action\u003d\u0027destroy\u0027,"},{"line_number":1221,"context_line":"                                              reason\u003d\u0027ID attribute not found\u0027)"},{"line_number":1222,"context_line":"        # Never delete any standard resource class, since the standard resource"},{"line_number":1223,"context_line":"        # classes don\u0027t even exist in the database table anyway."},{"line_number":1224,"context_line":"        _ensure_rc_cache(self._context)"}],"source_content_type":"text/x-python","patch_set":17,"id":"5a74a57a_0eb371ea","line":1221,"range":{"start_line":1221,"start_character":54,"end_line":1221,"end_character":76},"updated":"2016-12-01 00:21:33.000000000","message":"nit: seems like we usually say something like, \u0027not created yet\u0027? this is fine though.","commit_id":"d1c75df6793274fbbca92acbbde821c436a36c76"},{"author":{"_account_id":7,"name":"Jay Pipes","email":"jaypipes@gmail.com","username":"jaypipes"},"change_message_id":"ef022b17c9e56428dc345468106cc69fb3a85c74","unresolved":false,"context_lines":[{"line_number":1218,"context_line":"    def destroy(self):"},{"line_number":1219,"context_line":"        if \u0027id\u0027 not in self:"},{"line_number":1220,"context_line":"            raise exception.ObjectActionError(action\u003d\u0027destroy\u0027,"},{"line_number":1221,"context_line":"                                              reason\u003d\u0027ID attribute not found\u0027)"},{"line_number":1222,"context_line":"        # Never delete any standard resource class, since the standard resource"},{"line_number":1223,"context_line":"        # classes don\u0027t even exist in the database table anyway."},{"line_number":1224,"context_line":"        _ensure_rc_cache(self._context)"}],"source_content_type":"text/x-python","patch_set":17,"id":"5a74a57a_71adaa87","line":1221,"range":{"start_line":1221,"start_character":54,"end_line":1221,"end_character":76},"in_reply_to":"5a74a57a_0eb371ea","updated":"2016-12-01 00:48:08.000000000","message":"Perhaps... copy/paste stuff :)","commit_id":"d1c75df6793274fbbca92acbbde821c436a36c76"},{"author":{"_account_id":6873,"name":"Matt Riedemann","email":"mriedem.os@gmail.com","username":"mriedem"},"change_message_id":"f407b1fd213fd888f4ff22db12df9af99f1cee50","unresolved":false,"context_lines":[{"line_number":1223,"context_line":"        # classes don\u0027t even exist in the database table anyway."},{"line_number":1224,"context_line":"        _ensure_rc_cache(self._context)"},{"line_number":1225,"context_line":"        standards \u003d _RC_CACHE.get_standards()"},{"line_number":1226,"context_line":"        if self.id in (rc[\u0027id\u0027] for rc in standards):"},{"line_number":1227,"context_line":"            raise exception.ResourceClassCannotDeleteStandard("},{"line_number":1228,"context_line":"                    resource_class\u003dself.name)"},{"line_number":1229,"context_line":""}],"source_content_type":"text/x-python","patch_set":17,"id":"5a74a57a_ee0b957b","line":1226,"range":{"start_line":1226,"start_character":22,"end_line":1226,"end_character":52},"updated":"2016-12-01 00:21:33.000000000","message":"would be nice if we didn\u0027t have to build this tuple every time...but ok to leave this for a future improvement.","commit_id":"d1c75df6793274fbbca92acbbde821c436a36c76"},{"author":{"_account_id":6873,"name":"Matt Riedemann","email":"mriedem.os@gmail.com","username":"mriedem"},"change_message_id":"f407b1fd213fd888f4ff22db12df9af99f1cee50","unresolved":false,"context_lines":[{"line_number":1225,"context_line":"        standards \u003d _RC_CACHE.get_standards()"},{"line_number":1226,"context_line":"        if self.id in (rc[\u0027id\u0027] for rc in standards):"},{"line_number":1227,"context_line":"            raise exception.ResourceClassCannotDeleteStandard("},{"line_number":1228,"context_line":"                    resource_class\u003dself.name)"},{"line_number":1229,"context_line":""},{"line_number":1230,"context_line":"        self._destroy(self._context, self.id)"},{"line_number":1231,"context_line":"        _RC_CACHE.clear()"}],"source_content_type":"text/x-python","patch_set":17,"id":"5a74a57a_8e1b01ca","line":1228,"range":{"start_line":1228,"start_character":35,"end_line":1228,"end_character":44},"updated":"2016-12-01 00:21:33.000000000","message":"I hope this is set...we could get the name from the standards list of dicts above when we hit a match...but meh.","commit_id":"d1c75df6793274fbbca92acbbde821c436a36c76"},{"author":{"_account_id":7,"name":"Jay Pipes","email":"jaypipes@gmail.com","username":"jaypipes"},"change_message_id":"ef022b17c9e56428dc345468106cc69fb3a85c74","unresolved":false,"context_lines":[{"line_number":1225,"context_line":"        standards \u003d _RC_CACHE.get_standards()"},{"line_number":1226,"context_line":"        if self.id in (rc[\u0027id\u0027] for rc in standards):"},{"line_number":1227,"context_line":"            raise exception.ResourceClassCannotDeleteStandard("},{"line_number":1228,"context_line":"                    resource_class\u003dself.name)"},{"line_number":1229,"context_line":""},{"line_number":1230,"context_line":"        self._destroy(self._context, self.id)"},{"line_number":1231,"context_line":"        _RC_CACHE.clear()"}],"source_content_type":"text/x-python","patch_set":17,"id":"5a74a57a_f1affa7a","line":1228,"range":{"start_line":1228,"start_character":35,"end_line":1228,"end_character":44},"in_reply_to":"5a74a57a_8e1b01ca","updated":"2016-12-01 00:48:08.000000000","message":"If id is set (the guard on line 1219), then name will always be set.","commit_id":"d1c75df6793274fbbca92acbbde821c436a36c76"},{"author":{"_account_id":6873,"name":"Matt Riedemann","email":"mriedem.os@gmail.com","username":"mriedem"},"change_message_id":"f407b1fd213fd888f4ff22db12df9af99f1cee50","unresolved":false,"context_lines":[{"line_number":1243,"context_line":"        res \u003d context.session.query(models.ResourceClass).filter("},{"line_number":1244,"context_line":"                models.ResourceClass.id \u003d\u003d _id).delete()"},{"line_number":1245,"context_line":"        if not res:"},{"line_number":1246,"context_line":"            raise exception.NotFound()"},{"line_number":1247,"context_line":""},{"line_number":1248,"context_line":""},{"line_number":1249,"context_line":"@base.NovaObjectRegistry.register"}],"source_content_type":"text/x-python","patch_set":17,"id":"5a74a57a_aeed1d90","line":1246,"range":{"start_line":1246,"start_character":28,"end_line":1246,"end_character":36},"updated":"2016-12-01 00:21:33.000000000","message":"nit: ResourceClassNotFound would be more appropriate here and would be nice to use since we already have it.","commit_id":"d1c75df6793274fbbca92acbbde821c436a36c76"},{"author":{"_account_id":7,"name":"Jay Pipes","email":"jaypipes@gmail.com","username":"jaypipes"},"change_message_id":"ef022b17c9e56428dc345468106cc69fb3a85c74","unresolved":false,"context_lines":[{"line_number":1243,"context_line":"        res \u003d context.session.query(models.ResourceClass).filter("},{"line_number":1244,"context_line":"                models.ResourceClass.id \u003d\u003d _id).delete()"},{"line_number":1245,"context_line":"        if not res:"},{"line_number":1246,"context_line":"            raise exception.NotFound()"},{"line_number":1247,"context_line":""},{"line_number":1248,"context_line":""},{"line_number":1249,"context_line":"@base.NovaObjectRegistry.register"}],"source_content_type":"text/x-python","patch_set":17,"id":"5a74a57a_51c50e3b","line":1246,"range":{"start_line":1246,"start_character":28,"end_line":1246,"end_character":36},"in_reply_to":"5a74a57a_aeed1d90","updated":"2016-12-01 00:48:08.000000000","message":"good point, will fix in followup.","commit_id":"d1c75df6793274fbbca92acbbde821c436a36c76"}]}
