)]}'
{"/COMMIT_MSG":[{"author":{"_account_id":13177,"name":"Emma Foley","email":"efoley@redhat.com","username":"emma-l-foley"},"change_message_id":"02e575e7a489575971f8df501b59109c54c09235","unresolved":true,"context_lines":[{"line_number":27,"context_line":"SDK\u0027s availability_zone field as \u0027zone\u0027, preserving the field name used"},{"line_number":28,"context_line":"by prom_exporter and the Gnocchi resource type."},{"line_number":29,"context_line":""},{"line_number":30,"context_line":"VolumeProviderPoolCapacityTotal, VolumeProviderPoolCapacityFree, and"},{"line_number":31,"context_line":"VolumeProviderPoolCapacityAllocated now skip pools that do not report"},{"line_number":32,"context_line":"the respective capacity field in their capabilities rather than raising"},{"line_number":33,"context_line":"a KeyError or yielding a sample with a None volume."},{"line_number":34,"context_line":""},{"line_number":35,"context_line":"VolumeProviderPoolCapacityVirtualFree guards against missing"},{"line_number":36,"context_line":"reserved_percentage, total_capacity_gb, thin_provisioning_support, and"},{"line_number":37,"context_line":"max_over_subscription_ratio capability fields, using safe defaults"},{"line_number":38,"context_line":"rather than raising a KeyError."},{"line_number":39,"context_line":""},{"line_number":40,"context_line":"Add KEYSTONE_REQUIRED_FOR_SERVICE \u003d \u0027cinder\u0027 to _BaseDiscovery so the"},{"line_number":41,"context_line":"polling infrastructure can gate on Cinder service availability."}],"source_content_type":"text/x-gerrit-commit-message","patch_set":3,"id":"1d5e6892_6b8a0628","line":38,"range":{"start_line":30,"start_character":0,"end_line":38,"end_character":31},"updated":"2026-05-07 21:36:03.000000000","message":"The previous behaviour in the sample creation needs to be validated via unit tests.\nThis change should not modify these behaviours drastically i.e. continue to raise some error rather than silently fail.","commit_id":"f90d5ddac5cd93f4dc7afa68c69a584226156b8e"}],"/PATCHSET_LEVEL":[{"author":{"_account_id":13177,"name":"Emma Foley","email":"efoley@redhat.com","username":"emma-l-foley"},"change_message_id":"041a2e17bdb0ea2c09d87ec297f3b11083211612","unresolved":false,"context_lines":[],"source_content_type":"","patch_set":1,"id":"213f0e79_4942e7f9","updated":"2026-05-01 21:29:04.000000000","message":"I\u0027m spotted a few needed change now that I\u0027m looking at this in a different context","commit_id":"fb5d8e21ca91d6a101a1f662be38280948551790"},{"author":{"_account_id":13177,"name":"Emma Foley","email":"efoley@redhat.com","username":"emma-l-foley"},"change_message_id":"9b99421e37cbc374be6b46bdf0d71ea24261a56b","unresolved":false,"context_lines":[],"source_content_type":"","patch_set":4,"id":"4a219cce_2cc83d53","updated":"2026-05-07 21:37:40.000000000","message":"I need to update the sample creation logic to preserve the previous behaviour","commit_id":"c7a108ffc1035027a71f1c9dbb3ebe625b658f80"}],"ceilometer/tests/unit/test_cinder_client.py":[{"author":{"_account_id":34975,"name":"Jaromír Wysoglad","email":"jwysogla@redhat.com","username":"jwysogla"},"change_message_id":"236f37ef380b223c4db93d2684ca3fafdfc75f0b","unresolved":true,"context_lines":[{"line_number":55,"context_line":""},{"line_number":56,"context_line":"        self.assertEqual(fakes.VOLUME_LIST, result)"},{"line_number":57,"context_line":""},{"line_number":58,"context_line":"    def test_list_volumes_passes_search_opts(self):"},{"line_number":59,"context_line":"        self.client.list_volumes(search_opts\u003d{\u0027all_projects\u0027: True})"},{"line_number":60,"context_line":""},{"line_number":61,"context_line":"        self.fake_conn.block_storage.volumes.assert_called_once_with("}],"source_content_type":"text/x-python","patch_set":10,"id":"179f7748_884a54b9","line":58,"updated":"2026-06-16 08:21:15.000000000","message":"This test doesn\u0027t do anything right now I think. Look at the test case below `test_list_volumes_default_opts`. Both testcases result in the same call to fake_conn.block_storage.volumes, meaning this test is using the default opts anyway, so even if the \"passes_search_opts\" part doesn\u0027t work this testcase would succeed.\n\nI think you should give the list_volumes some non-default option, which you can later test. e.g. `\u0027all_projects\u0027: False`","commit_id":"c0fe404b195a293dbc2c829d27ddde0e04985966"},{"author":{"_account_id":34975,"name":"Jaromír Wysoglad","email":"jwysogla@redhat.com","username":"jwysogla"},"change_message_id":"236f37ef380b223c4db93d2684ca3fafdfc75f0b","unresolved":true,"context_lines":[{"line_number":81,"context_line":""},{"line_number":82,"context_line":"        self.assertEqual(fakes.SNAPSHOT_LIST, result)"},{"line_number":83,"context_line":""},{"line_number":84,"context_line":"    def test_list_volume_snapshots_passes_search_opts(self):"},{"line_number":85,"context_line":"        self.client.list_volume_snapshots(search_opts\u003d{\u0027all_projects\u0027: True})"},{"line_number":86,"context_line":""},{"line_number":87,"context_line":"        self.fake_conn.block_storage.snapshots.assert_called_once_with("}],"source_content_type":"text/x-python","patch_set":10,"id":"36056cf6_ad16ad8c","line":84,"updated":"2026-06-16 08:21:15.000000000","message":"Same as `test_list_volumes_passes_search_opts`","commit_id":"c0fe404b195a293dbc2c829d27ddde0e04985966"},{"author":{"_account_id":34975,"name":"Jaromír Wysoglad","email":"jwysogla@redhat.com","username":"jwysogla"},"change_message_id":"236f37ef380b223c4db93d2684ca3fafdfc75f0b","unresolved":true,"context_lines":[{"line_number":106,"context_line":""},{"line_number":107,"context_line":"        self.assertEqual(fakes.BACKUP_LIST, result)"},{"line_number":108,"context_line":""},{"line_number":109,"context_line":"    def test_list_backups_passes_search_opts(self):"},{"line_number":110,"context_line":"        self.client.list_backups(search_opts\u003d{\u0027all_projects\u0027: True})"},{"line_number":111,"context_line":""},{"line_number":112,"context_line":"        self.fake_conn.block_storage.backups.assert_called_once_with("}],"source_content_type":"text/x-python","patch_set":10,"id":"ec5dfd22_e35c4d7c","line":109,"updated":"2026-06-16 08:21:15.000000000","message":"Same as `test_list_volumes_passes_search_opts`","commit_id":"c0fe404b195a293dbc2c829d27ddde0e04985966"}],"ceilometer/volume/cinder.py":[{"author":{"_account_id":13177,"name":"Emma Foley","email":"efoley@redhat.com","username":"emma-l-foley"},"change_message_id":"041a2e17bdb0ea2c09d87ec297f3b11083211612","unresolved":true,"context_lines":[{"line_number":133,"context_line":"class _VolumeProviderPoolBase(_Base):"},{"line_number":134,"context_line":"    def extract_metadata(self, obj):"},{"line_number":135,"context_line":"        metadata \u003d super().extract_metadata(obj)"},{"line_number":136,"context_line":"        caps \u003d obj.capabilities or {}"},{"line_number":137,"context_line":"        metadata[\u0027pool_name\u0027] \u003d caps.get(\"pool_name\")"},{"line_number":138,"context_line":"        return metadata"},{"line_number":139,"context_line":""}],"source_content_type":"text/x-python","patch_set":1,"id":"f5e9e0e3_517802bb","line":136,"range":{"start_line":136,"start_character":8,"end_line":136,"end_character":37},"updated":"2026-05-01 21:29:04.000000000","message":"If obj.capabilities is a required attribute for the obj, then this check is not necessary, and this can be simplified to just get the value from obj.capabilities","commit_id":"fb5d8e21ca91d6a101a1f662be38280948551790"},{"author":{"_account_id":13177,"name":"Emma Foley","email":"efoley@redhat.com","username":"emma-l-foley"},"change_message_id":"02e575e7a489575971f8df501b59109c54c09235","unresolved":false,"context_lines":[{"line_number":133,"context_line":"class _VolumeProviderPoolBase(_Base):"},{"line_number":134,"context_line":"    def extract_metadata(self, obj):"},{"line_number":135,"context_line":"        metadata \u003d super().extract_metadata(obj)"},{"line_number":136,"context_line":"        caps \u003d obj.capabilities or {}"},{"line_number":137,"context_line":"        metadata[\u0027pool_name\u0027] \u003d caps.get(\"pool_name\")"},{"line_number":138,"context_line":"        return metadata"},{"line_number":139,"context_line":""}],"source_content_type":"text/x-python","patch_set":1,"id":"f7cf41ce_71e431d6","line":136,"range":{"start_line":136,"start_character":8,"end_line":136,"end_character":37},"in_reply_to":"f5e9e0e3_517802bb","updated":"2026-05-07 21:36:03.000000000","message":"Done","commit_id":"fb5d8e21ca91d6a101a1f662be38280948551790"},{"author":{"_account_id":13177,"name":"Emma Foley","email":"efoley@redhat.com","username":"emma-l-foley"},"change_message_id":"041a2e17bdb0ea2c09d87ec297f3b11083211612","unresolved":true,"context_lines":[{"line_number":134,"context_line":"    def extract_metadata(self, obj):"},{"line_number":135,"context_line":"        metadata \u003d super().extract_metadata(obj)"},{"line_number":136,"context_line":"        caps \u003d obj.capabilities or {}"},{"line_number":137,"context_line":"        metadata[\u0027pool_name\u0027] \u003d caps.get(\"pool_name\")"},{"line_number":138,"context_line":"        return metadata"},{"line_number":139,"context_line":""},{"line_number":140,"context_line":""}],"source_content_type":"text/x-python","patch_set":1,"id":"c2e53f02_58a6c47b","line":137,"range":{"start_line":137,"start_character":42,"end_line":137,"end_character":53},"updated":"2026-05-01 21:29:04.000000000","message":"this needs to default to None","commit_id":"fb5d8e21ca91d6a101a1f662be38280948551790"},{"author":{"_account_id":13177,"name":"Emma Foley","email":"efoley@redhat.com","username":"emma-l-foley"},"change_message_id":"041a2e17bdb0ea2c09d87ec297f3b11083211612","unresolved":true,"context_lines":[{"line_number":146,"context_line":"    def get_samples(self, manager, cache, resources):"},{"line_number":147,"context_line":"        for pool in resources:"},{"line_number":148,"context_line":"            caps \u003d pool.capabilities or {}"},{"line_number":149,"context_line":"            if caps.get(\u0027total_capacity_gb\u0027) is not None:"},{"line_number":150,"context_line":"                yield sample.Sample("},{"line_number":151,"context_line":"                    name\u003d\u0027volume.provider.pool.capacity.total\u0027,"},{"line_number":152,"context_line":"                    type\u003dsample.TYPE_GAUGE,"}],"source_content_type":"text/x-python","patch_set":1,"id":"da5dd96c_9c14911a","line":149,"range":{"start_line":149,"start_character":12,"end_line":149,"end_character":57},"updated":"2026-05-01 21:29:04.000000000","message":"I\u0027m not sure if this is the right way to go.\nI think that previously, there would have been an error if \"total_capacity_gb\" didn\u0027t exist, rather than silent skipping.\n\nPerhaps raising a ceilometerInvalidSampleData error might be the answer here? However, this is another change in behaviour, and if that is the way we go, then I suggest reverting this change, and leaving the Attribute or Type Error get raised for now, instead of this change to silently drop the sample.\n\nLater, we can follow up to enhance the error and make it more useful.","commit_id":"fb5d8e21ca91d6a101a1f662be38280948551790"},{"author":{"_account_id":13177,"name":"Emma Foley","email":"efoley@redhat.com","username":"emma-l-foley"},"change_message_id":"5060476c5e00d041905063780ec0763752008703","unresolved":true,"context_lines":[{"line_number":146,"context_line":"    def get_samples(self, manager, cache, resources):"},{"line_number":147,"context_line":"        for pool in resources:"},{"line_number":148,"context_line":"            caps \u003d pool.capabilities or {}"},{"line_number":149,"context_line":"            if caps.get(\u0027total_capacity_gb\u0027) is not None:"},{"line_number":150,"context_line":"                yield sample.Sample("},{"line_number":151,"context_line":"                    name\u003d\u0027volume.provider.pool.capacity.total\u0027,"},{"line_number":152,"context_line":"                    type\u003dsample.TYPE_GAUGE,"}],"source_content_type":"text/x-python","patch_set":1,"id":"45e7493f_a8957076","line":149,"range":{"start_line":149,"start_character":12,"end_line":149,"end_character":57},"in_reply_to":"ada1fa6c_42a0a824","updated":"2026-06-16 12:50:35.000000000","message":"It\u0027s because capabilities can be unset, and when it is set, the keys can vary. I think it depends on the storage drivers used.\n\nHowever, given that I use caps.get(\u0027total_capacity_gb\u0027) later, both checks are not necessary.\nI need to check what the previous behavior was, and preserve that. i.e. silently skip the sample or raise an error","commit_id":"fb5d8e21ca91d6a101a1f662be38280948551790"},{"author":{"_account_id":34975,"name":"Jaromír Wysoglad","email":"jwysogla@redhat.com","username":"jwysogla"},"change_message_id":"236f37ef380b223c4db93d2684ca3fafdfc75f0b","unresolved":true,"context_lines":[{"line_number":146,"context_line":"    def get_samples(self, manager, cache, resources):"},{"line_number":147,"context_line":"        for pool in resources:"},{"line_number":148,"context_line":"            caps \u003d pool.capabilities or {}"},{"line_number":149,"context_line":"            if caps.get(\u0027total_capacity_gb\u0027) is not None:"},{"line_number":150,"context_line":"                yield sample.Sample("},{"line_number":151,"context_line":"                    name\u003d\u0027volume.provider.pool.capacity.total\u0027,"},{"line_number":152,"context_line":"                    type\u003dsample.TYPE_GAUGE,"}],"source_content_type":"text/x-python","patch_set":1,"id":"ada1fa6c_42a0a824","line":149,"range":{"start_line":149,"start_character":12,"end_line":149,"end_character":57},"in_reply_to":"da5dd96c_9c14911a","updated":"2026-06-16 08:21:15.000000000","message":"So you have encountered an API response, where the total_capacity_gb was missing? Looking at the API docs, I\u0027d assume it\u0027s always there https://docs.openstack.org/api-ref/block-storage/v3/#list-all-back-end-storage-pools . If it was optional, I\u0027d assume it\u0027d be noted in the docs, for example similarly to the replication_status in https://docs.openstack.org/api-ref/block-storage/v3/#enable-cluster\n\nSimilar comment (question) would apply to the other classes in this file.","commit_id":"fb5d8e21ca91d6a101a1f662be38280948551790"},{"author":{"_account_id":13177,"name":"Emma Foley","email":"efoley@redhat.com","username":"emma-l-foley"},"change_message_id":"041a2e17bdb0ea2c09d87ec297f3b11083211612","unresolved":true,"context_lines":[{"line_number":209,"context_line":"    def get_samples(self, manager, cache, resources):"},{"line_number":210,"context_line":"        for pool in resources:"},{"line_number":211,"context_line":"            caps \u003d pool.capabilities or {}"},{"line_number":212,"context_line":"            if caps.get(\u0027provisioned_capacity_gb\u0027):"},{"line_number":213,"context_line":"                reserved_size \u003d math.floor("},{"line_number":214,"context_line":"                    (caps[\u0027reserved_percentage\u0027] / 100) *"},{"line_number":215,"context_line":"                    caps[\u0027total_capacity_gb\u0027]"}],"source_content_type":"text/x-python","patch_set":1,"id":"6db4d5a8_73b10ecc","line":212,"range":{"start_line":212,"start_character":48,"end_line":212,"end_character":51},"updated":"2026-05-01 21:29:04.000000000","message":"oops, this should have a default of None","commit_id":"fb5d8e21ca91d6a101a1f662be38280948551790"},{"author":{"_account_id":13177,"name":"Emma Foley","email":"efoley@redhat.com","username":"emma-l-foley"},"change_message_id":"041a2e17bdb0ea2c09d87ec297f3b11083211612","unresolved":true,"context_lines":[{"line_number":222,"context_line":"                value \u003d ("},{"line_number":223,"context_line":"                    max_over_subscription_ratio *"},{"line_number":224,"context_line":"                    (caps[\u0027total_capacity_gb\u0027] - reserved_size) -"},{"line_number":225,"context_line":"                    caps[\u0027provisioned_capacity_gb\u0027]"},{"line_number":226,"context_line":"                )"},{"line_number":227,"context_line":"                yield sample.Sample("},{"line_number":228,"context_line":"                    name\u003d\u0027volume.provider.pool.capacity.virtual_free\u0027,"}],"source_content_type":"text/x-python","patch_set":1,"id":"e8268e96_c7b0e57b","line":225,"range":{"start_line":225,"start_character":20,"end_line":225,"end_character":51},"updated":"2026-05-01 21:29:04.000000000","message":"These need some more work. I think .get() should be used, and have some default set.\n\n\nPreviously, an Attribute error would have been raised, if the pool object didn\u0027t have the expected attributes. So the behaviour is going to change regardless, unless I catch the exception and manually raise an Attribute error to maintain the previous behaviour.","commit_id":"fb5d8e21ca91d6a101a1f662be38280948551790"},{"author":{"_account_id":13177,"name":"Emma Foley","email":"efoley@redhat.com","username":"emma-l-foley"},"change_message_id":"041a2e17bdb0ea2c09d87ec297f3b11083211612","unresolved":true,"context_lines":[{"line_number":264,"context_line":"    def default_discovery(self):"},{"line_number":265,"context_line":"        return \u0027volume_services\u0027"},{"line_number":266,"context_line":""},{"line_number":267,"context_line":"    FIELDS \u003d [\u0027binary\u0027, \u0027host\u0027, \u0027availability_zone\u0027, \u0027status\u0027]"},{"line_number":268,"context_line":""},{"line_number":269,"context_line":"    def get_samples(self, manager, cache, resources):"},{"line_number":270,"context_line":"        for svc in resources:"}],"source_content_type":"text/x-python","patch_set":1,"id":"996dcfc4_f9b76e80","line":267,"range":{"start_line":267,"start_character":33,"end_line":267,"end_character":50},"updated":"2026-05-01 21:29:04.000000000","message":"Either we should have both \"zone\" and \"availability_zone\" included in the metadata, or only have zone, which is an alias for the \"availability_zone\" member in the service resource \n\nWDYT?\nWe need to at least keep \"zone\", so that the publisher plugins are not impacted. There might be additional impact on users if they are filtering on  this metadata.","commit_id":"fb5d8e21ca91d6a101a1f662be38280948551790"},{"author":{"_account_id":13177,"name":"Emma Foley","email":"efoley@redhat.com","username":"emma-l-foley"},"change_message_id":"02e575e7a489575971f8df501b59109c54c09235","unresolved":true,"context_lines":[{"line_number":264,"context_line":"    def default_discovery(self):"},{"line_number":265,"context_line":"        return \u0027volume_services\u0027"},{"line_number":266,"context_line":""},{"line_number":267,"context_line":"    FIELDS \u003d [\u0027binary\u0027, \u0027host\u0027, \u0027availability_zone\u0027, \u0027status\u0027]"},{"line_number":268,"context_line":""},{"line_number":269,"context_line":"    def get_samples(self, manager, cache, resources):"},{"line_number":270,"context_line":"        for svc in resources:"}],"source_content_type":"text/x-python","patch_set":1,"id":"c72dfc28_e74d6fb7","line":267,"range":{"start_line":267,"start_character":33,"end_line":267,"end_character":50},"in_reply_to":"996dcfc4_f9b76e80","updated":"2026-05-07 21:36:03.000000000","message":"This is addressed, I think. The extract_metadata method update adds a compatability layer so that the new availability_zone property gets mapped to the old zone metadata","commit_id":"fb5d8e21ca91d6a101a1f662be38280948551790"},{"author":{"_account_id":34975,"name":"Jaromír Wysoglad","email":"jwysogla@redhat.com","username":"jwysogla"},"change_message_id":"1f6ab334137450c2e1a17c9f2a045dc793743006","unresolved":true,"context_lines":[{"line_number":132,"context_line":"                volume\u003dbackup.size,"},{"line_number":133,"context_line":"                user_id\u003dbackup.user_id,"},{"line_number":134,"context_line":"                project_id\u003dgetattr("},{"line_number":135,"context_line":"                    backup, \u0027project_id\u0027, None),"},{"line_number":136,"context_line":"                resource_id\u003dbackup.id,"},{"line_number":137,"context_line":"                resource_metadata\u003dself.extract_metadata(backup),"},{"line_number":138,"context_line":"            )"}],"source_content_type":"text/x-python","patch_set":10,"id":"f9563a33_a66bc901","line":135,"updated":"2026-06-16 08:28:19.000000000","message":"This is now inconsistent with how the project_id is handled in the other classes (VolumeSnapshotSize and VolumeSizePolster). This class is the only one still using getattr. Is there a reason for not keeping them the same? I\u0027d say keeping the guard with None as default value is a safe bet here in case the API is allowed to not provide the project_id.","commit_id":"c0fe404b195a293dbc2c829d27ddde0e04985966"},{"author":{"_account_id":13177,"name":"Emma Foley","email":"efoley@redhat.com","username":"emma-l-foley"},"change_message_id":"5060476c5e00d041905063780ec0763752008703","unresolved":true,"context_lines":[{"line_number":132,"context_line":"                volume\u003dbackup.size,"},{"line_number":133,"context_line":"                user_id\u003dbackup.user_id,"},{"line_number":134,"context_line":"                project_id\u003dgetattr("},{"line_number":135,"context_line":"                    backup, \u0027project_id\u0027, None),"},{"line_number":136,"context_line":"                resource_id\u003dbackup.id,"},{"line_number":137,"context_line":"                resource_metadata\u003dself.extract_metadata(backup),"},{"line_number":138,"context_line":"            )"}],"source_content_type":"text/x-python","patch_set":10,"id":"eb31a2ac_07a58e3f","line":135,"in_reply_to":"f9563a33_a66bc901","updated":"2026-06-16 12:50:35.000000000","message":"Agreed, there needs to be more consistency","commit_id":"c0fe404b195a293dbc2c829d27ddde0e04985966"}]}
