Merge "Add pool capacity pollsters"

This commit is contained in:
Zuul 2025-03-28 08:59:11 +00:00 committed by Gerrit Code Review
commit d5b6d7966a
7 changed files with 272 additions and 9 deletions

View File

@ -5,7 +5,8 @@
required-projects: required-projects:
- opendev.org/openstack/grenade - opendev.org/openstack/grenade
- opendev.org/openstack/ceilometer - opendev.org/openstack/ceilometer
- gnocchixyz/gnocchi - name: gnocchixyz/gnocchi
override-checkout: stable/4.6
vars: vars:
configure_swap_size: 8192 configure_swap_size: 8192
grenade_devstack_localrc: grenade_devstack_localrc:

View File

@ -134,6 +134,34 @@ BACKUP_LIST = [
'size': 1}) 'size': 1})
] ]
POOL_LIST = [
type('VolumePool', (object,),
{'name': 'localhost.localdomain@lvmdriver-1#lvmdriver-1',
'pool_name': 'lvmdriver-1',
'total_capacity_gb': 28.5,
'free_capacity_gb': 28.39,
'reserved_percentage': 0,
'location_info':
'LVMVolumeDriver:localhost.localdomain:stack-volumes:thin:0',
'QoS_support': False,
'provisioned_capacity_gb': 4.0,
'max_over_subscription_ratio': 20.0,
'thin_provisioning_support': True,
'thick_provisioning_support': False,
'total_volumes': 3,
'filter_function': None,
'goodness_function': None,
'multiattach': True,
'backend_state': 'up',
'allocated_capacity_gb': 4,
'cacheable': True,
'volume_backend_name': 'lvmdriver-1',
'storage_protocol': 'iSCSI',
'vendor_name': 'Open Source',
'driver_version': '3.0.0',
'timestamp': '2025-03-21T14:19:02.901750'})
]
class TestVolumeSizePollster(base.BaseTestCase): class TestVolumeSizePollster(base.BaseTestCase):
def setUp(self): def setUp(self):
@ -203,3 +231,94 @@ class TestVolumeBackupSizePollster(base.BaseTestCase):
self.assertEqual(1, volume_backup_size_samples[0].volume) self.assertEqual(1, volume_backup_size_samples[0].volume)
self.assertEqual('75a52125-85ff-4a8d-b2aa-580f3b22273f', self.assertEqual('75a52125-85ff-4a8d-b2aa-580f3b22273f',
volume_backup_size_samples[0].resource_id) volume_backup_size_samples[0].resource_id)
class TestVolumeProviderPoolCapacityTotalPollster(base.BaseTestCase):
def setUp(self):
super(TestVolumeProviderPoolCapacityTotalPollster, self).setUp()
conf = service.prepare_service([], [])
self.manager = manager.AgentManager(0, conf)
self.pollster = cinder.VolumeProviderPoolCapacityTotal(conf)
def test_volume_provider_pool_capacity_total_pollster(self):
volume_pool_size_total_samples = list(
self.pollster.get_samples(self.manager, {}, resources=POOL_LIST))
self.assertEqual(1, len(volume_pool_size_total_samples))
self.assertEqual('volume.provider.pool.capacity.total',
volume_pool_size_total_samples[0].name)
self.assertEqual(28.5, volume_pool_size_total_samples[0].volume)
self.assertEqual('localhost.localdomain@lvmdriver-1#lvmdriver-1',
volume_pool_size_total_samples[0].resource_id)
class TestVolumeProviderPoolCapacityFreePollster(base.BaseTestCase):
def setUp(self):
super(TestVolumeProviderPoolCapacityFreePollster, self).setUp()
conf = service.prepare_service([], [])
self.manager = manager.AgentManager(0, conf)
self.pollster = cinder.VolumeProviderPoolCapacityFree(conf)
def test_volume_provider_pool_capacity_free_pollster(self):
volume_pool_size_free_samples = list(
self.pollster.get_samples(self.manager, {}, resources=POOL_LIST))
self.assertEqual(1, len(volume_pool_size_free_samples))
self.assertEqual('volume.provider.pool.capacity.free',
volume_pool_size_free_samples[0].name)
self.assertEqual(28.39, volume_pool_size_free_samples[0].volume)
self.assertEqual('localhost.localdomain@lvmdriver-1#lvmdriver-1',
volume_pool_size_free_samples[0].resource_id)
class TestVolumeProviderPoolCapacityProvisionedPollster(base.BaseTestCase):
def setUp(self):
super(TestVolumeProviderPoolCapacityProvisionedPollster, self).setUp()
conf = service.prepare_service([], [])
self.manager = manager.AgentManager(0, conf)
self.pollster = cinder.VolumeProviderPoolCapacityProvisioned(conf)
def test_volume_provider_pool_capacity_provisioned_pollster(self):
volume_pool_size_provisioned_samples = list(
self.pollster.get_samples(self.manager, {}, resources=POOL_LIST))
self.assertEqual(1, len(volume_pool_size_provisioned_samples))
self.assertEqual('volume.provider.pool.capacity.provisioned',
volume_pool_size_provisioned_samples[0].name)
self.assertEqual(4.0, volume_pool_size_provisioned_samples[0].volume)
self.assertEqual('localhost.localdomain@lvmdriver-1#lvmdriver-1',
volume_pool_size_provisioned_samples[0].resource_id)
class TestVolumeProviderPoolCapacityVirtualFreePollster(base.BaseTestCase):
def setUp(self):
super(TestVolumeProviderPoolCapacityVirtualFreePollster, self).setUp()
conf = service.prepare_service([], [])
self.manager = manager.AgentManager(0, conf)
self.pollster = cinder.VolumeProviderPoolCapacityVirtualFree(conf)
def test_volume_provider_pool_capacity_virtual_free_pollster(self):
volume_pool_size_virtual_free_samples = list(
self.pollster.get_samples(self.manager, {}, resources=POOL_LIST))
self.assertEqual(1, len(volume_pool_size_virtual_free_samples))
self.assertEqual('volume.provider.pool.capacity.virtual_free',
volume_pool_size_virtual_free_samples[0].name)
self.assertEqual(566.0,
volume_pool_size_virtual_free_samples[0].volume)
self.assertEqual('localhost.localdomain@lvmdriver-1#lvmdriver-1',
volume_pool_size_virtual_free_samples[0].resource_id)
class TestVolumeProviderPoolCapacityAllocatedPollster(base.BaseTestCase):
def setUp(self):
super(TestVolumeProviderPoolCapacityAllocatedPollster, self).setUp()
conf = service.prepare_service([], [])
self.manager = manager.AgentManager(0, conf)
self.pollster = cinder.VolumeProviderPoolCapacityAllocated(conf)
def test_volume_provider_pool_capacity_allocated_pollster(self):
volume_pool_size_allocated_samples = list(
self.pollster.get_samples(self.manager, {}, resources=POOL_LIST))
self.assertEqual(1, len(volume_pool_size_allocated_samples))
self.assertEqual('volume.provider.pool.capacity.allocated',
volume_pool_size_allocated_samples[0].name)
self.assertEqual(4, volume_pool_size_allocated_samples[0].volume)
self.assertEqual('localhost.localdomain@lvmdriver-1#lvmdriver-1',
volume_pool_size_allocated_samples[0].resource_id)

