)]}'
{"nova/api/openstack/compute/contrib/flavorlifecycle.py":[{"author":{"_account_id":1155,"name":"sleepsonthefloor","username":"sleepsonthefloor"},"change_message_id":"d1ab79f3b9cb7af21e9564c947d9359c819e2cb3","unresolved":false,"context_lines":[{"line_number":27,"context_line":"LOG \u003d logging.getLogger(\u0027nova.api.openstack.compute.contrib.flavorlifecycle\u0027)"},{"line_number":28,"context_line":""},{"line_number":29,"context_line":""},{"line_number":30,"context_line":"class FlavorLifecycleController(wsgi.Controller):"},{"line_number":31,"context_line":"    \"\"\""},{"line_number":32,"context_line":"    The Flavor Lifecycle API controller for the OpenStack API."},{"line_number":33,"context_line":"    \"\"\""}],"source_content_type":"text/x-python","patch_set":1,"id":"AAAAD3%2F%2F8Tg%3D","line":30,"updated":"2012-01-20 00:16:03.000000000","message":"Maybe FlavorExtensionsController ?","commit_id":"595bfc0c50f6136b58f3d57142662e890b131d73"},{"author":{"_account_id":1783,"name":"Cole Robinson","email":"crobinso@redhat.com","username":"crobinso"},"change_message_id":"56d5c3a1dfc097525d8921c6fe6ad4b838ce4b29","unresolved":false,"context_lines":[{"line_number":27,"context_line":"LOG \u003d logging.getLogger(\u0027nova.api.openstack.compute.contrib.flavorlifecycle\u0027)"},{"line_number":28,"context_line":""},{"line_number":29,"context_line":""},{"line_number":30,"context_line":"class FlavorLifecycleController(wsgi.Controller):"},{"line_number":31,"context_line":"    \"\"\""},{"line_number":32,"context_line":"    The Flavor Lifecycle API controller for the OpenStack API."},{"line_number":33,"context_line":"    \"\"\""}],"source_content_type":"text/x-python","patch_set":1,"id":"AAAAEH%2F%2F%2F9g%3D","line":30,"in_reply_to":"AAAAD3%2F%2F8QI%3D","updated":"2012-01-23 16:56:26.000000000","message":"I\u0027ll use this, thanks!","commit_id":"595bfc0c50f6136b58f3d57142662e890b131d73"},{"author":{"_account_id":1132,"name":"Brian Waldon","email":"brian@waldon.cc","username":"bcwaldon"},"change_message_id":"bbfde512f598e1e1f59cae9e7f247f9298d675ec","unresolved":false,"context_lines":[{"line_number":27,"context_line":"LOG \u003d logging.getLogger(\u0027nova.api.openstack.compute.contrib.flavorlifecycle\u0027)"},{"line_number":28,"context_line":""},{"line_number":29,"context_line":""},{"line_number":30,"context_line":"class FlavorLifecycleController(wsgi.Controller):"},{"line_number":31,"context_line":"    \"\"\""},{"line_number":32,"context_line":"    The Flavor Lifecycle API controller for the OpenStack API."},{"line_number":33,"context_line":"    \"\"\""}],"source_content_type":"text/x-python","patch_set":1,"id":"AAAAD3%2F%2F8QI%3D","line":30,"in_reply_to":"AAAAD3%2F%2F8Tg%3D","updated":"2012-01-20 02:41:10.000000000","message":"\u0027FlavorManageController\u0027 is an idea","commit_id":"595bfc0c50f6136b58f3d57142662e890b131d73"},{"author":{"_account_id":1132,"name":"Brian Waldon","email":"brian@waldon.cc","username":"bcwaldon"},"change_message_id":"bbfde512f598e1e1f59cae9e7f247f9298d675ec","unresolved":false,"context_lines":[{"line_number":41,"context_line":"        env \u003d urlparse.parse_qs(qs)"},{"line_number":42,"context_line":""},{"line_number":43,"context_line":"        purge \u003d env.get(\u0027purge\u0027, None)"},{"line_number":44,"context_line":"        purge \u003d bool(purge and purge[0] \u003d\u003d \u00271\u0027)"},{"line_number":45,"context_line":"        flavor \u003d instance_types.get_instance_type_by_flavor_id(id)"},{"line_number":46,"context_line":""},{"line_number":47,"context_line":"        LOG.debug(\"Delete flavor\u003d%s purge\u003d%s\", id, purge)"}],"source_content_type":"text/x-python","patch_set":1,"id":"AAAAD3%2F%2F8P4%3D","line":44,"updated":"2012-01-20 02:41:10.000000000","message":"I\u0027m not really a fan of this since for a couple of reasons:\n1) Typically we use query args as a filter, not as a behavior modifier\n2) This only addresses the case when you know you want the flavor gone forever. What if you DELETE without purge\u003d1? There\u0027s no way to get yourself out of that name collision with this interface. I would almost say that we don\u0027t support purging through this API, that\u0027s something you have to do in the database itself.","commit_id":"595bfc0c50f6136b58f3d57142662e890b131d73"},{"author":{"_account_id":1783,"name":"Cole Robinson","email":"crobinso@redhat.com","username":"crobinso"},"change_message_id":"56d5c3a1dfc097525d8921c6fe6ad4b838ce4b29","unresolved":false,"context_lines":[{"line_number":41,"context_line":"        env \u003d urlparse.parse_qs(qs)"},{"line_number":42,"context_line":""},{"line_number":43,"context_line":"        purge \u003d env.get(\u0027purge\u0027, None)"},{"line_number":44,"context_line":"        purge \u003d bool(purge and purge[0] \u003d\u003d \u00271\u0027)"},{"line_number":45,"context_line":"        flavor \u003d instance_types.get_instance_type_by_flavor_id(id)"},{"line_number":46,"context_line":""},{"line_number":47,"context_line":"        LOG.debug(\"Delete flavor\u003d%s purge\u003d%s\", id, purge)"}],"source_content_type":"text/x-python","patch_set":1,"id":"AAAAEH%2F%2F%2F9c%3D","line":44,"in_reply_to":"AAAAD3%2F%2F8P4%3D","updated":"2012-01-23 16:56:26.000000000","message":"Okay I\u0027ll drop the purge option and have the default always be equivalent of purge\u003d0. Sounds like Vish wants that particular nuance to change anyways but presumably that can happen separate of this patch.","commit_id":"595bfc0c50f6136b58f3d57142662e890b131d73"},{"author":{"_account_id":1132,"name":"Brian Waldon","email":"brian@waldon.cc","username":"bcwaldon"},"change_message_id":"bbfde512f598e1e1f59cae9e7f247f9298d675ec","unresolved":false,"context_lines":[{"line_number":55,"context_line":""},{"line_number":56,"context_line":"    @wsgi.serializers(xml\u003dflavors_api.FlavorTemplate)"},{"line_number":57,"context_line":"    def create(self, req, body):"},{"line_number":58,"context_line":"        name \u003d body[\u0027flavor\u0027].get(\u0027name\u0027)"},{"line_number":59,"context_line":"        memory_mb \u003d body[\u0027flavor\u0027].get(\u0027ram\u0027)"},{"line_number":60,"context_line":"        vcpus \u003d body[\u0027flavor\u0027].get(\u0027vcpus\u0027)"},{"line_number":61,"context_line":"        local_gb \u003d body[\u0027flavor\u0027].get(\u0027disk\u0027)"}],"source_content_type":"text/x-python","patch_set":1,"id":"AAAAD3%2F%2F8Pw%3D","line":58,"updated":"2012-01-20 02:41:10.000000000","message":"Are you gracefully handling all required data here? I feel like we should always have to specify a name. This line will default it to None.","commit_id":"595bfc0c50f6136b58f3d57142662e890b131d73"},{"author":{"_account_id":1783,"name":"Cole Robinson","email":"crobinso@redhat.com","username":"crobinso"},"change_message_id":"56d5c3a1dfc097525d8921c6fe6ad4b838ce4b29","unresolved":false,"context_lines":[{"line_number":55,"context_line":""},{"line_number":56,"context_line":"    @wsgi.serializers(xml\u003dflavors_api.FlavorTemplate)"},{"line_number":57,"context_line":"    def create(self, req, body):"},{"line_number":58,"context_line":"        name \u003d body[\u0027flavor\u0027].get(\u0027name\u0027)"},{"line_number":59,"context_line":"        memory_mb \u003d body[\u0027flavor\u0027].get(\u0027ram\u0027)"},{"line_number":60,"context_line":"        vcpus \u003d body[\u0027flavor\u0027].get(\u0027vcpus\u0027)"},{"line_number":61,"context_line":"        local_gb \u003d body[\u0027flavor\u0027].get(\u0027disk\u0027)"}],"source_content_type":"text/x-python","patch_set":1,"id":"AAAAEH%2F%2F%2F9Y%3D","line":58,"in_reply_to":"AAAAD3%2F%2F8Pw%3D","updated":"2012-01-23 16:56:26.000000000","message":"Good point, I\u0027ll address this.","commit_id":"595bfc0c50f6136b58f3d57142662e890b131d73"},{"author":{"_account_id":1812,"name":"p-draigbrady","email":"P@draigBrady.com","username":"p-draigbrady"},"change_message_id":"d1b4bfd135ef5113b8adea795e44f8019c1b8e12","unresolved":false,"context_lines":[{"line_number":61,"context_line":"        local_gb \u003d body[\u0027flavor\u0027].get(\u0027disk\u0027)"},{"line_number":62,"context_line":"        flavorid \u003d body[\u0027flavor\u0027].get(\u0027id\u0027)"},{"line_number":63,"context_line":"        swap \u003d body[\u0027flavor\u0027].get(\u0027swap\u0027, 0)"},{"line_number":64,"context_line":"        rxtx_factor \u003d body[\u0027flavor\u0027].get(\u0027rxtx_factor\u0027, 1)"},{"line_number":65,"context_line":""},{"line_number":66,"context_line":"        flavor \u003d instance_types.create(name, memory_mb, vcpus,"},{"line_number":67,"context_line":"                                       local_gb, flavorid,"}],"source_content_type":"text/x-python","patch_set":1,"id":"AAAAD3%2F%2F8SU%3D","line":64,"updated":"2012-01-20 00:58:48.000000000","message":"To avoid some dict lookups and to clean the code a little, I\u0027d\n\n    _flavor \u003d body[\u0027flavor\u0027]\n    name \u003d _flavor.get(\u0027name\u0027)\n    ...","commit_id":"595bfc0c50f6136b58f3d57142662e890b131d73"},{"author":{"_account_id":1783,"name":"Cole Robinson","email":"crobinso@redhat.com","username":"crobinso"},"change_message_id":"56d5c3a1dfc097525d8921c6fe6ad4b838ce4b29","unresolved":false,"context_lines":[{"line_number":61,"context_line":"        local_gb \u003d body[\u0027flavor\u0027].get(\u0027disk\u0027)"},{"line_number":62,"context_line":"        flavorid \u003d body[\u0027flavor\u0027].get(\u0027id\u0027)"},{"line_number":63,"context_line":"        swap \u003d body[\u0027flavor\u0027].get(\u0027swap\u0027, 0)"},{"line_number":64,"context_line":"        rxtx_factor \u003d body[\u0027flavor\u0027].get(\u0027rxtx_factor\u0027, 1)"},{"line_number":65,"context_line":""},{"line_number":66,"context_line":"        flavor \u003d instance_types.create(name, memory_mb, vcpus,"},{"line_number":67,"context_line":"                                       local_gb, flavorid,"}],"source_content_type":"text/x-python","patch_set":1,"id":"AAAAEH%2F%2F%2F9E%3D","line":64,"in_reply_to":"AAAAD3%2F%2F8SU%3D","updated":"2012-01-23 16:56:26.000000000","message":"Thanks Pádraig, I\u0027ll address those nits.","commit_id":"595bfc0c50f6136b58f3d57142662e890b131d73"},{"author":{"_account_id":1132,"name":"Brian Waldon","email":"brian@waldon.cc","username":"bcwaldon"},"change_message_id":"bbfde512f598e1e1f59cae9e7f247f9298d675ec","unresolved":false,"context_lines":[{"line_number":76,"context_line":"    \"\"\""},{"line_number":77,"context_line":""},{"line_number":78,"context_line":"    name \u003d \"FlavorLifecycle\""},{"line_number":79,"context_line":"    alias \u003d \"os-flavor-lifecycle\""},{"line_number":80,"context_line":"    namespace \u003d (\"http://docs.openstack.org/compute/ext/\""},{"line_number":81,"context_line":"                 \"flavor_lifecycle/api/v1.1\")"},{"line_number":82,"context_line":"    updated \u003d \"2012-01-19T00:00:00+00:00\""}],"source_content_type":"text/x-python","patch_set":1,"id":"AAAAD3%2F%2F8QE%3D","line":79,"updated":"2012-01-20 02:41:10.000000000","message":"I\u0027d be more in favor of calling this a flavor management api, so officially calling it \u0027FlavorManage\u0027 with the alias \u0027os-flavor-manage\u0027","commit_id":"595bfc0c50f6136b58f3d57142662e890b131d73"},{"author":{"_account_id":1155,"name":"sleepsonthefloor","username":"sleepsonthefloor"},"change_message_id":"d1ab79f3b9cb7af21e9564c947d9359c819e2cb3","unresolved":false,"context_lines":[{"line_number":84,"context_line":"    def get_resources(self):"},{"line_number":85,"context_line":"        resources \u003d []"},{"line_number":86,"context_line":""},{"line_number":87,"context_line":"        res \u003d extensions.ResourceExtension(\u0027os-flavor-lifecycle\u0027,"},{"line_number":88,"context_line":"                         FlavorLifecycleController(),"},{"line_number":89,"context_line":"                         member_actions\u003d{})"},{"line_number":90,"context_line":"        resources.append(res)"}],"source_content_type":"text/x-python","patch_set":1,"id":"AAAAD3%2F%2F8Tk%3D","line":87,"updated":"2012-01-20 00:16:03.000000000","message":"Rather than create a new resource, you can create an extension to the existing flavors resource.  An example of how to do this is  in admin_actions.py, which extends the servers resource.","commit_id":"595bfc0c50f6136b58f3d57142662e890b131d73"},{"author":{"_account_id":1783,"name":"Cole Robinson","email":"crobinso@redhat.com","username":"crobinso"},"change_message_id":"56d5c3a1dfc097525d8921c6fe6ad4b838ce4b29","unresolved":false,"context_lines":[{"line_number":84,"context_line":"    def get_resources(self):"},{"line_number":85,"context_line":"        resources \u003d []"},{"line_number":86,"context_line":""},{"line_number":87,"context_line":"        res \u003d extensions.ResourceExtension(\u0027os-flavor-lifecycle\u0027,"},{"line_number":88,"context_line":"                         FlavorLifecycleController(),"},{"line_number":89,"context_line":"                         member_actions\u003d{})"},{"line_number":90,"context_line":"        resources.append(res)"}],"source_content_type":"text/x-python","patch_set":1,"id":"AAAAEH%2F%2F%2F9M%3D","line":87,"in_reply_to":"AAAAD3%2F%2F8Tk%3D","updated":"2012-01-23 16:56:26.000000000","message":"Great! I\u0027ll take a look at that.","commit_id":"595bfc0c50f6136b58f3d57142662e890b131d73"}],"nova/api/openstack/compute/contrib/flavormanage.py":[{"author":{"_account_id":1132,"name":"Brian Waldon","email":"brian@waldon.cc","username":"bcwaldon"},"change_message_id":"cc58ba3ec8214c30c2a8a3fea1f6a6fa707f6f7c","unresolved":false,"context_lines":[{"line_number":87,"context_line":"    namespace \u003d (\"http://docs.openstack.org/compute/ext/\""},{"line_number":88,"context_line":"                 \"flavor_manage/api/v1.1\")"},{"line_number":89,"context_line":"    updated \u003d \"2012-01-19T00:00:00+00:00\""},{"line_number":90,"context_line":"    admin_only \u003d True"},{"line_number":91,"context_line":""},{"line_number":92,"context_line":"    def get_controller_extensions(self):"},{"line_number":93,"context_line":"        controller \u003d FlavorManageController()"}],"source_content_type":"text/x-python","patch_set":3,"id":"AAAAEH%2F%2F%2Fp4%3D","line":90,"updated":"2012-01-23 20:34:14.000000000","message":"Sorry, I should have caught this sooner. With a recent patch, we no longer use an \u0027admin_only\u0027 attribute to make an extension accessible solely by admins. Take a look at the admin_actions extension, etc/nova/policy.json and nova/tests/policy.json to see how we do authentication.","commit_id":"2869c0780bf61c379670bca09c6c7184bff6c411"}],"nova/db/sqlalchemy/api.py":[{"author":{"_account_id":1155,"name":"sleepsonthefloor","username":"sleepsonthefloor"},"change_message_id":"d1ab79f3b9cb7af21e9564c947d9359c819e2cb3","unresolved":false,"context_lines":[{"line_number":3186,"context_line":""},{"line_number":3187,"context_line":""},{"line_number":3188,"context_line":"def _dict_with_extra_specs(inst_type_query):"},{"line_number":3189,"context_line":"    \"\"\"Takes an instance OR volume type query returned by sqlalchemy"},{"line_number":3190,"context_line":"    and returns it as a dictionary, converting the extra_specs"},{"line_number":3191,"context_line":"    entry from a list of dicts:"},{"line_number":3192,"context_line":""}],"source_content_type":"text/x-python","patch_set":1,"id":"AAAAD3%2F%2F8TU%3D","line":3189,"updated":"2012-01-20 00:16:03.000000000","message":"perhaps this function needs its doc string updated slightly, since you are using it in neither instance nor vol","commit_id":"595bfc0c50f6136b58f3d57142662e890b131d73"}],"nova/tests/api/openstack/compute/contrib/test_flavor_lifecycle.py":[{"author":{"_account_id":1812,"name":"p-draigbrady","email":"P@draigBrady.com","username":"p-draigbrady"},"change_message_id":"d1b4bfd135ef5113b8adea795e44f8019c1b8e12","unresolved":false,"context_lines":[{"line_number":105,"context_line":"        body[\u0027flavor\u0027][\u0027disk\u0027] \u003d 10"},{"line_number":106,"context_line":"        body[\u0027flavor\u0027][\u0027id\u0027] \u003d 1235"},{"line_number":107,"context_line":"        body[\u0027flavor\u0027][\u0027swap\u0027] \u003d 512"},{"line_number":108,"context_line":"        body[\u0027flavor\u0027][\u0027rxtx_factor\u0027] \u003d 1"},{"line_number":109,"context_line":""},{"line_number":110,"context_line":"        req \u003d fakes.HTTPRequest.blank("},{"line_number":111,"context_line":"              \u0027/v2/123/os-flavor-lifecycle/create/\u0027)"}],"source_content_type":"text/x-python","patch_set":1,"id":"AAAAD3%2F%2F8SM%3D","line":108,"updated":"2012-01-20 00:58:48.000000000","message":"More pedantry:\n\n    body \u003d {\u0027flavor\u0027: {\n      \u0027name\u0027:\u0027test\u0027,\n      \u0027ram\u0027: 512,\n      ...\n    }}","commit_id":"595bfc0c50f6136b58f3d57142662e890b131d73"},{"author":{"_account_id":1812,"name":"p-draigbrady","email":"P@draigBrady.com","username":"p-draigbrady"},"change_message_id":"d1b4bfd135ef5113b8adea795e44f8019c1b8e12","unresolved":false,"context_lines":[{"line_number":118,"context_line":"        self.assertEquals(res[\"flavor\"][\"disk\"], 10)"},{"line_number":119,"context_line":"        self.assertEquals(res[\"flavor\"][\"id\"], 1235)"},{"line_number":120,"context_line":"        self.assertEquals(res[\"flavor\"][\"swap\"], 512)"},{"line_number":121,"context_line":"        self.assertEquals(res[\"flavor\"][\"rxtx_factor\"], 1)"}],"source_content_type":"text/x-python","patch_set":1,"id":"AAAAD3%2F%2F8SA%3D","line":121,"updated":"2012-01-20 00:58:48.000000000","message":"Perhaps the above block can be simplified to:\n\n    self.assertEquals(res, body)\n\nIf res has other attributes to preclude that, then I\u0027d do:\n\n    for k in body:\n        self.assertEquals(body[k], res[k])","commit_id":"595bfc0c50f6136b58f3d57142662e890b131d73"},{"author":{"_account_id":1812,"name":"p-draigbrady","email":"P@draigBrady.com","username":"p-draigbrady"},"change_message_id":"a381da42a71d5a161349f34966d33545732ce3d5","unresolved":false,"context_lines":[{"line_number":118,"context_line":"        self.assertEquals(res[\"flavor\"][\"disk\"], 10)"},{"line_number":119,"context_line":"        self.assertEquals(res[\"flavor\"][\"id\"], 1235)"},{"line_number":120,"context_line":"        self.assertEquals(res[\"flavor\"][\"swap\"], 512)"},{"line_number":121,"context_line":"        self.assertEquals(res[\"flavor\"][\"rxtx_factor\"], 1)"}],"source_content_type":"text/x-python","patch_set":1,"id":"AAAAEH%2F%2F%2F7E%3D","line":121,"in_reply_to":"AAAAD3%2F%2F8SA%3D","updated":"2012-01-23 12:39:18.000000000","message":"In fact there seems to be a self.assertDictMatch() for this","commit_id":"595bfc0c50f6136b58f3d57142662e890b131d73"},{"author":{"_account_id":1783,"name":"Cole Robinson","email":"crobinso@redhat.com","username":"crobinso"},"change_message_id":"56d5c3a1dfc097525d8921c6fe6ad4b838ce4b29","unresolved":false,"context_lines":[{"line_number":118,"context_line":"        self.assertEquals(res[\"flavor\"][\"disk\"], 10)"},{"line_number":119,"context_line":"        self.assertEquals(res[\"flavor\"][\"id\"], 1235)"},{"line_number":120,"context_line":"        self.assertEquals(res[\"flavor\"][\"swap\"], 512)"},{"line_number":121,"context_line":"        self.assertEquals(res[\"flavor\"][\"rxtx_factor\"], 1)"}],"source_content_type":"text/x-python","patch_set":1,"id":"AAAAEH%2F%2F%2F3A%3D","line":121,"in_reply_to":"AAAAEH%2F%2F%2F7E%3D","updated":"2012-01-23 16:56:26.000000000","message":"Thanks for the pointer, though I don\u0027t think we can use it in this case since we are only comparing a subset of the results dictionary keys.","commit_id":"595bfc0c50f6136b58f3d57142662e890b131d73"}]}
