Convert percent metrics back into the [0, 1] range
With the recent revamp of the Nova metrics framework in the Liberty cycle, there was a problem introduced in terms of how the percentage- based metrics (e.g., cpu.percent) are represented. That is, prior to Liberty, we stored the percentages in compute_nodes.metrics as a floating point value in the range [0, 1]. For example, 17.5% was represented as 0.175. The revamped framework expects the MonitorMetric.value properties to be integers, so when the percentages such as 0.175 are stored in this object, they're erroneously converted to 0. This patch multiplies the 'problematic' fields by 100 in preparation for storage within the MonitorMetric object and then divides the same problematic fields by 100.0 when converting back to their JSON format, which will preserve RPC notifier and database compatibility. Added some unit tests to test the conversions as well as making some of the unit tests more explicit so this doesn't happen again. Change-Id: I17a9412c63eeeb78ba2b2600f9007e9b58fcbf68 Closes-Bug: #1488696
This commit is contained in:
parent
764c4d467e
commit
87e1d8fab2
|
@ -77,17 +77,20 @@ class Monitor(base.CPUMonitorBase):
|
|||
+ stats["idle"] + stats["iowait"])
|
||||
cputime = float(stats["total"] - self._cpu_stats.get("total", 0))
|
||||
|
||||
# NOTE(jwcroppe): Convert all the `perc` values to their integer forms
|
||||
# since pre-conversion their values are within the range [0, 1] and the
|
||||
# objects.MonitorMetric.value field requires an integer.
|
||||
perc = (stats["user"] - self._cpu_stats.get("user", 0)) / cputime
|
||||
self._data["cpu.user.percent"] = perc
|
||||
self._data["cpu.user.percent"] = int(perc * 100)
|
||||
|
||||
perc = (stats["kernel"] - self._cpu_stats.get("kernel", 0)) / cputime
|
||||
self._data["cpu.kernel.percent"] = perc
|
||||
self._data["cpu.kernel.percent"] = int(perc * 100)
|
||||
|
||||
perc = (stats["idle"] - self._cpu_stats.get("idle", 0)) / cputime
|
||||
self._data["cpu.idle.percent"] = perc
|
||||
self._data["cpu.idle.percent"] = int(perc * 100)
|
||||
|
||||
perc = (stats["iowait"] - self._cpu_stats.get("iowait", 0)) / cputime
|
||||
self._data["cpu.iowait.percent"] = perc
|
||||
self._data["cpu.iowait.percent"] = int(perc * 100)
|
||||
|
||||
# Compute the current system-wide CPU utilization as a percentage.
|
||||
used = stats["user"] + stats["kernel"] + stats["iowait"]
|
||||
|
@ -95,6 +98,6 @@ class Monitor(base.CPUMonitorBase):
|
|||
+ self._cpu_stats.get("kernel", 0)
|
||||
+ self._cpu_stats.get("iowait", 0))
|
||||
perc = (used - prev_used) / cputime
|
||||
self._data["cpu.percent"] = perc
|
||||
self._data["cpu.percent"] = int(perc * 100)
|
||||
|
||||
self._cpu_stats = stats.copy()
|
||||
|
|
|
@ -17,6 +17,16 @@ from nova.objects import fields
|
|||
from nova import utils
|
||||
|
||||
|
||||
# NOTE(jwcroppe): Used to determine which fields whose value we need to adjust
|
||||
# (read: divide by 100.0) before sending information to the RPC notifier since
|
||||
# these values were expected to be within the range [0, 1].
|
||||
FIELDS_REQUIRING_CONVERSION = [fields.MonitorMetricType.CPU_USER_PERCENT,
|
||||
fields.MonitorMetricType.CPU_KERNEL_PERCENT,
|
||||
fields.MonitorMetricType.CPU_IDLE_PERCENT,
|
||||
fields.MonitorMetricType.CPU_IOWAIT_PERCENT,
|
||||
fields.MonitorMetricType.CPU_PERCENT]
|
||||
|
||||
|
||||
@base.NovaObjectRegistry.register
|
||||
class MonitorMetric(base.NovaObject):
|
||||
# Version 1.0: Initial version
|
||||
|
@ -54,7 +64,10 @@ class MonitorMetric(base.NovaObject):
|
|||
}
|
||||
|
||||
if self.obj_attr_is_set('value'):
|
||||
dict_to_return['value'] = self.value
|
||||
if self.name in FIELDS_REQUIRING_CONVERSION:
|
||||
dict_to_return['value'] = self.value / 100.0
|
||||
else:
|
||||
dict_to_return['value'] = self.value
|
||||
elif self.obj_attr_is_set('numa_membw_values'):
|
||||
dict_to_return['numa_membw_values'] = self.numa_membw_values
|
||||
|
||||
|
|
|
@ -65,13 +65,8 @@ class VirtDriverCPUMonitorTestCase(test.NoDBTestCase):
|
|||
self.assertEqual(metrics["cpu.kernel.time"], 5664160000000)
|
||||
self.assertEqual(metrics["cpu.idle.time"], 1592705190000000)
|
||||
self.assertEqual(metrics["cpu.iowait.time"], 6121490000000)
|
||||
self.assertTrue(metrics["cpu.user.percent"] <= 1
|
||||
and metrics["cpu.user.percent"] >= 0)
|
||||
self.assertTrue(metrics["cpu.kernel.percent"] <= 1
|
||||
and metrics["cpu.kernel.percent"] >= 0)
|
||||
self.assertTrue(metrics["cpu.idle.percent"] <= 1
|
||||
and metrics["cpu.idle.percent"] >= 0)
|
||||
self.assertTrue(metrics["cpu.iowait.percent"] <= 1
|
||||
and metrics["cpu.iowait.percent"] >= 0)
|
||||
self.assertTrue(metrics["cpu.percent"] <= 1
|
||||
and metrics["cpu.percent"] >= 0)
|
||||
self.assertEqual(metrics["cpu.user.percent"], 1)
|
||||
self.assertEqual(metrics["cpu.kernel.percent"], 0)
|
||||
self.assertEqual(metrics["cpu.idle.percent"], 97)
|
||||
self.assertEqual(metrics["cpu.iowait.percent"], 0)
|
||||
self.assertEqual(metrics["cpu.percent"], 2)
|
||||
|
|
|
@ -25,6 +25,13 @@ _monitor_metric_spec = {
|
|||
'source': 'nova.virt.libvirt.driver'
|
||||
}
|
||||
|
||||
_monitor_metric_perc_spec = {
|
||||
'name': fields.MonitorMetricType.CPU_PERCENT,
|
||||
'value': 0.17,
|
||||
'timestamp': timeutils.strtime(_ts_now),
|
||||
'source': 'nova.virt.libvirt.driver'
|
||||
}
|
||||
|
||||
_monitor_numa_metric_spec = {
|
||||
'name': fields.MonitorMetricType.NUMA_MEM_BW_CURRENT,
|
||||
'numa_membw_values': {"0": 10, "1": 43},
|
||||
|
@ -43,6 +50,14 @@ class _TestMonitorMetricObject(object):
|
|||
source='nova.virt.libvirt.driver')
|
||||
self.assertEqual(_monitor_metric_spec, obj.to_dict())
|
||||
|
||||
def test_monitor_metric_perc_to_dict(self):
|
||||
"""Test to ensure division by 100.0 occurs on percentage value."""
|
||||
obj = objects.MonitorMetric(name='cpu.percent',
|
||||
value=17,
|
||||
timestamp=_ts_now,
|
||||
source='nova.virt.libvirt.driver')
|
||||
self.assertEqual(_monitor_metric_perc_spec, obj.to_dict())
|
||||
|
||||
def test_monitor_metric_list_to_list(self):
|
||||
obj = objects.MonitorMetric(name='cpu.frequency',
|
||||
value=1000,
|
||||
|
|
Loading…
Reference in New Issue