nova/nova/objects/monitor_metric.py

115 lines
4.6 KiB
Python

# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
from oslo_serialization import jsonutils
from oslo_utils import versionutils
from nova.objects import base
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
# 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 = versionutils.convert_version_to_tuple(target_version)
if target_version < (1, 1) and 'numa_membw_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):
dict_to_return = {
'name': self.name,
# 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': utils.strtime(self.timestamp),
'source': self.source,
}
if self.obj_attr_is_set('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
return dict_to_return
@base.NovaObjectRegistry.register
class MonitorMetricList(base.ObjectListBase, base.NovaObject):
# Version 1.0: Initial version
# Version 1.1: MonitorMetric version 1.1
VERSION = '1.1'
fields = {
'objects': fields.ListOfObjectsField('MonitorMetric'),
}
@classmethod
def from_json(cls, metrics):
"""Converts a legacy json object into a list of MonitorMetric objs
and finally returns of MonitorMetricList
:param metrics: a string of json serialized objects
:returns: a MonitorMetricList Object.
"""
metrics = jsonutils.loads(metrics) if metrics else []
# NOTE(suro-patz): While instantiating the MonitorMetric() from
# JSON-ified string, we need to re-convert the
# normalized metrics to avoid truncation to 0 by
# typecasting into an integer.
metric_list = []
for metric in metrics:
if ('value' in metric and metric['name'] in
FIELDS_REQUIRING_CONVERSION):
metric['value'] = metric['value'] * 100
metric_list.append(MonitorMetric(**metric))
return MonitorMetricList(objects=metric_list)
# NOTE(jaypipes): This method exists to convert the object to the
# format expected by the RPC notifier for metrics events.
def to_list(self):
return [m.to_dict() for m in self.objects]