From 70ba79d52555268dac072db06e8c319db8b6474b Mon Sep 17 00:00:00 2001 From: Drew Thorstensen Date: Thu, 2 Jul 2015 16:16:02 -0400 Subject: [PATCH] Add CPU frequency to host stats This change set builds on the prior function and includes a function to gather the CPU frequency from the system. This change completes the functions needed to get the proper CPU Host Stats from within Nova for the PowerVM hypervisor. Change-Id: I7a2e9d76d22d3d857b14a9f378e24d6d73423ecc --- nova_powervm/tests/virt/powervm/test_host.py | 19 ++++++++++++++++--- nova_powervm/virt/powervm/driver.py | 7 +------ nova_powervm/virt/powervm/host.py | 12 +++++++++++- 3 files changed, 28 insertions(+), 10 deletions(-) diff --git a/nova_powervm/tests/virt/powervm/test_host.py b/nova_powervm/tests/virt/powervm/test_host.py index 7ac88010..d2dbf330 100644 --- a/nova_powervm/tests/virt/powervm/test_host.py +++ b/nova_powervm/tests/virt/powervm/test_host.py @@ -107,10 +107,13 @@ class TestHostCPUStats(test.TestCase): return lpar return None + @mock.patch('nova_powervm.virt.powervm.host.HostCPUStats._get_cpu_freq') @mock.patch('pypowervm.tasks.monitor.util.MetricCache._refresh_if_needed') @mock.patch('pypowervm.tasks.monitor.util.ensure_ltm_monitors') - def test_update_internal_metric(self, mock_ensure_ltm, mock_refresh): + def test_update_internal_metric(self, mock_ensure_ltm, mock_refresh, + mock_cpu_freq): host_stats = pvm_host.HostCPUStats(self.adpt, 'host_uuid') + mock_cpu_freq.return_value = 4116.0 # Make sure None is returned if there is no data. host_stats.cur_phyp = None @@ -124,7 +127,8 @@ class TestHostCPUStats(test.TestCase): # Validate the dictionary... expect = {'iowait': 0, 'idle': 1.6125096675799704e+16, - 'kernel': 58599310268, 'user': 789903553028} + 'kernel': 58599310268, 'user': 789903553028, + 'frequency': 4116.0} self.assertEqual(expect, host_stats.cur_data) # Now 'increment' it with a new current/previous @@ -135,9 +139,18 @@ class TestHostCPUStats(test.TestCase): # Validate this dictionary. Note that the values are still higher # overall, even though we add the 'deltas' from each VM. expect = {'iowait': 0, 'idle': 1.6125066665694504e+16, - 'kernel': 58599310268, 'user': 819913658228} + 'kernel': 58599310268, 'user': 819913658228, + 'frequency': 4116.0} self.assertEqual(expect, host_stats.cur_data) + @mock.patch('subprocess.check_output') + @mock.patch('pypowervm.tasks.monitor.util.MetricCache._refresh_if_needed') + @mock.patch('pypowervm.tasks.monitor.util.ensure_ltm_monitors') + def test_get_cpu_freq(self, mock_ensure_ltm, mock_refresh, mock_cmd): + host_stats = pvm_host.HostCPUStats(self.adpt, 'host_uuid') + mock_cmd.return_value = '4116.000000MHz\n' + self.assertEqual(4116.0, host_stats._get_cpu_freq()) + @mock.patch('pypowervm.tasks.monitor.util.MetricCache._refresh_if_needed') @mock.patch('pypowervm.tasks.monitor.util.ensure_ltm_monitors') def test_gather_user_cycles(self, mock_ensure_ltm, mock_refresh): diff --git a/nova_powervm/virt/powervm/driver.py b/nova_powervm/virt/powervm/driver.py index a268b5c1..ac226792 100644 --- a/nova_powervm/virt/powervm/driver.py +++ b/nova_powervm/virt/powervm/driver.py @@ -172,12 +172,7 @@ class PowerVMDriver(driver.ComputeDriver): def get_host_cpu_stats(self): """Return the current CPU state of the host.""" - host_stats = self.host_cpu_stats.get_host_cpu_stats() - - # TODO(thorst) Implement a frequency check. - host_stats['frequency'] = 3500 - - return host_stats + return self.host_cpu_stats.get_host_cpu_stats() def spawn(self, context, instance, image_meta, injected_files, admin_password, network_info=None, block_device_info=None, diff --git a/nova_powervm/virt/powervm/host.py b/nova_powervm/virt/powervm/host.py index 020aa525..89587fb5 100644 --- a/nova_powervm/virt/powervm/host.py +++ b/nova_powervm/virt/powervm/host.py @@ -18,6 +18,7 @@ import math from nova.compute import arch from nova.compute import hv_type from nova.compute import vm_mode +import subprocess from oslo_concurrency import lockutils from oslo_log import log as logging @@ -159,9 +160,12 @@ class HostCPUStats(pcm_util.MetricCache): # Idle is the subtraction of all. idle_cycles = tot_cycles - user_cycles - fw_cycles + # Get the processor frequency. + freq = self._get_cpu_freq() + # Now save these cycles to the internal data structure. self.cur_data = {'idle': idle_cycles, 'kernel': fw_cycles, - 'user': user_cycles, 'iowait': 0} + 'user': user_cycles, 'iowait': 0, 'frequency': freq} def _gather_user_cycles(self): """The estimated total user cycles. @@ -205,6 +209,12 @@ class HostCPUStats(pcm_util.MetricCache): else self.prev_data['user']) return prev_user_cycles + vm_delta_cycles + vios_delta_cycles + @staticmethod + def _get_cpu_freq(): + # The output will be similar to '4116.000000MHz' on a POWER system. + cmd = ['/usr/bin/awk', '/clock/ {print $3; exit}', '/proc/cpuinfo'] + return float(subprocess.check_output(cmd).rstrip("MHz\n")) + def _delta_proc_cycles(self, samples, prev_samples): """Sums all the processor delta cycles for a set of VM/VIOS samples.