Use vcpu.x.time and vcpu.x.wait values in libvirt inspector

If possible, calculate cputime from vcpu time + vcpu wait.
Fall back to cpu.time, if any vcpu.x.time or vcpu.x.wait
values are missing.
derived from I7bce33854dfe9c7b0e03b8c22721d04028183701

Co-Authored-By: Michael Ly <msly@us.ibm.com>
Co-Authored-By: Avi Weit <WEIT@il.ibm.com>
Co-Authored-By: Jorge Rodriguez <jorgedr@us.ibm.com>
Co-Authored-By: Karolyn Chambers <Karolyn.Chambers@target.com>
Co-Authored-By: Daniel Berrange <berrange@redhat.com>
Co-Authored-By: gordon chung <gord@live.ca>

Change-Id: I20700a32d608b3444b22c5ae460002eeb86d78ae
Closes-bug: #1677159
Closes-bug: #1421584
This commit is contained in:
Gyorgy Szombathelyi
2017-03-29 11:34:52 +02:00
parent 2008444a23
commit a4ec0911a3
2 changed files with 48 additions and 2 deletions

View File

@@ -173,10 +173,30 @@ class LibvirtInspector(virt_inspector.Inspector):
# TODO(sileht): stats also have the disk/vnic info # TODO(sileht): stats also have the disk/vnic info
# we could use that instead of the old method for Queen # we could use that instead of the old method for Queen
stats = self.connection.domainListGetStats([domain], 0)[0][1] stats = self.connection.domainListGetStats([domain], 0)[0][1]
cpu_time = 0
current_cpus = stats.get('vcpu.current')
# Iterate over the maximum number of CPUs here, and count the
# actual number encountered, since the vcpu.x structure can
# have holes according to
# https://libvirt.org/git/?p=libvirt.git;a=blob;f=src/libvirt-domain.c
# virConnectGetAllDomainStats()
for vcpu in six.moves.range(stats.get('vcpu.maximum', 0)):
try:
cpu_time += (stats.get('vcpu.%s.time' % vcpu) +
stats.get('vcpu.%s.wait' % vcpu))
current_cpus -= 1
except TypeError:
# pass here, if there are too many holes, the cpu count will
# not match, so don't need special error handling.
pass
if current_cpus:
# There wasn't enough data, so fall back
cpu_time = stats.get('cpu.time')
return virt_inspector.InstanceStats( return virt_inspector.InstanceStats(
cpu_number=stats.get('vcpu.current'), cpu_number=stats.get('vcpu.current'),
cpu_time=stats.get('cpu.time'), cpu_time=cpu_time,
memory_usage=memory_used, memory_usage=memory_used,
memory_resident=memory_resident, memory_resident=memory_resident,
cpu_cycles=stats.get("perf.cpu_cycles"), cpu_cycles=stats.get("perf.cpu_cycles"),

View File

@@ -60,7 +60,12 @@ class TestLibvirtInspection(base.BaseTestCase):
conn.lookupByUUIDString.return_value = domain conn.lookupByUUIDString.return_value = domain
conn.domainListGetStats.return_value = [({}, { conn.domainListGetStats.return_value = [({}, {
'cpu.time': 999999, 'cpu.time': 999999,
'vcpu.maximum': 4,
'vcpu.current': 2, 'vcpu.current': 2,
'vcpu.0.time': 10000,
'vcpu.0.wait': 10000,
'vcpu.2.time': 10000,
'vcpu.2.wait': 10000,
'perf.cmt': 90112, 'perf.cmt': 90112,
'perf.cpu_cycles': 7259361, 'perf.cpu_cycles': 7259361,
'perf.instructions': 8815623, 'perf.instructions': 8815623,
@@ -73,7 +78,7 @@ class TestLibvirtInspection(base.BaseTestCase):
'refresh_libvirt_connection', return_value=conn): 'refresh_libvirt_connection', return_value=conn):
stats = self.inspector.inspect_instance(self.instance) stats = self.inspector.inspect_instance(self.instance)
self.assertEqual(2, stats.cpu_number) self.assertEqual(2, stats.cpu_number)
self.assertEqual(999999, stats.cpu_time) self.assertEqual(40000, stats.cpu_time)
self.assertEqual(90112, stats.cpu_l3_cache_usage) self.assertEqual(90112, stats.cpu_l3_cache_usage)
self.assertEqual(25600 / units.Ki, stats.memory_usage) self.assertEqual(25600 / units.Ki, stats.memory_usage)
self.assertEqual(30000 / units.Ki, stats.memory_resident) self.assertEqual(30000 / units.Ki, stats.memory_resident)
@@ -84,6 +89,27 @@ class TestLibvirtInspection(base.BaseTestCase):
self.assertEqual(74184, stats.cache_references) self.assertEqual(74184, stats.cache_references)
self.assertEqual(16737, stats.cache_misses) self.assertEqual(16737, stats.cache_misses)
def test_inspect_instance_stats_fallback_cpu_time(self):
domain = mock.Mock()
domain.info.return_value = (0, 0, 0, 2, 20000)
domain.memoryStats.return_value = {'available': 51200,
'unused': 25600,
'rss': 30000}
conn = mock.Mock()
conn.lookupByUUIDString.return_value = domain
conn.domainListGetStats.return_value = [({}, {
'vcpu.current': 2,
'vcpu.maximum': 4,
'vcpu.0.time': 10000,
'vcpu.1.time': 10000,
'cpu.time': 999999})]
with mock.patch('ceilometer.compute.virt.libvirt.utils.'
'refresh_libvirt_connection', return_value=conn):
stats = self.inspector.inspect_instance(self.instance)
self.assertEqual(2, stats.cpu_number)
self.assertEqual(999999, stats.cpu_time)
def test_inspect_cpus_with_domain_shutoff(self): def test_inspect_cpus_with_domain_shutoff(self):
domain = mock.Mock() domain = mock.Mock()
domain.info.return_value = (5, 0, 0, 2, 999999) domain.info.return_value = (5, 0, 0, 2, 999999)