Merge "Add support for remote consumers of Ceilometer event data."

This commit is contained in:
Zuul 2018-05-09 16:21:54 +00:00 committed by Gerrit Code Review
commit 1cd0316ec0
14 changed files with 143 additions and 3 deletions

View File

@ -239,3 +239,13 @@ options:
Openstack mostly defaults to using public endpoints for
internal communication between services. If set to True this option
will configure services to use internal endpoints where possible.
remote-sink:
type: string
default:
description: |
Space delimited list of remote consumers of Ceilometer event reporting
which reside outside of the deployed model. Only supported for Mitaka
and later clouds. e.g.
.
'udp://<host>:<port>/'
'prometheus://pushgateway-host:9091/metrics/job/openstack-telemetry'

View File

@ -153,7 +153,9 @@ def metric_service_joined():
"identity-credentials-relation-changed",
"identity-credentials-relation-departed",
"metric-service-relation-changed",
"metric-service-relation-departed")
"metric-service-relation-departed",
"event-service-relation-changed",
"event-service-relation-departed",)
@restart_on_change(restart_map())
def any_changed():
CONFIGS.write_all()

View File

@ -0,0 +1 @@
ceilometer_hooks.py

View File

@ -0,0 +1 @@
ceilometer_hooks.py

View File

@ -0,0 +1 @@
ceilometer_hooks.py

View File

@ -0,0 +1 @@
ceilometer_hooks.py

View File

@ -140,6 +140,26 @@ class HAProxyContext(OSContextGenerator):
return ctxt
class RemoteSinksContext(OSContextGenerator):
interfaces = ['event-service']
def __call__(self):
'''Generates context for remote sinks for Panko and other compatible
remote consumers of Ceilometer event data.
'''
ctxt = {}
if config('remote-sink'):
ctxt['remote_sinks'] = config('remote-sink').split(' ')
for relid in relation_ids('event-service'):
for unit in related_units(relid):
publisher = relation_get('publisher', unit=unit, rid=relid)
if publisher:
if not ctxt.get('internal_sinks'):
ctxt['internal_sinks'] = {}
ctxt['internal_sinks'][unit.split('/')[0]] = publisher
return ctxt
class ApacheSSLContext(SSLContext):
external_ports = [CEILOMETER_PORT]

View File

@ -31,6 +31,7 @@ from ceilometer_contexts import (
HAProxyContext,
MetricServiceContext,
CEILOMETER_PORT,
RemoteSinksContext,
)
from charmhelpers.contrib.openstack.utils import (
get_os_codename_package,
@ -51,6 +52,7 @@ from charmhelpers.core.hookenv import (
is_leader,
log,
DEBUG,
relation_ids,
)
from charmhelpers.fetch import apt_update, apt_install, apt_upgrade
from charmhelpers.core.host import init_is_systemd
@ -67,6 +69,7 @@ HTTPS_APACHE_24_CONF = "/etc/apache2/sites-available/" \
"openstack_https_frontend.conf"
CLUSTER_RES = 'grp_ceilometer_vips'
MEMCACHED_CONF = '/etc/memcached.conf'
PIPELINE_CONF = '/etc/ceilometer/event_pipeline.yaml'
CEILOMETER_BASE_SERVICES = [
'ceilometer-agent-central',
@ -242,6 +245,8 @@ def register_configs():
CeilometerContext(),
HAProxyContext()]
)
if CompareOpenStackReleases(release) >= 'mitaka':
configs.register(PIPELINE_CONF, [RemoteSinksContext()])
return configs
@ -424,6 +429,17 @@ def set_shared_secret(secret):
secret_file.write(secret)
def get_optional_relations():
"""Return a dictionary of optional relations.
@returns {relation: relation_name}
"""
optional_interfaces = {}
if relation_ids('event-service'):
optional_interfaces['event-service'] = ['event-service']
return optional_interfaces
def assess_status(configs):
"""Assess status of current unit
@ -448,6 +464,7 @@ def resolve_required_interfaces():
@returns dict - a dictionary keyed by high-level type of interfaces names
"""
required_ints = deepcopy(REQUIRED_INTERFACES)
required_ints.update(get_optional_relations())
if CompareOpenStackReleases(os_release('ceilometer-common')) >= 'mitaka':
required_ints['database'].append('metric-service')
if CompareOpenStackReleases(os_release('ceilometer-common')) >= 'queens':

View File

@ -43,6 +43,8 @@ requires:
scope: container
metric-service:
interface: gnocchi
event-service:
interface: event-service
peers:
cluster:
interface: ceilometer-ha

View File

