deb-gnocchi/gnocchi/indexer/__init__.py

412 lines
13 KiB
Python

# -*- encoding: utf-8 -*-
#
# Copyright © 2014-2015 eNovance
#
# 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 hashlib
import os
import iso8601
from oslo_config import cfg
import six
from six.moves.urllib import parse
from stevedore import driver
from gnocchi import exceptions
OPTS = [
cfg.StrOpt('url',
secret=True,
required=True,
default=os.getenv("GNOCCHI_INDEXER_URL"),
help='Indexer driver to use'),
]
_marker = object()
class Resource(object):
def get_metric(self, metric_name):
for m in self.metrics:
if m.name == metric_name:
return m
def __eq__(self, other):
return (self.id == other.id
and self.type == other.type
and self.revision == other.revision
and self.revision_start == other.revision_start
and self.revision_end == other.revision_end
and self.creator == other.creator
and self.user_id == other.user_id
and self.project_id == other.project_id
and self.started_at == other.started_at
and self.ended_at == other.ended_at)
@property
def etag(self):
etag = hashlib.sha1()
etag.update(six.text_type(self.id).encode('utf-8'))
etag.update(six.text_type(
self.revision_start.isoformat()).encode('utf-8'))
return etag.hexdigest()
@property
def lastmodified(self):
# less precise revision start for Last-Modified http header
return self.revision_start.replace(microsecond=0,
tzinfo=iso8601.iso8601.UTC)
def get_driver(conf):
"""Return the configured driver."""
split = parse.urlsplit(conf.indexer.url)
d = driver.DriverManager('gnocchi.indexer',
split.scheme).driver
return d(conf)
class IndexerException(Exception):
"""Base class for all exceptions raised by an indexer."""
class NoSuchResourceType(IndexerException):
"""Error raised when the resource type is unknown."""
def __init__(self, type):
super(NoSuchResourceType, self).__init__(
"Resource type %s does not exist" % type)
self.type = type
class NoSuchMetric(IndexerException):
"""Error raised when a metric does not exist."""
def __init__(self, metric):
super(NoSuchMetric, self).__init__("Metric %s does not exist" %
metric)
self.metric = metric
class NoSuchResource(IndexerException):
"""Error raised when a resource does not exist."""
def __init__(self, resource):
super(NoSuchResource, self).__init__("Resource %s does not exist" %
resource)
self.resource = resource
class NoSuchArchivePolicy(IndexerException):
"""Error raised when an archive policy does not exist."""
def __init__(self, archive_policy):
super(NoSuchArchivePolicy, self).__init__(
"Archive policy %s does not exist" % archive_policy)
self.archive_policy = archive_policy
class UnsupportedArchivePolicyChange(IndexerException):
"""Error raised when modifying archive policy if not supported."""
def __init__(self, archive_policy, message):
super(UnsupportedArchivePolicyChange, self).__init__(
"Archive policy %s does not support change: %s" %
(archive_policy, message))
self.archive_policy = archive_policy
self.message = message
class ArchivePolicyInUse(IndexerException):
"""Error raised when an archive policy is still being used."""
def __init__(self, archive_policy):
super(ArchivePolicyInUse, self).__init__(
"Archive policy %s is still in use" % archive_policy)
self.archive_policy = archive_policy
class ResourceTypeInUse(IndexerException):
"""Error raised when an resource type is still being used."""
def __init__(self, resource_type):
super(ResourceTypeInUse, self).__init__(
"Resource type %s is still in use" % resource_type)
self.resource_type = resource_type
class UnexpectedResourceTypeState(IndexerException):
"""Error raised when an resource type state is not expected."""
def __init__(self, resource_type, expected_state, state):
super(UnexpectedResourceTypeState, self).__init__(
"Resource type %s state is %s (expected: %s)" % (
resource_type, state, expected_state))
self.resource_type = resource_type
self.expected_state = expected_state
self.state = state
class NoSuchArchivePolicyRule(IndexerException):
"""Error raised when an archive policy rule does not exist."""
def __init__(self, archive_policy_rule):
super(NoSuchArchivePolicyRule, self).__init__(
"Archive policy rule %s does not exist" %
archive_policy_rule)
self.archive_policy_rule = archive_policy_rule
class NoArchivePolicyRuleMatch(IndexerException):
"""Error raised when no archive policy rule found for metric."""
def __init__(self, metric_name):
super(NoArchivePolicyRuleMatch, self).__init__(
"No Archive policy rule found for metric %s" %
metric_name)
self.metric_name = metric_name
class NamedMetricAlreadyExists(IndexerException):
"""Error raised when a named metric already exists."""
def __init__(self, metric):
super(NamedMetricAlreadyExists, self).__init__(
"Named metric %s already exists" % metric)
self.metric = metric
class ResourceAlreadyExists(IndexerException):
"""Error raised when a resource already exists."""
def __init__(self, resource):
super(ResourceAlreadyExists, self).__init__(
"Resource %s already exists" % resource)
self.resource = resource
class ResourceTypeAlreadyExists(IndexerException):
"""Error raised when a resource type already exists."""
def __init__(self, resource_type):
super(ResourceTypeAlreadyExists, self).__init__(
"Resource type %s already exists" % resource_type)
self.resource_type = resource_type
class ResourceAttributeError(IndexerException, AttributeError):
"""Error raised when an attribute does not exist for a resource type."""
def __init__(self, resource, attribute):
super(ResourceAttributeError, self).__init__(
"Resource type %s has no %s attribute" % (resource, attribute))
self.resource = resource
self.attribute = attribute
class ResourceValueError(IndexerException, ValueError):
"""Error raised when an attribute value is invalid for a resource type."""
def __init__(self, resource_type, attribute, value):
super(ResourceValueError, self).__init__(
"Value %s for attribute %s on resource type %s is invalid"
% (value, attribute, resource_type))
self.resource_type = resource_type
self.attribute = attribute
self.value = value
class ArchivePolicyAlreadyExists(IndexerException):
"""Error raised when an archive policy already exists."""
def __init__(self, name):
super(ArchivePolicyAlreadyExists, self).__init__(
"Archive policy %s already exists" % name)
self.name = name
class ArchivePolicyRuleAlreadyExists(IndexerException):
"""Error raised when an archive policy rule already exists."""
def __init__(self, name):
super(ArchivePolicyRuleAlreadyExists, self).__init__(
"Archive policy rule %s already exists" % name)
self.name = name
class QueryError(IndexerException):
def __init__(self):
super(QueryError, self).__init__("Unable to parse this query")
class QueryValueError(QueryError, ValueError):
def __init__(self, v, f):
super(QueryError, self).__init__("Invalid value: `%s' for field `%s'"
% (v, f))
class QueryInvalidOperator(QueryError):
def __init__(self, op):
self.op = op
super(QueryError, self).__init__("Unknown operator `%s'" % op)
class QueryAttributeError(QueryError, ResourceAttributeError):
def __init__(self, resource, attribute):
ResourceAttributeError.__init__(self, resource, attribute)
class InvalidPagination(IndexerException):
"""Error raised when a resource does not exist."""
def __init__(self, reason):
self.reason = reason
super(InvalidPagination, self).__init__(
"Invalid pagination: `%s'" % reason)
class IndexerDriver(object):
@staticmethod
def __init__(conf):
pass
@staticmethod
def connect():
pass
@staticmethod
def disconnect():
pass
@staticmethod
def upgrade(nocreate=False):
pass
@staticmethod
def get_resource(resource_type, resource_id, with_metrics=False):
"""Get a resource from the indexer.
:param resource_type: The type of the resource to look for.
:param resource_id: The UUID of the resource.
:param with_metrics: Whether to include metrics information.
"""
raise exceptions.NotImplementedError
@staticmethod
def list_resources(resource_type='generic',
attribute_filter=None,
details=False,
history=False,
limit=None,
marker=None,
sorts=None):
raise exceptions.NotImplementedError
@staticmethod
def list_archive_policies():
raise exceptions.NotImplementedError
@staticmethod
def get_archive_policy(name):
raise exceptions.NotImplementedError
@staticmethod
def update_archive_policy(name, ap_items):
raise exceptions.NotImplementedError
@staticmethod
def delete_archive_policy(name):
raise exceptions.NotImplementedError
@staticmethod
def get_archive_policy_rule(name):
raise exceptions.NotImplementedError
@staticmethod
def list_archive_policy_rules():
raise exceptions.NotImplementedError
@staticmethod
def create_archive_policy_rule(name, metric_pattern, archive_policy_name):
raise exceptions.NotImplementedError
@staticmethod
def delete_archive_policy_rule(name):
raise exceptions.NotImplementedError
@staticmethod
def create_metric(id, creator,
archive_policy_name, name=None, unit=None,
resource_id=None):
raise exceptions.NotImplementedError
@staticmethod
def list_metrics(names=None, ids=None, details=False, status='active',
limit=None, marker=None, sorts=None, **kwargs):
raise exceptions.NotImplementedError
@staticmethod
def create_archive_policy(archive_policy):
raise exceptions.NotImplementedError
@staticmethod
def create_resource(resource_type, id, creator,
user_id=None, project_id=None,
started_at=None, ended_at=None, metrics=None,
**kwargs):
raise exceptions.NotImplementedError
@staticmethod
def update_resource(resource_type, resource_id, ended_at=_marker,
metrics=_marker,
append_metrics=False,
create_revision=True,
**kwargs):
raise exceptions.NotImplementedError
@staticmethod
def delete_resource(uuid):
raise exceptions.NotImplementedError
@staticmethod
def delete_resources(resource_type='generic',
attribute_filter=None):
raise exceptions.NotImplementedError
@staticmethod
def delete_metric(id):
raise exceptions.NotImplementedError
@staticmethod
def expunge_metric(id):
raise exceptions.NotImplementedError
def get_archive_policy_for_metric(self, metric_name):
"""Helper to get the archive policy according archive policy rules."""
rules = self.list_archive_policy_rules()
for rule in rules:
if fnmatch.fnmatch(metric_name or "", rule.metric_pattern):
return self.get_archive_policy(rule.archive_policy_name)
raise NoArchivePolicyRuleMatch(metric_name)
@staticmethod
def create_resource_type(resource_type):
raise exceptions.NotImplementedError
@staticmethod
def get_resource_type(name):
"""Get a resource type from the indexer.
:param name: name of the resource type
"""
raise exceptions.NotImplementedError
@staticmethod
def list_resource_types(attribute_filter=None,
limit=None,
marker=None,
sorts=None):
raise exceptions.NotImplementedError
@staticmethod
def get_resource_attributes_schemas():
raise exceptions.NotImplementedError
@staticmethod
def get_resource_type_schema():
raise exceptions.NotImplementedError