View File

@ -12,6 +12,7 @@
# under the License. # under the License.
"""Common code for working with volumes """Common code for working with volumes
""" """
import math
from ceilometer.polling import plugin_base from ceilometer.polling import plugin_base
from ceilometer import sample from ceilometer import sample
@ -117,3 +118,119 @@ class VolumeBackupSize(_Base):
resource_id=backup.id, resource_id=backup.id,
resource_metadata=self.extract_metadata(backup), resource_metadata=self.extract_metadata(backup),
) )
class VolumeProviderPoolCapacityTotal(_Base):
@property
def default_discovery(self):
return 'volume_pools'
FIELDS = ['pool_name']
def get_samples(self, manager, cache, resources):
for pool in resources:
yield sample.Sample(
name='volume.provider.pool.capacity.total',
type=sample.TYPE_GAUGE,
unit='GB',
volume=pool.total_capacity_gb,
user_id=None,
project_id=None,
resource_id=pool.name,
resource_metadata=self.extract_metadata(pool),
)
class VolumeProviderPoolCapacityFree(_Base):
@property
def default_discovery(self):
return 'volume_pools'
FIELDS = ['pool_name']
def get_samples(self, manager, cache, resources):
for pool in resources:
yield sample.Sample(
name='volume.provider.pool.capacity.free',
type=sample.TYPE_GAUGE,
unit='GB',
volume=pool.free_capacity_gb,
user_id=None,
project_id=None,
resource_id=pool.name,
resource_metadata=self.extract_metadata(pool),
)
class VolumeProviderPoolCapacityProvisioned(_Base):
@property
def default_discovery(self):
return 'volume_pools'
FIELDS = ['pool_name']
def get_samples(self, manager, cache, resources):
for pool in resources:
yield sample.Sample(
name='volume.provider.pool.capacity.provisioned',
type=sample.TYPE_GAUGE,
unit='GB',
volume=pool.provisioned_capacity_gb,
user_id=None,
project_id=None,
resource_id=pool.name,
resource_metadata=self.extract_metadata(pool),
)
class VolumeProviderPoolCapacityVirtualFree(_Base):
@property
def default_discovery(self):
return 'volume_pools'
FIELDS = ['pool_name']
def get_samples(self, manager, cache, resources):
for pool in resources:
reserved_size = math.floor(
(pool.reserved_percentage / 100) * pool.total_capacity_gb
)
max_over_subscription_ratio = 1.0
if pool.thin_provisioning_support:
max_over_subscription_ratio = pool.max_over_subscription_ratio
value = (
max_over_subscription_ratio *
(pool.total_capacity_gb - reserved_size) -
pool.provisioned_capacity_gb
)
yield sample.Sample(
name='volume.provider.pool.capacity.virtual_free',
type=sample.TYPE_GAUGE,
unit='GB',
volume=value,
user_id=None,
project_id=None,
resource_id=pool.name,
resource_metadata=self.extract_metadata(pool),
)
class VolumeProviderPoolCapacityAllocated(_Base):
@property
def default_discovery(self):
return 'volume_pools'
FIELDS = ['pool_name']
def get_samples(self, manager, cache, resources):
for pool in resources:
yield sample.Sample(
name='volume.provider.pool.capacity.allocated',
type=sample.TYPE_GAUGE,
unit='GB',
volume=pool.allocated_capacity_gb,
user_id=None,
project_id=None,
resource_id=pool.name,
resource_metadata=self.extract_metadata(pool),
)

