Merge "Rely on VM UUID to fetch metrics in libvirt"

This commit is contained in:
Jenkins 2014-12-04 21:25:28 +00:00 committed by Gerrit Code Review
commit 31e5435910
9 changed files with 84 additions and 63 deletions

View File

@ -32,9 +32,8 @@ class CPUPollster(plugin.ComputePollster):
def get_samples(self, manager, cache, resources):
for instance in resources:
LOG.debug(_('checking instance %s'), instance.id)
instance_name = util.instance_name(instance)
try:
cpu_info = manager.inspector.inspect_cpus(instance_name)
cpu_info = manager.inspector.inspect_cpus(instance)
LOG.debug(_("CPUTIME USAGE: %(instance)s %(time)d"),
{'instance': instance.__dict__,
'time': cpu_info.time})

View File

@ -61,9 +61,9 @@ class _Base(plugin.ComputePollster):
CACHE_KEY_DISK = 'diskio'
def _populate_cache(self, inspector, cache, instance, instance_name):
def _populate_cache(self, inspector, cache, instance):
i_cache = cache.setdefault(self.CACHE_KEY_DISK, {})
if instance_name not in i_cache:
if instance.id not in i_cache:
r_bytes = 0
r_requests = 0
w_bytes = 0
@ -72,7 +72,7 @@ class _Base(plugin.ComputePollster):
per_device_read_requests = {}
per_device_write_bytes = {}
per_device_write_requests = {}
for disk, info in inspector.inspect_disks(instance_name):
for disk, info in inspector.inspect_disks(instance):
LOG.debug(self.DISKIO_USAGE_MESSAGE,
instance, disk.device, info.read_requests,
info.read_bytes, info.write_requests,
@ -92,14 +92,14 @@ class _Base(plugin.ComputePollster):
'write_bytes': per_device_write_bytes,
'write_requests': per_device_write_requests,
}
i_cache[instance_name] = DiskIOData(
i_cache[instance.id] = DiskIOData(
r_bytes=r_bytes,
r_requests=r_requests,
w_bytes=w_bytes,
w_requests=w_requests,
per_disk_requests=per_device_requests,
)
return i_cache[instance_name]
return i_cache[instance.id]
@abc.abstractmethod
def _get_samples(instance, c_data):
@ -113,7 +113,6 @@ class _Base(plugin.ComputePollster):
manager.inspector,
cache,
instance,
instance_name,
)
for s in self._get_samples(instance, c_data):
yield s

View File

