From ca55c319da02b743f12257695f765705d71fa17c Mon Sep 17 00:00:00 2001 From: Piyush Masrani Date: Tue, 4 Mar 2014 18:35:57 +0530 Subject: [PATCH] VMware vSphere: Changes for cpu_util Added a pollster to poll CPU_Util from VMware Vsphere inspector. Change-Id: Ibbfce0dd2ef5175f84a9b901a4653da8dca9c8b2 Implements: blueprint vmware-vcenter-server --- ceilometer/compute/pollsters/cpu.py | 33 +++++++++++++++++++ ceilometer/compute/virt/inspector.py | 14 ++++++++ ceilometer/compute/virt/vmware/inspector.py | 12 +++++++ .../tests/compute/pollsters/test_cpu.py | 33 +++++++++++++++++++ .../compute/virt/vmware/test_inspector.py | 21 ++++++++++++ setup.cfg | 1 + 6 files changed, 114 insertions(+) diff --git a/ceilometer/compute/pollsters/cpu.py b/ceilometer/compute/pollsters/cpu.py index 1cb64b43f..f7403c5db 100644 --- a/ceilometer/compute/pollsters/cpu.py +++ b/ceilometer/compute/pollsters/cpu.py @@ -51,7 +51,40 @@ class CPUPollster(plugin.ComputePollster): except virt_inspector.InstanceNotFoundException as err: # Instance was deleted while getting samples. Ignore it. LOG.debug(_('Exception while getting samples %s'), err) + except NotImplementedError: + # Selected inspector does not implement this pollster. + LOG.debug(_('Obtaining CPU time is not implemented for %s' + ), manager.inspector.__class__.__name__) except Exception as err: LOG.error(_('could not get CPU time for %(id)s: %(e)s') % ( {'id': instance.id, 'e': err})) LOG.exception(err) + + +class CPUUtilPollster(plugin.ComputePollster): + + def get_samples(self, manager, cache, resources): + for instance in resources: + LOG.debug(_('Checking CPU util for instance %s'), instance.id) + try: + cpu_info = manager.inspector.inspect_cpu_util(instance) + LOG.debug(_("CPU UTIL: %(instance)s %(util)d"), + ({'instance': instance.__dict__, + 'util': cpu_info.util})) + yield util.make_sample_from_instance( + instance, + name='cpu_util', + type=sample.TYPE_GAUGE, + unit='%', + volume=cpu_info.util, + ) + except virt_inspector.InstanceNotFoundException as err: + # Instance was deleted while getting samples. Ignore it. + LOG.debug(_('Exception while getting samples %s'), err) + except NotImplementedError: + # Selected inspector does not implement this pollster. + LOG.debug(_('Obtaining CPU Util is not implemented for %s' + ), manager.inspector.__class__.__name__) + except Exception as err: + LOG.error(_('Could not get CPU Util for %(id)s: %(e)s'), ( + {'id': instance.id, 'e': err})) diff --git a/ceilometer/compute/virt/inspector.py b/ceilometer/compute/virt/inspector.py index 8a615ca01..7f57ab929 100644 --- a/ceilometer/compute/virt/inspector.py +++ b/ceilometer/compute/virt/inspector.py @@ -53,6 +53,12 @@ Instance = collections.namedtuple('Instance', ['name', 'UUID']) # CPUStats = collections.namedtuple('CPUStats', ['number', 'time']) +# Named tuple representing CPU Utilization statistics. +# +# util: CPU utilization in percentage +# +CPUUtilStats = collections.namedtuple('CPUUtilStats', ['util']) + # Named tuple representing Memory usage statistics. # # usage: Amount of memory used @@ -131,6 +137,14 @@ class Inspector(object): """ raise NotImplementedError() + def inspect_cpu_util(self, instance): + """Inspect the CPU Utilization (%) for an instance. + + :param instance: the target instance + :return: the percentage of CPU utilization + """ + raise NotImplementedError() + def inspect_vnics(self, instance_name): """Inspect the vNIC statistics for an instance. diff --git a/ceilometer/compute/virt/vmware/inspector.py b/ceilometer/compute/virt/vmware/inspector.py index 56b62a012..f94471b85 100644 --- a/ceilometer/compute/virt/vmware/inspector.py +++ b/ceilometer/compute/virt/vmware/inspector.py @@ -50,6 +50,7 @@ cfg.CONF.register_group(opt_group) cfg.CONF.register_opts(OPTS, group=opt_group) VC_AVERAGE_MEMORY_CONSUMED_CNTR = 'mem:consumed:average' +VC_AVERAGE_CPU_CONSUMED_CNTR = 'cpu:usage:average' def get_api_session(): @@ -78,6 +79,17 @@ class VsphereInspector(virt_inspector.Inspector): def inspect_cpus(self, instance_name): raise NotImplementedError() + def inspect_cpu_util(self, instance): + vm_moid = self._ops.get_vm_moid(instance.id) + if vm_moid is None: + raise virt_inspector.InstanceNotFoundException( + _('VM %s not found in VMware Vsphere') % instance.id) + cpu_util_counter_id = self._ops.get_perf_counter_id( + VC_AVERAGE_CPU_CONSUMED_CNTR) + cpu_util = self._ops.query_vm_aggregate_stats(vm_moid, + cpu_util_counter_id) + return virt_inspector.CPUUtilStats(util=cpu_util) + def inspect_vnics(self, instance_name): raise NotImplementedError() diff --git a/ceilometer/tests/compute/pollsters/test_cpu.py b/ceilometer/tests/compute/pollsters/test_cpu.py index 15aa65139..054ad6287 100644 --- a/ceilometer/tests/compute/pollsters/test_cpu.py +++ b/ceilometer/tests/compute/pollsters/test_cpu.py @@ -79,3 +79,36 @@ class TestCPUPollster(base.TestPollsterBase): self.assertEqual(len(samples), 1) self.assertEqual(samples[0].volume, 10 ** 6) self.assertEqual(len(cache), 0) + + +class TestCPUUtilPollster(base.TestPollsterBase): + + def setUp(self): + super(TestCPUUtilPollster, self).setUp() + + @mock.patch('ceilometer.pipeline.setup_pipeline', mock.MagicMock()) + def test_get_samples(self): + next_value = iter(( + virt_inspector.CPUUtilStats(util=40), + virt_inspector.CPUUtilStats(util=60), + )) + + def inspect_cpu_util(name): + return six.next(next_value) + + self.inspector.inspect_cpu_util = \ + mock.Mock(side_effect=inspect_cpu_util) + + mgr = manager.AgentManager() + pollster = cpu.CPUUtilPollster() + + def _verify_cpu_util_metering(expected_util): + cache = {} + samples = list(pollster.get_samples(mgr, cache, [self.instance])) + self.assertEqual(1, len(samples)) + self.assertEqual(set(['cpu_util']), + set([s.name for s in samples])) + self.assertEqual(expected_util, samples[0].volume) + + _verify_cpu_util_metering(40) + _verify_cpu_util_metering(60) diff --git a/ceilometer/tests/compute/virt/vmware/test_inspector.py b/ceilometer/tests/compute/virt/vmware/test_inspector.py index 7d8b1a9a1..803a088d4 100644 --- a/ceilometer/tests/compute/virt/vmware/test_inspector.py +++ b/ceilometer/tests/compute/virt/vmware/test_inspector.py @@ -59,3 +59,24 @@ class TestVsphereInspection(test.BaseTestCase): fake_memory_value memory_stat = self._inspector.inspect_memory_usage(fake_instance) self.assertEqual(fake_stat, memory_stat) + + def test_inspect_cpu_util(self): + fake_instance_moid = 'fake_instance_moid' + fake_instance_id = 'fake_instance_id' + fake_perf_counter_id = 'fake_perf_counter_id' + fake_cpu_util_value = 60 + fake_stat = virt_inspector.CPUUtilStats(util=60) + + def construct_mock_instance_object(fake_instance_id): + instance_object = mock.MagicMock() + instance_object.id = fake_instance_id + return instance_object + + fake_instance = construct_mock_instance_object(fake_instance_id) + self._inspector._ops.get_vm_moid.return_value = fake_instance_moid + self._inspector._ops.get_perf_counter_id.return_value = \ + fake_perf_counter_id + self._inspector._ops.query_vm_aggregate_stats.return_value = \ + fake_cpu_util_value + cpu_util_stat = self._inspector.inspect_cpu_util(fake_instance) + self.assertEqual(fake_stat, cpu_util_stat) diff --git a/setup.cfg b/setup.cfg index 029c7b624..ffa764438 100644 --- a/setup.cfg +++ b/setup.cfg @@ -73,6 +73,7 @@ ceilometer.poll.compute = disk.read.bytes = ceilometer.compute.pollsters.disk:ReadBytesPollster disk.write.bytes = ceilometer.compute.pollsters.disk:WriteBytesPollster cpu = ceilometer.compute.pollsters.cpu:CPUPollster + cpu_util = ceilometer.compute.pollsters.cpu:CPUUtilPollster network.incoming.bytes = ceilometer.compute.pollsters.net:IncomingBytesPollster network.incoming.packets = ceilometer.compute.pollsters.net:IncomingPacketsPollster network.outgoing.bytes = ceilometer.compute.pollsters.net:OutgoingBytesPollster