Adds memory stats meter to libvirt inspector

Uses libvirt 'virDomainMemoryStats' to retrive the memory
that is used by domain, implements 'inspect_memory_usage'
function in libvirt inspector.

Change-Id: I5bf17d51d82d10d2f31b9c81583f53b81c1c5268
Implements: blueprint libvirt-memory-utilization-inspector
This commit is contained in:
kiwik-chenrui 2014-04-25 17:29:01 -05:00
parent f3994f0a8b
commit 135961088d
3 changed files with 80 additions and 1 deletions

View File

@ -18,8 +18,10 @@
from lxml import etree from lxml import etree
from oslo.config import cfg from oslo.config import cfg
from oslo.utils import units
import six import six
from ceilometer.compute.pollsters import util
from ceilometer.compute.virt import inspector as virt_inspector from ceilometer.compute.virt import inspector as virt_inspector
from ceilometer.openstack.common.gettextutils import _ from ceilometer.openstack.common.gettextutils import _
from ceilometer.openstack.common import log as logging from ceilometer.openstack.common import log as logging
@ -178,3 +180,35 @@ class LibvirtInspector(virt_inspector.Inspector):
write_bytes=block_stats[3], write_bytes=block_stats[3],
errors=block_stats[4]) errors=block_stats[4])
yield (disk, stats) yield (disk, stats)
def inspect_memory_usage(self, instance, duration=None):
instance_name = util.instance_name(instance)
domain = self._lookup_by_name(instance_name)
state = domain.info()[0]
if state == libvirt.VIR_DOMAIN_SHUTOFF:
LOG.warn(_('Failed to inspect memory usage of %(instance_name)s, '
'domain is in state of SHUTOFF'),
{'instance_name': instance_name})
return
try:
memory_stats = domain.memoryStats()
if (memory_stats and
memory_stats.get('available') and
memory_stats.get('unused')):
memory_used = (memory_stats.get('available') -
memory_stats.get('unused'))
# Stat provided from libvirt is in KB, converting it to MB.
memory_used = memory_used / units.Ki
return virt_inspector.MemoryUsageStats(usage=memory_used)
else:
LOG.warn(_('Failed to inspect memory usage of '
'%(instance_name)s, can not get info from libvirt'),
{'instance_name': instance_name})
# memoryStats might launch an exception if the method
# is not supported by the underlying hypervisor being
# used by libvirt
except libvirt.libvirtError as e:
LOG.warn(_('Failed to inspect memory usage of %(instance_name)s, '
'can not get info from libvirt: %(error)s'),
{'instance_name': instance_name, 'error': e})

View File

@ -22,6 +22,7 @@ import contextlib
import fixtures import fixtures
import mock import mock
from oslo.utils import units
from oslotest import base from oslotest import base
from ceilometer.compute.virt import inspector as virt_inspector from ceilometer.compute.virt import inspector as virt_inspector
@ -245,6 +246,44 @@ class TestLibvirtInspection(base.BaseTestCase):
disks = list(self.inspector.inspect_disks(self.instance_name)) disks = list(self.inspector.inspect_disks(self.instance_name))
self.assertEqual(disks, []) self.assertEqual(disks, [])
def test_inspect_memory_usage(self):
fake_memory_stats = {'available': 51200L, 'unused': 25600L}
connection = self.inspector.connection
with mock.patch.object(connection, 'lookupByName',
return_value=self.domain):
with mock.patch.object(self.domain, 'info',
return_value=(0L, 0L, 51200L,
2L, 999999L)):
with mock.patch.object(self.domain, 'memoryStats',
return_value=fake_memory_stats):
memory = self.inspector.inspect_memory_usage(
self.instance_name)
self.assertEqual(25600L / units.Ki, memory.usage)
def test_inspect_memory_usage_with_domain_shutoff(self):
connection = self.inspector.connection
with mock.patch.object(connection, 'lookupByName',
return_value=self.domain):
with mock.patch.object(self.domain, 'info',
return_value=(5L, 0L, 0L,
2L, 999999L)):
memory = self.inspector.inspect_memory_usage(
self.instance_name)
self.assertIsNone(memory)
def test_inspect_memory_usage_with_empty_stats(self):
connection = self.inspector.connection
with mock.patch.object(connection, 'lookupByName',
return_value=self.domain):
with mock.patch.object(self.domain, 'info',
return_value=(0L, 0L, 51200L,
2L, 999999L)):
with mock.patch.object(self.domain, 'memoryStats',
return_value={}):
memory = self.inspector.inspect_memory_usage(
self.instance_name)
self.assertIsNone(memory)
class TestLibvirtInspectionWithError(base.BaseTestCase): class TestLibvirtInspectionWithError(base.BaseTestCase):

View File

@ -71,7 +71,7 @@ Name Type* Unit Resource Origin** Support**
instance g instance inst ID both 1, 2, 3, 4 Existence of instance instance g instance inst ID both 1, 2, 3, 4 Existence of instance
instance:<type> g instance inst ID both 1, 2, 3, 4 Existence of instance <type> (openstack types) instance:<type> g instance inst ID both 1, 2, 3, 4 Existence of instance <type> (openstack types)
memory g MB inst ID n 1, 2 Volume of RAM allocated in MB memory g MB inst ID n 1, 2 Volume of RAM allocated in MB
memory.usage g MB inst ID p 3, 4 Volume of RAM used in MB memory.usage g MB inst ID p 1, 3, 4 Volume of RAM used in MB
cpu c ns inst ID p 1, 2 CPU time used cpu c ns inst ID p 1, 2 CPU time used
cpu_util g % inst ID p 1, 2, 3, 4 Average CPU utilisation cpu_util g % inst ID p 1, 2, 3, 4 Average CPU utilisation
vcpus g vcpu inst ID n 1, 2 Number of VCPUs vcpus g vcpu inst ID n 1, 2 Number of VCPUs
@ -118,6 +118,12 @@ network.outgoing.packets.rate g packet/s iface ID p 1, 2, 3,
[3]: Vsphere support [3]: Vsphere support
[4]: XenAPI support [4]: XenAPI support
.. note:: To enable the libvirt memory.usage supporting, you need libvirt
version 1.1.1+, qemu version 1.5+, and you need to prepare suitable balloon
driver in the image, particularly for Windows guests, most modern Linuxes
have it built in. The memory.usage meters can't be fetched without image
balloon driver.
Contributors are welcome to extend other virtualization backends' meters Contributors are welcome to extend other virtualization backends' meters
or complete the existing ones. or complete the existing ones.