collector: use an intermediate proxy class for event dispatcher

This makes sure that the base class EventDispatcherBase does not owns
any code itself. This makes external plugin easier to implement as they
don't _have_ to inherit from EventDispatcherBase, they just need to
implement a `record_events(events)' method and that's it.

This will allow Panko to provide the database dispatcher without having
a hard dependency on Ceilometer.

Change-Id: I094aed1e7e081fe1de130d987035a6c9d977d25e
This commit is contained in:
Julien Danjou 2016-05-10 18:26:07 +02:00
parent f99cedf11f
commit 984042084f
3 changed files with 20 additions and 37 deletions

View File

@ -24,7 +24,7 @@ from oslo_utils import netutils
from oslo_utils import units
from ceilometer import dispatcher
from ceilometer.i18n import _, _LE
from ceilometer.i18n import _, _LE, _LW
from ceilometer import messaging
from ceilometer import service_base
from ceilometer import utils
@ -94,7 +94,8 @@ class CollectorService(service_base.ServiceBase):
self.event_listener = (
messaging.get_batch_notification_listener(
transport, [event_target],
[EventEndpoint(self.event_manager)],
[EventEndpoint(
EventDispatcherVerificator(self.event_manager))],
allow_requeue=True,
batch_size=cfg.CONF.collector.batch_size,
batch_timeout=cfg.CONF.collector.batch_timeout))
@ -161,6 +162,23 @@ class SampleEndpoint(CollectorEndpoint):
ep_type = 'sample'
class EventDispatcherVerificator(object):
def __init__(self, dispatcher):
self.dispatcher = dispatcher
def verify_and_record_events(self, events):
"""Verify event signature and record them."""
goods = []
for event in events:
if utils.verify_signature(
event, self.conf.publisher.telemetry_secret):
goods.append(event)
else:
LOG.warning(_LW(
'event signature invalid, discarding event: %s'), event)
return self.dispatcher.record_events(goods)
class EventEndpoint(CollectorEndpoint):
method = 'verify_and_record_events'
ep_type = 'event'

View File

@ -21,7 +21,6 @@ import six
from stevedore import named
from ceilometer.i18n import _LW
from ceilometer.publisher import utils
LOG = log.getLogger(__name__)
@ -108,15 +107,3 @@ class EventDispatcherBase(Base):
@abc.abstractmethod
def record_events(self, events):
"""Record events."""
def verify_and_record_events(self, events):
"""Verify event signature and record them."""
goods = []
for event in events:
if utils.verify_signature(
event, self.conf.publisher.telemetry_secret):
goods.append(event)
else:
LOG.warning(_LW(
'event signature invalid, discarding event: %s'), event)
return self.record_events(goods)

View File

@ -44,28 +44,6 @@ class TestDispatcherDB(base.BaseTestCase):
self.dispatcher.record_events(event)
self.assertEqual(1, len(record_events.call_args_list[0][0][0]))
@mock.patch('ceilometer.publisher.utils.verify_signature')
def test_event_with_bad_signature(self, mocked_verify):
event = event_models.Event(uuid.uuid4(), 'test',
datetime.datetime(2012, 7, 2, 13, 53, 40),
[], {}).serialize()
def _fake_verify(ev, secret):
if ev.get('message_signature') == 'bad_signature':
return False
return True
mocked_verify.side_effect = _fake_verify
with mock.patch.object(self.dispatcher.event_conn,
'record_events') as record_events:
event['message_signature'] = 'bad_signature'
self.dispatcher.verify_and_record_events([event])
self.assertEqual([], record_events.call_args_list[0][0][0])
del event['message_signature']
event['message_signature'] = utils.compute_signature(
event, self.CONF.publisher.telemetry_secret)
self.dispatcher.verify_and_record_events([event])
self.assertEqual(1, len(record_events.call_args_list[1][0][0]))
def test_valid_message(self):
msg = {'counter_name': 'test',
'resource_id': self.id(),