diff --git a/nova/objects/fields.py b/nova/objects/fields.py index ff2b7ab7ed35..515159e7f87e 100644 --- a/nova/objects/fields.py +++ b/nova/objects/fields.py @@ -344,6 +344,8 @@ class MonitorMetricType(Enum): CPU_IDLE_PERCENT = "cpu.idle.percent" CPU_IOWAIT_PERCENT = "cpu.iowait.percent" CPU_PERCENT = "cpu.percent" + NUMA_MEM_BW_MAX = "numa.membw.max" + NUMA_MEM_BW_CURRENT = "numa.membw.current" ALL = ( CPU_FREQUENCY, @@ -356,6 +358,8 @@ class MonitorMetricType(Enum): CPU_IDLE_PERCENT, CPU_IOWAIT_PERCENT, CPU_PERCENT, + NUMA_MEM_BW_MAX, + NUMA_MEM_BW_CURRENT, ) def __init__(self): diff --git a/nova/objects/monitor_metric.py b/nova/objects/monitor_metric.py index 22a86dcd771e..0e5fdbab11d0 100644 --- a/nova/objects/monitor_metric.py +++ b/nova/objects/monitor_metric.py @@ -14,46 +14,65 @@ from oslo_utils import timeutils from nova.objects import base from nova.objects import fields +from nova import utils @base.NovaObjectRegistry.register class MonitorMetric(base.NovaObject): # Version 1.0: Initial version - VERSION = '1.0' + # Version 1.1: Added NUMA support + + VERSION = '1.1' fields = { 'name': fields.MonitorMetricTypeField(nullable=False), 'value': fields.IntegerField(nullable=False), + 'numa_membw_values': fields.DictOfIntegersField(nullable=True), 'timestamp': fields.DateTimeField(nullable=False), # This will be the stevedore extension full class name # for the plugin from which the metric originates. 'source': fields.StringField(nullable=False), } + def obj_make_compatible(self, primitive, target_version): + super(MonitorMetric, self).obj_make_compatible(primitive, + target_version) + target_version = utils.convert_version_to_tuple(target_version) + if target_version < (1, 1) and 'numa_nodes_values' in primitive: + del primitive['numa_membw_values'] + # NOTE(jaypipes): This method exists to convert the object to the # format expected by the RPC notifier for metrics events. def to_dict(self): - return { + dict_to_return = { 'name': self.name, - 'value': self.value, # NOTE(jaypipes): This is what jsonutils.dumps() does to # datetime.datetime objects, which is what timestamp is in # this object as well as the original simple dict metrics 'timestamp': timeutils.strtime(self.timestamp), - 'source': self.source + 'source': self.source, } + if self.obj_attr_is_set('value'): + 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 + + return dict_to_return + @base.NovaObjectRegistry.register class MonitorMetricList(base.ObjectListBase, base.NovaObject): # Version 1.0: Initial version - VERSION = '1.0' + # Version 1.1: MonitorMetric version 1.1 + VERSION = '1.1' fields = { 'objects': fields.ListOfObjectsField('MonitorMetric'), } child_versions = { '1.0': '1.0', + '1.1': '1.1', } # NOTE(jaypipes): This method exists to convert the object to the diff --git a/nova/tests/unit/objects/test_monitor_metric.py b/nova/tests/unit/objects/test_monitor_metric.py index ca41ab2a11f9..2e9d9fbc2d08 100644 --- a/nova/tests/unit/objects/test_monitor_metric.py +++ b/nova/tests/unit/objects/test_monitor_metric.py @@ -25,6 +25,13 @@ _monitor_metric_spec = { 'source': 'nova.virt.libvirt.driver' } +_monitor_numa_metric_spec = { + 'name': fields.MonitorMetricType.NUMA_MEM_BW_CURRENT, + 'numa_membw_values': {"0": 10, "1": 43}, + 'timestamp': timeutils.strtime(_ts_now), + 'source': 'nova.virt.libvirt.driver' +} + _monitor_metric_list_spec = [_monitor_metric_spec] @@ -44,6 +51,13 @@ class _TestMonitorMetricObject(object): list_obj = objects.MonitorMetricList(objects=[obj]) self.assertEqual(_monitor_metric_list_spec, list_obj.to_list()) + def test_monitor_NUMA_metric_to_dict(self): + obj = objects.MonitorMetric(name='numa.membw.current', + numa_membw_values={"0": 10, "1": 43}, + timestamp=_ts_now, + source='nova.virt.libvirt.driver') + self.assertEqual(_monitor_numa_metric_spec, obj.to_dict()) + class TestMonitorMetricObject(test_objects._LocalTest, _TestMonitorMetricObject): diff --git a/nova/tests/unit/objects/test_objects.py b/nova/tests/unit/objects/test_objects.py index 41b3a257c274..5113c104c94b 100644 --- a/nova/tests/unit/objects/test_objects.py +++ b/nova/tests/unit/objects/test_objects.py @@ -1132,8 +1132,8 @@ object_data = { 'KeyPairList': '1.2-60f984184dc5a8eba6e34e20cbabef04', 'Migration': '1.2-8784125bedcea0a9227318511904e853', 'MigrationList': '1.2-5e79c0693d7ebe4e9ac03b5db11ab243', - 'MonitorMetric': '1.0-4fe7f3fb1777567883ac842120ec5800', - 'MonitorMetricList': '1.0-1b54e51ad0fc1f3a8878f5010e7e16dc', + 'MonitorMetric': '1.1-53b1db7c4ae2c531db79761e7acc52ba', + 'MonitorMetricList': '1.1-ea2a8e1c1ecf3608af2956e657adeb4c', 'NUMACell': '1.2-74fc993ac5c83005e76e34e8487f1c05', 'NUMAPagesTopology': '1.0-c71d86317283266dc8364c149155e48e', 'NUMATopology': '1.2-c63fad38be73b6afd04715c9c1b29220', @@ -1207,7 +1207,7 @@ object_relationships = { 'InstancePCIRequests': {'InstancePCIRequest': '1.1'}, 'KeyPairList': {'KeyPair': '1.3'}, 'MigrationList': {'Migration': '1.2'}, - 'MonitorMetricList': {'MonitorMetric': '1.0'}, + 'MonitorMetricList': {'MonitorMetric': '1.1'}, 'NetworkList': {'Network': '1.2'}, 'NetworkRequestList': {'NetworkRequest': '1.1'}, 'NUMACell': {'NUMAPagesTopology': '1.0'},