diff --git a/ceilometer_powervm/compute/virt/powervm/inspector.py b/ceilometer_powervm/compute/virt/powervm/inspector.py index f2707d9..cd4856c 100644 --- a/ceilometer_powervm/compute/virt/powervm/inspector.py +++ b/ceilometer_powervm/compute/virt/powervm/inspector.py @@ -84,12 +84,18 @@ class PowerVMInspector(virt_inspector.Inspector): LOG.debug("Host UUID: %s" % hosts[0].uuid) return hosts[0].uuid - def inspect_cpus(self, instance): - """Inspect the CPU statistics for an instance. + def inspect_instance(self, instance, duration=None): + """Inspect the statistics for an instance. :param instance: the target instance - :return: the number of CPUs and cumulative CPU time + :param duration: the last 'n' seconds, over which the value should be + inspected. + + The PowerVM implementation does not make use of the duration + field. + :return: the instance statistics """ + uuid = self._puuid(instance) cur_date, cur_metric = self.vm_metrics.get_latest_metric(uuid) @@ -102,20 +108,8 @@ class PowerVMInspector(virt_inspector.Inspector): cpu_time = (cur_metric.processor.util_cap_proc_cycles + cur_metric.processor.util_uncap_proc_cycles) - return virt_inspector.CPUStats(number=cur_metric.processor.virt_procs, - time=cpu_time) + cpu_num = cur_metric.processor.virt_procs - def inspect_cpu_util(self, instance, duration=None): - """Inspect the CPU Utilization (%) for an instance. - - :param instance: the target instance - :param duration: the last 'n' seconds, over which the value should be - inspected. - - The PowerVM implementation does not make use of the duration - field. - :return: the percentage of CPU utilization - """ # The duration is ignored. There is precedent for this in other # inspectors if the platform doesn't support duration. # @@ -126,17 +120,8 @@ class PowerVMInspector(virt_inspector.Inspector): # Get the current and previous sample. Delta is performed between # these two. - uuid = self._puuid(instance) - cur_date, cur_metric = self.vm_metrics.get_latest_metric(uuid) prev_date, prev_metric = self.vm_metrics.get_previous_metric(uuid) - # If the current is none, then the instance can not be found in the - # sample and an error should be raised. - if cur_metric is None: - raise virt_inspector.InstanceNotFoundException( - _('VM %s not found in PowerVM Metrics Sample.') % - instance.name) - # Get the current data. cur_util_cap = cur_metric.processor.util_cap_proc_cycles cur_util_uncap = cur_metric.processor.util_uncap_proc_cycles @@ -157,9 +142,8 @@ class PowerVMInspector(virt_inspector.Inspector): "It is either a new VM or was recently migrated. " "It will be collected in the next inspection " "cycle."), instance.name) - message = (_("Unable to derive CPU Utilization for VM %s.") % - instance.name) - raise virt_inspector.InstanceNotFoundException(message) + return virt_inspector.InstanceStats( + cpu_time=cpu_time, cpu_number=cpu_num) # Gather the previous metrics prev_util_cap = prev_metric.processor.util_cap_proc_cycles @@ -203,14 +187,13 @@ class PowerVMInspector(virt_inspector.Inspector): # If the entitled is zero, that generally means that the VM has not # been started yet (everything else would be zero as well). So to # avoid a divide by zero error, just return 0% in that case. - if entitled == 0: - return virt_inspector.CPUUtilStats(util=0.0) - - util = float(util_cap + util_uncap - idle - donated) / float(entitled) + util = (float(util_cap + util_uncap - idle - donated) / float(entitled) + if entitled else 0.0) # Utilization is reported as percents. Therefore, multiply by 100.0 # to get a readable percentage based format. - return virt_inspector.CPUUtilStats(util=util * 100.0) + return virt_inspector.InstanceStats( + cpu_util=util * 100.0, cpu_time=cpu_time, cpu_number=cpu_num) @staticmethod def mac_for_metric_cna(metric_cna, client_cnas): @@ -279,14 +262,13 @@ class PowerVMInspector(virt_inspector.Inspector): # The name will be the location code. MAC is identified from # above. Others appear libvirt specific. - interface = virt_inspector.Interface( - name=metric_cna.physical_location, - mac=mac, fref=None, parameters=None) - + # # PowerVM doesn't specify drops by receive vs. transmit. Since we # have the client adapter, we assume all are receive drops. # There are no error metrics available. - stats = virt_inspector.InterfaceStats( + yield virt_inspector.InterfaceStats( + name=metric_cna.physical_location, + mac=mac, fref=None, parameters=None, rx_bytes=metric_cna.received_bytes, rx_packets=metric_cna.received_packets, rx_drop=metric_cna.dropped_packets, @@ -296,9 +278,6 @@ class PowerVMInspector(virt_inspector.Inspector): tx_drop=0, tx_errors=0) - # Yield the stats up to the invoker - yield (interface, stats) - def inspect_vnic_rates(self, instance, duration=None): """Inspect the vNIC rate statistics for an instance. @@ -358,12 +337,6 @@ class PowerVMInspector(virt_inspector.Inspector): if mac is None: continue - # The name will be the location code. MAC is identified from - # above. Others appear libvirt specific. - interface = virt_inspector.Interface( - name=metric_cna.physical_location, - mac=mac, fref=None, parameters=None) - # Note that here, the previous may be none. That simply indicates # that the adapter was dynamically added to the VM before the # previous collection. Not the migration scenario above. @@ -378,10 +351,13 @@ class PowerVMInspector(virt_inspector.Inspector): # in time between the two samples. rx_rate = float(rx_bytes_diff) / float(date_delta_num) tx_rate = float(tx_bytes_diff) / float(date_delta_num) - stats = virt_inspector.InterfaceRateStats(rx_rate, tx_rate) - # Yield the results back to the invoker. - yield (interface, stats) + # The name will be the location code. MAC is identified from + # above. Others appear libvirt specific. + yield virt_inspector.InterfaceRateStats( + name=metric_cna.physical_location, + mac=mac, fref=None, parameters=None, + rx_bytes_rate=rx_rate, tx_bytes_rate=tx_rate) def inspect_disks(self, instance): """Inspect the disk statistics for an instance. @@ -419,12 +395,10 @@ class PowerVMInspector(virt_inspector.Inspector): for adpt in adpts: # PowerVM only shows the connection (SCSI or FC). Name after # the connection name - disk = virt_inspector.Disk(device=adpt.name) - stats = virt_inspector.DiskStats( - read_requests=adpt.num_reads, read_bytes=adpt.read_bytes, - write_requests=adpt.num_writes, write_bytes=adpt.write_bytes, - errors=0) - yield (disk, stats) + yield virt_inspector.DiskStats( + device=adpt.name, read_requests=adpt.num_reads, + read_bytes=adpt.read_bytes, write_requests=adpt.num_writes, + write_bytes=adpt.write_bytes, errors=0) def inspect_disk_iops(self, instance): """Inspect the Disk Input/Output operations per second for an instance. @@ -494,6 +468,5 @@ class PowerVMInspector(virt_inspector.Inspector): # PowerVM only shows the connection (SCSI or FC). Name after # the connection name - disk = virt_inspector.Disk(device=cur_adpt.name) - stats = virt_inspector.DiskIOPSStats(iops_count=iops) - yield (disk, stats) + yield virt_inspector.DiskIOPSStats(device=cur_adpt.name, + iops_count=iops) diff --git a/ceilometer_powervm/tests/compute/virt/powervm/test_inspector.py b/ceilometer_powervm/tests/compute/virt/powervm/test_inspector.py index 96d03c7..32cd24e 100644 --- a/ceilometer_powervm/tests/compute/virt/powervm/test_inspector.py +++ b/ceilometer_powervm/tests/compute/virt/powervm/test_inspector.py @@ -79,41 +79,18 @@ class TestPowerVMInspector(base.BaseTestCase): self.inspector = p_inspect.PowerVMInspector(None) self.inspector.vm_metrics = self.mock_metrics - def test_inspect_cpus(self): - """Validates PowerVM's inspect_cpus method.""" + def test_inspect_instance_stats(self): + """Validates PowerVM's inspect_instance method.""" # Validate that an error is raised if the instance can't be found # in the sample self.mock_metrics.get_latest_metric.return_value = None, None self.assertRaises(virt_inspector.InstanceNotFoundException, - self.inspector.inspect_cpus, mock.Mock()) - - # Build a response from the metric cache. - metric = mock.MagicMock() - metric.processor.util_cap_proc_cycles = 5 - metric.processor.util_uncap_proc_cycles = 6 - metric.processor.virt_procs = 12 - self.mock_metrics.get_latest_metric.return_value = mock.Mock(), metric - - # Invoke with the test data - resp = self.inspector.inspect_cpus(mock.Mock()) - - # Validate the metrics that came back - self.assertEqual(11, resp.time) - self.assertEqual(12, resp.number) - - def test_inspect_cpu_util(self): - """Validates PowerVM's inspect_cpu_util method.""" - # Validate that an error is raised if the instance can't be found in - # the sample data. - self.mock_metrics.get_latest_metric.return_value = None, None - self.mock_metrics.get_previous_metric.return_value = None, None - self.assertRaises(virt_inspector.InstanceNotFoundException, - self.inspector.inspect_cpu_util, - mock.Mock(), duration=30) + self.inspector.inspect_instance, mock.Mock()) def mock_metric(util_cap, util_uncap, idle, donated, entitled): """Helper method to create mock proc metrics.""" metric = mock.MagicMock() + metric.processor.virt_procs = 12 metric.processor.util_cap_proc_cycles = util_cap metric.processor.util_uncap_proc_cycles = util_uncap metric.processor.idle_proc_cycles = idle @@ -126,8 +103,9 @@ class TestPowerVMInspector(base.BaseTestCase): self.mock_metrics.get_latest_metric.return_value = ( mock.Mock(), mock_metric(7000, 50, 1000, 5000, 10000)) self.mock_metrics.get_previous_metric.return_value = None, None - self.assertRaises(virt_inspector.InstanceNotFoundException, - self.inspector.inspect_cpu_util, mock.Mock()) + resp = self.inspector.inspect_instance(mock.Mock()) + self.assertEqual(7050, resp.cpu_time) + self.assertEqual(12, resp.cpu_number) # Mock up a mixed use environment. cur = mock_metric(7000, 50, 1000, 5000, 10000) @@ -136,8 +114,8 @@ class TestPowerVMInspector(base.BaseTestCase): self.mock_metrics.get_previous_metric.return_value = mock.Mock(), prev # Execute and validate - resp = self.inspector.inspect_cpu_util(mock.Mock()) - self.assertEqual(.5, resp.util) + resp = self.inspector.inspect_instance(mock.Mock()) + self.assertEqual(.5, resp.cpu_util) # Mock an instance with a dedicated processor, but idling and donating # cycles to others. In these scenarios, util_cap shows full use, but @@ -148,8 +126,8 @@ class TestPowerVMInspector(base.BaseTestCase): self.mock_metrics.get_previous_metric.return_value = mock.Mock(), prev # Execute and validate - resp = self.inspector.inspect_cpu_util(mock.Mock()) - self.assertEqual(51.0, resp.util) + resp = self.inspector.inspect_instance(mock.Mock()) + self.assertEqual(51.0, resp.cpu_util) # Mock an instance with a shared processor. By nature, this doesn't # idle or donate. If it is 'idling' it is simply giving the cycles @@ -160,8 +138,8 @@ class TestPowerVMInspector(base.BaseTestCase): self.mock_metrics.get_previous_metric.return_value = mock.Mock(), prev # Execute and validate - resp = self.inspector.inspect_cpu_util(mock.Mock()) - self.assertEqual(80.0, resp.util) + resp = self.inspector.inspect_instance(mock.Mock()) + self.assertEqual(80.0, resp.cpu_util) # Mock an instance with a shared processor - but using cycles from # the uncap pool. This means it is using extra cycles from other @@ -173,8 +151,8 @@ class TestPowerVMInspector(base.BaseTestCase): # Execute and validate. This should be running at 300% CPU # utilization. Fast! - resp = self.inspector.inspect_cpu_util(mock.Mock()) - self.assertEqual(300.0, resp.util) + resp = self.inspector.inspect_instance(mock.Mock()) + self.assertEqual(300.0, resp.cpu_util) # Mock an instance that hasn't been started yet. cur = mock_metric(0, 0, 0, 0, 0) @@ -183,8 +161,8 @@ class TestPowerVMInspector(base.BaseTestCase): self.mock_metrics.get_previous_metric.return_value = mock.Mock(), prev # This should have 0% utilization - resp = self.inspector.inspect_cpu_util(mock.Mock()) - self.assertEqual(0.0, resp.util) + resp = self.inspector.inspect_instance(mock.Mock()) + self.assertEqual(0.0, resp.cpu_util) @staticmethod def _mock_vnic_metric(rec_bytes, tx_bytes, rec_pkts, tx_pkts, phys_loc, @@ -252,9 +230,9 @@ class TestPowerVMInspector(base.BaseTestCase): resp = list(self.inspector.inspect_vnics(mock.Mock())) self.assertEqual(3, len(resp)) - interface1, stats1 = resp[0] - self.assertEqual('aa:bb:cc:dd:ee:ff', interface1.mac) - self.assertEqual('a', interface1.name) + stats1 = resp[0] + self.assertEqual('aa:bb:cc:dd:ee:ff', stats1.mac) + self.assertEqual('a', stats1.name) self.assertEqual(1000, stats1.rx_bytes) self.assertEqual(1000, stats1.tx_bytes) self.assertEqual(10, stats1.rx_packets) @@ -302,23 +280,23 @@ class TestPowerVMInspector(base.BaseTestCase): self.assertEqual(3, len(resp)) # First metric. No delta - interface1, stats1 = resp[0] - self.assertEqual('aa:bb:cc:dd:ee:ff', interface1.mac) - self.assertEqual('a', interface1.name) + stats1 = resp[0] + self.assertEqual('aa:bb:cc:dd:ee:ff', stats1.mac) + self.assertEqual('a', stats1.name) self.assertEqual(0, stats1.rx_bytes_rate) self.assertEqual(0, stats1.tx_bytes_rate) # Second metric - interface2, stats2 = resp[1] - self.assertEqual('aa:bb:cc:dd:ee:11', interface2.mac) - self.assertEqual('b', interface2.name) + stats2 = resp[1] + self.assertEqual('aa:bb:cc:dd:ee:11', stats2.mac) + self.assertEqual('b', stats2.name) self.assertEqual(60.0, stats2.rx_bytes_rate) self.assertEqual(60.0, stats2.tx_bytes_rate) # Third metric had no previous. - interface3, stats3 = resp[2] - self.assertEqual('aa:bb:cc:dd:ee:22', interface3.mac) - self.assertEqual('c', interface3.name) + stats3 = resp[2] + self.assertEqual('aa:bb:cc:dd:ee:22', stats3.mac) + self.assertEqual('c', stats3.name) self.assertEqual(100.0, stats3.rx_bytes_rate) self.assertEqual(100.0, stats3.tx_bytes_rate) @@ -387,17 +365,17 @@ class TestPowerVMInspector(base.BaseTestCase): self.assertEqual(3, len(resp)) # Two vSCSI's - disk1, stats1 = resp[0] - self.assertEqual('vscsi1', disk1.device) + stats1 = resp[0] + self.assertEqual('vscsi1', stats1.device) self.assertEqual(33, stats1.iops_count) - disk2, stats2 = resp[1] - self.assertEqual('vscsi2', disk2.device) + stats2 = resp[1] + self.assertEqual('vscsi2', stats2.device) self.assertEqual(133, stats2.iops_count) # Next is the vFC metric - disk3, stats3 = resp[2] - self.assertEqual('vfc1', disk3.device) + stats3 = resp[2] + self.assertEqual('vfc1', stats3.device) self.assertEqual(66, stats3.iops_count) def test_inspect_disks(self): @@ -425,16 +403,16 @@ class TestPowerVMInspector(base.BaseTestCase): self.assertEqual(3, len(resp)) # Two vSCSIs. - disk1, stats1 = resp[0] - self.assertEqual('vscsi1', disk1.device) + stats1 = resp[0] + self.assertEqual('vscsi1', stats1.device) self.assertEqual(1000, stats1.read_requests) self.assertEqual(100000, stats1.read_bytes) self.assertEqual(1000, stats1.write_requests) self.assertEqual(100000, stats1.write_bytes) self.assertEqual(0, stats1.errors) - disk2, stats2 = resp[1] - self.assertEqual('vscsi2', disk2.device) + stats2 = resp[1] + self.assertEqual('vscsi2', stats2.device) self.assertEqual(2000, stats2.read_requests) self.assertEqual(200000, stats2.read_bytes) self.assertEqual(2000, stats2.write_requests) @@ -442,8 +420,8 @@ class TestPowerVMInspector(base.BaseTestCase): self.assertEqual(0, stats1.errors) # Next is the vFC metric - disk3, stats3 = resp[2] - self.assertEqual('vfc1', disk3.device) + stats3 = resp[2] + self.assertEqual('vfc1', stats3.device) self.assertEqual(3000, stats3.read_requests) self.assertEqual(300000, stats3.read_bytes) self.assertEqual(3000, stats3.write_requests)