View File

@ -61,3 +61,10 @@ class VolumeBackupsDiscovery(_BaseDiscovery):
"""Discover volume resources to monitor.""" """Discover volume resources to monitor."""
return self.client.backups.list(search_opts={'all_tenants': True}) return self.client.backups.list(search_opts={'all_tenants': True})
class VolumePoolsDiscovery(_BaseDiscovery):
def discover(self, manager, param=None):
"""Discover volume resources to monitor."""
return self.client.pools.list(detailed=True)

View File

@ -443,22 +443,24 @@ The following meters are collected for OpenStack Block Storage:
| | | | | | on host | | | | | | | on host |
+--------------------+-------+--------+----------+----------+-----------------+ +--------------------+-------+--------+----------+----------+-----------------+
| volume.provider.po\| Gauge | GB | hostname\| Notifica\| Total volume | | volume.provider.po\| Gauge | GB | hostname\| Notifica\| Total volume |
| ol.capacity.total | | | #pool | tion | capacity in pool| | ol.capacity.total | | | #pool | tion, Po\| capacity in pool|
| | | | | llster | |
+--------------------+-------+--------+----------+----------+-----------------+ +--------------------+-------+--------+----------+----------+-----------------+
| volume.provider.po\| Gauge | GB | hostname\| Notifica\| Free volume | | volume.provider.po\| Gauge | GB | hostname\| Notifica\| Free volume |
| ol.capacity.free | | | #pool | tion | capacity in pool| | ol.capacity.free | | | #pool | tion, Po\| capacity in pool|
| | | | | llster | |
+--------------------+-------+--------+----------+----------+-----------------+ +--------------------+-------+--------+----------+----------+-----------------+
| volume.provider.po\| Gauge | GB | hostname\| Notifica\| Assigned volume | | volume.provider.po\| Gauge | GB | hostname\| Notifica\| Assigned volume |
| ol.capacity.alloca\| | | #pool | tion | capacity in pool| | ol.capacity.alloca\| | | #pool | tion, Po\| capacity in pool|
| ted | | | | | by Cinder | | ted | | | | llster | by Cinder |
+--------------------+-------+--------+----------+----------+-----------------+ +--------------------+-------+--------+----------+----------+-----------------+
| volume.provider.po\| Gauge | GB | hostname\| Notifica\| Assigned volume | | volume.provider.po\| Gauge | GB | hostname\| Notifica\| Assigned volume |
| ol.capacity.provis\| | | #pool | tion | capacity in pool| | ol.capacity.provis\| | | #pool | tion, Po\| capacity in pool|
| ioned | | | | | | | ioned | | | | llster | |
+--------------------+-------+--------+----------+----------+-----------------+ +--------------------+-------+--------+----------+----------+-----------------+
| volume.provider.po\| Gauge | GB | hostname\| Notifica\| Virtual free | | volume.provider.po\| Gauge | GB | hostname\| Notifica\| Virtual free |
| ol.capacity.virtua\| | | #pool | tion | volume capacity | | ol.capacity.virtua\| | | #pool | tion, Po\| volume capacity |
| l_free | | | | | in pool | | l_free | | | | llster | in pool |
+--------------------+-------+--------+----------+----------+-----------------+ +--------------------+-------+--------+----------+----------+-----------------+
OpenStack File Share OpenStack File Share

