412 lines
13 KiB
Python
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
|