Merge "Add the disk.ephemeral.size and disk.root.size pollsters"
This commit is contained in:
commit
774137434c
@ -170,3 +170,44 @@ class GenericComputePollster(plugin_base.PollsterBase):
|
||||
'Could not get %(name)s events for %(id)s: %(e)s', {
|
||||
'name': self.sample_name, 'id': instance.id, 'e': err},
|
||||
exc_info=True)
|
||||
|
||||
|
||||
class InstanceMetadataPollster(plugin_base.PollsterBase):
|
||||
"""A base class for implementing a pollster using instance metadata.
|
||||
|
||||
This metadata is originally supplied by Nova, but if
|
||||
instance_discovery_method is set to libvirt_metadata,
|
||||
metadata is fetched from the local libvirt socket,
|
||||
just like with the standard compute pollsters.
|
||||
"""
|
||||
|
||||
sample_name = None
|
||||
sample_unit = ''
|
||||
sample_type = sample.TYPE_GAUGE
|
||||
|
||||
@property
|
||||
def default_discovery(self):
|
||||
return 'local_instances'
|
||||
|
||||
def get_resource_id(self, instance):
|
||||
return instance.id
|
||||
|
||||
def get_volume(self, instance):
|
||||
raise ceilometer.NotImplementedError
|
||||
|
||||
def get_additional_metadata(self, instance):
|
||||
return {}
|
||||
|
||||
def get_samples(self, manager, cache, resources):
|
||||
for instance in resources:
|
||||
yield util.make_sample_from_instance(
|
||||
self.conf,
|
||||
instance,
|
||||
name=self.sample_name,
|
||||
unit=self.sample_unit,
|
||||
type=self.sample_type,
|
||||
resource_id=self.get_resource_id(instance),
|
||||
volume=self.get_volume(instance),
|
||||
additional_metadata=self.get_additional_metadata(instance),
|
||||
monotonic_time=now(),
|
||||
)
|
||||
|
@ -91,3 +91,20 @@ class PerDeviceDiskWriteLatencyPollster(PerDeviceDiskPollster):
|
||||
sample_type = sample.TYPE_CUMULATIVE
|
||||
sample_unit = 'ns'
|
||||
sample_stats_key = 'wr_total_times'
|
||||
|
||||
|
||||
class EphemeralSizePollster(pollsters.InstanceMetadataPollster):
|
||||
sample_name = 'disk.ephemeral.size'
|
||||
sample_unit = 'GB'
|
||||
|
||||
def get_volume(self, instance):
|
||||
return int(instance.flavor['ephemeral'])
|
||||
|
||||
|
||||
class RootSizePollster(pollsters.InstanceMetadataPollster):
|
||||
sample_name = 'disk.root.size'
|
||||
sample_unit = 'GB'
|
||||
|
||||
def get_volume(self, instance):
|
||||
return (int(instance.flavor['disk'])
|
||||
- int(instance.flavor['ephemeral']))
|
||||
|
130
ceilometer/tests/unit/compute/pollsters/test_disk.py
Normal file
130
ceilometer/tests/unit/compute/pollsters/test_disk.py
Normal file
@ -0,0 +1,130 @@
|
||||
# Copyright 2025 Catalyst Cloud Limited
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
# not use this file except in compliance with the License. You may obtain
|
||||
# a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
from unittest import mock
|
||||
|
||||
from ceilometer.compute.pollsters import disk
|
||||
from ceilometer.polling import manager
|
||||
from ceilometer.tests.unit.compute.pollsters import base
|
||||
|
||||
|
||||
class TestDiskPollsterBase(base.TestPollsterBase):
|
||||
|
||||
TYPE = 'gauge'
|
||||
|
||||
def setUp(self):
|
||||
super().setUp()
|
||||
self.instances = self._get_fake_instances()
|
||||
|
||||
def _get_fake_instances(self, ephemeral=0):
|
||||
instances = []
|
||||
for i in [1, 2]:
|
||||
instance = mock.MagicMock()
|
||||
instance.name = f'instance-{i}'
|
||||
setattr(instance, 'OS-EXT-SRV-ATTR:instance_name',
|
||||
instance.name)
|
||||
instance.id = i
|
||||
instance.flavor = {'name': 'm1.small', 'id': 2, 'vcpus': 1,
|
||||
'ram': 512, 'disk': 20, 'ephemeral': ephemeral}
|
||||
instance.status = 'active'
|
||||
instances.append(instance)
|
||||
return instances
|
||||
|
||||
def _check_get_samples(self,
|
||||
factory,
|
||||
name,
|
||||
instances=None,
|
||||
expected_count=2):
|
||||
pollster = factory(self.CONF)
|
||||
mgr = manager.AgentManager(0, self.CONF)
|
||||
samples = list(pollster.get_samples(mgr,
|
||||
{},
|
||||
instances or self.instances))
|
||||
self.assertGreater(len(samples), 0)
|
||||
self.assertEqual({name}, set(s.name for s in samples),
|
||||
(f"Only samples for meter {name} "
|
||||
"should be published"))
|
||||
self.assertEqual(expected_count, len(samples))
|
||||
return samples
|
||||
|
||||
|
||||
class TestDiskSizePollsters(TestDiskPollsterBase):
|
||||
|
||||
TYPE = 'gauge'
|
||||
|
||||
def test_ephemeral_disk_zero(self):
|
||||
samples = {
|
||||
sample.resource_id: sample
|
||||
for sample in self._check_get_samples(
|
||||
disk.EphemeralSizePollster,
|
||||
'disk.ephemeral.size',
|
||||
expected_count=len(self.instances))}
|
||||
for instance in self.instances:
|
||||
with self.subTest(instance.name):
|
||||
self.assertIn(instance.id, samples)
|
||||
sample = samples[instance.id]
|
||||
self.assertEqual(instance.flavor['ephemeral'],
|
||||
sample.volume)
|
||||
self.assertEqual(self.TYPE, sample.type)
|
||||
|
||||
def test_ephemeral_disk_nonzero(self):
|
||||
instances = self._get_fake_instances(ephemeral=10)
|
||||
samples = {
|
||||
sample.resource_id: sample
|
||||
for sample in self._check_get_samples(
|
||||
disk.EphemeralSizePollster,
|
||||
'disk.ephemeral.size',
|
||||
instances=instances,
|
||||
expected_count=len(instances))}
|
||||
for instance in instances:
|
||||
with self.subTest(instance.name):
|
||||
self.assertIn(instance.id, samples)
|
||||
sample = samples[instance.id]
|
||||
self.assertEqual(instance.flavor['ephemeral'],
|
||||
sample.volume)
|
||||
self.assertEqual(self.TYPE, sample.type)
|
||||
|
||||
def test_root_disk(self):
|
||||
samples = {
|
||||
sample.resource_id: sample
|
||||
for sample in self._check_get_samples(
|
||||
disk.RootSizePollster,
|
||||
'disk.root.size',
|
||||
expected_count=len(self.instances))}
|
||||
for instance in self.instances:
|
||||
with self.subTest(instance.name):
|
||||
self.assertIn(instance.id, samples)
|
||||
sample = samples[instance.id]
|
||||
self.assertEqual((instance.flavor['disk']
|
||||
- instance.flavor['ephemeral']),
|
||||
sample.volume)
|
||||
self.assertEqual(self.TYPE, sample.type)
|
||||
|
||||
def test_root_disk_ephemeral_nonzero(self):
|
||||
instances = self._get_fake_instances(ephemeral=10)
|
||||
samples = {
|
||||
sample.resource_id: sample
|
||||
for sample in self._check_get_samples(
|
||||
disk.RootSizePollster,
|
||||
'disk.root.size',
|
||||
instances=instances,
|
||||
expected_count=len(instances))}
|
||||
for instance in instances:
|
||||
with self.subTest(instance.name):
|
||||
self.assertIn(instance.id, samples)
|
||||
sample = samples[instance.id]
|
||||
self.assertEqual((instance.flavor['disk']
|
||||
- instance.flavor['ephemeral']),
|
||||
sample.volume)
|
||||
self.assertEqual(self.TYPE, sample.type)
|
@ -124,10 +124,12 @@ The following meters are collected for OpenStack Compute.
|
||||
| .bytes | | | | | | |
|
||||
+-----------+-------+------+----------+----------+---------+------------------+
|
||||
| disk.root\| Gauge | GB | instance | Notific\ | Libvirt | Size of root disk|
|
||||
| .size | | | ID | ation | | |
|
||||
| .size | | | ID | ation, \ | | |
|
||||
| | | | | Pollster | | |
|
||||
+-----------+-------+------+----------+----------+---------+------------------+
|
||||
| disk.ephe\| Gauge | GB | instance | Notific\ | Libvirt | Size of ephemeral|
|
||||
| meral.size| | | ID | ation | | disk |
|
||||
| meral.size| | | ID | ation, \ | | disk |
|
||||
| | | | | Pollster | | |
|
||||
+-----------+-------+------+----------+----------+---------+------------------+
|
||||
| disk.dev\ | Gauge | B | disk ID | Pollster | Libvirt | The amount of d\ |
|
||||
| ice.capa\ | | | | | | isk per device |
|
||||
|
@ -0,0 +1,8 @@
|
||||
---
|
||||
features:
|
||||
- |
|
||||
The ``disk.ephemeral.size`` meter is now published as a compute pollster,
|
||||
in addition to the existing notification meter.
|
||||
- |
|
||||
The ``disk.root.size`` meter is now published as a compute pollster,
|
||||
in addition to the existing notification meter.
|
@ -94,6 +94,8 @@ ceilometer.poll.compute =
|
||||
disk.device.capacity = ceilometer.compute.pollsters.disk:PerDeviceCapacityPollster
|
||||
disk.device.allocation = ceilometer.compute.pollsters.disk:PerDeviceAllocationPollster
|
||||
disk.device.usage = ceilometer.compute.pollsters.disk:PerDevicePhysicalPollster
|
||||
disk.ephemeral.size = ceilometer.compute.pollsters.disk:EphemeralSizePollster
|
||||
disk.root.size = ceilometer.compute.pollsters.disk:RootSizePollster
|
||||
perf.cpu.cycles = ceilometer.compute.pollsters.instance_stats:PerfCPUCyclesPollster
|
||||
perf.instructions = ceilometer.compute.pollsters.instance_stats:PerfInstructionsPollster
|
||||
perf.cache.references = ceilometer.compute.pollsters.instance_stats:PerfCacheReferencesPollster
|
||||
|
Loading…
x
Reference in New Issue
Block a user