diff --git a/ceilometer/compute/pollsters.py b/ceilometer/compute/pollsters.py index bddaa023c..1d147ba05 100644 --- a/ceilometer/compute/pollsters.py +++ b/ceilometer/compute/pollsters.py @@ -242,7 +242,7 @@ class CPUPollster(plugin.ComputePollster): utilization_map = {} - def get_cpu_util(self, instance, cpu_info): + def _get_cpu_util(self, instance, cpu_info): prev_times = self.utilization_map.get(instance.id) self.utilization_map[instance.id] = (cpu_info.time, datetime.datetime.now()) @@ -259,6 +259,14 @@ class CPUPollster(plugin.ComputePollster): cpu_util = 100 * cores_fraction * time_used / elapsed return cpu_util + CACHE_KEY_CPU = 'cpu' + + def _get_cpu_info(self, inspector, instance_name, cache): + i_cache = cache.setdefault(self.CACHE_KEY_CPU, {}) + if instance_name not in i_cache: + i_cache[instance_name] = inspector.inspect_cpus(instance_name) + return i_cache[instance_name] + @staticmethod def get_counter_names(): return ['cpu', 'cpu_util'] @@ -267,10 +275,14 @@ class CPUPollster(plugin.ComputePollster): self.LOG.info('checking instance %s', instance.id) instance_name = _instance_name(instance) try: - cpu_info = manager.inspector.inspect_cpus(instance_name) + cpu_info = self._get_cpu_info( + manager.inspector, + instance_name, + cache, + ) self.LOG.info("CPUTIME USAGE: %s %d", instance.__dict__, cpu_info.time) - cpu_util = self.get_cpu_util(instance, cpu_info) + cpu_util = self._get_cpu_util(instance, cpu_info) self.LOG.info("CPU UTILIZATION %%: %s %0.2f", instance.__dict__, cpu_util) # FIXME(eglynn): once we have a way of configuring which measures diff --git a/tests/compute/test_pollsters.py b/tests/compute/test_pollsters.py index b7fe91135..6623ccf44 100644 --- a/tests/compute/test_pollsters.py +++ b/tests/compute/test_pollsters.py @@ -316,7 +316,8 @@ class TestCPUPollster(TestPollsterBase): pollster = pollsters.CPUPollster() def _verify_cpu_metering(zero, expected_time): - counters = list(pollster.get_counters(mgr, {}, self.instance)) + cache = {} + counters = list(pollster.get_counters(mgr, cache, self.instance)) self.assertEquals(len(counters), 2) self.assertEqual(set([c.name for c in counters]), set(pollster.get_counter_names())) @@ -325,9 +326,37 @@ class TestCPUPollster(TestPollsterBase): counters[0].volume > 0.0) assert counters[1].name == 'cpu' assert counters[1].volume == expected_time + assert pollster.CACHE_KEY_CPU in cache + assert self.instance.name in cache[pollster.CACHE_KEY_CPU] # ensure elapsed time between polling cycles is non-zero time.sleep(0.001) _verify_cpu_metering(True, 1 * (10 ** 6)) _verify_cpu_metering(False, 3 * (10 ** 6)) _verify_cpu_metering(False, 2 * (10 ** 6)) + + @mock.patch('ceilometer.pipeline.setup_pipeline', mock.MagicMock()) + def test_get_counters_cache(self): + # self.inspector.inspect_cpus(self.instance.name).AndReturn( + # virt_inspector.CPUStats(time=1 * (10 ** 6), number=2)) + # self.inspector.inspect_cpus(self.instance.name).AndReturn( + # virt_inspector.CPUStats(time=3 * (10 ** 6), number=2)) + # # cpu_time resets on instance restart + # self.inspector.inspect_cpus(self.instance.name).AndReturn( + # virt_inspector.CPUStats(time=2 * (10 ** 6), number=2)) + self.mox.ReplayAll() + + mgr = manager.AgentManager() + pollster = pollsters.CPUPollster() + + cache = { + pollster.CACHE_KEY_CPU: { + self.instance.name: virt_inspector.CPUStats( + time=10 ** 6, + number=2, + ), + }, + } + counters = list(pollster.get_counters(mgr, cache, self.instance)) + self.assertEquals(len(counters), 2) + self.assertEquals(counters[1].volume, 10 ** 6)