From 031953992be18dbc52ee13fcd6633e6d197e6fda Mon Sep 17 00:00:00 2001 From: Ilya Tyaptin Date: Thu, 27 Mar 2014 18:00:14 +0400 Subject: [PATCH] Add encoding argument to deserialising udp packets in collector Samples from udp publisher failed signature verifying when they contain utf8 strs. It happened because msgpack.loads unpacked data without utf8 by default and in compute signature this strs are processed as different. This is fixed by adding of encoding in unpacking packets from udp Fixes: bug #1297731 Change-Id: I3a8072eb49a61364ff1a6bff1a14ad2c9925b88e --- ceilometer/collector.py | 2 +- ceilometer/tests/test_collector.py | 42 +++++++++++++++++++++++++----- 2 files changed, 37 insertions(+), 7 deletions(-) diff --git a/ceilometer/collector.py b/ceilometer/collector.py index e89563ac2..727034572 100644 --- a/ceilometer/collector.py +++ b/ceilometer/collector.py @@ -81,7 +81,7 @@ class CollectorService(service.DispatchedService, os_service.Service): # enough for anybody. data, source = udp.recvfrom(64 * units.Ki) try: - sample = msgpack.loads(data) + sample = msgpack.loads(data, encoding='utf-8') except Exception: LOG.warn(_("UDP: Cannot decode data sent by %s"), str(source)) else: diff --git a/ceilometer/tests/test_collector.py b/ceilometer/tests/test_collector.py index 7b5ba7982..0adebf3f8 100644 --- a/ceilometer/tests/test_collector.py +++ b/ceilometer/tests/test_collector.py @@ -26,6 +26,7 @@ from stevedore import extension from ceilometer import collector from ceilometer import messaging from ceilometer.openstack.common.fixture import config +from ceilometer.publisher import utils from ceilometer import sample from ceilometer.tests import base as tests_base @@ -43,6 +44,7 @@ class TestCollector(tests_base.BaseTestCase): self.CONF = self.useFixture(config.Config()).conf self.CONF.set_override("connection", "log://", group='database') self.srv = collector.CollectorService() + self.CONF.publisher.metering_secret = 'not-so-secret' self.counter = sample.Sample( name='foobar', type='bad', @@ -55,6 +57,21 @@ class TestCollector(tests_base.BaseTestCase): resource_metadata={}, ).as_dict() + self.utf8_msg = utils.meter_message_from_counter( + sample.Sample( + name=u'test', + type=sample.TYPE_CUMULATIVE, + unit=u'', + volume=1, + user_id=u'test', + project_id=u'test', + resource_id=u'test_run_tasks', + timestamp=u'NOW!', + resource_metadata={u'name': [([u'TestPublish'])]}, + source=u'testsource', + ), + 'not-so-secret') + def _make_test_manager(self, plugin): return extension.ExtensionManager.make_test_instance([ extension.Extension( @@ -65,11 +82,11 @@ class TestCollector(tests_base.BaseTestCase): ), ]) - def _make_fake_socket(self): + def _make_fake_socket(self, sample): def recvfrom(size): # Make the loop stop self.srv.stop() - return (msgpack.dumps(self.counter), ('127.0.0.1', 12345)) + return msgpack.dumps(sample), ('127.0.0.1', 12345) sock = mock.Mock() sock.recvfrom = recvfrom @@ -99,7 +116,7 @@ class TestCollector(tests_base.BaseTestCase): self.counter['counter_type'] = self.counter['type'] self.counter['counter_unit'] = self.counter['unit'] - udp_socket = self._make_fake_socket() + udp_socket = self._make_fake_socket(self.counter) with mock.patch('socket.socket', return_value=udp_socket): self.srv.start_udp() @@ -120,7 +137,7 @@ class TestCollector(tests_base.BaseTestCase): self.counter['counter_type'] = self.counter['type'] self.counter['counter_unit'] = self.counter['unit'] - udp_socket = self._make_fake_socket() + udp_socket = self._make_fake_socket(self.counter) with mock.patch('socket.socket', return_value=udp_socket): self.srv.start_udp() @@ -135,7 +152,7 @@ class TestCollector(tests_base.BaseTestCase): def test_udp_receive_bad_decoding(self): self.CONF.set_override('rpc_backend', '') - udp_socket = self._make_fake_socket() + udp_socket = self._make_fake_socket(self.counter) with mock.patch('socket.socket', return_value=udp_socket): with mock.patch('msgpack.loads', self._raise_error): self.srv.start_udp() @@ -147,7 +164,7 @@ class TestCollector(tests_base.BaseTestCase): def test_only_udp(self, udp_start, rpc_start): """Check that only UDP is started if rpc_backend is empty.""" self.CONF.set_override('rpc_backend', '') - udp_socket = self._make_fake_socket() + udp_socket = self._make_fake_socket(self.counter) with mock.patch('socket.socket', return_value=udp_socket): self.srv.start() @@ -168,3 +185,16 @@ class TestCollector(tests_base.BaseTestCase): eventlet.sleep(0) self.assertEqual(1, rpc_start.call_count) self.assertEqual(0, udp_start.call_count) + + def test_udp_receive_valid_encoding(self): + self.data_sent = [] + with mock.patch('socket.socket', + return_value=self._make_fake_socket(self.utf8_msg)): + self.srv.rpc_server = mock.MagicMock() + mock_dispatcher = mock.MagicMock() + self.srv.dispatcher_manager = \ + self._make_test_manager(mock_dispatcher) + self.srv.start_udp() + self.assertTrue(utils.verify_signature( + mock_dispatcher.method_calls[0][1][0], + "not-so-secret"))