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:
Elizabeth Burke 2017-07-28 15:54:59 +00:00
parent f86c539aaf
commit d256ab054a
26 changed files with 93 additions and 967 deletions

View File

@ -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)

View File

@ -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)

View File

@ -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

View File

@ -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)

View File

@ -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()

View File

@ -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')

View File

@ -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'))

View File

@ -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):

View File

@ -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
'

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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.
::

View File

@ -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;

View File

@ -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

View File

@ -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

View File

@ -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.

View File

@ -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
~~~~~~~~~~~~~~~~~~~~~

View File

@ -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

View File

@ -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"

View File

@ -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>

View File

@ -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"

View File

@ -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.