Use 'actual' memory statistic for memory pollster

The memory pollster was configured to use the 'available' memory
statistic in libvirt, which represents the amount of usable memory
as seen inside the domain.

What it should be using is the 'actual' statistic, which is the amount
of memory actually allocated to the domain, to match the notification
meter. This patch fixes this discrepancy.

From what I can tell, the memory_usage InstanceStats value is correct
as-is and does not need changing.

Change-Id: I28d966fb65a81aa97890e68f3859c76d69601dd1
Signed-off-by: Callum Dickinson <callum.dickinson@catalystcloud.nz>
This commit is contained in:
Callum Dickinson
2025-08-28 20:29:32 +12:00
parent 48b53bba8b
commit 174041ad58
5 changed files with 16 additions and 6 deletions

View File

@@ -47,7 +47,7 @@ class VCPUsPollster(InstanceStatsPollster):
class MemoryPollster(InstanceStatsPollster):
sample_name = 'memory'
sample_unit = 'MB'
sample_stats_key = 'memory_available'
sample_stats_key = 'memory_actual'
class MemoryUsagePollster(InstanceStatsPollster):

View File

@@ -43,7 +43,8 @@ class InstanceStats:
'power_state', # the power state of the domain
'cpu_number', # number: number of CPUs
'cpu_time', # time: cumulative CPU time
'memory_available', # available: Amount of allocated memory
'memory_actual', # actual: Amount of allocated memory
'memory_available', # available: Amount of usable memory
'memory_usage', # usage: Amount of memory used
'memory_resident', #
'memory_swap_in', # memory swap in

View File

@@ -207,11 +207,14 @@ class LibvirtInspector(virt_inspector.Inspector):
def inspect_instance(self, instance, duration=None):
domain = self._get_domain_not_shut_off_or_raise(instance)
memory_actual = None
memory_available = None
memory_used = memory_resident = None
memory_swap_in = memory_swap_out = None
memory_stats = domain.memoryStats()
# Stat provided from libvirt is in KB, converting it to MB.
if 'actual' in memory_stats:
memory_actual = memory_stats['actual'] / units.Ki
if 'available' in memory_stats:
memory_available = memory_stats['available'] / units.Ki
if 'usable' in memory_stats and 'available' in memory_stats:
@@ -254,6 +257,7 @@ class LibvirtInspector(virt_inspector.Inspector):
power_state=domain.info()[0],
cpu_number=stats.get('vcpu.current'),
cpu_time=cpu_time,
memory_actual=memory_actual,
memory_available=memory_available,
memory_usage=memory_used,
memory_resident=memory_resident,

View File

@@ -25,8 +25,8 @@ class TestMemoryPollster(base.TestPollsterBase):
def test_get_samples(self):
self._mock_inspect_instance(
virt_inspector.InstanceStats(memory_available=1024.0),
virt_inspector.InstanceStats(memory_available=2048.0),
virt_inspector.InstanceStats(memory_actual=1024.0),
virt_inspector.InstanceStats(memory_actual=2048.0),
virt_inspector.InstanceStats(),
virt_inspector.InstanceShutOffException(),
)

View File

@@ -52,7 +52,8 @@ class TestLibvirtInspection(base.BaseTestCase):
def test_inspect_instance_stats(self):
domain = mock.Mock()
domain.info.return_value = (0, 0, 0, 2, 999999)
domain.memoryStats.return_value = {'available': 51200,
domain.memoryStats.return_value = {'actual': 54400,
'available': 51200,
'unused': 25600,
'rss': 30000,
'swap_in': 5120,
@@ -78,6 +79,7 @@ class TestLibvirtInspection(base.BaseTestCase):
self.assertEqual(0, stats.power_state)
self.assertEqual(2, stats.cpu_number)
self.assertEqual(40000, stats.cpu_time)
self.assertEqual(54400 / units.Ki, stats.memory_actual)
self.assertEqual(51200 / units.Ki, stats.memory_available)
self.assertEqual(25600 / units.Ki, stats.memory_usage)
self.assertEqual(30000 / units.Ki, stats.memory_resident)
@@ -466,6 +468,7 @@ class TestLibvirtInspection(base.BaseTestCase):
with mock.patch('ceilometer.compute.virt.libvirt.utils.'
'refresh_libvirt_connection', return_value=conn):
stats = self.inspector.inspect_instance(self.instance, None)
self.assertIsNone(stats.memory_actual)
self.assertIsNone(stats.memory_available)
self.assertIsNone(stats.memory_usage)
self.assertIsNone(stats.memory_resident)
@@ -475,7 +478,8 @@ class TestLibvirtInspection(base.BaseTestCase):
def test_inspect_memory_with_usable(self):
domain = mock.Mock()
domain.info.return_value = (0, 0, 0, 2, 999999)
domain.memoryStats.return_value = {'available': 76800,
domain.memoryStats.return_value = {'actual': 80000,
'available': 76800,
'rss': 30000,
'swap_in': 5120,
'swap_out': 8192,
@@ -488,6 +492,7 @@ class TestLibvirtInspection(base.BaseTestCase):
with mock.patch('ceilometer.compute.virt.libvirt.utils.'
'refresh_libvirt_connection', return_value=conn):
stats = self.inspector.inspect_instance(self.instance, None)
self.assertEqual(80000 / units.Ki, stats.memory_actual)
self.assertEqual(76800 / units.Ki, stats.memory_available)
self.assertEqual(25600 / units.Ki, stats.memory_usage)
self.assertEqual(30000 / units.Ki, stats.memory_resident)