View File

@ -0,0 +1,11 @@
---
features:
- |
Added the following meters to the central agent to capture these metrics
for each storage pool by API.
- `volume.provider.pool.capacity.total`
- `volume.provider.pool.capacity.free`
- `volume.provider.pool.capacity.provisioned`
- `volume.provider.pool.capacity.virtual_free`
- `volume.provider.pool.capacity.allocated`

View File

@ -60,6 +60,7 @@ ceilometer.discover.central =
fip_services = ceilometer.network.services.discovery:FloatingIPDiscovery fip_services = ceilometer.network.services.discovery:FloatingIPDiscovery
images = ceilometer.image.discovery:ImagesDiscovery images = ceilometer.image.discovery:ImagesDiscovery
volumes = ceilometer.volume.discovery:VolumeDiscovery volumes = ceilometer.volume.discovery:VolumeDiscovery
volume_pools = ceilometer.volume.discovery:VolumePoolsDiscovery
volume_snapshots = ceilometer.volume.discovery:VolumeSnapshotsDiscovery volume_snapshots = ceilometer.volume.discovery:VolumeSnapshotsDiscovery
volume_backups = ceilometer.volume.discovery:VolumeBackupsDiscovery volume_backups = ceilometer.volume.discovery:VolumeBackupsDiscovery
@ -137,6 +138,11 @@ ceilometer.poll.central =
volume.size = ceilometer.volume.cinder:VolumeSizePollster volume.size = ceilometer.volume.cinder:VolumeSizePollster
volume.snapshot.size = ceilometer.volume.cinder:VolumeSnapshotSize volume.snapshot.size = ceilometer.volume.cinder:VolumeSnapshotSize
volume.backup.size = ceilometer.volume.cinder:VolumeBackupSize volume.backup.size = ceilometer.volume.cinder:VolumeBackupSize
volume.provider.pool.capacity.total = ceilometer.volume.cinder:VolumeProviderPoolCapacityTotal
volume.provider.pool.capacity.free = ceilometer.volume.cinder:VolumeProviderPoolCapacityFree
volume.provider.pool.capacity.provisioned = ceilometer.volume.cinder:VolumeProviderPoolCapacityProvisioned
volume.provider.pool.capacity.virtual_free = ceilometer.volume.cinder:VolumeProviderPoolCapacityVirtualFree
volume.provider.pool.capacity.allocated = ceilometer.volume.cinder:VolumeProviderPoolCapacityAllocated
ceilometer.compute.virt = ceilometer.compute.virt =
libvirt = ceilometer.compute.virt.libvirt.inspector:LibvirtInspector libvirt = ceilometer.compute.virt.libvirt.inspector:LibvirtInspector