@ -70,8 +70,7 @@ class _Base(plugin.ComputePollster):
CACHE_KEY_VNIC = 'vnics'
def _get_vnic_info(self, inspector, instance):
instance_name = util.instance_name(instance)
return inspector.inspect_vnics(instance_name)
return inspector.inspect_vnics(instance)
@staticmethod
def _get_rx_info(info):
@ -82,13 +81,12 @@ class _Base(plugin.ComputePollster):
return info.tx_bytes
def _get_vnics_for_instance(self, cache, inspector, instance):
instance_name = util.instance_name(instance)
i_cache = cache.setdefault(self.CACHE_KEY_VNIC, {})
if instance_name not in i_cache:
i_cache[instance_name] = list(
if instance.id not in i_cache:
i_cache[instance.id] = list(
self._get_vnic_info(inspector, instance)
)
return i_cache[instance_name]
return i_cache[instance.id]
def get_samples(self, manager, cache, resources):
self._inspection_duration = self._record_poll_time()

View File

@ -19,10 +19,12 @@
from oslo.config import cfg
from oslo.utils import units
from ceilometer.compute.pollsters import util
from ceilometer.compute.virt.hyperv import utilsv2
from ceilometer.compute.virt import inspector as virt_inspector
from ceilometer.openstack.common import log
CONF = cfg.CONF
LOG = log.getLogger(__name__)
@ -39,7 +41,8 @@ class HyperVInspector(virt_inspector.Inspector):
name=element_name,
UUID=name)
def inspect_cpus(self, instance_name):
def inspect_cpus(self, instance):
instance_name = util.instance_name(instance)
(cpu_clock_used,
cpu_count, uptime) = self._utils.get_cpu_metrics(instance_name)
host_cpu_clock, host_cpu_count = self._utils.get_host_cpu_info()
@ -51,7 +54,8 @@ class HyperVInspector(virt_inspector.Inspector):
return virt_inspector.CPUStats(number=cpu_count, time=cpu_time)
def inspect_vnics(self, instance_name):
def inspect_vnics(self, instance):
instance_name = util.instance_name(instance)
for vnic_metrics in self._utils.get_vnic_metrics(instance_name):
interface = virt_inspector.Interface(
name=vnic_metrics["element_name"],
@ -67,7 +71,8 @@ class HyperVInspector(virt_inspector.Inspector):
yield (interface, stats)
def inspect_disks(self, instance_name):
def inspect_disks(self, instance):
instance_name = util.instance_name(instance)
for disk_metrics in self._utils.get_disk_metrics(instance_name):
disk = virt_inspector.Disk(device=disk_metrics['instance_id'])
stats = virt_inspector.DiskStats(

View File

@ -151,10 +151,10 @@ class Inspector(object):
"""List the instances on the current host."""
raise ceilometer.NotImplementedError
def inspect_cpus(self, instance_name):
def inspect_cpus(self, instance):
"""Inspect the CPU statistics for an instance.
:param instance_name: the name of the target instance
:param instance: the target instance
:return: the number of CPUs and cumulative CPU time
"""
raise ceilometer.NotImplementedError
@ -169,10 +169,10 @@ class Inspector(object):
"""
raise ceilometer.NotImplementedError
def inspect_vnics(self, instance_name):
def inspect_vnics(self, instance):
"""Inspect the vNIC statistics for an instance.
:param instance_name: the name of the target instance
:param instance: the target instance
:return: for each vNIC, the number of bytes & packets
received and transmitted
"""
@ -189,10 +189,10 @@ class Inspector(object):
"""
raise ceilometer.NotImplementedError
def inspect_disks(self, instance_name):
def inspect_disks(self, instance):
"""Inspect the disk statistics for an instance.
:param instance_name: the name of the target instance
:param instance: the target instance
:return: for each disk, the number of bytes & operations
read and written, and the error count
"""

View File

@ -84,9 +84,10 @@ class LibvirtInspector(virt_inspector.Inspector):
return self.connection
@retry_on_disconnect
def _lookup_by_name(self, instance_name):
def _lookup_by_uuid(self, instance):
instance_name = util.instance_name(instance)
try:
return self._get_connection().lookupByName(instance_name)
return self._get_connection().lookupByUUIDString(instance.id)
except Exception as ex:
if not libvirt or not isinstance(ex, libvirt.libvirtError):
raise virt_inspector.InspectorException(six.text_type(ex))
@ -95,9 +96,11 @@ class LibvirtInspector(virt_inspector.Inspector):
ex.get_error_domain() in (libvirt.VIR_FROM_REMOTE,
libvirt.VIR_FROM_RPC)):
raise
msg = ("Error from libvirt while looking up %(instance_name)s: "
msg = ("Error from libvirt while looking up instance Name "
"%(instance_name)s UUID %(instance_uuid)s: "
"[Error Code %(error_code)s] "
"%(ex)s" % {'instance_name': instance_name,
'instance_uuid': instance.id,
'error_code': error_code,
'ex': ex})
raise virt_inspector.InstanceNotFoundException(msg)
@ -119,18 +122,21 @@ class LibvirtInspector(virt_inspector.Inspector):
# Instance was deleted while listing... ignore it
pass
def inspect_cpus(self, instance_name):
domain = self._lookup_by_name(instance_name)
def inspect_cpus(self, instance):
domain = self._lookup_by_uuid(instance)
dom_info = domain.info()
return virt_inspector.CPUStats(number=dom_info[3], time=dom_info[4])
def inspect_vnics(self, instance_name):
domain = self._lookup_by_name(instance_name)
def inspect_vnics(self, instance):
instance_name = util.instance_name(instance)
domain = self._lookup_by_uuid(instance)
state = domain.info()[0]
if state == libvirt.VIR_DOMAIN_SHUTOFF:
LOG.warn(_('Failed to inspect vnics of %(instance_name)s, '
LOG.warn(_('Failed to inspect vnics of instance Name '
'%(instance_name)s UUID %(instance_uuid)s, '
'domain is in state of SHUTOFF'),
{'instance_name': instance_name})
{'instance_name': instance_name,
'instance_uuid': instance.id})
return
tree = etree.fromstring(domain.XMLDesc(0))
for iface in tree.findall('devices/interface'):
@ -159,13 +165,16 @@ class LibvirtInspector(virt_inspector.Inspector):
tx_packets=dom_stats[5])
yield (interface, stats)
def inspect_disks(self, instance_name):
domain = self._lookup_by_name(instance_name)
def inspect_disks(self, instance):
instance_name = util.instance_name(instance)
domain = self._lookup_by_uuid(instance)
state = domain.info()[0]
if state == libvirt.VIR_DOMAIN_SHUTOFF:
LOG.warn(_('Failed to inspect disks of %(instance_name)s, '
LOG.warn(_('Failed to inspect disks of instance Name '
'%(instance_name)s UUID %(instance_uuid)s, '
'domain is in state of SHUTOFF'),
{'instance_name': instance_name})
{'instance_name': instance_name,
'instance_uuid': instance.id})
return
tree = etree.fromstring(domain.XMLDesc(0))
for device in filter(
@ -183,12 +192,14 @@ class LibvirtInspector(virt_inspector.Inspector):
def inspect_memory_usage(self, instance, duration=None):
instance_name = util.instance_name(instance)
domain = self._lookup_by_name(instance_name)
domain = self._lookup_by_uuid(instance)
state = domain.info()[0]
if state == libvirt.VIR_DOMAIN_SHUTOFF:
LOG.warn(_('Failed to inspect memory usage of %(instance_name)s, '
LOG.warn(_('Failed to inspect memory usage of instance Name '
'%(instance_name)s UUID %(instance_uuid)s, '
'domain is in state of SHUTOFF'),
{'instance_name': instance_name})
{'instance_name': instance_name,
'instance_uuid': instance.id})
return
try:
@ -202,13 +213,15 @@ class LibvirtInspector(virt_inspector.Inspector):
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})
LOG.warn(_('Failed to inspect memory usage of instance Name '
'%(instance_name)s UUID %(instance_uuid)s, '
'can not get info from libvirt'),
{'instance_name': instance_name,
'instance_uuid': instance.id})
# 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, '
LOG.warn(_('Failed to inspect memory usage of %(instance_uuid)s, '
'can not get info from libvirt: %(error)s'),
{'instance_name': instance_name, 'error': e})
{'instance_uuid': instance.id, 'error': e})

View File

@ -116,7 +116,7 @@ class TestDiskPollsters(TestBaseDiskIO):
self.assertIsNotEmpty(samples)
self.assertIn(pollster.CACHE_KEY_DISK, cache)
for instance in self.instance:
self.assertIn(instance.name, cache[pollster.CACHE_KEY_DISK])
self.assertIn(instance.id, cache[pollster.CACHE_KEY_DISK])
self.assertEqual(set([name]), set([s.name for s in samples]))
match = [s for s in samples if s.name == name]

View File

@ -215,7 +215,7 @@ class TestNetPollsterCache(base.TestPollsterBase):
pollster = factory()
cache = {
pollster.CACHE_KEY_VNIC: {
self.instance.name: vnics,
self.instance.id: vnics,
},
}
samples = list(pollster.get_samples(mgr, cache, [self.instance]))

View File

@ -33,7 +33,11 @@ class TestLibvirtInspection(base.BaseTestCase):
def setUp(self):
super(TestLibvirtInspection, self).setUp()
self.instance_name = 'instance-00000001'
class VMInstance:
id = 'ff58e738-12f4-4c58-acde-77617b68da56'
name = 'instance-00000001'
self.instance = VMInstance
self.inspector = libvirt_inspector.LibvirtInspector()
self.inspector.connection = mock.Mock()
libvirt_inspector.libvirt = mock.Mock()
@ -65,12 +69,12 @@ class TestLibvirtInspection(base.BaseTestCase):
def test_inspect_cpus(self):
with contextlib.nested(mock.patch.object(self.inspector.connection,
'lookupByName',
'lookupByUUIDString',
return_value=self.domain),
mock.patch.object(self.domain, 'info',
return_value=(0L, 0L, 0L,
2L, 999999L))):
cpu_info = self.inspector.inspect_cpus(self.instance_name)
cpu_info = self.inspector.inspect_cpus(self.instance)
self.assertEqual(2L, cpu_info.number)
self.assertEqual(999999L, cpu_info.time)
@ -140,7 +144,8 @@ class TestLibvirtInspection(base.BaseTestCase):
interfaceStats = interface_stats.__getitem__
connection = self.inspector.connection
with contextlib.nested(mock.patch.object(connection, 'lookupByName',
with contextlib.nested(mock.patch.object(connection,
'lookupByUUIDString',
return_value=self.domain),
mock.patch.object(self.domain, 'XMLDesc',
return_value=dom_xml),
@ -150,7 +155,7 @@ class TestLibvirtInspection(base.BaseTestCase):
mock.patch.object(self.domain, 'info',
return_value=(0L, 0L, 0L,
2L, 999999L))):
interfaces = list(self.inspector.inspect_vnics(self.instance_name))
interfaces = list(self.inspector.inspect_vnics(self.instance))
self.assertEqual(3, len(interfaces))
vnic0, info0 = interfaces[0]
@ -191,12 +196,13 @@ class TestLibvirtInspection(base.BaseTestCase):
def test_inspect_vnics_with_domain_shutoff(self):
connection = self.inspector.connection
with contextlib.nested(mock.patch.object(connection, 'lookupByName',
with contextlib.nested(mock.patch.object(connection,
'lookupByUUIDString',
return_value=self.domain),
mock.patch.object(self.domain, 'info',
return_value=(5L, 0L, 0L,
2L, 999999L))):
interfaces = list(self.inspector.inspect_vnics(self.instance_name))
interfaces = list(self.inspector.inspect_vnics(self.instance))
self.assertEqual([], interfaces)
def test_inspect_disks(self):
@ -216,7 +222,7 @@ class TestLibvirtInspection(base.BaseTestCase):
"""
with contextlib.nested(mock.patch.object(self.inspector.connection,
'lookupByName',
'lookupByUUIDString',
return_value=self.domain),
mock.patch.object(self.domain, 'XMLDesc',
return_value=dom_xml),
@ -226,7 +232,7 @@ class TestLibvirtInspection(base.BaseTestCase):
mock.patch.object(self.domain, 'info',
return_value=(0L, 0L, 0L,
2L, 999999L))):
disks = list(self.inspector.inspect_disks(self.instance_name))
disks = list(self.inspector.inspect_disks(self.instance))
self.assertEqual(1, len(disks))
disk0, info0 = disks[0]
@ -238,18 +244,19 @@ class TestLibvirtInspection(base.BaseTestCase):
def test_inspect_disks_with_domain_shutoff(self):
connection = self.inspector.connection
with contextlib.nested(mock.patch.object(connection, 'lookupByName',
with contextlib.nested(mock.patch.object(connection,
'lookupByUUIDString',
return_value=self.domain),
mock.patch.object(self.domain, 'info',
return_value=(5L, 0L, 0L,
2L, 999999L))):
disks = list(self.inspector.inspect_disks(self.instance_name))
disks = list(self.inspector.inspect_disks(self.instance))
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',
with mock.patch.object(connection, 'lookupByUUIDString',
return_value=self.domain):
with mock.patch.object(self.domain, 'info',
return_value=(0L, 0L, 51200L,
@ -257,23 +264,23 @@ class TestLibvirtInspection(base.BaseTestCase):
with mock.patch.object(self.domain, 'memoryStats',
return_value=fake_memory_stats):
memory = self.inspector.inspect_memory_usage(
self.instance_name)
self.instance)
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',
with mock.patch.object(connection, 'lookupByUUIDString',
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.instance)
self.assertIsNone(memory)
def test_inspect_memory_usage_with_empty_stats(self):
connection = self.inspector.connection
with mock.patch.object(connection, 'lookupByName',
with mock.patch.object(connection, 'lookupByUUIDString',
return_value=self.domain):
with mock.patch.object(self.domain, 'info',
return_value=(0L, 0L, 51200L,
@ -281,7 +288,7 @@ class TestLibvirtInspection(base.BaseTestCase):
with mock.patch.object(self.domain, 'memoryStats',
return_value={}):
memory = self.inspector.inspect_memory_usage(
self.instance_name)
self.instance)
self.assertIsNone(memory)