Fix work of udp publisher
* Signature is appended also to udp messages * All methods for convert from sample to message are moved to publisher/utils.py * In configs metering_secret is moved from group publisher_rpc to publisher * Changed tests for udp publisher Fixes: bug #1259171 Change-Id: Ic7727c69d4be6d17ff00f21e323341efd57122a7
This commit is contained in:
parent
e564c1e395
commit
cdab1401dc
@ -77,10 +77,6 @@ class CollectorService(service.DispatchedService, rpc_service.Service):
|
||||
LOG.warn(_("UDP: Cannot decode data sent by %s"), str(source))
|
||||
else:
|
||||
try:
|
||||
sample['counter_name'] = sample['name']
|
||||
sample['counter_volume'] = sample['volume']
|
||||
sample['counter_unit'] = sample['unit']
|
||||
sample['counter_type'] = sample['type']
|
||||
LOG.debug(_("UDP: Storing %s"), str(sample))
|
||||
self.dispatcher_manager.map_method('record_metering_data',
|
||||
sample)
|
||||
|
@ -20,7 +20,7 @@ from ceilometer import dispatcher
|
||||
from ceilometer.openstack.common.gettextutils import _ # noqa
|
||||
from ceilometer.openstack.common import log
|
||||
from ceilometer.openstack.common import timeutils
|
||||
from ceilometer.publisher import rpc as publisher_rpc
|
||||
from ceilometer.publisher import utils as publisher_utils
|
||||
from ceilometer import storage
|
||||
|
||||
LOG = log.getLogger(__name__)
|
||||
@ -54,9 +54,9 @@ class DatabaseDispatcher(dispatcher.Base):
|
||||
'resource_id': meter['resource_id'],
|
||||
'timestamp': meter.get('timestamp', 'NO TIMESTAMP'),
|
||||
'counter_volume': meter['counter_volume']}))
|
||||
if publisher_rpc.verify_signature(
|
||||
if publisher_utils.verify_signature(
|
||||
meter,
|
||||
self.conf.publisher_rpc.metering_secret):
|
||||
self.conf.publisher.metering_secret):
|
||||
try:
|
||||
# Convert the timestamp to a datetime instance.
|
||||
# Storage engines are responsible for converting
|
||||
|
@ -18,8 +18,7 @@
|
||||
"""Publish a sample using the preferred RPC mechanism.
|
||||
"""
|
||||
|
||||
import hashlib
|
||||
import hmac
|
||||
|
||||
import itertools
|
||||
import operator
|
||||
import urlparse
|
||||
@ -30,7 +29,7 @@ from ceilometer.openstack.common.gettextutils import _ # noqa
|
||||
from ceilometer.openstack.common import log
|
||||
from ceilometer.openstack.common import rpc
|
||||
from ceilometer import publisher
|
||||
from ceilometer import utils
|
||||
from ceilometer.publisher import utils
|
||||
|
||||
|
||||
LOG = log.getLogger(__name__)
|
||||
@ -41,12 +40,6 @@ METER_PUBLISH_OPTS = [
|
||||
help='the topic ceilometer uses for metering messages',
|
||||
deprecated_group="DEFAULT",
|
||||
),
|
||||
cfg.StrOpt('metering_secret',
|
||||
secret=True,
|
||||
default='change this or be hacked',
|
||||
help='Secret value for signing metering messages',
|
||||
deprecated_group="DEFAULT",
|
||||
),
|
||||
]
|
||||
|
||||
|
||||
@ -91,51 +84,6 @@ def override_backend_retry_config(value):
|
||||
cfg.CONF.set_override('rabbit_max_retries', value)
|
||||
|
||||
|
||||
def compute_signature(message, secret):
|
||||
"""Return the signature for a message dictionary.
|
||||
"""
|
||||
digest_maker = hmac.new(secret, '', hashlib.sha256)
|
||||
for name, value in utils.recursive_keypairs(message):
|
||||
if name == 'message_signature':
|
||||
# Skip any existing signature value, which would not have
|
||||
# been part of the original message.
|
||||
continue
|
||||
digest_maker.update(name)
|
||||
digest_maker.update(unicode(value).encode('utf-8'))
|
||||
return digest_maker.hexdigest()
|
||||
|
||||
|
||||
def verify_signature(message, secret):
|
||||
"""Check the signature in the message against the value computed
|
||||
from the rest of the contents.
|
||||
"""
|
||||
old_sig = message.get('message_signature')
|
||||
new_sig = compute_signature(message, secret)
|
||||
return new_sig == old_sig
|
||||
|
||||
|
||||
def meter_message_from_counter(sample, secret):
|
||||
"""Make a metering message ready to be published or stored.
|
||||
|
||||
Returns a dictionary containing a metering message
|
||||
for a notification message and a Sample instance.
|
||||
"""
|
||||
msg = {'source': sample.source,
|
||||
'counter_name': sample.name,
|
||||
'counter_type': sample.type,
|
||||
'counter_unit': sample.unit,
|
||||
'counter_volume': sample.volume,
|
||||
'user_id': sample.user_id,
|
||||
'project_id': sample.project_id,
|
||||
'resource_id': sample.resource_id,
|
||||
'timestamp': sample.timestamp,
|
||||
'resource_metadata': sample.resource_metadata,
|
||||
'message_id': sample.id,
|
||||
}
|
||||
msg['message_signature'] = compute_signature(msg, secret)
|
||||
return msg
|
||||
|
||||
|
||||
class RPCPublisher(publisher.PublisherBase):
|
||||
|
||||
def __init__(self, parsed_url):
|
||||
@ -175,9 +123,9 @@ class RPCPublisher(publisher.PublisherBase):
|
||||
"""
|
||||
|
||||
meters = [
|
||||
meter_message_from_counter(
|
||||
utils.meter_message_from_counter(
|
||||
sample,
|
||||
cfg.CONF.publisher_rpc.metering_secret)
|
||||
cfg.CONF.publisher.metering_secret)
|
||||
for sample in samples
|
||||
]
|
||||
|
||||
|
@ -2,7 +2,8 @@
|
||||
#
|
||||
# Copyright © 2013 eNovance
|
||||
#
|
||||
# Author: Julien Danjou <julien@danjou.info>
|
||||
# Author: Julien Danjou <julien@danjou.info>,
|
||||
# Tyaptin Ilya <ityaptin@mirantis.com>
|
||||
#
|
||||
# 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
|
||||
@ -27,6 +28,7 @@ from ceilometer.openstack.common.gettextutils import _ # noqa
|
||||
from ceilometer.openstack.common import log
|
||||
from ceilometer.openstack.common import network_utils
|
||||
from ceilometer import publisher
|
||||
from ceilometer.publisher import utils
|
||||
|
||||
cfg.CONF.import_opt('udp_port', 'ceilometer.collector',
|
||||
group='collector')
|
||||
@ -35,7 +37,6 @@ LOG = log.getLogger(__name__)
|
||||
|
||||
|
||||
class UDPPublisher(publisher.PublisherBase):
|
||||
|
||||
def __init__(self, parsed_url):
|
||||
self.host, self.port = network_utils.parse_host_port(
|
||||
parsed_url.netloc,
|
||||
@ -51,7 +52,9 @@ class UDPPublisher(publisher.PublisherBase):
|
||||
"""
|
||||
|
||||
for sample in samples:
|
||||
msg = sample.as_dict()
|
||||
msg = utils.meter_message_from_counter(
|
||||
sample,
|
||||
cfg.CONF.publisher.metering_secret)
|
||||
host = self.host
|
||||
port = self.port
|
||||
LOG.debug(_("Publishing sample %(msg)s over UDP to "
|
||||
|
93
ceilometer/publisher/utils.py
Normal file
93
ceilometer/publisher/utils.py
Normal file
@ -0,0 +1,93 @@
|
||||
# -*- encoding: utf-8 -*-
|
||||
#
|
||||
# Copyright © 2012 New Dream Network, LLC (DreamHost)
|
||||
#
|
||||
# Author: Doug Hellmann <doug.hellmann@dreamhost.com>
|
||||
# Tyaptin Ilya <ityaptin@mirantis.com>
|
||||
#
|
||||
# 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.
|
||||
"""Utils for publishers
|
||||
"""
|
||||
|
||||
import hashlib
|
||||
import hmac
|
||||
|
||||
from oslo.config import cfg
|
||||
|
||||
from ceilometer import utils
|
||||
|
||||
METER_PUBLISH_OPTS = [
|
||||
cfg.StrOpt('metering_secret',
|
||||
secret=True,
|
||||
default='change this or be hacked',
|
||||
help='Secret value for signing metering messages',
|
||||
deprecated_opts=[cfg.DeprecatedOpt("metering_secret",
|
||||
"DEFAULT"),
|
||||
cfg.DeprecatedOpt("metering_secret",
|
||||
"publisher_rpc")]
|
||||
),
|
||||
]
|
||||
|
||||
|
||||
def register_opts(config):
|
||||
"""Register the options for publishing metering messages.
|
||||
"""
|
||||
config.register_opts(METER_PUBLISH_OPTS, group="publisher")
|
||||
|
||||
|
||||
register_opts(cfg.CONF)
|
||||
|
||||
|
||||
def compute_signature(message, secret):
|
||||
"""Return the signature for a message dictionary.
|
||||
"""
|
||||
digest_maker = hmac.new(secret, '', hashlib.sha256)
|
||||
for name, value in utils.recursive_keypairs(message):
|
||||
if name == 'message_signature':
|
||||
# Skip any existing signature value, which would not have
|
||||
# been part of the original message.
|
||||
continue
|
||||
digest_maker.update(name)
|
||||
digest_maker.update(unicode(value).encode('utf-8'))
|
||||
return digest_maker.hexdigest()
|
||||
|
||||
|
||||
def verify_signature(message, secret):
|
||||
"""Check the signature in the message against the value computed
|
||||
from the rest of the contents.
|
||||
"""
|
||||
old_sig = message.get('message_signature')
|
||||
new_sig = compute_signature(message, secret)
|
||||
return new_sig == old_sig
|
||||
|
||||
|
||||
def meter_message_from_counter(sample, secret):
|
||||
"""Make a metering message ready to be published or stored.
|
||||
|
||||
Returns a dictionary containing a metering message
|
||||
for a notification message and a Sample instance.
|
||||
"""
|
||||
msg = {'source': sample.source,
|
||||
'counter_name': sample.name,
|
||||
'counter_type': sample.type,
|
||||
'counter_unit': sample.unit,
|
||||
'counter_volume': sample.volume,
|
||||
'user_id': sample.user_id,
|
||||
'project_id': sample.project_id,
|
||||
'resource_id': sample.resource_id,
|
||||
'timestamp': sample.timestamp,
|
||||
'resource_metadata': sample.resource_metadata,
|
||||
'message_id': sample.id,
|
||||
}
|
||||
msg['message_signature'] = compute_signature(msg, secret)
|
||||
return msg
|
@ -22,7 +22,7 @@
|
||||
import datetime
|
||||
import testscenarios
|
||||
|
||||
from ceilometer.publisher import rpc
|
||||
from ceilometer.publisher import utils
|
||||
from ceilometer import sample
|
||||
|
||||
from ceilometer.tests import api as tests_api
|
||||
@ -77,9 +77,9 @@ class TestListEvents(tests_api.TestBase,
|
||||
source='source1',
|
||||
),
|
||||
]:
|
||||
msg = rpc.meter_message_from_counter(
|
||||
msg = utils.meter_message_from_counter(
|
||||
cnt,
|
||||
self.CONF.publisher_rpc.metering_secret)
|
||||
self.CONF.publisher.metering_secret)
|
||||
self.conn.record_metering_data(msg)
|
||||
|
||||
def test_empty_project(self):
|
||||
|
@ -23,7 +23,7 @@ import datetime
|
||||
import logging
|
||||
import testscenarios
|
||||
|
||||
from ceilometer.publisher import rpc
|
||||
from ceilometer.publisher import utils
|
||||
from ceilometer import sample
|
||||
|
||||
from ceilometer.tests import api as tests_api
|
||||
@ -108,9 +108,9 @@ class TestListMeters(tests_api.TestBase,
|
||||
resource_metadata={'display_name': 'test-server',
|
||||
'tag': 'four.sample'},
|
||||
source='test_list_resources')]:
|
||||
msg = rpc.meter_message_from_counter(
|
||||
msg = utils.meter_message_from_counter(
|
||||
cnt,
|
||||
self.CONF.publisher_rpc.metering_secret)
|
||||
self.CONF.publisher.metering_secret)
|
||||
self.conn.record_metering_data(msg)
|
||||
|
||||
def test_list_meters(self):
|
||||
|
@ -23,7 +23,7 @@ import datetime
|
||||
import logging
|
||||
import testscenarios
|
||||
|
||||
from ceilometer.publisher import rpc
|
||||
from ceilometer.publisher import utils
|
||||
from ceilometer import sample
|
||||
|
||||
from ceilometer.tests import api as tests_api
|
||||
@ -60,9 +60,9 @@ class TestListProjects(tests_api.TestBase,
|
||||
'tag': 'self.sample'},
|
||||
source='test_list_projects',
|
||||
)
|
||||
msg = rpc.meter_message_from_counter(
|
||||
msg = utils.meter_message_from_counter(
|
||||
sample1,
|
||||
self.CONF.publisher_rpc.metering_secret,
|
||||
self.CONF.publisher.metering_secret,
|
||||
)
|
||||
self.conn.record_metering_data(msg)
|
||||
|
||||
@ -79,9 +79,9 @@ class TestListProjects(tests_api.TestBase,
|
||||
'tag': 'self.sample2'},
|
||||
source='test_list_users',
|
||||
)
|
||||
msg2 = rpc.meter_message_from_counter(
|
||||
msg2 = utils.meter_message_from_counter(
|
||||
sample2,
|
||||
self.CONF.publisher_rpc.metering_secret,
|
||||
self.CONF.publisher.metering_secret,
|
||||
)
|
||||
self.conn.record_metering_data(msg2)
|
||||
|
||||
|
@ -23,7 +23,7 @@ import datetime
|
||||
import logging
|
||||
import testscenarios
|
||||
|
||||
from ceilometer.publisher import rpc
|
||||
from ceilometer.publisher import utils
|
||||
from ceilometer import sample
|
||||
|
||||
from ceilometer.tests import api as tests_api
|
||||
@ -101,9 +101,9 @@ class TestListResourcesBase(tests_api.TestBase,
|
||||
'tag': 'self.sample4'},
|
||||
source='test_list_resources',
|
||||
)]:
|
||||
msg = rpc.meter_message_from_counter(
|
||||
msg = utils.meter_message_from_counter(
|
||||
cnt,
|
||||
self.CONF.publisher_rpc.metering_secret)
|
||||
self.CONF.publisher.metering_secret)
|
||||
self.conn.record_metering_data(msg)
|
||||
|
||||
|
||||
|
@ -23,7 +23,7 @@ import datetime
|
||||
import logging
|
||||
import testscenarios
|
||||
|
||||
from ceilometer.publisher import rpc
|
||||
from ceilometer.publisher import utils
|
||||
from ceilometer import sample
|
||||
|
||||
from ceilometer.tests import api as tests_api
|
||||
@ -62,9 +62,9 @@ class TestListUsers(tests_api.TestBase,
|
||||
},
|
||||
source='test_list_users',
|
||||
)
|
||||
msg = rpc.meter_message_from_counter(
|
||||
msg = utils.meter_message_from_counter(
|
||||
sample1,
|
||||
self.CONF.publisher_rpc.metering_secret,
|
||||
self.CONF.publisher.metering_secret,
|
||||
)
|
||||
self.conn.record_metering_data(msg)
|
||||
|
||||
@ -82,9 +82,9 @@ class TestListUsers(tests_api.TestBase,
|
||||
},
|
||||
source='not-test',
|
||||
)
|
||||
msg2 = rpc.meter_message_from_counter(
|
||||
msg2 = utils.meter_message_from_counter(
|
||||
sample2,
|
||||
self.CONF.publisher_rpc.metering_secret,
|
||||
self.CONF.publisher.metering_secret,
|
||||
)
|
||||
self.conn.record_metering_data(msg2)
|
||||
|
||||
|
@ -22,7 +22,7 @@
|
||||
import datetime
|
||||
import testscenarios
|
||||
|
||||
from ceilometer.publisher import rpc
|
||||
from ceilometer.publisher import utils
|
||||
from ceilometer import sample
|
||||
|
||||
from ceilometer.tests import api as tests_api
|
||||
@ -51,9 +51,9 @@ class TestMaxProjectVolume(tests_api.TestBase,
|
||||
},
|
||||
source='source1',
|
||||
)
|
||||
msg = rpc.meter_message_from_counter(
|
||||
msg = utils.meter_message_from_counter(
|
||||
s,
|
||||
self.CONF.publisher_rpc.metering_secret,
|
||||
self.CONF.publisher.metering_secret,
|
||||
)
|
||||
self.conn.record_metering_data(msg)
|
||||
|
||||
|
@ -21,7 +21,7 @@
|
||||
import datetime
|
||||
import testscenarios
|
||||
|
||||
from ceilometer.publisher import rpc
|
||||
from ceilometer.publisher import utils
|
||||
from ceilometer import sample
|
||||
|
||||
from ceilometer.tests import api as tests_api
|
||||
@ -50,9 +50,9 @@ class TestMaxResourceVolume(tests_api.TestBase,
|
||||
},
|
||||
source='source1',
|
||||
)
|
||||
msg = rpc.meter_message_from_counter(
|
||||
msg = utils.meter_message_from_counter(
|
||||
s,
|
||||
self.CONF.publisher_rpc.metering_secret,
|
||||
self.CONF.publisher.metering_secret,
|
||||
)
|
||||
self.conn.record_metering_data(msg)
|
||||
|
||||
|
@ -22,7 +22,7 @@
|
||||
import datetime
|
||||
import testscenarios
|
||||
|
||||
from ceilometer.publisher import rpc
|
||||
from ceilometer.publisher import utils
|
||||
from ceilometer import sample
|
||||
|
||||
from ceilometer.tests import api as tests_api
|
||||
@ -51,9 +51,9 @@ class TestSumProjectVolume(tests_api.TestBase,
|
||||
},
|
||||
source='source1',
|
||||
)
|
||||
msg = rpc.meter_message_from_counter(
|
||||
msg = utils.meter_message_from_counter(
|
||||
s,
|
||||
self.CONF.publisher_rpc.metering_secret,
|
||||
self.CONF.publisher.metering_secret,
|
||||
)
|
||||
self.conn.record_metering_data(msg)
|
||||
|
||||
|
@ -22,7 +22,7 @@
|
||||
import datetime
|
||||
import testscenarios
|
||||
|
||||
from ceilometer.publisher import rpc
|
||||
from ceilometer.publisher import utils
|
||||
from ceilometer import sample
|
||||
|
||||
from ceilometer.tests import api as tests_api
|
||||
@ -51,9 +51,9 @@ class TestSumResourceVolume(tests_api.TestBase,
|
||||
},
|
||||
source='source1',
|
||||
)
|
||||
msg = rpc.meter_message_from_counter(
|
||||
msg = utils.meter_message_from_counter(
|
||||
s,
|
||||
self.CONF.publisher_rpc.metering_secret,
|
||||
self.CONF.publisher.metering_secret,
|
||||
)
|
||||
self.conn.record_metering_data(msg)
|
||||
|
||||
|
@ -25,7 +25,7 @@ import testscenarios
|
||||
from ceilometer.api import acl
|
||||
from ceilometer.api.controllers import v2 as v2_api
|
||||
from ceilometer.openstack.common import timeutils
|
||||
from ceilometer.publisher import rpc
|
||||
from ceilometer.publisher import utils
|
||||
from ceilometer import sample
|
||||
from ceilometer.tests.api.v2 import FunctionalTest
|
||||
from ceilometer.tests import db as tests_db
|
||||
@ -104,9 +104,9 @@ class TestAPIACL(FunctionalTest,
|
||||
resource_metadata={'display_name': 'test-server',
|
||||
'tag': 'self.sample4'},
|
||||
source='test_source')]:
|
||||
msg = rpc.meter_message_from_counter(
|
||||
msg = utils.meter_message_from_counter(
|
||||
cnt,
|
||||
self.CONF.publisher_rpc.metering_secret)
|
||||
self.CONF.publisher.metering_secret)
|
||||
self.conn.record_metering_data(msg)
|
||||
|
||||
def get_json(self, path, expect_errors=False, headers=None,
|
||||
|
@ -24,7 +24,7 @@ import logging
|
||||
import testscenarios
|
||||
import webtest.app
|
||||
|
||||
from ceilometer.publisher import rpc
|
||||
from ceilometer.publisher import utils
|
||||
from ceilometer import sample
|
||||
from ceilometer.tests.api.v2 import FunctionalTest
|
||||
from ceilometer.tests import db as tests_db
|
||||
@ -56,9 +56,9 @@ class TestListEvents(FunctionalTest,
|
||||
},
|
||||
source='test_source',
|
||||
)
|
||||
msg = rpc.meter_message_from_counter(
|
||||
msg = utils.meter_message_from_counter(
|
||||
self.sample1,
|
||||
self.CONF.publisher_rpc.metering_secret,
|
||||
self.CONF.publisher.metering_secret,
|
||||
)
|
||||
self.conn.record_metering_data(msg)
|
||||
|
||||
@ -76,9 +76,9 @@ class TestListEvents(FunctionalTest,
|
||||
},
|
||||
source='source2',
|
||||
)
|
||||
msg2 = rpc.meter_message_from_counter(
|
||||
msg2 = utils.meter_message_from_counter(
|
||||
self.sample2,
|
||||
self.CONF.publisher_rpc.metering_secret,
|
||||
self.CONF.publisher.metering_secret,
|
||||
)
|
||||
self.conn.record_metering_data(msg2)
|
||||
|
||||
|
@ -24,7 +24,7 @@ import datetime
|
||||
import logging
|
||||
import testscenarios
|
||||
|
||||
from ceilometer.publisher import rpc
|
||||
from ceilometer.publisher import utils
|
||||
from ceilometer import sample
|
||||
from ceilometer.tests.api.v2 import FunctionalTest
|
||||
from ceilometer.tests import db as tests_db
|
||||
@ -128,9 +128,9 @@ class TestListMeters(FunctionalTest,
|
||||
'util': 0.58,
|
||||
'is_public': True},
|
||||
source='test_source1')]:
|
||||
msg = rpc.meter_message_from_counter(
|
||||
msg = utils.meter_message_from_counter(
|
||||
cnt,
|
||||
self.CONF.publisher_rpc.metering_secret)
|
||||
self.CONF.publisher.metering_secret)
|
||||
self.conn.record_metering_data(msg)
|
||||
|
||||
def test_list_meters(self):
|
||||
|
@ -23,8 +23,9 @@ import json
|
||||
import logging
|
||||
import testscenarios
|
||||
|
||||
|
||||
from ceilometer.openstack.common import timeutils
|
||||
from ceilometer.publisher import rpc
|
||||
from ceilometer.publisher import utils
|
||||
from ceilometer import sample
|
||||
from ceilometer.tests.api.v2 import FunctionalTest
|
||||
from ceilometer.tests import db as tests_db
|
||||
@ -66,9 +67,9 @@ class TestListResources(FunctionalTest,
|
||||
resource_metadata=None,
|
||||
source='test',
|
||||
)
|
||||
msg = rpc.meter_message_from_counter(
|
||||
msg = utils.meter_message_from_counter(
|
||||
sample1,
|
||||
self.CONF.publisher_rpc.metering_secret,
|
||||
self.CONF.publisher.metering_secret,
|
||||
)
|
||||
self.conn.record_metering_data(msg)
|
||||
|
||||
@ -95,9 +96,9 @@ class TestListResources(FunctionalTest,
|
||||
},
|
||||
source='test',
|
||||
)
|
||||
msg = rpc.meter_message_from_counter(
|
||||
msg = utils.meter_message_from_counter(
|
||||
sample1,
|
||||
self.CONF.publisher_rpc.metering_secret,
|
||||
self.CONF.publisher.metering_secret,
|
||||
)
|
||||
self.conn.record_metering_data(msg)
|
||||
|
||||
@ -115,9 +116,9 @@ class TestListResources(FunctionalTest,
|
||||
},
|
||||
source='test',
|
||||
)
|
||||
msg2 = rpc.meter_message_from_counter(
|
||||
msg2 = utils.meter_message_from_counter(
|
||||
sample2,
|
||||
self.CONF.publisher_rpc.metering_secret,
|
||||
self.CONF.publisher.metering_secret,
|
||||
)
|
||||
self.conn.record_metering_data(msg2)
|
||||
|
||||
@ -148,9 +149,9 @@ class TestListResources(FunctionalTest,
|
||||
},
|
||||
source='test',
|
||||
)
|
||||
msg = rpc.meter_message_from_counter(
|
||||
msg = utils.meter_message_from_counter(
|
||||
datapoint,
|
||||
self.CONF.publisher_rpc.metering_secret,
|
||||
self.CONF.publisher.metering_secret,
|
||||
)
|
||||
self.conn.record_metering_data(msg)
|
||||
|
||||
@ -173,9 +174,9 @@ class TestListResources(FunctionalTest,
|
||||
},
|
||||
source='test',
|
||||
)
|
||||
msg = rpc.meter_message_from_counter(
|
||||
msg = utils.meter_message_from_counter(
|
||||
sample1,
|
||||
self.CONF.publisher_rpc.metering_secret,
|
||||
self.CONF.publisher.metering_secret,
|
||||
)
|
||||
self.conn.record_metering_data(msg)
|
||||
|
||||
@ -193,9 +194,9 @@ class TestListResources(FunctionalTest,
|
||||
},
|
||||
source='test',
|
||||
)
|
||||
msg2 = rpc.meter_message_from_counter(
|
||||
msg2 = utils.meter_message_from_counter(
|
||||
sample2,
|
||||
self.CONF.publisher_rpc.metering_secret,
|
||||
self.CONF.publisher.metering_secret,
|
||||
)
|
||||
self.conn.record_metering_data(msg2)
|
||||
|
||||
@ -217,9 +218,9 @@ class TestListResources(FunctionalTest,
|
||||
},
|
||||
source='test_list_resources',
|
||||
)
|
||||
msg = rpc.meter_message_from_counter(
|
||||
msg = utils.meter_message_from_counter(
|
||||
sample1,
|
||||
self.CONF.publisher_rpc.metering_secret,
|
||||
self.CONF.publisher.metering_secret,
|
||||
)
|
||||
self.conn.record_metering_data(msg)
|
||||
|
||||
@ -237,9 +238,9 @@ class TestListResources(FunctionalTest,
|
||||
},
|
||||
source='not-test',
|
||||
)
|
||||
msg2 = rpc.meter_message_from_counter(
|
||||
msg2 = utils.meter_message_from_counter(
|
||||
sample2,
|
||||
self.CONF.publisher_rpc.metering_secret,
|
||||
self.CONF.publisher.metering_secret,
|
||||
)
|
||||
self.conn.record_metering_data(msg2)
|
||||
|
||||
@ -266,9 +267,9 @@ class TestListResources(FunctionalTest,
|
||||
},
|
||||
source='test_list_resources',
|
||||
)
|
||||
msg = rpc.meter_message_from_counter(
|
||||
msg = utils.meter_message_from_counter(
|
||||
sample1,
|
||||
self.CONF.publisher_rpc.metering_secret,
|
||||
self.CONF.publisher.metering_secret,
|
||||
)
|
||||
self.conn.record_metering_data(msg)
|
||||
|
||||
@ -286,9 +287,9 @@ class TestListResources(FunctionalTest,
|
||||
},
|
||||
source='test_list_resources',
|
||||
)
|
||||
msg2 = rpc.meter_message_from_counter(
|
||||
msg2 = utils.meter_message_from_counter(
|
||||
sample2,
|
||||
self.CONF.publisher_rpc.metering_secret,
|
||||
self.CONF.publisher.metering_secret,
|
||||
)
|
||||
self.conn.record_metering_data(msg2)
|
||||
|
||||
@ -319,9 +320,9 @@ class TestListResources(FunctionalTest,
|
||||
},
|
||||
source='test_list_resources',
|
||||
)
|
||||
msg = rpc.meter_message_from_counter(
|
||||
msg = utils.meter_message_from_counter(
|
||||
sample1,
|
||||
self.CONF.publisher_rpc.metering_secret,
|
||||
self.CONF.publisher.metering_secret,
|
||||
)
|
||||
self.conn.record_metering_data(msg)
|
||||
|
||||
@ -339,9 +340,9 @@ class TestListResources(FunctionalTest,
|
||||
},
|
||||
source='not-test',
|
||||
)
|
||||
msg2 = rpc.meter_message_from_counter(
|
||||
msg2 = utils.meter_message_from_counter(
|
||||
sample2,
|
||||
self.CONF.publisher_rpc.metering_secret,
|
||||
self.CONF.publisher.metering_secret,
|
||||
)
|
||||
self.conn.record_metering_data(msg2)
|
||||
|
||||
@ -366,9 +367,9 @@ class TestListResources(FunctionalTest,
|
||||
},
|
||||
source='test_list_resources',
|
||||
)
|
||||
msg = rpc.meter_message_from_counter(
|
||||
msg = utils.meter_message_from_counter(
|
||||
sample1,
|
||||
self.CONF.publisher_rpc.metering_secret,
|
||||
self.CONF.publisher.metering_secret,
|
||||
)
|
||||
self.conn.record_metering_data(msg)
|
||||
|
||||
@ -386,9 +387,9 @@ class TestListResources(FunctionalTest,
|
||||
},
|
||||
source='not-test',
|
||||
)
|
||||
msg2 = rpc.meter_message_from_counter(
|
||||
msg2 = utils.meter_message_from_counter(
|
||||
sample2,
|
||||
self.CONF.publisher_rpc.metering_secret,
|
||||
self.CONF.publisher.metering_secret,
|
||||
)
|
||||
self.conn.record_metering_data(msg2)
|
||||
|
||||
@ -413,9 +414,9 @@ class TestListResources(FunctionalTest,
|
||||
},
|
||||
source='not-test',
|
||||
)
|
||||
msg2 = rpc.meter_message_from_counter(
|
||||
msg2 = utils.meter_message_from_counter(
|
||||
sample1,
|
||||
self.CONF.publisher_rpc.metering_secret,
|
||||
self.CONF.publisher.metering_secret,
|
||||
)
|
||||
self.conn.record_metering_data(msg2)
|
||||
|
||||
@ -440,9 +441,9 @@ class TestListResources(FunctionalTest,
|
||||
},
|
||||
source='not-test',
|
||||
)
|
||||
msg2 = rpc.meter_message_from_counter(
|
||||
msg2 = utils.meter_message_from_counter(
|
||||
sample1,
|
||||
self.CONF.publisher_rpc.metering_secret,
|
||||
self.CONF.publisher.metering_secret,
|
||||
)
|
||||
self.conn.record_metering_data(msg2)
|
||||
|
||||
@ -469,9 +470,9 @@ class TestListResources(FunctionalTest,
|
||||
},
|
||||
source='test',
|
||||
)
|
||||
msg = rpc.meter_message_from_counter(
|
||||
msg = utils.meter_message_from_counter(
|
||||
sample1,
|
||||
self.CONF.publisher_rpc.metering_secret,
|
||||
self.CONF.publisher.metering_secret,
|
||||
)
|
||||
self.conn.record_metering_data(msg)
|
||||
|
||||
@ -499,9 +500,9 @@ class TestListResources(FunctionalTest,
|
||||
},
|
||||
source='test_list_resources',
|
||||
)
|
||||
msg = rpc.meter_message_from_counter(
|
||||
msg = utils.meter_message_from_counter(
|
||||
sample1,
|
||||
self.CONF.publisher_rpc.metering_secret,
|
||||
self.CONF.publisher.metering_secret,
|
||||
)
|
||||
self.conn.record_metering_data(msg)
|
||||
|
||||
|
@ -21,7 +21,7 @@ import datetime
|
||||
|
||||
import testscenarios
|
||||
|
||||
from ceilometer.publisher import rpc
|
||||
from ceilometer.publisher import utils
|
||||
from ceilometer import sample
|
||||
from ceilometer.tests.api.v2 import FunctionalTest
|
||||
from ceilometer.tests import db as tests_db
|
||||
@ -51,9 +51,9 @@ class TestMaxProjectVolume(FunctionalTest,
|
||||
},
|
||||
source='source1',
|
||||
)
|
||||
msg = rpc.meter_message_from_counter(
|
||||
msg = utils.meter_message_from_counter(
|
||||
s,
|
||||
self.CONF.publisher_rpc.metering_secret,
|
||||
self.CONF.publisher.metering_secret,
|
||||
)
|
||||
self.conn.record_metering_data(msg)
|
||||
|
||||
@ -149,9 +149,9 @@ class TestMaxResourceVolume(FunctionalTest,
|
||||
},
|
||||
source='source1',
|
||||
)
|
||||
msg = rpc.meter_message_from_counter(
|
||||
msg = utils.meter_message_from_counter(
|
||||
s,
|
||||
self.CONF.publisher_rpc.metering_secret,
|
||||
self.CONF.publisher.metering_secret,
|
||||
)
|
||||
self.conn.record_metering_data(msg)
|
||||
|
||||
@ -270,9 +270,9 @@ class TestSumProjectVolume(FunctionalTest,
|
||||
},
|
||||
source='source1',
|
||||
)
|
||||
msg = rpc.meter_message_from_counter(
|
||||
msg = utils.meter_message_from_counter(
|
||||
s,
|
||||
self.CONF.publisher_rpc.metering_secret,
|
||||
self.CONF.publisher.metering_secret,
|
||||
)
|
||||
self.conn.record_metering_data(msg)
|
||||
|
||||
@ -370,9 +370,9 @@ class TestSumResourceVolume(FunctionalTest,
|
||||
},
|
||||
source='source1',
|
||||
)
|
||||
msg = rpc.meter_message_from_counter(
|
||||
msg = utils.meter_message_from_counter(
|
||||
s,
|
||||
self.CONF.publisher_rpc.metering_secret,
|
||||
self.CONF.publisher.metering_secret,
|
||||
)
|
||||
self.conn.record_metering_data(msg)
|
||||
|
||||
@ -527,9 +527,9 @@ class TestGroupByInstance(FunctionalTest,
|
||||
'event': test_sample['metadata_event'], },
|
||||
source=test_sample['source'],
|
||||
)
|
||||
msg = rpc.meter_message_from_counter(
|
||||
msg = utils.meter_message_from_counter(
|
||||
c,
|
||||
self.CONF.publisher_rpc.metering_secret,
|
||||
self.CONF.publisher.metering_secret,
|
||||
)
|
||||
self.conn.record_metering_data(msg)
|
||||
|
||||
@ -1285,9 +1285,9 @@ class TestGroupBySource(FunctionalTest,
|
||||
'event': test_sample['metadata_event'], },
|
||||
source=test_sample['source'],
|
||||
)
|
||||
msg = rpc.meter_message_from_counter(
|
||||
msg = utils.meter_message_from_counter(
|
||||
c,
|
||||
self.CONF.publisher_rpc.metering_secret,
|
||||
self.CONF.publisher.metering_secret,
|
||||
)
|
||||
self.conn.record_metering_data(msg)
|
||||
|
||||
|
@ -22,7 +22,7 @@ import mock
|
||||
from ceilometer.dispatcher import database
|
||||
from ceilometer.openstack.common.fixture import config
|
||||
from ceilometer.openstack.common import test
|
||||
from ceilometer.publisher import rpc
|
||||
from ceilometer.publisher import utils
|
||||
|
||||
|
||||
class TestDispatcherDB(test.BaseTestCase):
|
||||
@ -38,9 +38,9 @@ class TestDispatcherDB(test.BaseTestCase):
|
||||
'resource_id': self.id(),
|
||||
'counter_volume': 1,
|
||||
}
|
||||
msg['message_signature'] = rpc.compute_signature(
|
||||
msg['message_signature'] = utils.compute_signature(
|
||||
msg,
|
||||
self.CONF.publisher_rpc.metering_secret,
|
||||
self.CONF.publisher.metering_secret,
|
||||
)
|
||||
|
||||
with mock.patch.object(self.dispatcher.storage_conn,
|
||||
@ -76,9 +76,9 @@ class TestDispatcherDB(test.BaseTestCase):
|
||||
'counter_volume': 1,
|
||||
'timestamp': '2012-07-02T13:53:40Z',
|
||||
}
|
||||
msg['message_signature'] = rpc.compute_signature(
|
||||
msg['message_signature'] = utils.compute_signature(
|
||||
msg,
|
||||
self.CONF.publisher_rpc.metering_secret,
|
||||
self.CONF.publisher.metering_secret,
|
||||
)
|
||||
|
||||
expected = msg.copy()
|
||||
@ -96,9 +96,9 @@ class TestDispatcherDB(test.BaseTestCase):
|
||||
'counter_volume': 1,
|
||||
'timestamp': '2012-09-30T15:31:50.262-08:00',
|
||||
}
|
||||
msg['message_signature'] = rpc.compute_signature(
|
||||
msg['message_signature'] = utils.compute_signature(
|
||||
msg,
|
||||
self.CONF.publisher_rpc.metering_secret,
|
||||
self.CONF.publisher.metering_secret,
|
||||
)
|
||||
|
||||
expected = msg.copy()
|
||||
|
@ -22,7 +22,7 @@ import tempfile
|
||||
from ceilometer.dispatcher import file
|
||||
from ceilometer.openstack.common.fixture import config
|
||||
from ceilometer.openstack.common import test
|
||||
from ceilometer.publisher import rpc
|
||||
from ceilometer.publisher import utils
|
||||
|
||||
|
||||
class TestDispatcherFile(test.BaseTestCase):
|
||||
@ -53,9 +53,9 @@ class TestDispatcherFile(test.BaseTestCase):
|
||||
'resource_id': self.id(),
|
||||
'counter_volume': 1,
|
||||
}
|
||||
msg['message_signature'] = rpc.compute_signature(
|
||||
msg['message_signature'] = utils.compute_signature(
|
||||
msg,
|
||||
self.CONF.publisher_rpc.metering_secret,
|
||||
self.CONF.publisher.metering_secret,
|
||||
)
|
||||
|
||||
# The record_metering_data method should exist and not produce errors.
|
||||
@ -85,9 +85,9 @@ class TestDispatcherFile(test.BaseTestCase):
|
||||
'resource_id': self.id(),
|
||||
'counter_volume': 1,
|
||||
}
|
||||
msg['message_signature'] = rpc.compute_signature(
|
||||
msg['message_signature'] = utils.compute_signature(
|
||||
msg,
|
||||
self.CONF.publisher_rpc.metering_secret,
|
||||
self.CONF.publisher.metering_secret,
|
||||
)
|
||||
|
||||
# The record_metering_data method should exist and not produce errors.
|
||||
|
@ -25,140 +25,13 @@ import fixtures
|
||||
import mock
|
||||
|
||||
from ceilometer.openstack.common.fixture import config
|
||||
from ceilometer.openstack.common import jsonutils
|
||||
from ceilometer.openstack.common import network_utils
|
||||
from ceilometer.openstack.common import test
|
||||
from ceilometer.publisher import rpc
|
||||
from ceilometer import sample
|
||||
|
||||
|
||||
class TestSignature(test.BaseTestCase):
|
||||
|
||||
def test_compute_signature_change_key(self):
|
||||
sig1 = rpc.compute_signature({'a': 'A', 'b': 'B'},
|
||||
'not-so-secret')
|
||||
sig2 = rpc.compute_signature({'A': 'A', 'b': 'B'},
|
||||
'not-so-secret')
|
||||
self.assertNotEqual(sig1, sig2)
|
||||
|
||||
def test_compute_signature_change_value(self):
|
||||
sig1 = rpc.compute_signature({'a': 'A', 'b': 'B'},
|
||||
'not-so-secret')
|
||||
sig2 = rpc.compute_signature({'a': 'a', 'b': 'B'},
|
||||
'not-so-secret')
|
||||
self.assertNotEqual(sig1, sig2)
|
||||
|
||||
def test_compute_signature_same(self):
|
||||
sig1 = rpc.compute_signature({'a': 'A', 'b': 'B'},
|
||||
'not-so-secret')
|
||||
sig2 = rpc.compute_signature({'a': 'A', 'b': 'B'},
|
||||
'not-so-secret')
|
||||
self.assertEqual(sig1, sig2)
|
||||
|
||||
def test_compute_signature_signed(self):
|
||||
data = {'a': 'A', 'b': 'B'}
|
||||
sig1 = rpc.compute_signature(data, 'not-so-secret')
|
||||
data['message_signature'] = sig1
|
||||
sig2 = rpc.compute_signature(data, 'not-so-secret')
|
||||
self.assertEqual(sig1, sig2)
|
||||
|
||||
def test_compute_signature_use_configured_secret(self):
|
||||
data = {'a': 'A', 'b': 'B'}
|
||||
sig1 = rpc.compute_signature(data, 'not-so-secret')
|
||||
sig2 = rpc.compute_signature(data, 'different-value')
|
||||
self.assertNotEqual(sig1, sig2)
|
||||
|
||||
def test_verify_signature_signed(self):
|
||||
data = {'a': 'A', 'b': 'B'}
|
||||
sig1 = rpc.compute_signature(data, 'not-so-secret')
|
||||
data['message_signature'] = sig1
|
||||
self.assertTrue(rpc.verify_signature(data, 'not-so-secret'))
|
||||
|
||||
def test_verify_signature_unsigned(self):
|
||||
data = {'a': 'A', 'b': 'B'}
|
||||
self.assertFalse(rpc.verify_signature(data, 'not-so-secret'))
|
||||
|
||||
def test_verify_signature_incorrect(self):
|
||||
data = {'a': 'A', 'b': 'B',
|
||||
'message_signature': 'Not the same'}
|
||||
self.assertFalse(rpc.verify_signature(data, 'not-so-secret'))
|
||||
|
||||
def test_verify_signature_nested(self):
|
||||
data = {'a': 'A',
|
||||
'b': 'B',
|
||||
'nested': {'a': 'A',
|
||||
'b': 'B',
|
||||
},
|
||||
}
|
||||
data['message_signature'] = rpc.compute_signature(
|
||||
data,
|
||||
'not-so-secret')
|
||||
self.assertTrue(rpc.verify_signature(data, 'not-so-secret'))
|
||||
|
||||
def test_verify_signature_nested_list_of_dict(self):
|
||||
small = 1
|
||||
big = 1 << 64
|
||||
nested = {small: 99, big: 42}
|
||||
data = {'a': 'A',
|
||||
'b': 'B',
|
||||
'nested': {'list': [nested]}}
|
||||
data['message_signature'] = rpc.compute_signature(
|
||||
data,
|
||||
'not-so-secret')
|
||||
# the keys 1 and 1<<64 cause a hash collision on 64bit platforms
|
||||
data['nested']['list'] = [{big: 42, small: 99}]
|
||||
self.assertTrue(rpc.verify_signature(data, 'not-so-secret'))
|
||||
|
||||
def test_verify_signature_nested_json(self):
|
||||
data = {'a': 'A',
|
||||
'b': 'B',
|
||||
'nested': {'a': 'A',
|
||||
'b': 'B',
|
||||
'c': ('c',),
|
||||
'd': ['d']
|
||||
},
|
||||
}
|
||||
data['message_signature'] = rpc.compute_signature(
|
||||
data,
|
||||
'not-so-secret')
|
||||
jsondata = jsonutils.loads(jsonutils.dumps(data))
|
||||
self.assertTrue(rpc.verify_signature(jsondata, 'not-so-secret'))
|
||||
|
||||
|
||||
class TestCounter(test.BaseTestCase):
|
||||
|
||||
TEST_COUNTER = sample.Sample(name='name',
|
||||
type='typ',
|
||||
unit='',
|
||||
volume=1,
|
||||
user_id='user',
|
||||
project_id='project',
|
||||
resource_id=2,
|
||||
timestamp='today',
|
||||
resource_metadata={'key': 'value'},
|
||||
source='rpc')
|
||||
|
||||
def test_meter_message_from_counter_signed(self):
|
||||
msg = rpc.meter_message_from_counter(self.TEST_COUNTER,
|
||||
'not-so-secret')
|
||||
self.assertIn('message_signature', msg)
|
||||
|
||||
def test_meter_message_from_counter_field(self):
|
||||
def compare(f, c, msg_f, msg):
|
||||
self.assertEqual(msg, c)
|
||||
msg = rpc.meter_message_from_counter(self.TEST_COUNTER,
|
||||
'not-so-secret')
|
||||
name_map = {'name': 'counter_name',
|
||||
'type': 'counter_type',
|
||||
'unit': 'counter_unit',
|
||||
'volume': 'counter_volume'}
|
||||
for f in self.TEST_COUNTER._fields:
|
||||
msg_f = name_map.get(f, f)
|
||||
yield compare, f, getattr(self.TEST_COUNTER, f), msg_f, msg[msg_f]
|
||||
|
||||
|
||||
class TestPublish(test.BaseTestCase):
|
||||
|
||||
test_data = [
|
||||
sample.Sample(
|
||||
name='test',
|
||||
@ -233,8 +106,8 @@ class TestPublish(test.BaseTestCase):
|
||||
self.published = []
|
||||
self.rpc_unreachable = False
|
||||
self.useFixture(fixtures.MonkeyPatch(
|
||||
"ceilometer.openstack.common.rpc.cast",
|
||||
self.faux_cast))
|
||||
"ceilometer.openstack.common.rpc.cast",
|
||||
self.faux_cast))
|
||||
|
||||
def test_published(self):
|
||||
publisher = rpc.RPCPublisher(
|
||||
@ -294,15 +167,15 @@ class TestPublish(test.BaseTestCase):
|
||||
|
||||
def faux_cast_wait(context, topic, msg):
|
||||
self.useFixture(fixtures.MonkeyPatch(
|
||||
"ceilometer.openstack.common.rpc.cast",
|
||||
faux_cast_go))
|
||||
"ceilometer.openstack.common.rpc.cast",
|
||||
faux_cast_go))
|
||||
# Sleep to simulate concurrency and allow other threads to work
|
||||
eventlet.sleep(0)
|
||||
self.published.append((topic, msg))
|
||||
|
||||
self.useFixture(fixtures.MonkeyPatch(
|
||||
"ceilometer.openstack.common.rpc.cast",
|
||||
faux_cast_wait))
|
||||
"ceilometer.openstack.common.rpc.cast",
|
||||
faux_cast_wait))
|
||||
|
||||
publisher = rpc.RPCPublisher(network_utils.urlsplit('rpc://'))
|
||||
job1 = eventlet.spawn(publisher.publish_samples, None, self.test_data)
|
||||
|
@ -27,6 +27,7 @@ from ceilometer.openstack.common.fixture import config
|
||||
from ceilometer.openstack.common import network_utils
|
||||
from ceilometer.openstack.common import test
|
||||
from ceilometer.publisher import udp
|
||||
from ceilometer.publisher import utils
|
||||
from ceilometer import sample
|
||||
|
||||
|
||||
@ -34,7 +35,6 @@ COUNTER_SOURCE = 'testsource'
|
||||
|
||||
|
||||
class TestUDPPublisher(test.BaseTestCase):
|
||||
|
||||
test_data = [
|
||||
sample.Sample(
|
||||
name='test',
|
||||
@ -102,14 +102,17 @@ class TestUDPPublisher(test.BaseTestCase):
|
||||
def _fake_socket_socket(family, type):
|
||||
def record_data(msg, dest):
|
||||
published.append((msg, dest))
|
||||
|
||||
udp_socket = mock.Mock()
|
||||
udp_socket.sendto = record_data
|
||||
return udp_socket
|
||||
|
||||
return _fake_socket_socket
|
||||
|
||||
def setUp(self):
|
||||
super(TestUDPPublisher, self).setUp()
|
||||
self.CONF = self.useFixture(config.Config()).conf
|
||||
self.CONF.publisher.metering_secret = 'not-so-secret'
|
||||
|
||||
def test_published(self):
|
||||
self.data_sent = []
|
||||
@ -134,7 +137,11 @@ class TestUDPPublisher(test.BaseTestCase):
|
||||
|
||||
# Check that counters are equal
|
||||
self.assertEqual(sorted(sent_counters),
|
||||
sorted([dict(d.as_dict()) for d in self.test_data]))
|
||||
sorted(
|
||||
[utils.meter_message_from_counter(
|
||||
d,
|
||||
"not-so-secret")
|
||||
for d in self.test_data]))
|
||||
|
||||
@staticmethod
|
||||
def _raise_ioerror(*args):
|
||||
|
103
ceilometer/tests/publisher/test_utils.py
Normal file
103
ceilometer/tests/publisher/test_utils.py
Normal file
@ -0,0 +1,103 @@
|
||||
# -*- encoding: utf-8 -*-
|
||||
#
|
||||
# Copyright © 2012 New Dream Network, LLC (DreamHost)
|
||||
#
|
||||
# Author: Doug Hellmann <doug.hellmann@dreamhost.com>
|
||||
# Julien Danjou <julien@danjou.info>
|
||||
# Tyaptin Ilya <ityaptin@mirantis.com>
|
||||
#
|
||||
# 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.
|
||||
"""Tests for ceilometer/publisher/utils.py
|
||||
"""
|
||||
|
||||
from ceilometer.openstack.common import jsonutils
|
||||
from ceilometer.openstack.common import test
|
||||
from ceilometer.publisher import utils
|
||||
|
||||
|
||||
class TestSignature(test.BaseTestCase):
|
||||
def test_compute_signature_change_key(self):
|
||||
sig1 = utils.compute_signature({'a': 'A', 'b': 'B'},
|
||||
'not-so-secret')
|
||||
sig2 = utils.compute_signature({'A': 'A', 'b': 'B'},
|
||||
'not-so-secret')
|
||||
self.assertNotEqual(sig1, sig2)
|
||||
|
||||
def test_compute_signature_change_value(self):
|
||||
sig1 = utils.compute_signature({'a': 'A', 'b': 'B'},
|
||||
'not-so-secret')
|
||||
sig2 = utils.compute_signature({'a': 'a', 'b': 'B'},
|
||||
'not-so-secret')
|
||||
self.assertNotEqual(sig1, sig2)
|
||||
|
||||
def test_compute_signature_same(self):
|
||||
sig1 = utils.compute_signature({'a': 'A', 'b': 'B'},
|
||||
'not-so-secret')
|
||||
sig2 = utils.compute_signature({'a': 'A', 'b': 'B'},
|
||||
'not-so-secret')
|
||||
self.assertEqual(sig1, sig2)
|
||||
|
||||
def test_compute_signature_signed(self):
|
||||
data = {'a': 'A', 'b': 'B'}
|
||||
sig1 = utils.compute_signature(data, 'not-so-secret')
|
||||
data['message_signature'] = sig1
|
||||
sig2 = utils.compute_signature(data, 'not-so-secret')
|
||||
self.assertEqual(sig1, sig2)
|
||||
|
||||
def test_compute_signature_use_configured_secret(self):
|
||||
data = {'a': 'A', 'b': 'B'}
|
||||
sig1 = utils.compute_signature(data, 'not-so-secret')
|
||||
sig2 = utils.compute_signature(data, 'different-value')
|
||||
self.assertNotEqual(sig1, sig2)
|
||||
|
||||
def test_verify_signature_signed(self):
|
||||
data = {'a': 'A', 'b': 'B'}
|
||||
sig1 = utils.compute_signature(data, 'not-so-secret')
|
||||
data['message_signature'] = sig1
|
||||
self.assertTrue(utils.verify_signature(data, 'not-so-secret'))
|
||||
|
||||
def test_verify_signature_unsigned(self):
|
||||
data = {'a': 'A', 'b': 'B'}
|
||||
self.assertFalse(utils.verify_signature(data, 'not-so-secret'))
|
||||
|
||||
def test_verify_signature_incorrect(self):
|
||||
data = {'a': 'A', 'b': 'B',
|
||||
'message_signature': 'Not the same'}
|
||||
self.assertFalse(utils.verify_signature(data, 'not-so-secret'))
|
||||
|
||||
def test_verify_signature_nested(self):
|
||||
data = {'a': 'A',
|
||||
'b': 'B',
|
||||
'nested': {'a': 'A',
|
||||
'b': 'B',
|
||||
},
|
||||
}
|
||||
data['message_signature'] = utils.compute_signature(
|
||||
data,
|
||||
'not-so-secret')
|
||||
self.assertTrue(utils.verify_signature(data, 'not-so-secret'))
|
||||
|
||||
def test_verify_signature_nested_json(self):
|
||||
data = {'a': 'A',
|
||||
'b': 'B',
|
||||
'nested': {'a': 'A',
|
||||
'b': 'B',
|
||||
'c': ('c',),
|
||||
'd': ['d']
|
||||
},
|
||||
}
|
||||
data['message_signature'] = utils.compute_signature(
|
||||
data,
|
||||
'not-so-secret')
|
||||
jsondata = jsonutils.loads(jsonutils.dumps(data))
|
||||
self.assertTrue(utils.verify_signature(jsondata, 'not-so-secret'))
|
@ -28,7 +28,7 @@ import copy
|
||||
import datetime
|
||||
from mock import patch
|
||||
|
||||
from ceilometer.publisher import rpc
|
||||
from ceilometer.publisher import utils
|
||||
from ceilometer import sample
|
||||
from ceilometer.storage import base
|
||||
from ceilometer.storage import impl_mongodb
|
||||
@ -180,7 +180,7 @@ class CompatibilityTest(test_storage_scenarios.DBTestBase,
|
||||
source='test',
|
||||
)
|
||||
self.counters.append(c)
|
||||
msg = rpc.meter_message_from_counter(
|
||||
msg = utils.meter_message_from_counter(
|
||||
c,
|
||||
secret='not-so-secret')
|
||||
self.conn.record_metering_data(self.conn, msg)
|
||||
|
@ -24,7 +24,7 @@ import datetime
|
||||
import testscenarios
|
||||
|
||||
from ceilometer.openstack.common import timeutils
|
||||
from ceilometer.publisher import rpc
|
||||
from ceilometer.publisher import utils
|
||||
from ceilometer import sample
|
||||
from ceilometer import storage
|
||||
from ceilometer.storage import base
|
||||
@ -51,8 +51,8 @@ class DBTestBase(tests_db.TestBase):
|
||||
timestamp=timestamp,
|
||||
resource_metadata=metadata, source=source
|
||||
)
|
||||
msg = rpc.meter_message_from_counter(
|
||||
s, self.CONF.publisher_rpc.metering_secret
|
||||
msg = utils.meter_message_from_counter(
|
||||
s, self.CONF.publisher.metering_secret
|
||||
)
|
||||
self.conn.record_metering_data(msg)
|
||||
return msg
|
||||
@ -730,7 +730,7 @@ class StatisticsTest(DBTestBase,
|
||||
},
|
||||
source='test',
|
||||
)
|
||||
msg = rpc.meter_message_from_counter(
|
||||
msg = utils.meter_message_from_counter(
|
||||
c,
|
||||
secret='not-so-secret',
|
||||
)
|
||||
@ -750,7 +750,7 @@ class StatisticsTest(DBTestBase,
|
||||
},
|
||||
source='test',
|
||||
)
|
||||
msg = rpc.meter_message_from_counter(
|
||||
msg = utils.meter_message_from_counter(
|
||||
c,
|
||||
secret='not-so-secret',
|
||||
)
|
||||
@ -971,9 +971,9 @@ class StatisticsGroupByTest(DBTestBase,
|
||||
'event': test_sample['metadata_event'], },
|
||||
source=test_sample['source'],
|
||||
)
|
||||
msg = rpc.meter_message_from_counter(
|
||||
msg = utils.meter_message_from_counter(
|
||||
c,
|
||||
self.CONF.publisher_rpc.metering_secret,
|
||||
self.CONF.publisher.metering_secret,
|
||||
)
|
||||
self.conn.record_metering_data(msg)
|
||||
|
||||
@ -1835,9 +1835,9 @@ class CounterDataTypeTest(DBTestBase,
|
||||
resource_metadata={},
|
||||
source='test-1',
|
||||
)
|
||||
msg = rpc.meter_message_from_counter(
|
||||
msg = utils.meter_message_from_counter(
|
||||
c,
|
||||
self.CONF.publisher_rpc.metering_secret,
|
||||
self.CONF.publisher.metering_secret,
|
||||
)
|
||||
|
||||
self.conn.record_metering_data(msg)
|
||||
@ -1854,9 +1854,9 @@ class CounterDataTypeTest(DBTestBase,
|
||||
resource_metadata={},
|
||||
source='test-1',
|
||||
)
|
||||
msg = rpc.meter_message_from_counter(
|
||||
msg = utils.meter_message_from_counter(
|
||||
c,
|
||||
self.CONF.publisher_rpc.metering_secret,
|
||||
self.CONF.publisher.metering_secret,
|
||||
)
|
||||
self.conn.record_metering_data(msg)
|
||||
|
||||
@ -1872,9 +1872,9 @@ class CounterDataTypeTest(DBTestBase,
|
||||
resource_metadata={},
|
||||
source='test-1',
|
||||
)
|
||||
msg = rpc.meter_message_from_counter(
|
||||
msg = utils.meter_message_from_counter(
|
||||
c,
|
||||
self.CONF.publisher_rpc.metering_secret,
|
||||
self.CONF.publisher.metering_secret,
|
||||
)
|
||||
self.conn.record_metering_data(msg)
|
||||
|
||||
@ -2356,6 +2356,6 @@ class BigIntegerTest(tests_db.TestBase,
|
||||
resource_id='resource-id',
|
||||
timestamp=datetime.datetime.utcnow(),
|
||||
resource_metadata=metadata)
|
||||
msg = rpc.meter_message_from_counter(
|
||||
s, self.CONF.publisher_rpc.metering_secret)
|
||||
msg = utils.meter_message_from_counter(
|
||||
s, self.CONF.publisher.metering_secret)
|
||||
self.conn.record_metering_data(msg)
|
||||
|
@ -877,6 +877,18 @@
|
||||
#store_events=false
|
||||
|
||||
|
||||
[publisher]
|
||||
|
||||
#
|
||||
# Options defined in ceilometer.publisher.utils
|
||||
#
|
||||
|
||||
# Secret value for signing metering messages (string value)
|
||||
# Deprecated group/name - [DEFAULT]/metering_secret
|
||||
# Deprecated group/name - [publisher_rpc]/metering_secret
|
||||
#metering_secret=change this or be hacked
|
||||
|
||||
|
||||
[publisher_rpc]
|
||||
|
||||
#
|
||||
@ -887,9 +899,6 @@
|
||||
# value)
|
||||
#metering_topic=metering
|
||||
|
||||
# Secret value for signing metering messages (string value)
|
||||
#metering_secret=change this or be hacked
|
||||
|
||||
|
||||
[rpc_notifier2]
|
||||
|
||||
|
@ -29,6 +29,7 @@ import sys
|
||||
from oslo.config import cfg
|
||||
|
||||
from ceilometer.publisher import rpc
|
||||
from ceilometer.publisher import utils
|
||||
from ceilometer import sample
|
||||
from ceilometer import storage
|
||||
from ceilometer.openstack.common import timeutils
|
||||
@ -131,9 +132,9 @@ def main():
|
||||
resource_metadata={},
|
||||
source='artificial',
|
||||
)
|
||||
data = rpc.meter_message_from_counter(
|
||||
data = utils.meter_message_from_counter(
|
||||
c,
|
||||
cfg.CONF.publisher_rpc.metering_secret)
|
||||
cfg.CONF.publisher.metering_secret)
|
||||
conn.record_metering_data(data)
|
||||
n += 1
|
||||
timestamp = timestamp + increment
|
||||
|
Loading…
Reference in New Issue
Block a user