@ -12,7 +12,7 @@ api_workers = {{ workers }}
collector_workers = {{ workers }}
notification_workers = {{ workers }}
event_pipeline_cfg_file = /etc/ceilometer/event_pipeline_alarm.yaml
event_pipeline_cfg_file = /etc/ceilometer/event_pipeline.yaml
{% if gnocchi_url -%}
meter_dispatchers = gnocchi

View File

@ -0,0 +1,37 @@
---
sources:
- name: event_source
events:
- "*"
sinks:
- event_sink
{%- if remote_sinks %}
- remote_sink
{% endif %}
{%- if internal_sinks %}
{%- for item in internal_sinks.keys() %}
- {{ item }}
{% endfor -%}
{% endif %}
sinks:
{%- if remote_sinks %}
- name: remote_sink
transformers:
publishers:
{% for item in remote_sinks -%}
- {{ item }}
{% endfor %}
{%- endif -%}
{%- if internal_sinks %}
{%- for item, target in internal_sinks.items() -%}
- name: {{ item }}
transformers:
publishers:
- {{ target }}
{%- endfor %}
{% endif %}
- name: event_sink
transformers:
publishers:
- notifier://
- notifier://?topic=alarm.all

View File

@ -8,7 +8,7 @@
debug = {{ debug }}
verbose = {{ verbose }}
use_syslog = {{ use_syslog }}
event_pipeline_cfg_file = /etc/ceilometer/event_pipeline_alarm.yaml
event_pipeline_cfg_file = /etc/ceilometer/event_pipeline.yaml
{% if gnocchi_url -%}
meter_dispatchers = gnocchi

View File

@ -193,3 +193,33 @@ class CeilometerContextsTest(CharmTestCase):
'port': api_port
}
self.assertEqual(contexts.HAProxyContext()(), expected)
def test_remote_sink_context_no_config(self):
self.relation_ids.return_value = []
self.os_release.return_value = 'mitaka'
self.assertEqual(contexts.RemoteSinksContext()(), {})
def test_remote_sink_context_event_service_relation(self):
self.relation_ids.return_value = ['event-service:0']
self.related_units.return_value = ['panko/0']
self.os_release.return_value = 'mitaka'
data = {
'publisher': 'panko://'
}
self.test_relation.set(data)
self.assertEqual(contexts.RemoteSinksContext()(),
{'internal_sinks': {'panko': 'panko://'}})
def test_remote_sink_context_with_single_config(self):
self.relation_ids.return_value = []
self.os_release.return_value = 'mitaka'
self.test_config.set('remote-sink', 'http://foo')
self.assertEqual(contexts.RemoteSinksContext()(),
{'remote_sinks': ['http://foo']})
def test_remote_sink_context_with_multiple_config(self):
self.relation_ids.return_value = []
self.os_release.return_value = 'mitaka'
self.test_config.set('remote-sink', 'http://foo http://bar')
self.assertEqual(contexts.RemoteSinksContext()(),
{'remote_sinks': ['http://foo', 'http://bar']})

View File

@ -39,6 +39,7 @@ TO_PATCH = [
'os_release',
'is_leader',
'reset_os_release',
'relation_ids',
]
@ -275,6 +276,7 @@ class CeilometerUtilsTest(CharmTestCase):
def test_resolve_required_interfaces(self):
self.os_release.side_effect = None
self.os_release.return_value = 'icehouse'
self.relation_ids.return_value = None
self.assertEqual(
utils.resolve_required_interfaces(),
{
@ -287,6 +289,7 @@ class CeilometerUtilsTest(CharmTestCase):
def test_resolve_required_interfaces_mitaka(self):
self.os_release.side_effect = None
self.os_release.return_value = 'mitaka'
self.relation_ids.return_value = None
self.assertEqual(
utils.resolve_required_interfaces(),
{
@ -299,6 +302,7 @@ class CeilometerUtilsTest(CharmTestCase):
def test_resolve_required_interfaces_queens(self):
self.os_release.side_effect = None
self.os_release.return_value = 'queens'
self.relation_ids.return_value = None
self.assertEqual(
utils.resolve_required_interfaces(),
{
@ -308,6 +312,20 @@ class CeilometerUtilsTest(CharmTestCase):
}
)
def test_resolve_optional_interfaces(self):
self.os_release.side_effect = None
self.os_release.return_value = 'icehouse'
self.relation_ids.return_value = [0]
self.assertEqual(
utils.resolve_required_interfaces(),
{
'database': ['mongodb'],
'messaging': ['amqp'],
'identity': ['identity-service'],
'event-service': ['event-service'],
}
)
@patch.object(utils, 'subprocess')
def test_ceilometer_upgrade(self, mock_subprocess):
self.is_leader.return_value = True