# # Copyright 2013 Intel Corp. # Copyright 2014 Red Hat, Inc # # 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. import fnmatch import os import pkg_resources from oslo_log import log import yaml LOG = log.getLogger(__name__) class ConfigException(Exception): def __init__(self, cfg_type, message, cfg): self.cfg_type = cfg_type self.msg = message self.cfg = cfg def __str__(self): return '%s %s: %s' % (self.cfg_type, self.cfg, self.msg) class SourceException(Exception): def __init__(self, message, cfg): self.msg = message self.cfg = cfg def __str__(self): return 'Source definition invalid: %s (%s)' % (self.msg, self.cfg) class ConfigManagerBase(object): """Base class for managing configuration file refresh""" def __init__(self, conf): self.conf = conf def load_config(self, cfg_file): """Load a configuration file and set its refresh values.""" if os.path.exists(cfg_file): cfg_loc = cfg_file else: cfg_loc = self.conf.find_file(cfg_file) if not cfg_loc: LOG.debug("No pipeline definitions configuration file found! " "Using default config.") cfg_loc = pkg_resources.resource_filename( __name__, 'pipeline/data/' + cfg_file) with open(cfg_loc) as fap: conf = yaml.safe_load(fap) LOG.debug("Config file: %s", conf) return conf class Source(object): """Represents a generic source""" def __init__(self, cfg): self.cfg = cfg try: self.name = cfg['name'] except KeyError as err: raise SourceException( "Required field %s not specified" % err.args[0], cfg) def __str__(self): return self.name def check_source_filtering(self, data, d_type): """Source data rules checking - At least one meaningful datapoint exist - Included type and excluded type can't co-exist on the same pipeline - Included type meter and wildcard can't co-exist at same pipeline """ if not data: raise SourceException('No %s specified' % d_type, self.cfg) if (any(x for x in data if x[0] not in '!*') and any(x for x in data if x[0] == '!')): raise SourceException( 'Both included and excluded %s specified' % d_type, self.cfg) if '*' in data and any(x for x in data if x[0] not in '!*'): raise SourceException( 'Included %s specified with wildcard' % d_type, self.cfg) @staticmethod def is_supported(dataset, data_name): # Support wildcard like storage.* and !disk.* # Start with negation, we consider that the order is deny, allow if any(fnmatch.fnmatch(data_name, datapoint[1:]) for datapoint in dataset if datapoint[0] == '!'): return False if any(fnmatch.fnmatch(data_name, datapoint) for datapoint in dataset if datapoint[0] != '!'): return True # if we only have negation, we suppose the default is allow return all(datapoint.startswith('!') for datapoint in dataset)