Merge "Add cpu.delay meter"
This commit is contained in:
commit
5a3f99d05b
9 files changed
+69
-5
No files matched your search
@@ -38,6 +38,17 @@ class CPUPollster(InstanceStatsPollster):
|
||||
return {'cpu_number': c_data.cpu_number}
|
||||
|
||||
|
||||
class CPUDelayPollster(InstanceStatsPollster):
|
||||
sample_name = 'cpu.delay'
|
||||
sample_unit = 'ns'
|
||||
sample_stats_key = 'cpu_delay'
|
||||
sample_type = sample.TYPE_CUMULATIVE
|
||||
|
||||
@staticmethod
|
||||
def get_additional_metadata(instance, c_data):
|
||||
return {'cpu_number': c_data.cpu_number}
|
||||
|
||||
|
||||
class VCPUsPollster(InstanceStatsPollster):
|
||||
sample_name = 'vcpus'
|
||||
sample_unit = 'vcpu'
|
||||
|
||||
@@ -43,6 +43,7 @@ class InstanceStats:
|
||||
'power_state', # the power state of the domain
|
||||
'cpu_number', # number: number of CPUs
|
||||
'cpu_time', # time: cumulative CPU time
|
||||
'cpu_delay', # delay: cumulative CPU steal time
|
||||
'memory_actual', # actual: Amount of allocated memory
|
||||
'memory_available', # available: Amount of usable memory
|
||||
'memory_usage', # usage: Amount of memory used
|
||||
|
||||
@@ -246,7 +246,7 @@ class LibvirtInspector(virt_inspector.Inspector):
|
||||
# TODO(sileht): stats also have the disk/vnic info
|
||||
# we could use that instead of the old method for Queen
|
||||
stats = self.connection.domainListGetStats([domain], 0)[0][1]
|
||||
cpu_time = 0
|
||||
cpu_time = cpu_delay = 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
|
||||
@@ -257,6 +257,7 @@ class LibvirtInspector(virt_inspector.Inspector):
|
||||
try:
|
||||
cpu_time += (stats.get('vcpu.%s.time' % vcpu) +
|
||||
stats.get('vcpu.%s.wait' % vcpu))
|
||||
cpu_delay += stats.get('vcpu.%s.delay' % vcpu)
|
||||
current_cpus -= 1
|
||||
except TypeError:
|
||||
# pass here, if there are too many holes, the cpu count will
|
||||
@@ -266,11 +267,13 @@ class LibvirtInspector(virt_inspector.Inspector):
|
||||
if current_cpus:
|
||||
# There wasn't enough data, so fall back
|
||||
cpu_time = stats.get('cpu.time')
|
||||
cpu_delay = 0
|
||||
|
||||
return virt_inspector.InstanceStats(
|
||||
power_state=domain.info()[0],
|
||||
cpu_number=stats.get('vcpu.current'),
|
||||
cpu_time=cpu_time,
|
||||
cpu_delay=cpu_delay,
|
||||
memory_actual=memory_actual,
|
||||
memory_available=memory_available,
|
||||
memory_usage=memory_used,
|
||||
|
||||
@@ -86,6 +86,8 @@ resources:
|
||||
power.state:
|
||||
cpu:
|
||||
archive_policy_name: ceilometer-low-rate
|
||||
cpu.delay:
|
||||
archive_policy_name: ceilometer-low-rate
|
||||
disk.root.size:
|
||||
disk.ephemeral.size:
|
||||
disk.latency:
|
||||
|
||||
@@ -104,6 +104,37 @@ class TestCPUPollster(base.TestPollsterBase):
|
||||
samples[0].resource_metadata['instance_type'])
|
||||
|
||||
|
||||
class TestCPUDelayPollster(base.TestPollsterBase):
|
||||
|
||||
def test_get_samples(self):
|
||||
self._mock_inspect_instance(
|
||||
virt_inspector.InstanceStats(
|
||||
cpu_delay=1 * (10 ** 6), cpu_number=2),
|
||||
virt_inspector.InstanceStats(
|
||||
cpu_delay=3 * (10 ** 6), cpu_number=2),
|
||||
# cpu_delay resets on instance restart
|
||||
virt_inspector.InstanceStats(
|
||||
cpu_delay=2 * (10 ** 6), cpu_number=2),
|
||||
)
|
||||
|
||||
mgr = manager.AgentManager(0, self.CONF)
|
||||
pollster = instance_stats.CPUDelayPollster(self.CONF)
|
||||
|
||||
def _verify_cpu_metering(expected_time):
|
||||
cache = {}
|
||||
samples = list(pollster.get_samples(mgr, cache, [self.instance]))
|
||||
self.assertEqual(1, len(samples))
|
||||
self.assertEqual({'cpu.delay'}, {s.name for s in samples})
|
||||
self.assertEqual(expected_time, samples[0].volume)
|
||||
self.assertEqual(2, samples[0].resource_metadata.get('cpu_number'))
|
||||
# ensure elapsed time between polling cycles is non-zero
|
||||
time.sleep(0.001)
|
||||
|
||||
_verify_cpu_metering(1 * (10 ** 6))
|
||||
_verify_cpu_metering(3 * (10 ** 6))
|
||||
_verify_cpu_metering(2 * (10 ** 6))
|
||||
|
||||
|
||||
class TestVCPUsPollster(base.TestPollsterBase):
|
||||
|
||||
def test_get_samples(self):
|
||||
|
||||
@@ -64,10 +64,12 @@ class TestLibvirtInspection(base.BaseTestCase):
|
||||
'cpu.time': 999999,
|
||||
'vcpu.maximum': 4,
|
||||
'vcpu.current': 2,
|
||||
'vcpu.0.time': 10000,
|
||||
'vcpu.0.wait': 10000,
|
||||
'vcpu.0.time': 20000,
|
||||
'vcpu.0.wait': 2000,
|
||||
'vcpu.0.delay': 100,
|
||||
'vcpu.2.time': 10000,
|
||||
'vcpu.2.wait': 10000,
|
||||
'vcpu.2.wait': 1000,
|
||||
'vcpu.2.delay': 200,
|
||||
'perf.cpu_cycles': 7259361,
|
||||
'perf.instructions': 8815623,
|
||||
'perf.cache_references': 74184,
|
||||
@@ -78,7 +80,8 @@ class TestLibvirtInspection(base.BaseTestCase):
|
||||
stats = self.inspector.inspect_instance(self.instance, None)
|
||||
self.assertEqual(0, stats.power_state)
|
||||
self.assertEqual(2, stats.cpu_number)
|
||||
self.assertEqual(40000, stats.cpu_time)
|
||||
self.assertEqual(33000, stats.cpu_time)
|
||||
self.assertEqual(300, stats.cpu_delay)
|
||||
self.assertEqual(54400 / units.Ki, stats.memory_actual)
|
||||
self.assertEqual(51200 / units.Ki, stats.memory_available)
|
||||
self.assertEqual(25600 / units.Ki, stats.memory_usage)
|
||||
@@ -110,6 +113,7 @@ class TestLibvirtInspection(base.BaseTestCase):
|
||||
stats = self.inspector.inspect_instance(self.instance)
|
||||
self.assertEqual(2, stats.cpu_number)
|
||||
self.assertEqual(999999, stats.cpu_time)
|
||||
self.assertEqual(0, stats.cpu_delay)
|
||||
|
||||
def test_inspect_instance_with_domain_shutoff(self):
|
||||
domain = mock.Mock()
|
||||
@@ -138,6 +142,7 @@ class TestLibvirtInspection(base.BaseTestCase):
|
||||
self.assertEqual(2, stats.cpu_number)
|
||||
self.assertEqual(2097152 / units.Ki, stats.memory_actual)
|
||||
self.assertIsNone(stats.cpu_time)
|
||||
self.assertIsNone(stats.cpu_delay)
|
||||
self.assertIsNone(stats.memory_available)
|
||||
self.assertIsNone(stats.memory_usage)
|
||||
self.assertIsNone(stats.memory_resident)
|
||||
|
||||
@@ -236,6 +236,11 @@ The following meters are collected for OpenStack Compute.
|
||||
| | | | | | | from within the |
|
||||
| | | | | | | instance |
|
||||
+-----------+-------+------+----------+----------+---------+------------------+
|
||||
| **Meters added in the Indri release** |
|
||||
+-----------+-------+------+----------+----------+---------+------------------+
|
||||
| cpu.delay | Cumu\ | ns | instance | Pollster | Libvirt | CPU steal time |
|
||||
| | lative| | ID | | | |
|
||||
+-----------+-------+------+----------+----------+---------+------------------+
|
||||
|
||||
.. note::
|
||||
|
||||
|
||||
@@ -103,6 +103,7 @@ local_node = "ceilometer.polling.discovery.localnode:LocalNodeDiscovery"
|
||||
"disk.device.write.latency" = "ceilometer.compute.pollsters.disk:PerDeviceDiskWriteLatencyPollster"
|
||||
"power.state" = "ceilometer.compute.pollsters.instance_stats:PowerStatePollster"
|
||||
"cpu" = "ceilometer.compute.pollsters.instance_stats:CPUPollster"
|
||||
"cpu.delay" = "ceilometer.compute.pollsters.instance_stats:CPUDelayPollster"
|
||||
"vcpus" = "ceilometer.compute.pollsters.instance_stats:VCPUsPollster"
|
||||
"network.incoming.bytes" = "ceilometer.compute.pollsters.net:IncomingBytesPollster"
|
||||
"network.incoming.packets" = "ceilometer.compute.pollsters.net:IncomingPacketsPollster"
|
||||
|
||||
@@ -0,0 +1,5 @@
|
||||
---
|
||||
features:
|
||||
- |
|
||||
The new ``cpu.delay`` meter has been added. This meter shows total CPU
|
||||
steal time observed per instance.
|
||||
Reference in new issue
Block a user