monasca-ceilometer/ceilosca/ceilometer/ceilosca_mapping/ceilometer_static_info_mapp...

187 lines
6.9 KiB
Python

#
# Copyright 2016 Hewlett Packard
#
# 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.
"""Static mapping for Ceilometer static info like unit and type information
"""
import os
import pkg_resources
import yaml
from oslo_config import cfg
from oslo_log import log
from ceilometer.i18n import _LE, _LW
from ceilometer import sample
LOG = log.getLogger(__name__)
OPTS = [
cfg.StrOpt('ceilometer_static_info_mapping',
default='ceilometer_static_info_mapping.yaml',
help='Configuration mapping file to map ceilometer meters to '
'their units an type informaiton'),
]
cfg.CONF.register_opts(OPTS, group='monasca')
class CeilometerStaticMappingDefinitionException(Exception):
def __init__(self, message, definition_cfg):
super(CeilometerStaticMappingDefinitionException,
self).__init__(message)
self.message = message
self.definition_cfg = definition_cfg
def __str__(self):
return '%s %s: %s' % (self.__class__.__name__,
self.definition_cfg, self.message)
class CeilometerStaticMappingDefinition(object):
REQUIRED_FIELDS = ['name', 'type', 'unit']
def __init__(self, definition_cfg):
self.cfg = definition_cfg
missing = [field for field in self.REQUIRED_FIELDS
if not self.cfg.get(field)]
if missing:
raise CeilometerStaticMappingDefinitionException(
_LE("Required fields %s not specified") % missing, self.cfg)
if ('type' not in self.cfg.get('lookup', []) and
self.cfg['type'] not in sample.TYPES):
raise CeilometerStaticMappingDefinitionException(
_LE("Invalid type %s specified") % self.cfg['type'], self.cfg)
def get_config_file():
config_file = cfg.CONF.monasca.ceilometer_static_info_mapping
if not os.path.exists(config_file):
config_file = cfg.CONF.find_file(config_file)
if not config_file:
config_file = pkg_resources.resource_filename(
__name__, "data/ceilometer_static_info_mapping.yaml")
return config_file
def setup_ceilometer_static_mapping_config():
"""Setup the meters definitions from yaml config file."""
config_file = get_config_file()
if config_file is not None:
LOG.debug("Static Ceilometer mapping file to map static info: %s",
config_file)
with open(config_file) as cf:
config = cf.read()
try:
ceilometer_static_mapping_config = yaml.safe_load(config)
except yaml.YAMLError as err:
if hasattr(err, 'problem_mark'):
mark = err.problem_mark
errmsg = (_LE("Invalid YAML syntax in static Ceilometer "
"Mapping Definitions file %(file)s at line: "
"%(line)s, column: %(column)s.")
% dict(file=config_file,
line=mark.line + 1,
column=mark.column + 1))
else:
errmsg = (_LE("YAML error reading static Ceilometer Mapping "
"Definitions file %(file)s") %
dict(file=config_file))
LOG.error(errmsg)
raise
else:
LOG.debug("No static Ceilometer Definitions configuration file "
"found! using default config.")
ceilometer_static_mapping_config = {}
LOG.debug("Ceilometer Monasca Definitions: %s",
ceilometer_static_mapping_config)
return ceilometer_static_mapping_config
def load_definitions(config_def):
if not config_def:
return []
ceilometer_static_mapping_defs = {}
for meter_info_static_map in reversed(config_def['meter_info_static_map']):
if meter_info_static_map.get('name') in ceilometer_static_mapping_defs:
# skip duplicate meters
LOG.warning(_LW("Skipping duplicate Ceilometer Monasca Mapping"
" Definition %s") % meter_info_static_map)
continue
try:
md = CeilometerStaticMappingDefinition(meter_info_static_map)
ceilometer_static_mapping_defs[meter_info_static_map['name']] = md
except CeilometerStaticMappingDefinitionException as me:
errmsg = (_LE("Error loading Ceilometer Static Mapping "
"Definition : %(err)s") % dict(err=me.message))
LOG.error(errmsg)
return ceilometer_static_mapping_defs.values()
class ProcessMappedCeilometerStaticInfo(object):
"""Implentation for class to provide static info for ceilometer meters
The class will be responsible for providing the static information of
ceilometer meters enabled using pipeline.yaml configuration.
get_list_supported_meters: is a get function which can be used to get
list of pipeline meters.
get_ceilometer_meter_static_definition: returns entire definition for
provided meter name
get_meter_static_info_key_val: returns specific value for provided meter
name and a particular key from definition
"""
_inited = False
_instance = None
def __new__(cls, *args, **kwargs):
"""Singleton to avoid duplicated initialization."""
if not cls._instance:
cls._instance = super(ProcessMappedCeilometerStaticInfo, cls).\
__new__(cls, *args, **kwargs)
return cls._instance
def __init__(self):
if not (self._instance and self._inited):
self._inited = True
self.__definitions = load_definitions(
setup_ceilometer_static_mapping_config())
self.__mapped_meter_info_map = dict()
for d in self.__definitions:
self.__mapped_meter_info_map[d.cfg['name']] = d
def get_list_supported_meters(self):
return self.__mapped_meter_info_map
def get_ceilometer_meter_static_definition(self, meter_name):
return self.__mapped_meter_info_map.get(meter_name)
def get_meter_static_info_key_val(self, meter_name, key):
return self.__mapped_meter_info_map.get(meter_name).cfg[key]
def reinitialize(self):
self.__definitions = load_definitions(
setup_ceilometer_static_mapping_config())
self.__mapped_meter_info_map = dict()
for d in self.__definitions:
self.__mapped_meter_info_map[d.cfg['name']] = d