Deleting ceilometer from the repository
-remove Collectd_Ceilometer folder -remove Ceilometer specific unit tests -Remove mentions in devstack, doc, and etc folders -Substitute refereces of Ceilometer with Gnocchi/Aodh Closes-Bug: #1710855 Change-Id: I210ca8182c489c4f90a6521b1b7fd6f8a391e602 Signed-off-by: Elizabeth Burke <elizabeth.burke@intel.com>
This commit is contained in:
parent
f86c539aaf
commit
d256ab054a
10
README.rst
10
README.rst
@ -24,10 +24,10 @@
|
||||
collectd-ceilometer-plugin
|
||||
==========================
|
||||
|
||||
Collectd plugins for publishing to OpenStack (Ceilometer, Gnocchi and Aodh).
|
||||
Collectd plugins for publishing to OpenStack (Gnocchi and Aodh).
|
||||
|
||||
This repositiory contains collectd plugins for publishing telemetry data
|
||||
(metrics and events) gathered by collectd to Ceilometer, Gnocchi and Aodh.
|
||||
(metrics and events) gathered by collectd to Gnocchi and Aodh.
|
||||
This allows a more comprehensive set of platform telemetry to be made available
|
||||
to OpenStack which enables service assurance, fault management and monitoring.
|
||||
|
||||
@ -48,9 +48,6 @@ The following are links to background information, collateral and references
|
||||
to provide a clearer view on the need for this plugin, what it does and how it
|
||||
works:
|
||||
|
||||
* An overview of Ceilometer and its architecture:
|
||||
http://docs.openstack.org/developer/ceilometer/overview.html
|
||||
http://docs.openstack.org/developer/ceilometer/architecture.html
|
||||
* Official collectd website:
|
||||
https://collectd.org/
|
||||
* Information on how collectd is enabled for Openstack:
|
||||
@ -61,9 +58,6 @@ works:
|
||||
Features
|
||||
--------
|
||||
|
||||
* Ceilometer plugin (for collectd)
|
||||
** Converts from collectd data sources to Ceilometer format
|
||||
** Adds units for Ceilometer
|
||||
* Gnocchi plugin (for collectd)
|
||||
** Store collectd metrics in Gnocchi
|
||||
* Aodh plugin (for collectd)
|
||||
|
@ -1,83 +0,0 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# 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.
|
||||
"""Ceilometer collectd plugin"""
|
||||
|
||||
import logging
|
||||
|
||||
try:
|
||||
# pylint: disable=import-error
|
||||
import collectd
|
||||
# pylint: enable=import-error
|
||||
except ImportError:
|
||||
collectd = None # when running unit tests collectd is not avaliable
|
||||
|
||||
import collectd_ceilometer
|
||||
from collectd_ceilometer.ceilometer.writer import Writer
|
||||
from collectd_ceilometer.common.logger import CollectdLogHandler
|
||||
from collectd_ceilometer.common.meters import MeterStorage
|
||||
from collectd_ceilometer.common.settings import Config
|
||||
|
||||
|
||||
LOGGER = logging.getLogger(__name__)
|
||||
ROOT_LOGGER = logging.getLogger(collectd_ceilometer.__name__)
|
||||
|
||||
|
||||
def register_plugin(collectd):
|
||||
"Bind plugin hooks to collectd and viceversa"
|
||||
|
||||
config = Config.instance()
|
||||
|
||||
# Setup loggging
|
||||
log_handler = CollectdLogHandler(collectd=collectd, config=config)
|
||||
ROOT_LOGGER.addHandler(log_handler)
|
||||
ROOT_LOGGER.setLevel(logging.DEBUG)
|
||||
|
||||
# Creates collectd plugin instance
|
||||
instance = Plugin(collectd=collectd, config=config)
|
||||
|
||||
# Register plugin callbacks
|
||||
collectd.register_config(instance.config)
|
||||
collectd.register_write(instance.write)
|
||||
collectd.register_shutdown(instance.shutdown)
|
||||
|
||||
|
||||
class Plugin(object):
|
||||
"""Ceilometer plugin with collectd callbacks"""
|
||||
# NOTE: this is multithreaded class
|
||||
|
||||
def __init__(self, collectd, config):
|
||||
self._config = config
|
||||
self._meters = MeterStorage(collectd=collectd)
|
||||
self._writer = Writer(self._meters, config=config)
|
||||
|
||||
def config(self, cfg):
|
||||
"""Configuration callback
|
||||
|
||||
@param cfg configuration node provided by collectd
|
||||
"""
|
||||
|
||||
self._config.read(cfg)
|
||||
|
||||
def write(self, vl, data=None):
|
||||
"""Collectd write callback"""
|
||||
self._writer.write(vl, data)
|
||||
|
||||
def shutdown(self):
|
||||
"""Shutdown callback"""
|
||||
LOGGER.info("SHUTDOWN")
|
||||
self._writer.flush()
|
||||
|
||||
|
||||
if collectd:
|
||||
register_plugin(collectd=collectd)
|
@ -1,50 +0,0 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# 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.
|
||||
"""Ceilometer collectd plugin implementation"""
|
||||
|
||||
from __future__ import division
|
||||
from __future__ import unicode_literals
|
||||
|
||||
import logging
|
||||
|
||||
from collectd_ceilometer.common import sender as common_sender
|
||||
from collectd_ceilometer.common.settings import Config
|
||||
|
||||
|
||||
LOGGER = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class Sender(common_sender.Sender):
|
||||
"""Sends the JSON serialized data to Ceilometer"""
|
||||
|
||||
def __init__(self):
|
||||
"""Create the Sender instance
|
||||
|
||||
The cofinguration must be initialized before the object is created.
|
||||
"""
|
||||
super(Sender, self).__init__()
|
||||
|
||||
def _on_authenticated(self):
|
||||
endpoint = self._keystone.get_service_endpoint(
|
||||
"ceilometer",
|
||||
Config.instance().CEILOMETER_URL_TYPE)
|
||||
|
||||
self._url_base = "{}/v2/meters/%s".format(endpoint)
|
||||
pass
|
||||
|
||||
def _create_request_url(self, metername, **kwargs):
|
||||
return self._url_base % metername
|
||||
|
||||
def _handle_http_error(self, exc, metername, payload, auth_token, **kwargs):
|
||||
raise exc
|
@ -1,111 +0,0 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# 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.
|
||||
"""Ceilometer collectd plugin implementation"""
|
||||
|
||||
from __future__ import unicode_literals
|
||||
|
||||
from collectd_ceilometer.ceilometer import sender as ceilometer_sender
|
||||
from collectd_ceilometer.common.meters.storage import SampleContainer
|
||||
from collections import namedtuple
|
||||
import json
|
||||
import logging
|
||||
import six
|
||||
import time
|
||||
|
||||
LOGGER = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class Sample(namedtuple('Sample', ['value', 'timestamp', 'meta',
|
||||
'resource_id', 'unit',
|
||||
'metername', 'sample_type'])):
|
||||
"""Sample data"""
|
||||
|
||||
def to_payload(self):
|
||||
"""Return a payload dictionary"""
|
||||
return {
|
||||
'counter_name': self.metername,
|
||||
'counter_type': self.sample_type,
|
||||
'counter_unit': self.unit,
|
||||
'counter_volume': self.value,
|
||||
'timestamp': self.timestamp,
|
||||
'resource_metadata': self.meta,
|
||||
'source': 'collectd',
|
||||
'resource_id': self.resource_id,
|
||||
}
|
||||
|
||||
|
||||
class Writer(object):
|
||||
"""Data collector"""
|
||||
|
||||
def __init__(self, meters, config):
|
||||
self._meters = meters
|
||||
self._samples = SampleContainer()
|
||||
self._sender = ceilometer_sender.Sender()
|
||||
self._config = config
|
||||
|
||||
def write(self, vl, data):
|
||||
"""Collect data from collectd
|
||||
|
||||
example of vl: collectd.Values(type='vmpage_action',
|
||||
type_instance='interleave_hit',plugin='numa',plugin_instance='node0',
|
||||
host='localhost',time=1443092594.625033,interval=10.0,values=[21383])
|
||||
"""
|
||||
|
||||
# take the plugin (specialized or default) for parsing the data
|
||||
plugin = self._meters.get(vl.plugin)
|
||||
# prepare all data related to the sample
|
||||
resource_id = plugin.resource_id(vl)
|
||||
metername = plugin.meter_name(vl)
|
||||
unit = plugin.unit(vl)
|
||||
timestamp = time.asctime(time.gmtime(vl.time))
|
||||
sample_type = plugin.sample_type(vl)
|
||||
|
||||
LOGGER.debug(
|
||||
'Writing: plugin="%s", metername="%s", unit="%s", type="%s"',
|
||||
vl.plugin, metername, unit, sample_type)
|
||||
|
||||
# store sample for every value
|
||||
data = [
|
||||
Sample(
|
||||
value=value, timestamp=timestamp, meta=vl.meta,
|
||||
resource_id=resource_id, unit=unit,
|
||||
metername=metername, sample_type=sample_type)
|
||||
for value in vl.values
|
||||
]
|
||||
|
||||
# add data to cache and get the samples to send
|
||||
to_send = self._samples.add(metername, data, self._config.BATCH_SIZE)
|
||||
if to_send:
|
||||
self._send_data(metername, to_send)
|
||||
|
||||
def flush(self):
|
||||
"""Flush all pending samples"""
|
||||
|
||||
# get all stored samples
|
||||
to_send = self._samples.reset()
|
||||
|
||||
# send all cached samples
|
||||
for key, samples in six.iteritems(to_send):
|
||||
if samples:
|
||||
self._send_data(key, samples)
|
||||
|
||||
def _send_data(self, metername, to_send):
|
||||
"""Send data to ceilometer"""
|
||||
|
||||
LOGGER.debug('Sending %d samples of %s',
|
||||
len(to_send), metername)
|
||||
|
||||
# ceilometer samples
|
||||
payload = json.dumps([sample.to_payload() for sample in to_send])
|
||||
self._sender.send(metername, payload)
|
@ -43,7 +43,7 @@ def get_status_name(status_code):
|
||||
|
||||
|
||||
class Sender(object):
|
||||
"""Sends the JSON serialized data to Ceilometer"""
|
||||
"""Sends the JSON serialized data to Gnocchi/Aodh"""
|
||||
|
||||
HTTP_CREATED = requests.codes['CREATED']
|
||||
HTTP_UNAUTHORIZED = requests.codes['UNAUTHORIZED']
|
||||
@ -124,7 +124,7 @@ class Sender(object):
|
||||
raise exc
|
||||
|
||||
def send(self, metername, payload, **kwargs):
|
||||
"""Send the payload to Ceilometer/Gnocchi/Aodh"""
|
||||
"""Send the payload to Gnocchi/Aodh"""
|
||||
|
||||
# get the auth_token
|
||||
auth_token = self._authenticate()
|
||||
|
@ -98,7 +98,7 @@ class Config(object):
|
||||
error = True
|
||||
if error:
|
||||
LOGGER.error(
|
||||
'Collectd plugin for Ceilometer will not work properly')
|
||||
'Collectd plugin will not work properly')
|
||||
else:
|
||||
LOGGER.info('Configuration OK')
|
||||
|
||||
|
@ -1,508 +0,0 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# Copyright 2010-2011 OpenStack Foundation
|
||||
# Copyright (c) 2015 Intel Corporation.
|
||||
#
|
||||
# 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.
|
||||
"""Plugin tests
|
||||
|
||||
"""
|
||||
|
||||
from collections import namedtuple
|
||||
|
||||
import logging
|
||||
import mock
|
||||
import requests
|
||||
import unittest
|
||||
|
||||
from collectd_ceilometer.ceilometer import plugin
|
||||
from collectd_ceilometer.common import keystone_light
|
||||
from collectd_ceilometer.common import sender as common_sender
|
||||
from collectd_ceilometer.tests import match
|
||||
|
||||
|
||||
Logger = logging.getLoggerClass()
|
||||
|
||||
|
||||
def mock_collectd(**kwargs):
|
||||
"Returns collecd module with collecd logging hooks."
|
||||
return mock.patch(
|
||||
__name__ + '.' + MockedCollectd.__name__, specs=True,
|
||||
get_dataset=mock.MagicMock(side_effect=Exception), **kwargs)
|
||||
|
||||
|
||||
class MockedCollectd(object):
|
||||
"Mocked collectd module specifications."
|
||||
|
||||
def debug(self, record):
|
||||
"Hook for debug messages"
|
||||
|
||||
def info(self, record):
|
||||
"Hook for info messages"
|
||||
|
||||
def warning(self, record):
|
||||
"Hook for warning messages"
|
||||
|
||||
def error(self, record):
|
||||
"Hook for error messages"
|
||||
|
||||
def register_init(self, hook):
|
||||
"Register an hook for init."
|
||||
|
||||
def register_config(self, hook):
|
||||
"Register an hook for config."
|
||||
|
||||
def register_write(self, hook):
|
||||
"Register an hook for write."
|
||||
|
||||
def register_shutdown(self, hook):
|
||||
"Register an hook for shutdown."
|
||||
|
||||
def get_dataset(self, s):
|
||||
"Gets a dataset."
|
||||
|
||||
|
||||
def mock_config(BATCH_SIZE=1, **kwargs):
|
||||
"Returns collecd module with collecd logging hooks."
|
||||
return mock.patch(
|
||||
__name__ + '.' + MockedConfig.__name__, specs=True,
|
||||
BATCH_SIZE=BATCH_SIZE, **kwargs)
|
||||
|
||||
|
||||
class MockedConfig(object):
|
||||
"Mocked config class."
|
||||
|
||||
BATCH_SIZE = 1
|
||||
OS_AUTH_URL = "http://test-url"
|
||||
|
||||
|
||||
def mock_value(
|
||||
host='localhost', plugin='cpu', plugin_instance='0',
|
||||
_type='freq', type_instance=None, time=123456789, values=(1234,),
|
||||
**kwargs):
|
||||
"""Create a mock value"""
|
||||
|
||||
return mock.patch(
|
||||
__name__ + '.' + MockedValue.__name__, specs=True,
|
||||
host=host, plugin=plugin, plugin_instance=plugin_instance, type=_type,
|
||||
type_instance=type_instance, time=time, values=list(values), meta=None,
|
||||
**kwargs)
|
||||
|
||||
|
||||
class MockedValue(object):
|
||||
"""Value used for testing"""
|
||||
|
||||
host = 'localhost'
|
||||
plugin = None
|
||||
plugin_instance = None
|
||||
type = None
|
||||
type_instance = None
|
||||
time = 123456789
|
||||
values = []
|
||||
meta = None
|
||||
|
||||
|
||||
class TestPlugin(unittest.TestCase):
|
||||
"""Test the collectd plugin"""
|
||||
|
||||
@mock.patch.object(plugin, 'Plugin', autospec=True)
|
||||
@mock.patch.object(plugin, 'Config', autospec=True)
|
||||
@mock.patch.object(plugin, 'CollectdLogHandler', autospec=True)
|
||||
@mock.patch.object(plugin, 'ROOT_LOGGER', autospec=True)
|
||||
@mock_collectd()
|
||||
def test_callbacks(
|
||||
self, collectd, ROOT_LOGGER, CollectdLogHandler, Config, Plugin):
|
||||
"""Verify that the callbacks are registered properly"""
|
||||
|
||||
# When plugin function is called
|
||||
plugin.register_plugin(collectd=collectd)
|
||||
|
||||
# Logger handler is set up
|
||||
ROOT_LOGGER.addHandler.assert_called_once_with(
|
||||
CollectdLogHandler.return_value)
|
||||
ROOT_LOGGER.setLevel.assert_called_once_with(logging.DEBUG)
|
||||
|
||||
# It create a plugin
|
||||
Plugin.assert_called_once_with(
|
||||
collectd=collectd, config=Config.instance.return_value)
|
||||
|
||||
# callbacks are registered to collectd
|
||||
instance = Plugin.return_value
|
||||
collectd.register_config.assert_called_once_with(instance.config)
|
||||
collectd.register_write.assert_called_once_with(instance.write)
|
||||
collectd.register_shutdown.assert_called_once_with(instance.shutdown)
|
||||
|
||||
@mock.patch.object(requests, 'post', spec=callable)
|
||||
@mock.patch.object(common_sender, 'ClientV3', autospec=True)
|
||||
@mock_collectd()
|
||||
@mock_config(BATCH_SIZE=2)
|
||||
@mock_value()
|
||||
def test_write(self, data, config, collectd, ClientV3, post):
|
||||
"""Test collectd data writing"""
|
||||
|
||||
auth_client = ClientV3.return_value
|
||||
auth_client.get_service_endpoint.return_value =\
|
||||
'https://test-ceilometer.tld'
|
||||
|
||||
post.return_value.status_code = common_sender.Sender.HTTP_CREATED
|
||||
post.return_value.text = 'Created'
|
||||
|
||||
# init instance
|
||||
instance = plugin.Plugin(collectd=collectd, config=config)
|
||||
|
||||
# no authentication has been performed so far
|
||||
ClientV3.assert_not_called()
|
||||
|
||||
# write first value
|
||||
instance.write(data)
|
||||
collectd.error.assert_not_called()
|
||||
|
||||
# no value has been sent to ceilometer
|
||||
post.assert_not_called()
|
||||
|
||||
# send the second value
|
||||
instance.write(data)
|
||||
collectd.error.assert_not_called()
|
||||
|
||||
# authentication client has been created
|
||||
ClientV3.assert_called_once()
|
||||
|
||||
# and values has been sent
|
||||
post.assert_called_once_with(
|
||||
'https://test-ceilometer.tld/v2/meters/cpu.freq',
|
||||
data=match.json([
|
||||
{"source": "collectd",
|
||||
"counter_name": "cpu.freq",
|
||||
"counter_unit": "jiffies",
|
||||
"counter_volume": 1234,
|
||||
"timestamp": "Thu Nov 29 21:33:09 1973",
|
||||
"resource_id": "localhost-0",
|
||||
"resource_metadata": None,
|
||||
"counter_type": "gauge"},
|
||||
{"source": "collectd",
|
||||
"counter_name": "cpu.freq",
|
||||
"counter_unit": "jiffies",
|
||||
"counter_volume": 1234,
|
||||
"timestamp": "Thu Nov 29 21:33:09 1973",
|
||||
"resource_id": "localhost-0",
|
||||
"resource_metadata": None,
|
||||
"counter_type": "gauge"}]),
|
||||
headers={'Content-type': 'application/json',
|
||||
'X-Auth-Token': auth_client.auth_token},
|
||||
timeout=1.0)
|
||||
|
||||
# reset post method
|
||||
post.reset_mock()
|
||||
|
||||
# write another values
|
||||
instance.write(data)
|
||||
collectd.error.assert_not_called()
|
||||
|
||||
# nothing has been sent
|
||||
post.assert_not_called()
|
||||
|
||||
# call shutdown
|
||||
instance.shutdown()
|
||||
|
||||
# no errors
|
||||
collectd.error.assert_not_called()
|
||||
|
||||
# previously written value has been sent
|
||||
post.assert_called_once_with(
|
||||
'https://test-ceilometer.tld/v2/meters/cpu.freq',
|
||||
data=match.json([
|
||||
{"source": "collectd",
|
||||
"counter_name": "cpu.freq",
|
||||
"counter_unit": "jiffies",
|
||||
"counter_volume": 1234,
|
||||
"timestamp": "Thu Nov 29 21:33:09 1973",
|
||||
"resource_id": "localhost-0",
|
||||
"resource_metadata": None,
|
||||
"counter_type": "gauge"}]),
|
||||
headers={
|
||||
'Content-type': 'application/json',
|
||||
'X-Auth-Token': auth_client.auth_token},
|
||||
timeout=1.0)
|
||||
|
||||
@mock.patch.object(requests, 'post', spec=callable)
|
||||
@mock.patch.object(common_sender, 'ClientV3', autospec=True)
|
||||
@mock.patch.object(plugin, 'LOGGER', autospec=True)
|
||||
@mock_collectd()
|
||||
@mock_config()
|
||||
@mock_value()
|
||||
def test_write_auth_failed(
|
||||
self, data, config, collectd, LOGGER, ClientV3, post):
|
||||
"""Test authentication failure"""
|
||||
|
||||
ClientV3.auth_url = "http://tst-url"
|
||||
# tell the auth client to rise an exception
|
||||
ClientV3.side_effect = RuntimeError('Test Client() exception')
|
||||
|
||||
# init instance
|
||||
instance = plugin.Plugin(collectd=collectd, config=config)
|
||||
|
||||
# write the value
|
||||
self.assertRaises(RuntimeError, instance.write, data)
|
||||
|
||||
# no requests method has been called
|
||||
post.assert_not_called()
|
||||
|
||||
@mock.patch.object(requests, 'post', spec=callable)
|
||||
@mock.patch.object(common_sender, 'ClientV3', autospec=True)
|
||||
@mock.patch.object(common_sender, 'LOGGER', autospec=True)
|
||||
@mock_collectd()
|
||||
@mock_config()
|
||||
@mock_value()
|
||||
def test_write_auth_failed2(
|
||||
self, data, config, collectd, LOGGER, ClientV3, post):
|
||||
"""Test authentication failure2"""
|
||||
|
||||
ClientV3.side_effect = keystone_light.KeystoneException(
|
||||
"Missing name 'xxx' in received services",
|
||||
"exception",
|
||||
"services list")
|
||||
|
||||
# init instance
|
||||
instance = plugin.Plugin(collectd=collectd, config=config)
|
||||
|
||||
# write the value
|
||||
instance.write(data)
|
||||
|
||||
LOGGER.error.assert_called_once_with(
|
||||
"Suspending error logs until successful auth")
|
||||
LOGGER.log.assert_called_once_with(
|
||||
logging.ERROR, "Authentication error: %s",
|
||||
"Missing name 'xxx' in received services\nReason: exception",
|
||||
exc_info=0)
|
||||
|
||||
# no requests method has been called
|
||||
post.assert_not_called()
|
||||
|
||||
@mock.patch.object(requests, 'post', spec=callable)
|
||||
@mock.patch.object(common_sender, 'ClientV3', autospec=True)
|
||||
@mock_collectd()
|
||||
@mock_config()
|
||||
@mock_value()
|
||||
def test_request_error(
|
||||
self, data, config, collectd, ClientV3, post):
|
||||
"""Test error raised by underlying requests module"""
|
||||
|
||||
# tell POST request to raise an exception
|
||||
post.side_effect = requests.RequestException('Test POST exception')
|
||||
|
||||
# init instance
|
||||
instance = plugin.Plugin(collectd=collectd, config=config)
|
||||
|
||||
# write the value
|
||||
self.assertRaises(requests.RequestException, instance.write, data)
|
||||
|
||||
@mock.patch.object(common_sender.Sender, '_perform_request', spec=callable)
|
||||
@mock.patch.object(requests, 'post', spec=callable)
|
||||
@mock.patch.object(common_sender, 'ClientV3', autospec=True)
|
||||
@mock_collectd()
|
||||
@mock_config()
|
||||
@mock_value()
|
||||
def test_reauthentication(self, data, config, collectd,
|
||||
ClientV3, post, perf_req):
|
||||
"""Test re-authentication"""
|
||||
|
||||
# response returned on success
|
||||
response_ok = requests.Response()
|
||||
response_ok.status_code = requests.codes["OK"]
|
||||
|
||||
# response returned on failure
|
||||
response_unauthorized = requests.Response()
|
||||
response_unauthorized.status_code = requests.codes["UNAUTHORIZED"]
|
||||
|
||||
# write the first value with success
|
||||
# subsequent call of POST method will fail due to the authentication
|
||||
perf_req.return_value = response_ok
|
||||
|
||||
client = ClientV3.return_value
|
||||
client.auth_url = "http://tst-url"
|
||||
client.auth_token = 'Test auth token'
|
||||
|
||||
# init instance
|
||||
instance = plugin.Plugin(collectd=collectd, config=config)
|
||||
|
||||
# write the value
|
||||
instance.write(data)
|
||||
|
||||
# verify the auth token
|
||||
perf_req.assert_called_once_with(
|
||||
mock.ANY, mock.ANY,
|
||||
'Test auth token')
|
||||
|
||||
# set a new auth token
|
||||
client.auth_token = 'New test auth token'
|
||||
perf_req.side_effect = \
|
||||
[requests.exceptions.HTTPError(response=response_unauthorized),
|
||||
response_ok]
|
||||
|
||||
# write the value
|
||||
instance.write(data)
|
||||
|
||||
# verify the auth token
|
||||
perf_req.assert_has_calls([
|
||||
mock.call(mock.ANY, mock.ANY,
|
||||
'Test auth token'),
|
||||
mock.call(mock.ANY, mock.ANY,
|
||||
'New test auth token')
|
||||
])
|
||||
|
||||
@mock.patch.object(requests, 'post', spec=callable)
|
||||
@mock.patch.object(common_sender, 'ClientV3', autospec=True)
|
||||
@mock.patch.object(plugin, 'LOGGER', autospec=True)
|
||||
@mock_collectd()
|
||||
@mock_config()
|
||||
@mock_value()
|
||||
def test_authentication_in_multiple_threads(
|
||||
self, data, config, collectd, LOGGER, ClientV3, post):
|
||||
"""Test authentication in muliple threads
|
||||
|
||||
This test simulates the authentication performed from different thread
|
||||
after the authentication lock has been acquired. The sender is not
|
||||
authenticated, the lock is acquired, the authentication token exists
|
||||
(i.e. it has been set by different thread) and it is used.
|
||||
"""
|
||||
# pylint: disable=protected-access
|
||||
|
||||
# init instance
|
||||
instance = plugin.Plugin(collectd=collectd, config=config)
|
||||
|
||||
# the sender used by the instance
|
||||
sender = instance._writer._sender
|
||||
|
||||
# create a dummy lock
|
||||
class DummyLock(namedtuple('LockBase', ['sender', 'token', 'urlbase'])):
|
||||
"""Lock simulation, which sets the auth token when locked"""
|
||||
|
||||
def __enter__(self, *args, **kwargs):
|
||||
# pylint: disable=protected-access
|
||||
self.sender._auth_token = self.token
|
||||
self.sender._url_base = self.urlbase
|
||||
|
||||
def __exit__(self, *args, **kwargs):
|
||||
pass
|
||||
|
||||
# replace the sender's lock by the dummy lock
|
||||
sender._auth_lock = DummyLock(sender, 'TOKEN', 'URLBASE/%s')
|
||||
|
||||
# write the value
|
||||
instance.write(data)
|
||||
|
||||
# No errors has been registered
|
||||
LOGGER.exception.assert_not_called()
|
||||
|
||||
# client has not been called at all
|
||||
ClientV3.assert_not_called()
|
||||
|
||||
# verify the auth token
|
||||
post.assert_called_once_with(
|
||||
'URLBASE/cpu.freq', data=mock.ANY,
|
||||
headers={
|
||||
'Content-type': 'application/json', 'X-Auth-Token': 'TOKEN'},
|
||||
timeout=1.0)
|
||||
|
||||
@mock.patch.object(requests, 'post', spec=callable)
|
||||
@mock.patch.object(common_sender, 'ClientV3', autospec=True)
|
||||
@mock.patch.object(plugin, 'Writer', autospec=True)
|
||||
@mock.patch.object(plugin, 'LOGGER', autospec=True)
|
||||
@mock_collectd()
|
||||
@mock_config()
|
||||
@mock_value()
|
||||
def test_exceptions(
|
||||
self, data, config, collectd, LOGGER, Writer, ClientV3, post):
|
||||
"""Test exception raised during write and shutdown"""
|
||||
|
||||
writer = Writer.return_value
|
||||
writer.write.side_effect = ValueError('Test write error')
|
||||
writer.flush.side_effect = RuntimeError('Test shutdown error')
|
||||
|
||||
# init instance
|
||||
instance = plugin.Plugin(collectd=collectd, config=config)
|
||||
|
||||
self.assertRaises(ValueError, instance.write, data)
|
||||
self.assertRaises(RuntimeError, instance.shutdown)
|
||||
|
||||
@mock.patch.object(plugin, 'ROOT_LOGGER', new_callable=Logger, name='me')
|
||||
@mock_collectd()
|
||||
def test_log_debug_to_collectd(self, collectd, ROOT_LOGGER):
|
||||
"""Verify that debug messages are sent to collectd."""
|
||||
|
||||
plugin.register_plugin(collectd=collectd)
|
||||
|
||||
# When log messages are produced
|
||||
ROOT_LOGGER.debug('some %s', 'noise')
|
||||
|
||||
# When plugin function is called
|
||||
collectd.debug.assert_called_once_with('some noise')
|
||||
|
||||
@mock.patch.object(plugin, 'ROOT_LOGGER', new_callable=Logger, name='me')
|
||||
@mock_collectd()
|
||||
def test_log_infos_to_collectd(self, collectd, ROOT_LOGGER):
|
||||
"""Verify that the callbacks are registered properly"""
|
||||
|
||||
plugin.register_plugin(collectd=collectd)
|
||||
|
||||
# When log messages are produced
|
||||
ROOT_LOGGER.info('%d info', 1)
|
||||
|
||||
# When plugin function is called
|
||||
collectd.info.assert_called_once_with('1 info')
|
||||
|
||||
@mock.patch.object(plugin, 'ROOT_LOGGER', new_callable=Logger, name='me')
|
||||
@mock_collectd()
|
||||
def test_log_errors_to_collectd(self, collectd, ROOT_LOGGER):
|
||||
"""Verify that the callbacks are registered properly"""
|
||||
|
||||
plugin.register_plugin(collectd=collectd)
|
||||
|
||||
# When log messages are produced
|
||||
ROOT_LOGGER.error('some error')
|
||||
|
||||
# When plugin function is called
|
||||
collectd.error.assert_called_once_with('some error')
|
||||
|
||||
@mock.patch.object(plugin, 'ROOT_LOGGER', new_callable=Logger, name='me')
|
||||
@mock_collectd()
|
||||
def test_log_fatal_to_collectd(self, collectd, ROOT_LOGGER):
|
||||
"""Verify that the callbacks are registered properly"""
|
||||
|
||||
plugin.register_plugin(collectd=collectd)
|
||||
|
||||
# When log messages are produced
|
||||
ROOT_LOGGER.fatal('some error')
|
||||
|
||||
# When plugin function is called
|
||||
collectd.error.assert_called_once_with('some error')
|
||||
|
||||
@mock.patch.object(plugin, 'ROOT_LOGGER', new_callable=Logger, name='me')
|
||||
@mock_collectd()
|
||||
def test_log_exceptions_to_collectd(self, collectd, ROOT_LOGGER):
|
||||
"""Verify that the callbacks are registered properly"""
|
||||
|
||||
plugin.register_plugin(collectd=collectd)
|
||||
|
||||
# When exception is logged
|
||||
try:
|
||||
raise ValueError('some error')
|
||||
except ValueError:
|
||||
ROOT_LOGGER.exception('got exception')
|
||||
|
||||
# When main function is called
|
||||
collectd.error.assert_called_once_with(
|
||||
match.wildcard('got exception\n'
|
||||
'Traceback (most recent call last):\n'
|
||||
'*'
|
||||
'ValueError: some error'))
|
@ -173,7 +173,7 @@ class TestConfig(TestCase):
|
||||
LOGGER.error.assert_has_calls([
|
||||
mock.call('No configuration value found for "%s"', "OS_AUTH_URL"),
|
||||
mock.call('Configuration parameter %s not set.', "OS_AUTH_URL"),
|
||||
mock.call('Collectd plugin for Ceilometer will not work properly')])
|
||||
mock.call('Collectd plugin will not work properly')])
|
||||
|
||||
@mock.patch.object(settings, 'LOGGER', autospec=True)
|
||||
def test_user_units(self, LOGGER):
|
||||
|
@ -4,9 +4,7 @@ export DEVSTACK_GATE_LIBVIRT_TYPE=kvm
|
||||
export DEVSTACK_GATE_TEMPEST=0
|
||||
export DEVSTACK_LOCAL_CONFIG='
|
||||
COLLECTD_INSTALL=True
|
||||
COLLECTD_CEILOMETER_VERBOSE=True
|
||||
COLLECTD_CEILOMETER_ENABLED=True
|
||||
COLLECTD_GNOCCHI_VERBOSE=True
|
||||
COLLECTD_GNOCCHI_ENABLED=True
|
||||
CEILOMETER_BACKEND=mysql
|
||||
GNOCCHI_USE_KEYSTONE=True
|
||||
'
|
||||
|
@ -7,7 +7,7 @@ date
|
||||
echo "Stacking is finished with all endpoints/services running"
|
||||
echo "Need to restart collectd, which went into some wrong state"
|
||||
echo "or ceilometer-collectd-plugin timeouts before establishing"
|
||||
echo "connections to both gnocchi & ceilometer"
|
||||
echo "connections to gnocchi"
|
||||
sudo service collectd status
|
||||
sudo service collectd restart
|
||||
|
||||
@ -17,7 +17,7 @@ export PATH=/usr/sbin:$PATH
|
||||
source /opt/stack/new/devstack/openrc admin
|
||||
|
||||
while [ "$retry_count" -le "$max_retry_count" ]; do
|
||||
if [ $(openstack metric metric list | grep interface | wc -l) -eq 0 ] || [ $(ceilometer meter-list -l 1000 | grep interface | wc -l) -eq 0 ]; then
|
||||
if [ $(openstack metric metric list | grep interface | wc -l) -eq 0 ]; then
|
||||
echo "Testing metric interface not yet visible in db $retry_count/$max_retry_count"
|
||||
else
|
||||
echo "Testing metric obtained from db"
|
||||
@ -33,4 +33,3 @@ echo "Let's check collectd status:"
|
||||
sudo service collectd status
|
||||
|
||||
exit 1
|
||||
|
||||
|
@ -7,7 +7,7 @@ date
|
||||
echo "Stacking is finished with all endpoints/services running"
|
||||
echo "Need to restart collectd, which went into some wrong state"
|
||||
echo "or ceilometer-collectd-plugin timeouts before establishing"
|
||||
echo "connections to both gnocchi & ceilometer"
|
||||
echo "connections to gnocchi"
|
||||
sudo service collectd status
|
||||
sudo service collectd restart
|
||||
|
||||
@ -17,7 +17,7 @@ export PATH=/usr/sbin:$PATH
|
||||
source /opt/stack/new/devstack/openrc admin
|
||||
|
||||
while [ "$retry_count" -le "$max_retry_count" ]; do
|
||||
if [ $(openstack metric metric list | grep interface | wc -l) -eq 0 ] || [ $(ceilometer meter-list -l 1000 | grep interface | wc -l) -eq 0 ]; then
|
||||
if [ $(openstack metric metric list | grep interface | wc -l) -eq 0 ]; then
|
||||
echo "Testing metric interface not yet visible in db $retry_count/$max_retry_count"
|
||||
else
|
||||
echo "Testing metric obtained from db"
|
||||
@ -33,4 +33,3 @@ echo "Let's check collectd status:"
|
||||
sudo service collectd status
|
||||
|
||||
exit 1
|
||||
|
||||
|
@ -115,24 +115,6 @@ function adapt_collectd_conf {
|
||||
CONF_FILE=$(sudo find /etc -name "collectd.conf")
|
||||
sudo sed -E -i 's|(^\|^#)Hostname.*$|Hostname "'$(hostname)'"|g' $CONF_FILE
|
||||
|
||||
# Configure collectd-ceilometer-plugin
|
||||
if [[ "$COLLECTD_CEILOMETER_ENABLED" == "True" ]]; then
|
||||
sudo cp $COLLECTD_CEILOMETER_DIR/etc/collectd.conf.d/collectd-ceilometer-plugin.conf $COLLECTD_CONF_DIR/
|
||||
|
||||
# Configure collectd-ceiloemter-plugin.conf
|
||||
sudo sed -i 's|ModulePath.*$|ModulePath "'$COLLECTD_CEILOMETER_DIR'"|g' $COLLECTD_CONF_DIR/collectd-ceilometer-plugin.conf
|
||||
sudo sed -i 's|VERBOSE.*$|VERBOSE '$COLLECTD_CEILOMETER_VERBOSE'|g' $COLLECTD_CONF_DIR/collectd-ceilometer-plugin.conf
|
||||
sudo sed -i 's|BATCH_SIZE.*$|BATCH_SIZE "'$COLLECTD_BATCH_SIZE'"|g' $COLLECTD_CONF_DIR/collectd-ceilometer-plugin.conf
|
||||
sudo sed -i 's|OS_AUTH_URL.*$|OS_AUTH_URL "'$OS_AUTH_URL'"|g' $COLLECTD_CONF_DIR/collectd-ceilometer-plugin.conf
|
||||
sudo sed -i 's|CEILOMETER_URL_TYPE.*$|CEILOMETER_URL_TYPE "'$CEILOMETER_URL_TYPE'"|g' $COLLECTD_CONF_DIR/collectd-ceilometer-plugin.conf
|
||||
sudo sed -i 's|CEILOMETER_TIMEOUT.*$|CEILOMETER_TIMEOUT "'$CEILOMETER_TIMEOUT'"|g' $COLLECTD_CONF_DIR/collectd-ceilometer-plugin.conf
|
||||
sudo sed -i 's|OS_PASSWORD.*$|OS_PASSWORD "'$SERVICE_PASSWORD'"|g' $COLLECTD_CONF_DIR/collectd-ceilometer-plugin.conf
|
||||
sudo sed -i 's|OS_TENANT_NAME.*$|OS_TENANT_NAME "'$SERVICE_TENANT_NAME'"|g' $COLLECTD_CONF_DIR/collectd-ceilometer-plugin.conf
|
||||
sudo sed -i 's|LIBVIRT_METER_ENABLED.*$|LIBVIRT_METER_ENABLED "'$LIBVIRT_METER_ENABLED'"|g' $COLLECTD_CONF_DIR/collectd-ceilometer-plugin.conf
|
||||
|
||||
config_custom_units "ceilometer" "$COLLECTD_CEILOMETER_UNITS"
|
||||
fi
|
||||
|
||||
# configure collectd-gnocchi plugin
|
||||
if [[ "$COLLECTD_GNOCCHI_ENABLED" == "True" ]]; then
|
||||
|
||||
|
@ -11,11 +11,9 @@ COLLECTD_CONF_DIR=${COLLECTD_CONF_DIR:-''}
|
||||
COLLECTD_REPO=${COLLECTD_REPO:-'https://github.com/collectd/collectd.git'}
|
||||
COLLECTD_PREFIX=${COLLECTD_PREFIX:-'/usr'}
|
||||
|
||||
COLLECTD_CEILOMETER_VERBOSE=$(trueorfalse False COLLECTD_CEILOMETER_VERBOSE)
|
||||
COLLECTD_GNOCCHI_VERBOSE=$(trueorfalse $COLLECTD_CEILOMETER_VERBOSE COLLECTD_GNOCCHI_VERBOSE)
|
||||
COLLECTD_AODH_VERBOSE=$(trueorfalse $COLLECTD_CEILOMETER_VERBOSE COLLECTD_AODH_VERBOSE)
|
||||
COLLECTD_GNOCCHI_VERBOSE=$(trueorfalse False COLLECTD_GNOCCHI_VERBOSE)
|
||||
COLLECTD_AODH_VERBOSE=$(trueorfalse $COLLECTD_GNOCCHI_VERBOSE COLLECTD_AODH_VERBOSE)
|
||||
|
||||
COLLECTD_CEILOMETER_ENABLED=$(trueorfalse False COLLECTD_CEILOMETER_ENABLED)
|
||||
COLLECTD_GNOCCHI_ENABLED=$(trueorfalse True COLLECTD_GNOCCHI_ENABLED)
|
||||
COLLECTD_AODH_ENABLED=$(trueorfalse False COLLECTD_AODH_ENABLED)
|
||||
|
||||
@ -44,7 +42,6 @@ if [ -z $COLLECTD_CONF_DIR ]; then
|
||||
fi
|
||||
|
||||
#Custom units feature
|
||||
COLLECTD_CEILOMETER_UNITS=${COLLECTD_CEILOMETER_CUSTOM_UNITS:-none}
|
||||
COLLECTD_GNOCCHI_UNITS=${COLLECTD_GNOCCHI_CUSTOM_UNITS:-none}
|
||||
|
||||
# Custom alarm severities feature
|
||||
|
@ -26,15 +26,16 @@ Getting Started with Collectd
|
||||
=============================
|
||||
|
||||
This is a getting started guide that describes the manual setup of collectd
|
||||
and the configuration of the plugins contained in this repository
|
||||
(Ceilometer, Gnocchi, Aodh).
|
||||
and the configuration of the plugins contained in this repository (Gnocchi, Aodh).
|
||||
|
||||
Pre-requisites
|
||||
--------------
|
||||
|
||||
- Access to the internet
|
||||
- A working OpenStack environment
|
||||
- Keystone and Ceilometer services enabled
|
||||
- Keystone service enabled
|
||||
- Gnocchi and/or Aodh service(s) enabled
|
||||
|
||||
|
||||
Collectd Installation
|
||||
---------------------
|
||||
@ -226,15 +227,15 @@ These files should be copied into the collectd configuration directory
|
||||
|
||||
$ sudo cp $COLLECTD_CEILOMETER_DIR/etc/collectd.conf.d/logfile.conf <COLLECTD_PREFIX>/etc/collectd.conf.d/01-logfile.conf
|
||||
|
||||
The following instructions apply to collectd-ceilometer, collect-gnocchi and
|
||||
collectd-aodh plugins.
|
||||
|
||||
In the collectd-{ceilometer,gnocchi,aodh}-plugin.conf file a few variables
|
||||
The following instructions apply to collectd-gnocchi and collectd-aodh plugins.
|
||||
|
||||
|
||||
In the collectd-{gnocchi,aodh}-plugin.conf file a few variables
|
||||
have to be changed to suit your environment:
|
||||
|
||||
* Set the ``ModulePath`` to be the location of your collectd-ceilometer-plugin
|
||||
directory (this values will be the same for Ceilometer, Gnocchi and Aodh
|
||||
plugins).
|
||||
directory (this values will be the same for Gnocchi and Aodh plugins).
|
||||
|
||||
::
|
||||
|
||||
@ -251,7 +252,7 @@ have to be changed to suit your environment:
|
||||
|
||||
$ openstack catalog list
|
||||
|
||||
* Update collectd-{ceilometer,gnocchi,aodh}-plugin.conf
|
||||
* Update collectd-{gnocchi,aodh}-plugin.conf
|
||||
|
||||
::
|
||||
|
||||
@ -259,14 +260,14 @@ have to be changed to suit your environment:
|
||||
|
||||
|
||||
* Modify the credentials for the openstack service that the plugin is using.
|
||||
These will be different for ceilometer, gnocchi and aodh.
|
||||
These values are set when creating the Ceilometer, Aodh and Gnocchi services in OpenStack.
|
||||
These will be different for gnocchi and aodh.
|
||||
These values are set when creating the Aodh and Gnocchi services in OpenStack.
|
||||
If you used an installer, some typical values are shown below.
|
||||
|
||||
::
|
||||
|
||||
# Service user creds
|
||||
OS_USERNAME "aodh"|"gnocchi"|"ceilometer"|etc
|
||||
OS_USERNAME "aodh"|"gnocchi"|etc
|
||||
OS_PASSWORD <password for the user>
|
||||
OS_TENANT_NAME "service"|"services"|etc
|
||||
|
||||
@ -294,20 +295,6 @@ To verify that the plugins are working with collectd, use the OpenStack client.
|
||||
|
||||
The following commands vary, depending on which plugins are configured.
|
||||
|
||||
If you are using collectd-ceilometer-plugin:
|
||||
|
||||
* Verify that the stats are going through to Ceilometer:
|
||||
|
||||
::
|
||||
|
||||
$ ceilometer meter-list
|
||||
|
||||
* List the samples for on of the meters:
|
||||
|
||||
::
|
||||
|
||||
$ ceilometer sample-list --meter <meter_name>
|
||||
|
||||
If you are using collectd-gnocchi-plugin:
|
||||
|
||||
* Verify that the metrics are being created in gnocchi:
|
||||
@ -346,9 +333,9 @@ new units for this meter.
|
||||
|
||||
.. NOTE::
|
||||
|
||||
This feature is for collectd-gnocchi and collectd_ceilometer.
|
||||
This feature is for collectd-gnocchi
|
||||
|
||||
* In your collectd-{ceilometer,gnocchi}-plugin.conf file add in the following lines
|
||||
* In your collectd-gnocchi-plugin.conf file add in the following lines
|
||||
at the end of the <Module> section. Edit the line to include the name of
|
||||
of your chosen meter and its new units.
|
||||
|
||||
@ -370,10 +357,6 @@ new units for this meter.
|
||||
* Verify that the units have been changed:
|
||||
|
||||
::
|
||||
# For Ceilometer:
|
||||
$ ceilometer meter-list | grep <meter_name>
|
||||
# OR
|
||||
$ ceilometer sample-list | grep <meter_name>
|
||||
# For Gnocchi:
|
||||
$ openstack metric metric list | grep <metric_name>
|
||||
# OR
|
||||
@ -382,8 +365,8 @@ new units for this meter.
|
||||
Troubleshooting
|
||||
---------------
|
||||
|
||||
If you are unable to verify that ceilometer is working with collectd, try
|
||||
restarting the service, then check the meter list again.
|
||||
If you are unable to verify that Gnocchi is working with collectd, try
|
||||
restarting the service, then check the metric list again.
|
||||
|
||||
::
|
||||
|
||||
|
@ -24,12 +24,12 @@
|
||||
Enabling Alarms for plugin metrics/meters
|
||||
=========================================
|
||||
|
||||
This guide provides a description of what Aodh features are available when
|
||||
either the collectd-gnocchi or the collectd-ceilometer plugin are enabled.
|
||||
It provides a list of the alarms that can be created and how to create them.
|
||||
This guide provides a description of what Aodh features are available when the
|
||||
collectd-gnocchi plugin is enabled. It provides a list of the alarms that can be
|
||||
created and how to create them.
|
||||
|
||||
collectd-gnocchi-plugin
|
||||
-----------------------
|
||||
Gnocchi Based Alarms
|
||||
--------------------
|
||||
|
||||
There are three types of gnocchi based alarms that can be created using Aodh:
|
||||
|
||||
@ -64,29 +64,12 @@ To create a simple gnocchi_aggregation_by_metrics_threshold alarm:
|
||||
--aggregation-method <AGGREGATION_METHOD>
|
||||
|
||||
|
||||
collectd-ceilometer-plugin
|
||||
--------------------------
|
||||
|
||||
When this plugin is enabled threshold alarms can be defined for the new meters
|
||||
that enabling this plugin generates.
|
||||
|
||||
- Threshold alarms can be created for meters via the following command;
|
||||
|
||||
::
|
||||
|
||||
aodh alarm create
|
||||
--name <ALARM_NAME>
|
||||
-t threshold
|
||||
-m <METER_NAME>
|
||||
--threshold <THRESHOLD>
|
||||
|
||||
|
||||
Event Alarms
|
||||
------------
|
||||
|
||||
Event alarms can be created for either of these plugins. They can be triggered
|
||||
by any type of event that can occur to either meters generated by the
|
||||
ceilometer plugin or metrics from the gnocchi-plugin.
|
||||
Event alarms can be created for any gnocchi metric. They would be triggered based
|
||||
on the status of the event defined for the alarm.
|
||||
|
||||
- To create event alarms enter the following command;
|
||||
|
||||
@ -101,9 +84,10 @@ ceilometer plugin or metrics from the gnocchi-plugin.
|
||||
Composite Alarms
|
||||
----------------
|
||||
|
||||
Like event alarms, composite alarms can be created for both the gnocchi and
|
||||
ceilometer plugins. A composite alarm is created by combining more than one
|
||||
type of alarm. Hence you can combine gnocchi and ceilometer based alarms.
|
||||
Like event alarms, composite alarms can be created for the gnocchi plugin.
|
||||
A composite alarm is created by combining more than one type of alarm.
|
||||
Hence you can combine alarms based on Gnocchi metrics with alarms from other
|
||||
sources.
|
||||
|
||||
- Composite alarms are generated by the following command;
|
||||
|
||||
|
@ -48,8 +48,8 @@ Configuration of DevStack
|
||||
-------------------------
|
||||
|
||||
These configuration instructions only allow for the minimal installation of
|
||||
collectd, ceilometer and the plugin. The sample local.conf provided must be
|
||||
edited to enable additional services.
|
||||
collectd, Gnocchi, Aodh and the plugins in this repo. The sample local.conf
|
||||
provided must be edited to enable additional services.
|
||||
|
||||
To configure DevStack for to install the plugin, download the sample local.conf
|
||||
from the collectd-ceilometer-plugin repo into your DevStack directory.
|
||||
@ -61,9 +61,6 @@ from the collectd-ceilometer-plugin repo into your DevStack directory.
|
||||
|
||||
Edit the "HOST_IP" varible to appropriately match your environment.
|
||||
|
||||
Include your chosen "CEILOMETER_BACKEND", as there is no default backend for
|
||||
ceilometer. The options for this backend include mysql,es,postgresql or mongodb.
|
||||
|
||||
If you wish to enable any extra features please follow the instructions in the
|
||||
"Additional Features" section below before moving on to the next step.
|
||||
|
||||
@ -73,8 +70,8 @@ Create your DevStack environment:
|
||||
|
||||
$ ./stack.sh
|
||||
|
||||
Verfication of collectd-ceilometer-plugin
|
||||
-----------------------------------------
|
||||
Verfication of collectd-gnocchi-plugin
|
||||
--------------------------------------
|
||||
|
||||
Confirm that the collectd service is up and running:
|
||||
|
||||
@ -82,13 +79,23 @@ Confirm that the collectd service is up and running:
|
||||
|
||||
$ sudo systemctl status collectd.service
|
||||
|
||||
By default, collectd enables the "cpu.cpu" meter. Check that the statistics for
|
||||
this meter are being sent to ceilometer, thus confirming that collectd is
|
||||
working with ceilometer.
|
||||
By default, collectd enables the "cpu.cpu" metric. Check that the statistics for
|
||||
this metric are being sent to gnocchi, thus confirming that collectd is
|
||||
working with gnocchi.
|
||||
|
||||
The commands you can use are:
|
||||
|
||||
::
|
||||
|
||||
$ ceilometer sample-list --meter cpu.cpu
|
||||
$ openstack metric metric list
|
||||
|
||||
to get a list of available metrics and
|
||||
|
||||
::
|
||||
|
||||
$ openstack metric measures show <metric id>
|
||||
|
||||
to see the measures.
|
||||
|
||||
Additional Features
|
||||
-------------------
|
||||
@ -184,8 +191,8 @@ You can set this severity to be one of three settings "low", "moderate" or
|
||||
severity will default to "moderate".
|
||||
|
||||
In addition to this, alarms can be created manually via the Aodh command line
|
||||
based on the metrics generated by the gnocchi plugin and meters from the
|
||||
ceilometer plugin. For more information on this please read
|
||||
based on the metrics generated by the gnocchi plugin.
|
||||
For more information on this please read
|
||||
:doc:`<alarms_guide.rst>`
|
||||
|
||||
Finally an alarm can also be created in a heat template. The instructions for
|
||||
|
@ -24,21 +24,21 @@
|
||||
Instructions for enabling auto-scaling using heat templates
|
||||
===========================================================
|
||||
|
||||
This is a guide that provides instructions on how to create a heat template
|
||||
to enable auto-scaling of a cloud application based on alarms.
|
||||
To make use of the metrics/meters generated by the ceilometer and gnocchi
|
||||
plugins, a heat template can be created that will auto-scale
|
||||
a user defined resource based on Aodh alarms. These alarms can monitor the new
|
||||
metrics/meters generated by the plugins. The template will outline the
|
||||
This is a guide that provides instructions on how to create a heat template to
|
||||
enable auto-scaling of a cloud application based on alarms. To make use of the
|
||||
metrics generated by the gnocchi plugin, a heat template can be created that
|
||||
will auto-scale a user defined resource based on Aodh alarms. These alarms can
|
||||
monitor the new metrics generated by the plugins. The template will outline the
|
||||
infrastructure of the desired cloud application, as well as the resources that
|
||||
will trigger and monitor the scaling feature, i.e. the alarms, groups and
|
||||
policies.
|
||||
|
||||
.. note::
|
||||
.. note::
|
||||
|
||||
The collectd-ceilometer and collectd-gnocchi plugins only support
|
||||
certain types of Aodh alarms. Please find a list of these options in
|
||||
https://github.com/openstack/collectd-ceilometer-plugin/blob/master/doc/source/alarms_guide.rst.
|
||||
The collectd-gnocchi plugin only supports certain types of Aodh alarms.
|
||||
Please find a list of these options in:
|
||||
|
||||
https://github.com/openstack/collectd-ceilometer-plugin/blob/master/doc/source/alarms_guide.rst.
|
||||
|
||||
|
||||
Creating a heat template for auto-scaling
|
||||
@ -142,14 +142,10 @@ https://docs.openstack.org/developer/heat/template_guide/openstack.html#OS::Aodh
|
||||
type: OS::Aodh::Alarm
|
||||
|
||||
|
||||
Please find a sample template for this type here:
|
||||
https://github.com/openstack/collectd-ceilometer-plugin/tree/master/doc/source/examples/templates/threshold.yml.
|
||||
Adjust variables accordingly to suit your environment.
|
||||
|
||||
collectd-gnocchi-plugin alarms
|
||||
------------------------------
|
||||
|
||||
Again, the alarms available for this plugin are defined in alarms_guide.rst.
|
||||
The alarms available for this plugin are defined in alarms_guide.rst.
|
||||
To create a "gnocchi_aggregation_by_metrics_alarm" in a heat template define an
|
||||
OS::Aodh::GnocchiAggregationByMetricsAlarm resource.
|
||||
Define this resource with the metric/s from the gnocchi plugin and the
|
||||
|
@ -33,14 +33,8 @@ the information below can help diagnose the problem:
|
||||
has been deprecated.
|
||||
- Support for Keystone V3 API is available for the Newton release and above.
|
||||
|
||||
- Is ceilometer-acompute service enabled?
|
||||
- The ceilometer-acompute service provides metrics as well.
|
||||
- If the metrics from ceilometer-acompute are available, then the issue is
|
||||
likely with authentication of collectd-ceilometer-plugin.
|
||||
- If the metrics from ceilometer-acompute are not available, then the issue
|
||||
is with the database/storage engine, since no metrics are being stored.
|
||||
|
||||
- Are the credentials in collectd-ceilometer-plugin.conf valid?
|
||||
- Are the credentials in collectd-{gnocchi,aodh}-plugin.conf valid?
|
||||
- Export these credentials to your environment as OS_PROJECT_NAME,
|
||||
OS_USERNAME and OS_PASSWORD, and use the openstack client.
|
||||
- If the credentials are valid, you should be able to interact with the
|
||||
@ -53,7 +47,7 @@ the information below can help diagnose the problem:
|
||||
::
|
||||
|
||||
$ openstack catalog show keystone
|
||||
$ grep "OS_AUTH_URL" /path/to/collectd.conf.d/collectd-ceilometer-plugin.conf
|
||||
$ grep "OS_AUTH_URL" /path/to/collectd.conf.d/collectd-{gnocchi,aodh}-plugin.conf
|
||||
|
||||
- Is collectd-ceilometer-plugin.conf being parsed?
|
||||
|
||||
@ -75,5 +69,5 @@ the information below can help diagnose the problem:
|
||||
configuration at `../etc/collectd.conf.d/logging.conf`_).
|
||||
|
||||
- Make sure to set the LogLevel to “debug” for maximum information
|
||||
- Use "VERBOSE True" in collectd-ceilometer-plugin.conf, in order to elevate
|
||||
- Use "VERBOSE True" in collectd-{aodh,gnocchi}-plugin.conf, in order to elevate
|
||||
debug messages to LogLevel info.
|
||||
|
@ -102,16 +102,6 @@ COLLECTD_LOG_LEVEL
|
||||
Default: info
|
||||
|
||||
|
||||
COLLECTD_CEILOMETER_CUSTOM_UNITS
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
(meter=unit) a comma seperated list of pairs, defining meters and their units.
|
||||
Allows existing units to be changed and new units to be set for new meters.
|
||||
The "meter" is generally in the form of "plugin.type", where plugin and
|
||||
plugin type are attributes of the collectd data.
|
||||
|
||||
Example: COLLECTD_CEILOMETER_CUSTOM_UNITS="<meter> <unit>,<meter> <unit>"
|
||||
|
||||
|
||||
COLLECTD_GNOCCHI_CUSTOM_UNITS
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
(meter=unit) a comma seperated list of pairs, defining meters and their units.
|
||||
@ -122,12 +112,6 @@ COLLECTD_GNOCCHI_CUSTOM_UNITS
|
||||
Example: COLLECTD_GNOCCHI_CUSTOM_UNITS="<meter> <unit>,<meter> <unit>"
|
||||
|
||||
|
||||
COLLECTD_CEILOMETER_ENABLED
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
(True|False) Toggle whether collectd-ceilometer-plugin is enabled.
|
||||
|
||||
Default: False
|
||||
|
||||
COLLECTD_GNOCCHI_ENABLED
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
(True|False) Toggles whether collectd-gnocchi-plugin is enabled.
|
||||
@ -140,21 +124,13 @@ COLLECTD_AODH_ENABLED
|
||||
|
||||
Default: False
|
||||
|
||||
COLLECTD_CEILOMETER_VERBOSE
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
(True|False) Set this to True to make collectd-ceilometer debugging messages
|
||||
visible as info messages. This is useful when running the plugin inside a
|
||||
collectd compiled without debug message support.
|
||||
|
||||
Default: False
|
||||
|
||||
COLLECTD_GNOCCHI_VERBOSE
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
(True|False) Set this to True to make collectd-gnocchi debugging messages
|
||||
visible as info messages. This is useful when running the plugin inside a
|
||||
collectd compiled without debug message support.
|
||||
|
||||
Default: $COLLECTD_CEILOMETER_VERBOSE
|
||||
Default: False
|
||||
|
||||
COLLECTD_AODH_VERBOSE
|
||||
~~~~~~~~~~~~~~~~~~~~~
|
||||
@ -162,7 +138,7 @@ COLLECTD_AODH_VERBOSE
|
||||
visible as info messages. This is useful when running the plugin inside
|
||||
a collectd compiled without debug message support.
|
||||
|
||||
Default: $COLLECTD_CEILOMETER_VERBOSE
|
||||
Default: $COLLECTD_GNOCCHI_VERBOSE
|
||||
|
||||
COLLECTD_INSTALL_TYPE
|
||||
~~~~~~~~~~~~~~~~~~~~~
|
||||
|
@ -111,18 +111,18 @@ Once the appliance is running connect to the running VM you can type following
|
||||
|
||||
$ vagrant ssh
|
||||
|
||||
During the provisioning process collectd and ceilometer are going to be
|
||||
During the provisioning process collectd is going to be
|
||||
installed and launched using devstack. To force updating the project and
|
||||
restacking it again please use one of the following commands
|
||||
|
||||
::
|
||||
|
||||
# when the machine is down and I want to take it up, update the software
|
||||
# and start all services (including collectd and ceilometer)
|
||||
# and start all services (including collectd )
|
||||
$ vagrant up --provision
|
||||
|
||||
# when the machine is running and I want to take reboot it, update the
|
||||
# software and re-start all services (including collectd and ceilometer)
|
||||
# software and re-start all services (including collectd)
|
||||
$ vagrant reload --provision
|
||||
|
||||
|
||||
|
@ -16,13 +16,13 @@
|
||||
# Service endpoint addresses
|
||||
OS_AUTH_URL "<OS_AUTH_URL>"
|
||||
|
||||
# Ceilometer address
|
||||
# Plugin address
|
||||
#CEILOMETER_URL_TYPE "internalURL"
|
||||
|
||||
# Ceilometer timeout in ms
|
||||
# Plugin timeout in ms
|
||||
#CEILOMETER_TIMEOUT "1000"
|
||||
|
||||
# # Ceilometer user creds
|
||||
# # Plugin user creds
|
||||
OS_USERNAME "aodh"
|
||||
OS_PASSWORD "password"
|
||||
OS_TENANT_NAME "service"
|
||||
|
@ -1,38 +0,0 @@
|
||||
<LoadPlugin python>
|
||||
Globals true
|
||||
</LoadPlugin>
|
||||
|
||||
<Plugin python>
|
||||
ModulePath "/opt/stack/collectd-ceilometer-plugin"
|
||||
LogTraces true
|
||||
Interactive false
|
||||
Import "collectd_ceilometer.ceilometer.plugin"
|
||||
|
||||
<Module "collectd_ceilometer.ceilometer.plugin">
|
||||
|
||||
# Verbosity True|False
|
||||
VERBOSE False
|
||||
|
||||
# Batch size
|
||||
BATCH_SIZE "1"
|
||||
|
||||
# Service endpoint addresses
|
||||
OS_AUTH_URL "<OS_AUTH_URL>"
|
||||
|
||||
# Ceilometer address
|
||||
CEILOMETER_URL_TYPE "internalURL"
|
||||
|
||||
# Ceilometer timeout in ms
|
||||
CEILOMETER_TIMEOUT "1000"
|
||||
|
||||
# # Ceilometer user creds
|
||||
OS_USERNAME "ceilometer"
|
||||
OS_PASSWORD "password"
|
||||
OS_TENANT_NAME "service"
|
||||
|
||||
# Libvirt meter enabled
|
||||
LIBVIRT_METER_ENABLED False
|
||||
<UNITS>
|
||||
</UNITS>
|
||||
</Module>
|
||||
</Plugin>
|
@ -19,13 +19,13 @@
|
||||
# Service endpoint addresses
|
||||
OS_AUTH_URL "<OS_AUTH_URL>"
|
||||
|
||||
# Ceilometer address
|
||||
# Plugin address
|
||||
CEILOMETER_URL_TYPE "internalURL"
|
||||
|
||||
# Ceilometer timeout in ms
|
||||
# Plugin timeout in ms
|
||||
CEILOMETER_TIMEOUT "1000"
|
||||
|
||||
# # Ceilometer user creds
|
||||
# # Plugin user creds
|
||||
OS_USERNAME "gnocchi"
|
||||
OS_PASSWORD "password"
|
||||
OS_TENANT_NAME "service"
|
||||
|
@ -0,0 +1,7 @@
|
||||
---
|
||||
deprecations:
|
||||
- |
|
||||
The ceilometer API has been deprecated for several months, and is no
|
||||
longer available. Therefore, the ceilometer plugin was removed from the
|
||||
repository. The colelctd-ceilometer source code, unit tests, deployment code
|
||||
and sample configurations were removed. Documentation was updated.
|
Loading…
Reference in New Issue
Block a user