)]}'
{"/COMMIT_MSG":[{"author":{"_account_id":6873,"name":"Matt Riedemann","email":"mriedem.os@gmail.com","username":"mriedem"},"change_message_id":"d5f31609ffaac097f9d20194bb43b4f84183f8d6","unresolved":false,"context_lines":[{"line_number":8,"context_line":""},{"line_number":9,"context_line":"This adds the ability to request image precache support for an aggregate"},{"line_number":10,"context_line":"in support of the matching server feature."},{"line_number":11,"context_line":""},{"line_number":12,"context_line":"Related to blueprint image-precache-support"},{"line_number":13,"context_line":""},{"line_number":14,"context_line":"Change-Id: Id354ccfa99e500a598685e6b794c12160ea2a990"}],"source_content_type":"text/x-gerrit-commit-message","patch_set":1,"id":"3fa7e38b_ca53ca38","line":11,"updated":"2019-10-07 21:03:47.000000000","message":"Add a Depends-On to the API change so we\u0027re sure this doesn\u0027t merge until after the API change lands:\n\nhttps://review.opendev.org/#/c/687140/","commit_id":"53b9dddb956f17aed982e1511b67330a79a3ce2c"}],"doc/source/cli/nova.rst":[{"author":{"_account_id":7634,"name":"Takashi Natsume","email":"takanattie@gmail.com","username":"natsumet"},"change_message_id":"5ba0cd65dd0fdc26268514b549dce64e688c705e","unresolved":false,"context_lines":[{"line_number":766,"context_line":""},{"line_number":767,"context_line":".. code-block:: console"},{"line_number":768,"context_line":""},{"line_number":769,"context_line":"   usage: nova aggregate-cache-images \u003caggregate\u003e \u003cimage\u003e [\u003cimage\u003e ..]"},{"line_number":770,"context_line":""},{"line_number":771,"context_line":"Request image(s) be pre-cached on hosts within the aggregate."},{"line_number":772,"context_line":""}],"source_content_type":"text/x-rst","patch_set":6,"id":"3fa7e38b_af9b6470","line":769,"range":{"start_line":769,"start_character":67,"end_line":769,"end_character":69},"updated":"2019-10-17 02:46:05.000000000","message":"...","commit_id":"07190f91e1f0f4d0701ecfda4de5f104cc322e4c"},{"author":{"_account_id":7634,"name":"Takashi Natsume","email":"takanattie@gmail.com","username":"natsumet"},"change_message_id":"5ba0cd65dd0fdc26268514b549dce64e688c705e","unresolved":false,"context_lines":[{"line_number":773,"context_line":"**Positional arguments:**"},{"line_number":774,"context_line":""},{"line_number":775,"context_line":"``\u003caggregate\u003e``"},{"line_number":776,"context_line":"  Name or ID of aggregate."},{"line_number":777,"context_line":""},{"line_number":778,"context_line":"``\u003cimage\u003e``"},{"line_number":779,"context_line":"  Name or ID of image(s) to cache."}],"source_content_type":"text/x-rst","patch_set":6,"id":"3fa7e38b_afc60467","line":776,"range":{"start_line":776,"start_character":2,"end_line":776,"end_character":26},"updated":"2019-10-17 02:46:05.000000000","message":"nit: It is not the same as the help message.\n\n  Name or ID of the aggregate.","commit_id":"07190f91e1f0f4d0701ecfda4de5f104cc322e4c"},{"author":{"_account_id":7634,"name":"Takashi Natsume","email":"takanattie@gmail.com","username":"natsumet"},"change_message_id":"5ba0cd65dd0fdc26268514b549dce64e688c705e","unresolved":false,"context_lines":[{"line_number":776,"context_line":"  Name or ID of aggregate."},{"line_number":777,"context_line":""},{"line_number":778,"context_line":"``\u003cimage\u003e``"},{"line_number":779,"context_line":"  Name or ID of image(s) to cache."},{"line_number":780,"context_line":""},{"line_number":781,"context_line":".. _nova_aggregate-create:"},{"line_number":782,"context_line":""}],"source_content_type":"text/x-rst","patch_set":6,"id":"3fa7e38b_6fa24cb0","line":779,"range":{"start_line":779,"start_character":2,"end_line":779,"end_character":34},"updated":"2019-10-17 02:46:05.000000000","message":"ditto.\n\n  Name or ID of image(s) to cache on the hosts within the aggregate.","commit_id":"07190f91e1f0f4d0701ecfda4de5f104cc322e4c"},{"author":{"_account_id":7634,"name":"Takashi Natsume","email":"takanattie@gmail.com","username":"natsumet"},"change_message_id":"9a90798aa758b073da6e84d5216ac84f610514fb","unresolved":false,"context_lines":[{"line_number":768,"context_line":""},{"line_number":769,"context_line":"   usage: nova aggregate-cache-images \u003caggregate\u003e \u003cimage\u003e [\u003cimage\u003e ..]"},{"line_number":770,"context_line":""},{"line_number":771,"context_line":"Request image(s) be pre-cached on hosts within the aggregate."},{"line_number":772,"context_line":""},{"line_number":773,"context_line":"**Positional arguments:**"},{"line_number":774,"context_line":""}],"source_content_type":"text/x-rst","patch_set":9,"id":"3fa7e38b_685d3f47","line":771,"updated":"2019-10-19 15:11:23.000000000","message":"nit:\n(Supported by API versions ‘2.81’ - ‘2.latest’)","commit_id":"71c29a184b388b38d81dc609b9883c5e8f7166cf"},{"author":{"_account_id":7634,"name":"Takashi Natsume","email":"takanattie@gmail.com","username":"natsumet"},"change_message_id":"9a90798aa758b073da6e84d5216ac84f610514fb","unresolved":false,"context_lines":[{"line_number":769,"context_line":"   usage: nova aggregate-cache-images \u003caggregate\u003e \u003cimage\u003e [\u003cimage\u003e ..]"},{"line_number":770,"context_line":""},{"line_number":771,"context_line":"Request image(s) be pre-cached on hosts within the aggregate."},{"line_number":772,"context_line":""},{"line_number":773,"context_line":"**Positional arguments:**"},{"line_number":774,"context_line":""},{"line_number":775,"context_line":"``\u003caggregate\u003e``"}],"source_content_type":"text/x-rst","patch_set":9,"id":"3fa7e38b_48540322","line":772,"updated":"2019-10-19 15:11:23.000000000","message":"nit:\n\n.. versionadded:: 16.0.0","commit_id":"71c29a184b388b38d81dc609b9883c5e8f7166cf"}],"novaclient/tests/unit/v2/test_aggregates.py":[{"author":{"_account_id":7634,"name":"Takashi Natsume","email":"takanattie@gmail.com","username":"natsumet"},"change_message_id":"a37b0b2e4750275729ed90c2c6c98b0364ab78d2","unresolved":false,"context_lines":[{"line_number":184,"context_line":"        expected_body \u003d {\u0027cache\u0027: [{\u0027id\u0027: image.id}"},{"line_number":185,"context_line":"                                   for image in _images]}"},{"line_number":186,"context_line":"        self.assert_called(\u0027POST\u0027, \u0027/os-aggregates/1/images\u0027,"},{"line_number":187,"context_line":"                           expected_body)"}],"source_content_type":"text/x-python","patch_set":2,"id":"3fa7e38b_b5b666f8","line":187,"updated":"2019-10-16 05:03:51.000000000","message":"Add a test for microversion 2.80.\n\nFor example:\n\nhttps://github.com/openstack/python-novaclient/blob/6c0e4d7a3940ba6d4d11d0c89933cc00b898ed9e/novaclient/tests/unit/v2/test_servers.py#L1898-L1901","commit_id":"68915059736069e2ce4a8f838c16c7e87ae78974"},{"author":{"_account_id":4393,"name":"Dan Smith","email":"dms@danplanet.com","username":"danms"},"change_message_id":"7448f80e421eaa4fa1add1c2456892f19c11aae1","unresolved":false,"context_lines":[{"line_number":184,"context_line":"        expected_body \u003d {\u0027cache\u0027: [{\u0027id\u0027: image.id}"},{"line_number":185,"context_line":"                                   for image in _images]}"},{"line_number":186,"context_line":"        self.assert_called(\u0027POST\u0027, \u0027/os-aggregates/1/images\u0027,"},{"line_number":187,"context_line":"                           expected_body)"}],"source_content_type":"text/x-python","patch_set":2,"id":"3fa7e38b_d11e8f6e","line":187,"in_reply_to":"3fa7e38b_b5b666f8","updated":"2019-10-16 14:06:20.000000000","message":"Done","commit_id":"68915059736069e2ce4a8f838c16c7e87ae78974"},{"author":{"_account_id":6873,"name":"Matt Riedemann","email":"mriedem.os@gmail.com","username":"mriedem"},"change_message_id":"4602719b6cc41fcec81058e13e4080423e0f3edc","unresolved":false,"context_lines":[{"line_number":179,"context_line":""},{"line_number":180,"context_line":"    def test_cache_images(self):"},{"line_number":181,"context_line":"        aggregate \u003d self.cs.aggregates.list()[0]"},{"line_number":182,"context_line":"        _images \u003d [images.Image(self.cs.aggregates, {\u0027id\u0027: \u00271\u0027}),"},{"line_number":183,"context_line":"                   images.Image(self.cs.aggregates, {\u0027id\u0027: \u00272\u0027})]"},{"line_number":184,"context_line":"        aggregate.cache_images(_images)"},{"line_number":185,"context_line":"        expected_body \u003d {\u0027cache\u0027: [{\u0027id\u0027: image.id}"}],"source_content_type":"text/x-python","patch_set":4,"id":"3fa7e38b_6c9ca40d","line":182,"range":{"start_line":182,"start_character":19,"end_line":182,"end_character":31},"updated":"2019-10-16 14:45:13.000000000","message":"This works because the code is expecting this object rather than a string, but I\u0027d expect the python API binding method to take either so we should test both cases.","commit_id":"18b3f9e5e770fda2824be23b30b9cce68a507bb8"}],"novaclient/tests/unit/v2/test_shell.py":[{"author":{"_account_id":7634,"name":"Takashi Natsume","email":"takanattie@gmail.com","username":"natsumet"},"change_message_id":"a37b0b2e4750275729ed90c2c6c98b0364ab78d2","unresolved":false,"context_lines":[{"line_number":2894,"context_line":"                      {\u0027id\u0027: FAKE_UUID_2}],"},{"line_number":2895,"context_line":"        }"},{"line_number":2896,"context_line":"        self.assert_called(\u0027POST\u0027, \u0027/os-aggregates/1/images\u0027, body)"},{"line_number":2897,"context_line":""},{"line_number":2898,"context_line":"    def test_live_migration(self):"},{"line_number":2899,"context_line":"        self.run_command(\u0027live-migration sample-server hostname\u0027)"},{"line_number":2900,"context_line":"        self.assert_called(\u0027POST\u0027, \u0027/servers/1234/action\u0027,"}],"source_content_type":"text/x-python","patch_set":2,"id":"3fa7e38b_75cc6e88","line":2897,"updated":"2019-10-16 05:03:51.000000000","message":"ditto\n\nFor example:\nhttps://github.com/openstack/python-novaclient/blob/6c0e4d7a3940ba6d4d11d0c89933cc00b898ed9e/novaclient/tests/unit/v2/test_shell.py#L2507-L2512","commit_id":"68915059736069e2ce4a8f838c16c7e87ae78974"},{"author":{"_account_id":4393,"name":"Dan Smith","email":"dms@danplanet.com","username":"danms"},"change_message_id":"7448f80e421eaa4fa1add1c2456892f19c11aae1","unresolved":false,"context_lines":[{"line_number":2894,"context_line":"                      {\u0027id\u0027: FAKE_UUID_2}],"},{"line_number":2895,"context_line":"        }"},{"line_number":2896,"context_line":"        self.assert_called(\u0027POST\u0027, \u0027/os-aggregates/1/images\u0027, body)"},{"line_number":2897,"context_line":""},{"line_number":2898,"context_line":"    def test_live_migration(self):"},{"line_number":2899,"context_line":"        self.run_command(\u0027live-migration sample-server hostname\u0027)"},{"line_number":2900,"context_line":"        self.assert_called(\u0027POST\u0027, \u0027/servers/1234/action\u0027,"}],"source_content_type":"text/x-python","patch_set":2,"id":"3fa7e38b_9114974e","line":2897,"in_reply_to":"3fa7e38b_75cc6e88","updated":"2019-10-16 14:06:20.000000000","message":"Done","commit_id":"68915059736069e2ce4a8f838c16c7e87ae78974"},{"author":{"_account_id":6873,"name":"Matt Riedemann","email":"mriedem.os@gmail.com","username":"mriedem"},"change_message_id":"4602719b6cc41fcec81058e13e4080423e0f3edc","unresolved":false,"context_lines":[{"line_number":2894,"context_line":"                      {\u0027id\u0027: FAKE_UUID_2}],"},{"line_number":2895,"context_line":"        }"},{"line_number":2896,"context_line":"        self.assert_called(\u0027POST\u0027, \u0027/os-aggregates/1/images\u0027, body)"},{"line_number":2897,"context_line":""},{"line_number":2898,"context_line":"    def test_aggregate_cache_images_pre281(self):"},{"line_number":2899,"context_line":"        self.assertRaises(SystemExit,"},{"line_number":2900,"context_line":"                          self.run_command,"}],"source_content_type":"text/x-python","patch_set":4,"id":"3fa7e38b_0c7970c3","line":2897,"updated":"2019-10-16 14:45:13.000000000","message":"How about a test where one of the images isn\u0027t found?","commit_id":"18b3f9e5e770fda2824be23b30b9cce68a507bb8"}],"novaclient/v2/aggregates.py":[{"author":{"_account_id":7634,"name":"Takashi Natsume","email":"takanattie@gmail.com","username":"natsumet"},"change_message_id":"a37b0b2e4750275729ed90c2c6c98b0364ab78d2","unresolved":false,"context_lines":[{"line_number":46,"context_line":"        \"\"\""},{"line_number":47,"context_line":"        return self.manager.delete(self)"},{"line_number":48,"context_line":""},{"line_number":49,"context_line":"    @api_versions.wraps(\"2.80\")"},{"line_number":50,"context_line":"    def cache_images(self, images):"},{"line_number":51,"context_line":"        return self.manager.cache_images(self, images)"},{"line_number":52,"context_line":""}],"source_content_type":"text/x-python","patch_set":2,"id":"3fa7e38b_d5d44222","line":49,"range":{"start_line":49,"start_character":25,"end_line":49,"end_character":29},"updated":"2019-10-16 05:03:51.000000000","message":"2.81","commit_id":"68915059736069e2ce4a8f838c16c7e87ae78974"},{"author":{"_account_id":4393,"name":"Dan Smith","email":"dms@danplanet.com","username":"danms"},"change_message_id":"7448f80e421eaa4fa1add1c2456892f19c11aae1","unresolved":false,"context_lines":[{"line_number":46,"context_line":"        \"\"\""},{"line_number":47,"context_line":"        return self.manager.delete(self)"},{"line_number":48,"context_line":""},{"line_number":49,"context_line":"    @api_versions.wraps(\"2.80\")"},{"line_number":50,"context_line":"    def cache_images(self, images):"},{"line_number":51,"context_line":"        return self.manager.cache_images(self, images)"},{"line_number":52,"context_line":""}],"source_content_type":"text/x-python","patch_set":2,"id":"3fa7e38b_310fe337","line":49,"range":{"start_line":49,"start_character":25,"end_line":49,"end_character":29},"in_reply_to":"3fa7e38b_d5d44222","updated":"2019-10-16 14:06:20.000000000","message":"Done (oops)","commit_id":"68915059736069e2ce4a8f838c16c7e87ae78974"},{"author":{"_account_id":7634,"name":"Takashi Natsume","email":"takanattie@gmail.com","username":"natsumet"},"change_message_id":"a37b0b2e4750275729ed90c2c6c98b0364ab78d2","unresolved":false,"context_lines":[{"line_number":115,"context_line":"        Request images be cached on a given aggregate."},{"line_number":116,"context_line":""},{"line_number":117,"context_line":"        :param aggregate: The aggregate to target"},{"line_number":118,"context_line":"        :param images: A list of image IDs to request caching"},{"line_number":119,"context_line":"        \"\"\""},{"line_number":120,"context_line":"        body \u003d {"},{"line_number":121,"context_line":"            \u0027cache\u0027: [{\u0027id\u0027: image.id} for image in images],"}],"source_content_type":"text/x-python","patch_set":2,"id":"3fa7e38b_35c27654","line":118,"updated":"2019-10-16 05:03:51.000000000","message":"nit: Add \u0027returns\u0027.","commit_id":"68915059736069e2ce4a8f838c16c7e87ae78974"},{"author":{"_account_id":4393,"name":"Dan Smith","email":"dms@danplanet.com","username":"danms"},"change_message_id":"7448f80e421eaa4fa1add1c2456892f19c11aae1","unresolved":false,"context_lines":[{"line_number":115,"context_line":"        Request images be cached on a given aggregate."},{"line_number":116,"context_line":""},{"line_number":117,"context_line":"        :param aggregate: The aggregate to target"},{"line_number":118,"context_line":"        :param images: A list of image IDs to request caching"},{"line_number":119,"context_line":"        \"\"\""},{"line_number":120,"context_line":"        body \u003d {"},{"line_number":121,"context_line":"            \u0027cache\u0027: [{\u0027id\u0027: image.id} for image in images],"}],"source_content_type":"text/x-python","patch_set":2,"id":"3fa7e38b_510a9f25","line":118,"in_reply_to":"3fa7e38b_35c27654","updated":"2019-10-16 14:06:20.000000000","message":"Done","commit_id":"68915059736069e2ce4a8f838c16c7e87ae78974"},{"author":{"_account_id":6873,"name":"Matt Riedemann","email":"mriedem.os@gmail.com","username":"mriedem"},"change_message_id":"4602719b6cc41fcec81058e13e4080423e0f3edc","unresolved":false,"context_lines":[{"line_number":115,"context_line":"        Request images be cached on a given aggregate."},{"line_number":116,"context_line":""},{"line_number":117,"context_line":"        :param aggregate: The aggregate to target"},{"line_number":118,"context_line":"        :param images: A list of image IDs to request caching"},{"line_number":119,"context_line":"        :returns: An instance of novaclient.base.TupleWithMeta"},{"line_number":120,"context_line":"        \"\"\""},{"line_number":121,"context_line":"        body \u003d {"}],"source_content_type":"text/x-python","patch_set":4,"id":"3fa7e38b_ec1e54b9","line":118,"range":{"start_line":118,"start_character":23,"end_line":118,"end_character":61},"updated":"2019-10-16 14:45:13.000000000","message":"This isn\u0027t accurate. The code (and test) are assuming Image objects, right?","commit_id":"18b3f9e5e770fda2824be23b30b9cce68a507bb8"},{"author":{"_account_id":6873,"name":"Matt Riedemann","email":"mriedem.os@gmail.com","username":"mriedem"},"change_message_id":"11f20234bf2ecd30a074cb0c97d07aeff8ddde4c","unresolved":false,"context_lines":[{"line_number":115,"context_line":"        Request images be cached on a given aggregate."},{"line_number":116,"context_line":""},{"line_number":117,"context_line":"        :param aggregate: The aggregate to target"},{"line_number":118,"context_line":"        :param images: A list of image IDs to request caching"},{"line_number":119,"context_line":"        :returns: An instance of novaclient.base.TupleWithMeta"},{"line_number":120,"context_line":"        \"\"\""},{"line_number":121,"context_line":"        body \u003d {"}],"source_content_type":"text/x-python","patch_set":4,"id":"3fa7e38b_d5ed18f0","line":118,"range":{"start_line":118,"start_character":23,"end_line":118,"end_character":61},"in_reply_to":"3fa7e38b_159970c2","updated":"2019-10-16 15:48:34.000000000","message":"If you want to be unambiguous then I guess it should be the Image object even though aggregate can be an Aggregate object or id.\n\nLooking at other API methods that take an image, server create says it takes an Image object:\n\nhttps://github.com/openstack/python-novaclient/blob/6c0e4d7a3940ba6d4d11d0c89933cc00b898ed9e/novaclient/v2/servers.py#L1337\n\nBut it still handles it being a string ID:\n\nhttps://github.com/openstack/python-novaclient/blob/6c0e4d7a3940ba6d4d11d0c89933cc00b898ed9e/novaclient/v2/servers.py#L722\n\nSame story with rescue:\n\nhttps://github.com/openstack/python-novaclient/blob/6c0e4d7a3940ba6d4d11d0c89933cc00b898ed9e/novaclient/v2/servers.py#L1204\n\nhttps://github.com/openstack/python-novaclient/blob/6c0e4d7a3940ba6d4d11d0c89933cc00b898ed9e/novaclient/v2/servers.py#L1211\n\nrebuild says it takes either:\n\nhttps://github.com/openstack/python-novaclient/blob/6c0e4d7a3940ba6d4d11d0c89933cc00b898ed9e/novaclient/v2/servers.py#L1562\n\nSo I don\u0027t really have a strong preference either way but we should be clear and consistent in the docstring if we\u0027re going to take one or the other and not both.","commit_id":"18b3f9e5e770fda2824be23b30b9cce68a507bb8"},{"author":{"_account_id":4393,"name":"Dan Smith","email":"dms@danplanet.com","username":"danms"},"change_message_id":"e8cd214242d9afd689976a8b432b1bc397553c8a","unresolved":false,"context_lines":[{"line_number":115,"context_line":"        Request images be cached on a given aggregate."},{"line_number":116,"context_line":""},{"line_number":117,"context_line":"        :param aggregate: The aggregate to target"},{"line_number":118,"context_line":"        :param images: A list of image IDs to request caching"},{"line_number":119,"context_line":"        :returns: An instance of novaclient.base.TupleWithMeta"},{"line_number":120,"context_line":"        \"\"\""},{"line_number":121,"context_line":"        body \u003d {"}],"source_content_type":"text/x-python","patch_set":4,"id":"3fa7e38b_159970c2","line":118,"range":{"start_line":118,"start_character":23,"end_line":118,"end_character":61},"in_reply_to":"3fa7e38b_ec1e54b9","updated":"2019-10-16 15:40:36.000000000","message":"I wrote this when I was just passing through what was on the command line. Then I realized I should probably be resolving it there first.\n\nSo what do you want this to be? Image() or string? I\u0027d prefer it to be unambiguous in the API and let the CLI resolve the name-or-id. However, I dunno what the convention is, so tell me and I\u0027ll update the code and the comment to match.","commit_id":"18b3f9e5e770fda2824be23b30b9cce68a507bb8"},{"author":{"_account_id":6873,"name":"Matt Riedemann","email":"mriedem.os@gmail.com","username":"mriedem"},"change_message_id":"4602719b6cc41fcec81058e13e4080423e0f3edc","unresolved":false,"context_lines":[{"line_number":119,"context_line":"        :returns: An instance of novaclient.base.TupleWithMeta"},{"line_number":120,"context_line":"        \"\"\""},{"line_number":121,"context_line":"        body \u003d {"},{"line_number":122,"context_line":"            \u0027cache\u0027: [{\u0027id\u0027: image.id} for image in images],"},{"line_number":123,"context_line":"        }"},{"line_number":124,"context_line":"        resp, body \u003d self.api.client.post("},{"line_number":125,"context_line":"            \"/os-aggregates/%s/images\" % base.getid(aggregate),"}],"source_content_type":"text/x-python","patch_set":4,"id":"3fa7e38b_6ce7c4ad","line":122,"range":{"start_line":122,"start_character":29,"end_line":122,"end_character":37},"updated":"2019-10-16 14:45:13.000000000","message":"Per the above, if the method is going to take a list of IDs or Image objects, this should be using a helper method that tries to get the id attribute from the image variable and handles AttributeError and just returns the image value. I could have sworn there was a pre-existing helper method in here that did that, e.g. something like this:\n\ndef get_id(obj_or_id):\n    try:\n        return obj_or_id.id\n    except AttributeError:\n        return obj_or_id","commit_id":"18b3f9e5e770fda2824be23b30b9cce68a507bb8"},{"author":{"_account_id":6873,"name":"Matt Riedemann","email":"mriedem.os@gmail.com","username":"mriedem"},"change_message_id":"4602719b6cc41fcec81058e13e4080423e0f3edc","unresolved":false,"context_lines":[{"line_number":122,"context_line":"            \u0027cache\u0027: [{\u0027id\u0027: image.id} for image in images],"},{"line_number":123,"context_line":"        }"},{"line_number":124,"context_line":"        resp, body \u003d self.api.client.post("},{"line_number":125,"context_line":"            \"/os-aggregates/%s/images\" % base.getid(aggregate),"},{"line_number":126,"context_line":"            body\u003dbody)"},{"line_number":127,"context_line":"        return self.convert_into_with_meta(body, resp)"}],"source_content_type":"text/x-python","patch_set":4,"id":"3fa7e38b_8cea4071","line":125,"range":{"start_line":125,"start_character":46,"end_line":125,"end_character":51},"updated":"2019-10-16 14:45:13.000000000","message":"Heh, yeah - this is exactly what I was looking for.","commit_id":"18b3f9e5e770fda2824be23b30b9cce68a507bb8"}],"novaclient/v2/shell.py":[{"author":{"_account_id":6873,"name":"Matt Riedemann","email":"mriedem.os@gmail.com","username":"mriedem"},"change_message_id":"4602719b6cc41fcec81058e13e4080423e0f3edc","unresolved":false,"context_lines":[{"line_number":3522,"context_line":"@utils.arg("},{"line_number":3523,"context_line":"    \u0027aggregate\u0027, metavar\u003d\u0027\u003caggregate\u003e\u0027)"},{"line_number":3524,"context_line":"@utils.arg("},{"line_number":3525,"context_line":"    \u0027images\u0027, metavar\u003d\u0027\u003cimage\u003e\u0027, nargs\u003d\u0027+\u0027)"},{"line_number":3526,"context_line":"def do_aggregate_cache_images(cs, args):"},{"line_number":3527,"context_line":"    \"\"\"Request images be cached.\"\"\""},{"line_number":3528,"context_line":"    aggregate \u003d _find_aggregate(cs, args.aggregate)"}],"source_content_type":"text/x-python","patch_set":4,"id":"3fa7e38b_cc3598f8","line":3525,"range":{"start_line":3525,"start_character":40,"end_line":3525,"end_character":41},"updated":"2019-10-16 14:45:13.000000000","message":"With nargs\u003d+ we could have a test to make sure we fail if no image is specified.","commit_id":"18b3f9e5e770fda2824be23b30b9cce68a507bb8"},{"author":{"_account_id":6873,"name":"Matt Riedemann","email":"mriedem.os@gmail.com","username":"mriedem"},"change_message_id":"4602719b6cc41fcec81058e13e4080423e0f3edc","unresolved":false,"context_lines":[{"line_number":3519,"context_line":""},{"line_number":3520,"context_line":""},{"line_number":3521,"context_line":"@api_versions.wraps(\"2.81\")"},{"line_number":3522,"context_line":"@utils.arg("},{"line_number":3523,"context_line":"    \u0027aggregate\u0027, metavar\u003d\u0027\u003caggregate\u003e\u0027)"},{"line_number":3524,"context_line":"@utils.arg("},{"line_number":3525,"context_line":"    \u0027images\u0027, metavar\u003d\u0027\u003cimage\u003e\u0027, nargs\u003d\u0027+\u0027)"},{"line_number":3526,"context_line":"def do_aggregate_cache_images(cs, args):"},{"line_number":3527,"context_line":"    \"\"\"Request images be cached.\"\"\""},{"line_number":3528,"context_line":"    aggregate \u003d _find_aggregate(cs, args.aggregate)"}],"source_content_type":"text/x-python","patch_set":4,"id":"3fa7e38b_0c8bb0bf","line":3525,"range":{"start_line":3522,"start_character":0,"end_line":3525,"end_character":43},"updated":"2019-10-16 14:45:13.000000000","message":"You\u0027re missing help on these.","commit_id":"18b3f9e5e770fda2824be23b30b9cce68a507bb8"},{"author":{"_account_id":6873,"name":"Matt Riedemann","email":"mriedem.os@gmail.com","username":"mriedem"},"change_message_id":"24967a453fe4ee52115e928105985d00a35756fc","unresolved":false,"context_lines":[{"line_number":3522,"context_line":"@utils.arg("},{"line_number":3523,"context_line":"    \u0027aggregate\u0027, metavar\u003d\u0027\u003caggregate\u003e\u0027)"},{"line_number":3524,"context_line":"@utils.arg("},{"line_number":3525,"context_line":"    \u0027images\u0027, metavar\u003d\u0027\u003cimage\u003e\u0027, nargs\u003d\u0027+\u0027)"},{"line_number":3526,"context_line":"def do_aggregate_cache_images(cs, args):"},{"line_number":3527,"context_line":"    \"\"\"Request images be cached.\"\"\""},{"line_number":3528,"context_line":"    aggregate \u003d _find_aggregate(cs, args.aggregate)"}],"source_content_type":"text/x-python","patch_set":4,"id":"3fa7e38b_b8bf21a9","line":3525,"range":{"start_line":3525,"start_character":40,"end_line":3525,"end_character":41},"in_reply_to":"3fa7e38b_b88e532b","updated":"2019-10-17 16:33:03.000000000","message":"That\u0027s not the intent, it\u0027s making sure we don\u0027t regress if for some reason in the future the + was accidentally dropped. It\u0027s not a big deal though, I\u0027m already +2.","commit_id":"18b3f9e5e770fda2824be23b30b9cce68a507bb8"},{"author":{"_account_id":4393,"name":"Dan Smith","email":"dms@danplanet.com","username":"danms"},"change_message_id":"52ac7f051b42b603c4d69883153944dd343f0b11","unresolved":false,"context_lines":[{"line_number":3522,"context_line":"@utils.arg("},{"line_number":3523,"context_line":"    \u0027aggregate\u0027, metavar\u003d\u0027\u003caggregate\u003e\u0027)"},{"line_number":3524,"context_line":"@utils.arg("},{"line_number":3525,"context_line":"    \u0027images\u0027, metavar\u003d\u0027\u003cimage\u003e\u0027, nargs\u003d\u0027+\u0027)"},{"line_number":3526,"context_line":"def do_aggregate_cache_images(cs, args):"},{"line_number":3527,"context_line":"    \"\"\"Request images be cached.\"\"\""},{"line_number":3528,"context_line":"    aggregate \u003d _find_aggregate(cs, args.aggregate)"}],"source_content_type":"text/x-python","patch_set":4,"id":"3fa7e38b_b88e532b","line":3525,"range":{"start_line":3525,"start_character":40,"end_line":3525,"end_character":41},"in_reply_to":"3fa7e38b_cc3598f8","updated":"2019-10-17 13:52:41.000000000","message":"Yeah, again, this seems like just testing the infrastructure, but... okay.","commit_id":"18b3f9e5e770fda2824be23b30b9cce68a507bb8"},{"author":{"_account_id":6873,"name":"Matt Riedemann","email":"mriedem.os@gmail.com","username":"mriedem"},"change_message_id":"4602719b6cc41fcec81058e13e4080423e0f3edc","unresolved":false,"context_lines":[{"line_number":3529,"context_line":"    images \u003d []"},{"line_number":3530,"context_line":"    for image_spec in args.images:"},{"line_number":3531,"context_line":"        image \u003d _find_image(cs, image_spec)"},{"line_number":3532,"context_line":"        if not image:"},{"line_number":3533,"context_line":"            raise exceptions.CommandError("},{"line_number":3534,"context_line":"                \"Unable to find image %r\" % image_spec)"},{"line_number":3535,"context_line":"        images.append(image)"}],"source_content_type":"text/x-python","patch_set":4,"id":"3fa7e38b_8c6d6004","line":3532,"range":{"start_line":3532,"start_character":8,"end_line":3532,"end_character":21},"updated":"2019-10-16 14:45:13.000000000","message":"I don\u0027t think _find_image will return None will it? If it doesn\u0027t find the image it raises CommandError.","commit_id":"18b3f9e5e770fda2824be23b30b9cce68a507bb8"},{"author":{"_account_id":4393,"name":"Dan Smith","email":"dms@danplanet.com","username":"danms"},"change_message_id":"e8cd214242d9afd689976a8b432b1bc397553c8a","unresolved":false,"context_lines":[{"line_number":3529,"context_line":"    images \u003d []"},{"line_number":3530,"context_line":"    for image_spec in args.images:"},{"line_number":3531,"context_line":"        image \u003d _find_image(cs, image_spec)"},{"line_number":3532,"context_line":"        if not image:"},{"line_number":3533,"context_line":"            raise exceptions.CommandError("},{"line_number":3534,"context_line":"                \"Unable to find image %r\" % image_spec)"},{"line_number":3535,"context_line":"        images.append(image)"}],"source_content_type":"text/x-python","patch_set":4,"id":"3fa7e38b_95ea400c","line":3532,"range":{"start_line":3532,"start_character":8,"end_line":3532,"end_character":21},"in_reply_to":"3fa7e38b_8c6d6004","updated":"2019-10-16 15:40:36.000000000","message":"I copied this from somewhere else. But if so, cool.","commit_id":"18b3f9e5e770fda2824be23b30b9cce68a507bb8"},{"author":{"_account_id":6873,"name":"Matt Riedemann","email":"mriedem.os@gmail.com","username":"mriedem"},"change_message_id":"11f20234bf2ecd30a074cb0c97d07aeff8ddde4c","unresolved":false,"context_lines":[{"line_number":3529,"context_line":"    images \u003d []"},{"line_number":3530,"context_line":"    for image_spec in args.images:"},{"line_number":3531,"context_line":"        image \u003d _find_image(cs, image_spec)"},{"line_number":3532,"context_line":"        if not image:"},{"line_number":3533,"context_line":"            raise exceptions.CommandError("},{"line_number":3534,"context_line":"                \"Unable to find image %r\" % image_spec)"},{"line_number":3535,"context_line":"        images.append(image)"}],"source_content_type":"text/x-python","patch_set":4,"id":"3fa7e38b_d5c67868","line":3532,"range":{"start_line":3532,"start_character":8,"end_line":3532,"end_character":21},"in_reply_to":"3fa7e38b_95ea400c","updated":"2019-10-16 15:48:34.000000000","message":"Looking at other uses of _find_image in here it looks like commands where image is optional so maybe that\u0027s why.","commit_id":"18b3f9e5e770fda2824be23b30b9cce68a507bb8"},{"author":{"_account_id":6873,"name":"Matt Riedemann","email":"mriedem.os@gmail.com","username":"mriedem"},"change_message_id":"98c82efac5e0c4988621a40ead0f8075afc82c10","unresolved":false,"context_lines":[{"line_number":3524,"context_line":"    help\u003d_(\u0027Name or ID of the aggregate.\u0027))"},{"line_number":3525,"context_line":"@utils.arg("},{"line_number":3526,"context_line":"    \u0027images\u0027, metavar\u003d\u0027\u003cimage\u003e\u0027, nargs\u003d\u0027+\u0027,"},{"line_number":3527,"context_line":"    help\u003d_(\u0027The image to cache on the hosts within the aggregate.\u0027))"},{"line_number":3528,"context_line":"def do_aggregate_cache_images(cs, args):"},{"line_number":3529,"context_line":"    \"\"\"Request images be cached.\"\"\""},{"line_number":3530,"context_line":"    aggregate \u003d _find_aggregate(cs, args.aggregate)"}],"source_content_type":"text/x-python","patch_set":5,"id":"3fa7e38b_461f405a","line":3527,"range":{"start_line":3527,"start_character":16,"end_line":3527,"end_character":21},"updated":"2019-10-16 18:18:31.000000000","message":"image(s)\n\nOr just re-using what you have in the docs is good too:\n\n\"Name or ID of image(s) to cache.\"","commit_id":"3124945e20e3e8b34000623674abfb4e929a8158"},{"author":{"_account_id":9545,"name":"Andriy Kurilin","email":"andr.kurilin@gmail.com","username":"akurilin"},"change_message_id":"b0d3cedff4bb22718a2dfd03f3f2a85ffa422305","unresolved":false,"context_lines":[{"line_number":3530,"context_line":"    \"\"\"Request images be cached.\"\"\""},{"line_number":3531,"context_line":"    aggregate \u003d _find_aggregate(cs, args.aggregate)"},{"line_number":3532,"context_line":"    images \u003d []"},{"line_number":3533,"context_line":"    for image_spec in args.images:"},{"line_number":3534,"context_line":"        image \u003d _find_image(cs, image_spec)"},{"line_number":3535,"context_line":"        images.append(image)"},{"line_number":3536,"context_line":"    cs.aggregates.cache_images(aggregate, images)"},{"line_number":3537,"context_line":""},{"line_number":3538,"context_line":""}],"source_content_type":"text/x-python","patch_set":6,"id":"3fa7e38b_430e478c","line":3535,"range":{"start_line":3533,"start_character":4,"end_line":3535,"end_character":28},"updated":"2019-10-17 11:03:49.000000000","message":"it would be nice to transform `_find_image` to `_find_images` and use the whole power of glance listing API (it supports listing by several names[*]), so we can reduce the number of API calls.\n\n[*] - https://docs.openstack.org/api-ref/image/v2/?expanded\u003dlist-images-detail#list-images","commit_id":"07190f91e1f0f4d0701ecfda4de5f104cc322e4c"},{"author":{"_account_id":4393,"name":"Dan Smith","email":"dms@danplanet.com","username":"danms"},"change_message_id":"52ac7f051b42b603c4d69883153944dd343f0b11","unresolved":false,"context_lines":[{"line_number":3530,"context_line":"    \"\"\"Request images be cached.\"\"\""},{"line_number":3531,"context_line":"    aggregate \u003d _find_aggregate(cs, args.aggregate)"},{"line_number":3532,"context_line":"    images \u003d []"},{"line_number":3533,"context_line":"    for image_spec in args.images:"},{"line_number":3534,"context_line":"        image \u003d _find_image(cs, image_spec)"},{"line_number":3535,"context_line":"        images.append(image)"},{"line_number":3536,"context_line":"    cs.aggregates.cache_images(aggregate, images)"},{"line_number":3537,"context_line":""},{"line_number":3538,"context_line":""}],"source_content_type":"text/x-python","patch_set":6,"id":"3fa7e38b_a7b2a448","line":3535,"range":{"start_line":3533,"start_character":4,"end_line":3535,"end_character":28},"in_reply_to":"3fa7e38b_430e478c","updated":"2019-10-17 13:52:41.000000000","message":"Are you asking me to do that refactor before I can land this change?","commit_id":"07190f91e1f0f4d0701ecfda4de5f104cc322e4c"},{"author":{"_account_id":9545,"name":"Andriy Kurilin","email":"andr.kurilin@gmail.com","username":"akurilin"},"change_message_id":"1b4c1dd6abed1d5bf7960930d6bc93eba3670252","unresolved":false,"context_lines":[{"line_number":3530,"context_line":"    \"\"\"Request images be cached.\"\"\""},{"line_number":3531,"context_line":"    aggregate \u003d _find_aggregate(cs, args.aggregate)"},{"line_number":3532,"context_line":"    images \u003d []"},{"line_number":3533,"context_line":"    for image_spec in args.images:"},{"line_number":3534,"context_line":"        image \u003d _find_image(cs, image_spec)"},{"line_number":3535,"context_line":"        images.append(image)"},{"line_number":3536,"context_line":"    cs.aggregates.cache_images(aggregate, images)"},{"line_number":3537,"context_line":""},{"line_number":3538,"context_line":""}],"source_content_type":"text/x-python","patch_set":6,"id":"3fa7e38b_ae56f829","line":3535,"range":{"start_line":3533,"start_character":4,"end_line":3535,"end_character":28},"in_reply_to":"3fa7e38b_98f02594","updated":"2019-10-17 21:25:57.000000000","message":"\u003e Client-side we\u0027d have to validate that the number of images we get\n \u003e back from glance is equal to the number provided or fail and when\n \u003e failing we would have to figure out the difference (what is\n \u003e missing?) so it\u0027s more complicated than just listing the images\n \u003e since the listing API won\u0027t 404 if something is missing.\n\nIt is just a few lines of code:\n\n   def find_images(self, names_or_ids):\n        with self.alternate_service_type(\n                \u0027image\u0027, allowed_types\u003d(\u0027image\u0027,)):\n            matches \u003d self._list(\u0027/v2/images?id\u003din:%s\u0027 % \u0027,\u0027.join(names_or_ids))\n            matches.extend(self._list(\u0027/v2/images?names\u003din:%s\u0027 % \u0027,\u0027.join(names_or_ids)))\n            missed \u003d names_or_ids - set(m.name for m in matches) - set(m.id for m in matches)\n            if missed:\n                raise Exception()\n            additional \u003d set()\n            for i in matches:\n                 if i.name not in names_or_ids and i.uuid not in names_or_ids:\n                     additional.add(i)\n            if addtional:\n                 raise Exceiption()","commit_id":"07190f91e1f0f4d0701ecfda4de5f104cc322e4c"},{"author":{"_account_id":9545,"name":"Andriy Kurilin","email":"andr.kurilin@gmail.com","username":"akurilin"},"change_message_id":"1b4c1dd6abed1d5bf7960930d6bc93eba3670252","unresolved":false,"context_lines":[{"line_number":3530,"context_line":"    \"\"\"Request images be cached.\"\"\""},{"line_number":3531,"context_line":"    aggregate \u003d _find_aggregate(cs, args.aggregate)"},{"line_number":3532,"context_line":"    images \u003d []"},{"line_number":3533,"context_line":"    for image_spec in args.images:"},{"line_number":3534,"context_line":"        image \u003d _find_image(cs, image_spec)"},{"line_number":3535,"context_line":"        images.append(image)"},{"line_number":3536,"context_line":"    cs.aggregates.cache_images(aggregate, images)"},{"line_number":3537,"context_line":""},{"line_number":3538,"context_line":""}],"source_content_type":"text/x-python","patch_set":6,"id":"3fa7e38b_4e48a486","line":3535,"range":{"start_line":3533,"start_character":4,"end_line":3535,"end_character":28},"in_reply_to":"3fa7e38b_a7b2a448","updated":"2019-10-17 21:25:57.000000000","message":"\u003e Are you asking me to do that refactor before I can land this\n \u003e change?\n\nUnfortunately, my experience says that if I agree with doing it at follow up the patch, it will never happen :)\nAnd I think that it is a real performance issue. If someone requests to cache 10 images, the current implementation will  make 10 separate API calls to Glance instead of just 2(maybe it is even one, I did not check the glance API for combination of searching by id and name)...\n\nPS: I did not put -2, so I\u0027m ok that others will ignore my comment.","commit_id":"07190f91e1f0f4d0701ecfda4de5f104cc322e4c"},{"author":{"_account_id":6873,"name":"Matt Riedemann","email":"mriedem.os@gmail.com","username":"mriedem"},"change_message_id":"24967a453fe4ee52115e928105985d00a35756fc","unresolved":false,"context_lines":[{"line_number":3530,"context_line":"    \"\"\"Request images be cached.\"\"\""},{"line_number":3531,"context_line":"    aggregate \u003d _find_aggregate(cs, args.aggregate)"},{"line_number":3532,"context_line":"    images \u003d []"},{"line_number":3533,"context_line":"    for image_spec in args.images:"},{"line_number":3534,"context_line":"        image \u003d _find_image(cs, image_spec)"},{"line_number":3535,"context_line":"        images.append(image)"},{"line_number":3536,"context_line":"    cs.aggregates.cache_images(aggregate, images)"},{"line_number":3537,"context_line":""},{"line_number":3538,"context_line":""}],"source_content_type":"text/x-python","patch_set":6,"id":"3fa7e38b_98f02594","line":3535,"range":{"start_line":3533,"start_character":4,"end_line":3535,"end_character":28},"in_reply_to":"3fa7e38b_a7b2a448","updated":"2019-10-17 16:33:03.000000000","message":"I don\u0027t think that\u0027s probably reasonable in v1 of this, it could be a follow up optimization. Note that I also had that idea in the server side review:\n\nhttps://review.opendev.org/#/c/687139/4/nova/conductor/api.py@165\n\nClient-side we\u0027d have to validate that the number of images we get back from glance is equal to the number provided or fail and when failing we would have to figure out the difference (what is missing?) so it\u0027s more complicated than just listing the images since the listing API won\u0027t 404 if something is missing.","commit_id":"07190f91e1f0f4d0701ecfda4de5f104cc322e4c"},{"author":{"_account_id":26458,"name":"Brin Zhang","email":"zhangbailin@inspur.com","username":"zhangbailin"},"change_message_id":"e891fe3b807e814ec49fdffed833bbe47c403d08","unresolved":false,"context_lines":[{"line_number":3530,"context_line":"    \"\"\"Request images be cached.\"\"\""},{"line_number":3531,"context_line":"    aggregate \u003d _find_aggregate(cs, args.aggregate)"},{"line_number":3532,"context_line":"    images \u003d []"},{"line_number":3533,"context_line":"    for image_spec in args.images:"},{"line_number":3534,"context_line":"        image \u003d _find_image(cs, image_spec)"},{"line_number":3535,"context_line":"        images.append(image)"},{"line_number":3536,"context_line":"    cs.aggregates.cache_images(aggregate, images)"},{"line_number":3537,"context_line":""},{"line_number":3538,"context_line":""}],"source_content_type":"text/x-python","patch_set":6,"id":"3fa7e38b_9f4ec494","line":3535,"range":{"start_line":3533,"start_character":4,"end_line":3535,"end_character":28},"in_reply_to":"3fa7e38b_ae56f829","updated":"2019-10-18 03:18:59.000000000","message":"If there are a lot of images (\u003e2) for the cache request, I agree with @Andrey\u0027s point of view that \"_find_images\" is necessary, which will reduce the number of calls to the glance API and improve performance. But if the requested image is small, comparing the two implementations, the performance loss here is almost negligible. It\u0027s just my personal opinion.","commit_id":"07190f91e1f0f4d0701ecfda4de5f104cc322e4c"}],"releasenotes/notes/microversion-v2_81-3ddd8e2fc7e45030.yaml":[{"author":{"_account_id":6873,"name":"Matt Riedemann","email":"mriedem.os@gmail.com","username":"mriedem"},"change_message_id":"4602719b6cc41fcec81058e13e4080423e0f3edc","unresolved":false,"context_lines":[{"line_number":4,"context_line":"    Added support for `microversion 2.81`_ which adds image pre-caching support by"},{"line_number":5,"context_line":"    aggregate."},{"line_number":6,"context_line":""},{"line_number":7,"context_line":"     - The ``aggregate-cache-images`` command is added to the CLI"},{"line_number":8,"context_line":"     - The ``cache_images()`` method is added to the python API binding"},{"line_number":9,"context_line":""},{"line_number":10,"context_line":"    .. _microversion 2.81: https://docs.openstack.org/nova/latest/reference/api-microversion-history.html#id73"}],"source_content_type":"text/x-yaml","patch_set":4,"id":"3fa7e38b_8c3b20e8","line":7,"range":{"start_line":7,"start_character":4,"end_line":7,"end_character":5},"updated":"2019-10-16 14:45:13.000000000","message":"Nix the space since it screw up formatting.","commit_id":"18b3f9e5e770fda2824be23b30b9cce68a507bb8"}]}
