diff --git a/ceilometer/agent/manager.py b/ceilometer/agent/manager.py index cec15abb..53d25382 100644 --- a/ceilometer/agent/manager.py +++ b/ceilometer/agent/manager.py @@ -19,11 +19,9 @@ import pkg_resources from nova import manager -from nova import rpc -from ceilometer import meter -from ceilometer import cfg from ceilometer import log +from ceilometer import publish LOG = log.getLogger(__name__) @@ -67,16 +65,7 @@ class AgentManager(manager.Manager): LOG.info('polling %s', name) for c in pollster.get_counters(self, context): LOG.info('COUNTER: %s', c) - msg = { - 'method': 'record_metering_data', - 'version': '1.0', - 'args': {'data': meter.meter_message_from_counter(c), - }, - } - rpc.cast(context, cfg.CONF.metering_topic, msg) - rpc.cast(context, - cfg.CONF.metering_topic + '.' + c.name, - msg) + publish.publish_counter(context, c) except Exception as err: LOG.warning('Continuing after error from %s: %s', name, err) LOG.exception(err) diff --git a/ceilometer/collector/manager.py b/ceilometer/collector/manager.py index 059683bd..cbaf0637 100644 --- a/ceilometer/collector/manager.py +++ b/ceilometer/collector/manager.py @@ -19,13 +19,12 @@ from nova import context from nova import flags from nova import manager -from nova import rpc as nova_rpc from nova.rpc import dispatcher as rpc_dispatcher -from ceilometer import rpc -from ceilometer import log -from ceilometer import meter from ceilometer import cfg +from ceilometer import log +from ceilometer import publish +from ceilometer import rpc from ceilometer.collector import dispatcher # FIXME(dhellmann): There must be another way to do this. @@ -68,21 +67,8 @@ class CollectorManager(manager.Manager): def _publish_counter(self, counter): """Create a metering message for the counter and publish it.""" - msg = meter.meter_message_from_counter(counter) - LOG.info('PUBLISH: %s', str(msg)) - # FIXME(dhellmann): Need to publish the message on the - # metering queue. - msg = { - 'method': 'record_metering_data', - 'version': '1.0', - 'args': {'data': msg, - }, - } ctxt = context.get_admin_context() - nova_rpc.cast(ctxt, cfg.CONF.metering_topic, msg) - nova_rpc.cast(ctxt, - cfg.CONF.metering_topic + '.' + counter.name, - msg) + publish.publish_counter(ctxt, counter) def record_metering_data(self, context, data): """This method is triggered when metering data is diff --git a/ceilometer/publish.py b/ceilometer/publish.py new file mode 100644 index 00000000..85fcd3df --- /dev/null +++ b/ceilometer/publish.py @@ -0,0 +1,49 @@ +# -*- encoding: utf-8 -*- +# +# Copyright © 2012 New Dream Network, LLC (DreamHost) +# +# Author: Doug Hellmann +# +# 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. +"""Publish a counter using the preferred RPC mechanism. +""" + +from nova import log as logging +from nova import rpc + +from ceilometer import cfg +from ceilometer import meter + +# FIXME(dhellmann): We need to have the main program set up logging +# correctly so messages from modules outside of the nova package +# appear in the output. +LOG = logging.getLogger('nova.' + __name__) + + +def publish_counter(context, counter): + """Send a metering message for the data represented by the counter. + + :param context: Execution context from the service or RPC call + :param counter: ceilometer.counter.Counter instance + """ + msg = { + 'method': 'record_metering_data', + 'version': '1.0', + 'args': {'data': meter.meter_message_from_counter(counter), + }, + } + LOG.debug('PUBLISH: %s', str(msg)) + rpc.cast(context, cfg.CONF.metering_topic, msg) + rpc.cast(context, + cfg.CONF.metering_topic + '.' + counter.name, + msg) diff --git a/run_tests.sh b/run_tests.sh index 58c24ad0..9e252499 100755 --- a/run_tests.sh +++ b/run_tests.sh @@ -1,6 +1,12 @@ #!/bin/sh -# Simple test runner, should be replaced with tox +# Wrap tox to force it to enable global site-packages until +# https://bitbucket.org/hpk42/tox/issue/32 is released. + +set -x rm -rf cover -nosetests -P -d -v --cover-erase --with-coverage --cover-package=ceilometer --cover-inclusive tests -tox -e pep8 +if [ ! -z "$VIRTUAL_ENV" ] +then + rm -f $VIRTUAL_ENV/lib/python*/no-global-site-packages.txt +fi +nosetests "$@" diff --git a/tests/agent/test_manager.py b/tests/agent/test_manager.py index ec98dfd0..3947678a 100644 --- a/tests/agent/test_manager.py +++ b/tests/agent/test_manager.py @@ -26,6 +26,7 @@ from nova import test from ceilometer.agent import manager from ceilometer import counter +from ceilometer import publish def test_load_plugins(): @@ -57,13 +58,13 @@ class TestRunTasks(test.TestCase): self.counters.append((manager, context)) return [self.test_data] - def faux_notify(self, context, topic, msg): - self.notifications.append((topic, msg)) + def faux_notify(self, context, msg): + self.notifications.append(msg) def setUp(self): super(TestRunTasks, self).setUp() self.notifications = [] - self.stubs.Set(rpc, 'cast', self.faux_notify) + self.stubs.Set(publish, 'publish_counter', self.faux_notify) self.mgr = manager.AgentManager() self.mgr.pollsters = [('test', self.Pollster())] self.ctx = context.RequestContext("user", "project") @@ -71,10 +72,3 @@ class TestRunTasks(test.TestCase): def test_message(self): assert self.Pollster.counters[0][1] is self.ctx - - def test_notify(self): - assert len(self.notifications) == 2 - - def test_notify_topics(self): - topics = [n[0] for n in self.notifications] - assert topics == ['metering', 'metering.test'] diff --git a/tests/compute/test_libvirt.py b/tests/compute/test_libvirt.py index a93beb7c..46ac2e5c 100644 --- a/tests/compute/test_libvirt.py +++ b/tests/compute/test_libvirt.py @@ -19,11 +19,13 @@ """Tests for manager. """ -# import unittest -# import mox -# import stubout +try: + import libvirt +except ImportError: + libvirt_missing = True +else: + libvirt_missing = False -# import nova.tests.fakelibvirt as libvirt from nova import context from nova import flags from nova import test @@ -41,9 +43,11 @@ class TestDiskIOPollster(test.TestCase): self.pollster = libvirt.DiskIOPollster() super(TestDiskIOPollster, self).setUp() + @test.skip_if(libvirt_missing, 'Test requires libvirt') def test_fetch_diskio(self): list(self.pollster.get_counters(self.manager, self.context)) + @test.skip_if(libvirt_missing, 'Test requires libvirt') def test_fetch_diskio_with_libvirt_non_existent_instance(self): flags.FLAGS.connection_type = 'libvirt' diff --git a/tests/test_publish.py b/tests/test_publish.py new file mode 100644 index 00000000..b68cb19d --- /dev/null +++ b/tests/test_publish.py @@ -0,0 +1,62 @@ +# -*- encoding: utf-8 -*- +# +# Copyright © 2012 New Dream Network, LLC (DreamHost) +# +# Author: Doug Hellmann +# +# 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/publish.py +""" + +import datetime + +from nova import context +from nova import rpc +from nova import test + +from ceilometer import counter +from ceilometer import publish + + +class TestPublish(test.TestCase): + + test_data = counter.Counter( + source='test', + name='test', + type='cumulative', + volume=1, + user_id='test', + project_id='test', + resource_id='test_run_tasks', + timestamp=datetime.datetime.utcnow().isoformat(), + duration=0, + resource_metadata={'name': 'TestPublish', + }, + ) + + def faux_notify(self, context, topic, msg): + self.notifications.append((topic, msg)) + + def setUp(self): + super(TestPublish, self).setUp() + self.notifications = [] + self.stubs.Set(rpc, 'cast', self.faux_notify) + self.ctx = context.RequestContext("user", "project") + publish.publish_counter(self.ctx, self.test_data) + + def test_notify(self): + assert len(self.notifications) == 2 + + def test_notify_topics(self): + topics = [n[0] for n in self.notifications] + assert topics == ['metering', 'metering.test'] diff --git a/tools/test-requires b/tools/test-requires index 7cbc5d21..23aa4bc8 100644 --- a/tools/test-requires +++ b/tools/test-requires @@ -3,3 +3,4 @@ openstack.nose_plugin coverage pep8>=1.0 mox +glance>=2011.3.1 \ No newline at end of file diff --git a/tox.ini b/tox.ini index a93713be..c1dc90c6 100644 --- a/tox.ini +++ b/tox.ini @@ -10,7 +10,8 @@ setenv = VIRTUAL_ENV={envdir} NOSE_OPENSTACK_SHOW_ELAPSED=1 deps = -r{toxinidir}/tools/pip-requires -r{toxinidir}/tools/test-requires -commands = nosetests +commands = {toxinidir}/run_tests.sh +sitepackages = True [testenv:pep8] deps = pep8