Add memory.resident libvirt meter for Ceilometer
The 'memory.resident' metric will expose the physical hosts view of the amount of host memory that is actually used to run the VM process DocImpact: https://review.openstack.org/#/c/164724 Change-Id: I9f2ad784479f234679e1145efd96d9d707dd19d0 Implements: blueprint memory-resident
This commit is contained in:
parent
b5cfcb620c
commit
a2c650b478
@ -16,7 +16,7 @@ import ceilometer
|
||||
from ceilometer.compute import pollsters
|
||||
from ceilometer.compute.pollsters import util
|
||||
from ceilometer.compute.virt import inspector as virt_inspector
|
||||
from ceilometer.i18n import _, _LW
|
||||
from ceilometer.i18n import _, _LW, _LE
|
||||
from ceilometer.openstack.common import log
|
||||
from ceilometer import sample
|
||||
|
||||
@ -63,3 +63,46 @@ class MemoryUsagePollster(pollsters.BaseComputePollster):
|
||||
LOG.exception(_('Could not get Memory Usage for '
|
||||
'%(id)s: %(e)s'), {'id': instance.id,
|
||||
'e': err})
|
||||
|
||||
|
||||
class MemoryResidentPollster(pollsters.BaseComputePollster):
|
||||
|
||||
def get_samples(self, manager, cache, resources):
|
||||
self._inspection_duration = self._record_poll_time()
|
||||
for instance in resources:
|
||||
LOG.debug(_('Checking resident memory for instance %s'),
|
||||
instance.id)
|
||||
try:
|
||||
memory_info = self.inspector.inspect_memory_resident(
|
||||
instance, self._inspection_duration)
|
||||
LOG.debug(_("RESIDENT MEMORY: %(instance)s %(resident)f"),
|
||||
({'instance': instance.__dict__,
|
||||
'resident': memory_info.resident}))
|
||||
yield util.make_sample_from_instance(
|
||||
instance,
|
||||
name='memory.resident',
|
||||
type=sample.TYPE_GAUGE,
|
||||
unit='MB',
|
||||
volume=memory_info.resident,
|
||||
)
|
||||
except virt_inspector.InstanceNotFoundException as err:
|
||||
# Instance was deleted while getting samples. Ignore it.
|
||||
LOG.debug(_('Exception while getting samples %s'), err)
|
||||
except virt_inspector.InstanceShutOffException as e:
|
||||
LOG.warn(_LW('Instance %(instance_id)s was shut off while '
|
||||
'getting samples of %(pollster)s: %(exc)s'),
|
||||
{'instance_id': instance.id,
|
||||
'pollster': self.__class__.__name__, 'exc': e})
|
||||
except virt_inspector.NoDataException as e:
|
||||
LOG.warn(_LW('Cannot inspect data of %(pollster)s for '
|
||||
'%(instance_id)s, non-fatal reason: %(exc)s'),
|
||||
{'pollster': self.__class__.__name__,
|
||||
'instance_id': instance.id, 'exc': e})
|
||||
except ceilometer.NotImplementedError:
|
||||
# Selected inspector does not implement this pollster.
|
||||
LOG.debug(_('Obtaining Resident Memory is not implemented'
|
||||
' for %s'), self.inspector.__class__.__name__)
|
||||
except Exception as err:
|
||||
LOG.exception(_LE('Could not get Resident Memory Usage for '
|
||||
'%(id)s: %(e)s'), {'id': instance.id,
|
||||
'e': err})
|
||||
|
@ -63,6 +63,14 @@ CPUUtilStats = collections.namedtuple('CPUUtilStats', ['util'])
|
||||
MemoryUsageStats = collections.namedtuple('MemoryUsageStats', ['usage'])
|
||||
|
||||
|
||||
# Named tuple representing Resident Memory usage statistics.
|
||||
#
|
||||
# resident: Amount of resident memory
|
||||
#
|
||||
MemoryResidentStats = collections.namedtuple('MemoryResidentStats',
|
||||
['resident'])
|
||||
|
||||
|
||||
# Named tuple representing vNICs.
|
||||
#
|
||||
# name: the name of the vNIC
|
||||
|
@ -212,3 +212,8 @@ class LibvirtInspector(virt_inspector.Inspector):
|
||||
physical=block_info[2])
|
||||
|
||||
yield (disk, info)
|
||||
|
||||
def inspect_memory_resident(self, instance, duration=None):
|
||||
domain = self._get_domain_not_shut_off_or_raise(instance)
|
||||
memory = domain.memoryStats()['rss'] / units.Ki
|
||||
return virt_inspector.MemoryResidentStats(resident=memory)
|
||||
|
@ -64,3 +64,51 @@ class TestMemoryPollster(base.TestPollsterBase):
|
||||
_verify_memory_metering(1, 2.0)
|
||||
_verify_memory_metering(0, 0)
|
||||
_verify_memory_metering(0, 0)
|
||||
|
||||
|
||||
class TestResidentMemoryPollster(base.TestPollsterBase):
|
||||
|
||||
def setUp(self):
|
||||
super(TestResidentMemoryPollster, self).setUp()
|
||||
|
||||
@mock.patch('ceilometer.pipeline.setup_pipeline', mock.MagicMock())
|
||||
def test_get_samples(self):
|
||||
next_value = iter((
|
||||
virt_inspector.MemoryResidentStats(resident=1.0),
|
||||
virt_inspector.MemoryResidentStats(resident=2.0),
|
||||
virt_inspector.NoDataException(),
|
||||
virt_inspector.InstanceShutOffException(),
|
||||
))
|
||||
|
||||
def inspect_memory_resident(instance, duration):
|
||||
value = next(next_value)
|
||||
if isinstance(value, virt_inspector.MemoryResidentStats):
|
||||
return value
|
||||
else:
|
||||
raise value
|
||||
|
||||
self.inspector.inspect_memory_resident = mock.Mock(
|
||||
side_effect=inspect_memory_resident)
|
||||
|
||||
mgr = manager.AgentManager()
|
||||
pollster = memory.MemoryResidentPollster()
|
||||
|
||||
@mock.patch('ceilometer.compute.pollsters.memory.LOG')
|
||||
def _verify_resident_memory_metering(expected_count,
|
||||
expected_resident_memory_mb,
|
||||
mylog):
|
||||
samples = list(pollster.get_samples(mgr, {}, [self.instance]))
|
||||
self.assertEqual(expected_count, len(samples))
|
||||
if expected_count > 0:
|
||||
self.assertEqual(set(['memory.resident']),
|
||||
set([s.name for s in samples]))
|
||||
self.assertEqual(expected_resident_memory_mb,
|
||||
samples[0].volume)
|
||||
else:
|
||||
self.assertEqual(1, mylog.warn.call_count)
|
||||
self.assertEqual(0, mylog.exception.call_count)
|
||||
|
||||
_verify_resident_memory_metering(1, 1.0)
|
||||
_verify_resident_memory_metering(1, 2.0)
|
||||
_verify_resident_memory_metering(0, 0)
|
||||
_verify_resident_memory_metering(0, 0)
|
||||
|
@ -142,6 +142,7 @@ ceilometer.poll.compute =
|
||||
instance = ceilometer.compute.pollsters.instance:InstancePollster
|
||||
instance_flavor = ceilometer.compute.pollsters.instance:InstanceFlavorPollster
|
||||
memory.usage = ceilometer.compute.pollsters.memory:MemoryUsagePollster
|
||||
memory.resident = ceilometer.compute.pollsters.memory:MemoryResidentPollster
|
||||
disk.capacity = ceilometer.compute.pollsters.disk:CapacityPollster
|
||||
disk.allocation = ceilometer.compute.pollsters.disk:AllocationPollster
|
||||
disk.usage = ceilometer.compute.pollsters.disk:PhysicalPollster
|
||||
|
Loading…
Reference in New Issue
Block a user