From aa87cc10d6a02d74f1466dc1a4e0e39c1a0878da Mon Sep 17 00:00:00 2001 From: Andrew Bogott Date: Thu, 28 Jun 2012 19:18:20 -0500 Subject: [PATCH] Switch to common notifiers. - Added notifier files to openstack-common.conf, merged from common. - Import notifiers from common rather than nova. - Removed nova-specific notifier code. - Update some driver paths to refer to the new location within nova. Should be a no-op, as the common notification code is freshly copied from Nova. Change-Id: Icdf892bc3826b683fc74f22ead00939beda2859f --- nova/compute/manager.py | 2 +- nova/compute/utils.py | 3 +- nova/flags.py | 3 - nova/network/manager.py | 2 +- nova/notifications.py | 2 +- nova/notifier/capacity_notifier.py | 81 -------- nova/openstack/common/context.py | 81 ++++++++ nova/openstack/common/log.py | 2 +- .../common}/notifier/__init__.py | 0 nova/{ => openstack/common}/notifier/api.py | 23 ++- .../common}/notifier/list_notifier.py | 58 +++++- .../common}/notifier/log_notifier.py | 15 +- .../common}/notifier/no_op_notifier.py | 0 .../common}/notifier/rabbit_notifier.py | 16 +- .../common}/notifier/test_notifier.py | 3 - nova/scheduler/filter_scheduler.py | 2 +- nova/scheduler/manager.py | 2 +- nova/tests/compute/test_compute.py | 4 +- nova/tests/notifier/__init__.py | 16 -- nova/tests/notifier/test_capacity_notifier.py | 59 ------ nova/tests/notifier/test_list_notifier.py | 84 -------- nova/tests/test_compute_utils.py | 4 +- nova/tests/test_notifications.py | 4 +- nova/tests/test_notifier.py | 184 ------------------ nova/tests/test_volume.py | 4 +- nova/tests/test_volume_utils.py | 4 +- nova/volume/utils.py | 2 +- openstack-common.conf | 2 +- 28 files changed, 180 insertions(+), 482 deletions(-) delete mode 100644 nova/notifier/capacity_notifier.py create mode 100644 nova/openstack/common/context.py rename nova/{ => openstack/common}/notifier/__init__.py (100%) rename nova/{ => openstack/common}/notifier/api.py (87%) rename nova/{ => openstack/common}/notifier/list_notifier.py (54%) rename nova/{ => openstack/common}/notifier/log_notifier.py (73%) rename nova/{ => openstack/common}/notifier/no_op_notifier.py (100%) rename nova/{ => openstack/common}/notifier/rabbit_notifier.py (80%) rename nova/{ => openstack/common}/notifier/test_notifier.py (94%) delete mode 100644 nova/tests/notifier/__init__.py delete mode 100644 nova/tests/notifier/test_capacity_notifier.py delete mode 100644 nova/tests/notifier/test_list_notifier.py delete mode 100644 nova/tests/test_notifier.py diff --git a/nova/compute/manager.py b/nova/compute/manager.py index afd422253f2e..cc816bf136f4 100644 --- a/nova/compute/manager.py +++ b/nova/compute/manager.py @@ -62,12 +62,12 @@ from nova import manager from nova import network from nova.network import model as network_model from nova import notifications -from nova.notifier import api as notifier from nova.openstack.common import cfg from nova.openstack.common import excutils from nova.openstack.common import importutils from nova.openstack.common import jsonutils from nova.openstack.common import log as logging +from nova.openstack.common.notifier import api as notifier from nova.openstack.common import rpc from nova.openstack.common import timeutils from nova import utils diff --git a/nova/compute/utils.py b/nova/compute/utils.py index a6a0a8eebd9c..04d8a842c18d 100644 --- a/nova/compute/utils.py +++ b/nova/compute/utils.py @@ -21,9 +21,8 @@ from nova import exception from nova import flags from nova.network import model as network_model from nova import notifications -from nova.notifier import api as notifier_api from nova.openstack.common import log -from nova import utils +from nova.openstack.common.notifier import api as notifier_api FLAGS = flags.FLAGS diff --git a/nova/flags.py b/nova/flags.py index cff3b46ae57c..ec91d8260dbd 100644 --- a/nova/flags.py +++ b/nova/flags.py @@ -316,9 +316,6 @@ global_opts = [ cfg.StrOpt('node_availability_zone', default='nova', help='availability zone of this node'), - cfg.StrOpt('notification_driver', - default='nova.notifier.no_op_notifier', - help='Default driver for sending notifications'), cfg.ListOpt('memcached_servers', default=None, help='Memcached servers or None for in process cache.'), diff --git a/nova/network/manager.py b/nova/network/manager.py index d4937d90bcca..6b2918838cbc 100644 --- a/nova/network/manager.py +++ b/nova/network/manager.py @@ -61,12 +61,12 @@ from nova import ipv6 from nova import manager from nova.network import api as network_api from nova.network import model as network_model -from nova.notifier import api as notifier from nova.openstack.common import cfg from nova.openstack.common import excutils from nova.openstack.common import importutils from nova.openstack.common import jsonutils from nova.openstack.common import log as logging +from nova.openstack.common.notifier import api as notifier from nova.openstack.common import rpc from nova.openstack.common import timeutils import nova.policy diff --git a/nova/notifications.py b/nova/notifications.py index 09e83f823aa5..7ab0f045bd7a 100644 --- a/nova/notifications.py +++ b/nova/notifications.py @@ -25,9 +25,9 @@ from nova import exception from nova import flags from nova import network from nova.network import model as network_model -from nova.notifier import api as notifier_api from nova.openstack.common import cfg from nova.openstack.common import log +from nova.openstack.common.notifier import api as notifier_api from nova.openstack.common import timeutils from nova import utils diff --git a/nova/notifier/capacity_notifier.py b/nova/notifier/capacity_notifier.py deleted file mode 100644 index ea78382d83ff..000000000000 --- a/nova/notifier/capacity_notifier.py +++ /dev/null @@ -1,81 +0,0 @@ -# Copyright 2011 OpenStack LLC. -# All Rights Reserved. -# -# 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. - -from nova import context -from nova import db -from nova.openstack.common import log as logging - - -LOG = logging.getLogger(__name__) - - -def notify(_context, message): - """Look for specific compute manager events and interprete them - so as to keep the Capacity table up to date. - - NOTE: the True/False return codes are only for testing. - """ - - # The event_type must start with 'compute.instance.' - event_type = message.get('event_type', None) - preamble = 'compute.instance.' - if not event_type or not event_type.startswith(preamble): - return False - - # Events we're interested in end with .start and .end - event = event_type[len(preamble):] - parts = event.split('.') - suffix = parts[-1].lower() - event = event[:(-len(suffix) - 1)] - - if suffix not in ['start', 'end']: - return False - started = suffix == 'start' - ended = suffix == 'end' - - if started and event == 'create': - # We've already updated this stuff in the scheduler. Don't redo the - # work here. - return False - - work = 1 if started else -1 - - # Extract the host name from the publisher id ... - publisher_preamble = 'compute.' - publisher = message.get('publisher_id', None) - if not publisher or not publisher.startswith(publisher_preamble): - return False - host = publisher[len(publisher_preamble):] - - # If we deleted an instance, make sure we reclaim the resources. - # We may need to do something explicit for rebuild/migrate. - free_ram_mb = 0 - free_disk_gb = 0 - vms = 0 - if ended and event == 'delete': - vms = -1 - payload = message.get('payload', {}) - free_ram_mb = payload.get('memory_mb', 0) - free_disk_gb = payload.get('disk_gb', 0) - - LOG.debug("EventType=%(event_type)s -> host %(host)s: " - "ram %(free_ram_mb)d, disk %(free_disk_gb)d, " - "work %(work)d, vms%(vms)d" % locals()) - - db.api.compute_node_utilization_update(context.get_admin_context(), host, - free_ram_mb_delta=free_ram_mb, free_disk_gb_delta=free_disk_gb, - work_delta=work, vm_delta=vms) - - return True diff --git a/nova/openstack/common/context.py b/nova/openstack/common/context.py new file mode 100644 index 000000000000..dd7dd04c38a7 --- /dev/null +++ b/nova/openstack/common/context.py @@ -0,0 +1,81 @@ +# vim: tabstop=4 shiftwidth=4 softtabstop=4 + +# Copyright 2011 OpenStack LLC. +# All Rights Reserved. +# +# 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. + +""" +Simple class that stores security context information in the web request. + +Projects should subclass this class if they wish to enhance the request +context or provide additional information in their specific WSGI pipeline. +""" + +import itertools +import uuid + + +def generate_request_id(): + return 'req-' + str(uuid.uuid4()) + + +class RequestContext(object): + + """ + Stores information about the security context under which the user + accesses the system, as well as additional request information. + """ + + def __init__(self, auth_tok=None, user=None, tenant=None, is_admin=False, + read_only=False, show_deleted=False, request_id=None): + self.auth_tok = auth_tok + self.user = user + self.tenant = tenant + self.is_admin = is_admin + self.read_only = read_only + self.show_deleted = show_deleted + if not request_id: + request_id = generate_request_id() + self.request_id = request_id + + def to_dict(self): + return {'user': self.user, + 'tenant': self.tenant, + 'is_admin': self.is_admin, + 'read_only': self.read_only, + 'show_deleted': self.show_deleted, + 'auth_token': self.auth_tok, + 'request_id': self.request_id} + + +def get_admin_context(show_deleted="no"): + context = RequestContext(None, + tenant=None, + is_admin=True, + show_deleted=show_deleted) + return context + + +def get_context_from_function_and_args(function, args, kwargs): + """Find an arg of type RequestContext and return it. + + This is useful in a couple of decorators where we don't + know much about the function we're wrapping. + """ + + for arg in itertools.chain(kwargs.values(), args): + if isinstance(arg, RequestContext): + return arg + + return None diff --git a/nova/openstack/common/log.py b/nova/openstack/common/log.py index 42491b717b4e..b25a4eefcc9b 100644 --- a/nova/openstack/common/log.py +++ b/nova/openstack/common/log.py @@ -40,10 +40,10 @@ import stat import sys import traceback -from nova import notifier from nova.openstack.common import cfg from nova.openstack.common import jsonutils from nova.openstack.common import local +from nova.openstack.common import notifier log_opts = [ diff --git a/nova/notifier/__init__.py b/nova/openstack/common/notifier/__init__.py similarity index 100% rename from nova/notifier/__init__.py rename to nova/openstack/common/notifier/__init__.py diff --git a/nova/notifier/api.py b/nova/openstack/common/notifier/api.py similarity index 87% rename from nova/notifier/api.py rename to nova/openstack/common/notifier/api.py index df3b39a68178..4a09d0ac2208 100644 --- a/nova/notifier/api.py +++ b/nova/openstack/common/notifier/api.py @@ -13,11 +13,11 @@ # License for the specific language governing permissions and limitations # under the License. +import inspect import uuid -from nova import exception -from nova import flags from nova.openstack.common import cfg +from nova.openstack.common import context from nova.openstack.common import importutils from nova.openstack.common import jsonutils from nova.openstack.common import log as logging @@ -27,6 +27,9 @@ from nova.openstack.common import timeutils LOG = logging.getLogger(__name__) notifier_opts = [ + cfg.StrOpt('notification_driver', + default='nova.openstack.common.notifier.no_op_notifier', + help='Default driver for sending notifications'), cfg.StrOpt('default_notification_level', default='INFO', help='Default notification level for outgoing notifications'), @@ -35,8 +38,8 @@ notifier_opts = [ help='Default publisher_id for outgoing notifications'), ] -FLAGS = flags.FLAGS -FLAGS.register_opts(notifier_opts) +CONF = cfg.CONF +CONF.register_opts(notifier_opts) WARN = 'WARN' INFO = 'INFO' @@ -68,11 +71,11 @@ def notify_decorator(name, fn): for key in kwarg: body['kwarg'][key] = kwarg[key] - context = exception.get_context_from_function_and_args(fn, args, kwarg) - notify(context, - FLAGS.default_publisher_id, + ctxt = context.get_context_from_function_and_args(fn, args, kwarg) + notify(ctxt, + CONF.default_publisher_id, name, - FLAGS.default_notification_level, + CONF.default_notification_level, body) return fn(*args, **kwarg) return wrapped_func @@ -80,7 +83,7 @@ def notify_decorator(name, fn): def publisher_id(service, host=None): if not host: - host = FLAGS.host + host = CONF.host return "%s.%s" % (service, host) @@ -123,7 +126,7 @@ def notify(context, publisher_id, event_type, priority, payload): # Ensure everything is JSON serializable. payload = jsonutils.to_primitive(payload, convert_instances=True) - driver = importutils.import_module(FLAGS.notification_driver) + driver = importutils.import_module(CONF.notification_driver) msg = dict(message_id=str(uuid.uuid4()), publisher_id=publisher_id, event_type=event_type, diff --git a/nova/notifier/list_notifier.py b/nova/openstack/common/notifier/list_notifier.py similarity index 54% rename from nova/notifier/list_notifier.py rename to nova/openstack/common/notifier/list_notifier.py index 5aa7738b205b..7c2ec6e6da06 100644 --- a/nova/notifier/list_notifier.py +++ b/nova/openstack/common/notifier/list_notifier.py @@ -13,18 +13,17 @@ # License for the specific language governing permissions and limitations # under the License. -from nova import flags from nova.openstack.common import cfg from nova.openstack.common import importutils from nova.openstack.common import log as logging list_notifier_drivers_opt = cfg.MultiStrOpt('list_notifier_drivers', - default=['nova.notifier.no_op_notifier'], + default=['nova.openstack.common.notifier.no_op_notifier'], help='List of drivers to send notifications') -FLAGS = flags.FLAGS -FLAGS.register_opt(list_notifier_drivers_opt) +CONF = cfg.CONF +CONF.register_opt(list_notifier_drivers_opt) LOG = logging.getLogger(__name__) @@ -44,9 +43,9 @@ class ImportFailureNotifier(object): def _get_drivers(): """Instantiates and returns drivers based on the flag values.""" global drivers - if not drivers: + if drivers is None: drivers = [] - for notification_driver in FLAGS.list_notifier_drivers: + for notification_driver in CONF.list_notifier_drivers: try: drivers.append(importutils.import_module(notification_driver)) except ImportError as e: @@ -54,6 +53,53 @@ def _get_drivers(): return drivers +def add_driver(notification_driver): + """Add a notification driver at runtime.""" + # Make sure the driver list is initialized. + _get_drivers() + if isinstance(notification_driver, basestring): + # Load and add + try: + drivers.append(importutils.import_module(notification_driver)) + except ImportError as e: + drivers.append(ImportFailureNotifier(e)) + else: + # Driver is already loaded; just add the object. + drivers.append(notification_driver) + + +def _object_name(obj): + name = [] + if hasattr(obj, '__module__'): + name.append(obj.__module__) + if hasattr(obj, '__name__'): + name.append(obj.__name__) + else: + name.append(obj.__class__.__name__) + return '.'.join(name) + + +def remove_driver(notification_driver): + """Remove a notification driver at runtime.""" + # Make sure the driver list is initialized. + _get_drivers() + removed = False + if notification_driver in drivers: + # We're removing an object. Easy. + drivers.remove(notification_driver) + removed = True + else: + # We're removing a driver by name. Search for it. + for driver in drivers: + if _object_name(driver) == notification_driver: + drivers.remove(driver) + removed = True + + if not removed: + raise ValueError("Cannot remove; %s is not in list" % + notification_driver) + + def notify(context, message): """Passes notification to multiple notifiers in a list.""" for driver in _get_drivers(): diff --git a/nova/notifier/log_notifier.py b/nova/openstack/common/notifier/log_notifier.py similarity index 73% rename from nova/notifier/log_notifier.py rename to nova/openstack/common/notifier/log_notifier.py index 5ce6dc4af183..5bf0ce3b85ae 100644 --- a/nova/notifier/log_notifier.py +++ b/nova/openstack/common/notifier/log_notifier.py @@ -13,21 +13,22 @@ # License for the specific language governing permissions and limitations # under the License. -from nova import flags -from nova.openstack.common import jsonutils +import json + +from nova.openstack.common import cfg from nova.openstack.common import log as logging -FLAGS = flags.FLAGS +CONF = cfg.CONF def notify(_context, message): """Notifies the recipient of the desired event given the model. - Log notifications using nova's default logging system""" + Log notifications using openstack's default logging system""" priority = message.get('priority', - FLAGS.default_notification_level) + CONF.default_notification_level) priority = priority.lower() logger = logging.getLogger( - 'nova.notification.%s' % message['event_type']) - getattr(logger, priority)(jsonutils.dumps(message)) + 'nova.openstack.common.notification.%s' % message['event_type']) + getattr(logger, priority)(json.dumps(message)) diff --git a/nova/notifier/no_op_notifier.py b/nova/openstack/common/notifier/no_op_notifier.py similarity index 100% rename from nova/notifier/no_op_notifier.py rename to nova/openstack/common/notifier/no_op_notifier.py diff --git a/nova/notifier/rabbit_notifier.py b/nova/openstack/common/notifier/rabbit_notifier.py similarity index 80% rename from nova/notifier/rabbit_notifier.py rename to nova/openstack/common/notifier/rabbit_notifier.py index 867ad9c19b5f..a74e29480fed 100644 --- a/nova/notifier/rabbit_notifier.py +++ b/nova/openstack/common/notifier/rabbit_notifier.py @@ -14,10 +14,8 @@ # under the License. -import nova.context - -from nova import flags from nova.openstack.common import cfg +from nova.openstack.common import context as req_context from nova.openstack.common import log as logging from nova.openstack.common import rpc @@ -25,20 +23,20 @@ LOG = logging.getLogger(__name__) notification_topic_opt = cfg.ListOpt('notification_topics', default=['notifications', ], - help='AMQP topic used for Nova notifications') + help='AMQP topic used for openstack notifications') -FLAGS = flags.FLAGS -FLAGS.register_opt(notification_topic_opt) +CONF = cfg.CONF +CONF.register_opt(notification_topic_opt) def notify(context, message): """Sends a notification to the RabbitMQ""" if not context: - context = nova.context.get_admin_context() + context = req_context.get_admin_context() priority = message.get('priority', - FLAGS.default_notification_level) + CONF.default_notification_level) priority = priority.lower() - for topic in FLAGS.notification_topics: + for topic in CONF.notification_topics: topic = '%s.%s' % (topic, priority) try: rpc.notify(context, topic, message) diff --git a/nova/notifier/test_notifier.py b/nova/openstack/common/notifier/test_notifier.py similarity index 94% rename from nova/notifier/test_notifier.py rename to nova/openstack/common/notifier/test_notifier.py index 3dbaa2dbb0a5..5e348803dc14 100644 --- a/nova/notifier/test_notifier.py +++ b/nova/openstack/common/notifier/test_notifier.py @@ -13,9 +13,6 @@ # License for the specific language governing permissions and limitations # under the License. -from nova import flags - -FLAGS = flags.FLAGS NOTIFICATIONS = [] diff --git a/nova/scheduler/filter_scheduler.py b/nova/scheduler/filter_scheduler.py index c186ceeb40f8..dce7f9ae07fb 100644 --- a/nova/scheduler/filter_scheduler.py +++ b/nova/scheduler/filter_scheduler.py @@ -23,9 +23,9 @@ import operator from nova import exception from nova import flags -from nova.notifier import api as notifier from nova.openstack.common import importutils from nova.openstack.common import log as logging +from nova.openstack.common.notifier import api as notifier from nova.scheduler import driver from nova.scheduler import least_cost from nova.scheduler import scheduler_options diff --git a/nova/scheduler/manager.py b/nova/scheduler/manager.py index 436df0946adf..b0ab8bc38c01 100644 --- a/nova/scheduler/manager.py +++ b/nova/scheduler/manager.py @@ -29,11 +29,11 @@ from nova import exception from nova import flags from nova import manager from nova import notifications -from nova.notifier import api as notifier from nova.openstack.common import cfg from nova.openstack.common import excutils from nova.openstack.common import importutils from nova.openstack.common import log as logging +from nova.openstack.common.notifier import api as notifier from nova import quota diff --git a/nova/tests/compute/test_compute.py b/nova/tests/compute/test_compute.py index 784054d0e55c..bbf000836fb6 100644 --- a/nova/tests/compute/test_compute.py +++ b/nova/tests/compute/test_compute.py @@ -39,9 +39,9 @@ from nova import context from nova import db from nova import exception from nova import flags -from nova.notifier import test_notifier from nova.openstack.common import importutils from nova.openstack.common import log as logging +from nova.openstack.common.notifier import test_notifier from nova.openstack.common import policy as common_policy from nova.openstack.common import rpc from nova.openstack.common.rpc import common as rpc_common @@ -109,7 +109,7 @@ class BaseTestCase(test.TestCase): super(BaseTestCase, self).setUp() self.flags(compute_driver='nova.virt.fake.FakeDriver', stub_network=True, - notification_driver='nova.notifier.test_notifier', + notification_driver='nova.openstack.common.notifier.test_notifier', network_manager='nova.network.manager.FlatManager') self.compute = importutils.import_object(FLAGS.compute_manager) diff --git a/nova/tests/notifier/__init__.py b/nova/tests/notifier/__init__.py deleted file mode 100644 index 3fdfb7550bf9..000000000000 --- a/nova/tests/notifier/__init__.py +++ /dev/null @@ -1,16 +0,0 @@ -# Copyright 2011 OpenStack LLC. -# All Rights Reserved. -# -# 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. - -from nova.tests import * diff --git a/nova/tests/notifier/test_capacity_notifier.py b/nova/tests/notifier/test_capacity_notifier.py deleted file mode 100644 index 3b642a77b7c5..000000000000 --- a/nova/tests/notifier/test_capacity_notifier.py +++ /dev/null @@ -1,59 +0,0 @@ -# Copyright 2011 OpenStack LLC. -# All Rights Reserved. -# -# 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. - -import nova.db.api -from nova.notifier import capacity_notifier as cn -from nova.openstack.common import jsonutils -from nova import test - - -class CapacityNotifierTestCase(test.TestCase): - """Test case for the Capacity updating notifier.""" - - def _make_msg(self, host, event): - usage_info = dict(memory_mb=123, disk_gb=456) - payload = jsonutils.to_primitive(usage_info, convert_instances=True) - return dict( - publisher_id="compute.%s" % host, - event_type="compute.instance.%s" % event, - payload=payload - ) - - def test_event_type(self): - msg = self._make_msg("myhost", "mymethod") - msg['event_type'] = 'random' - self.assertFalse(cn.notify(None, msg)) - - def test_bad_event_suffix(self): - msg = self._make_msg("myhost", "mymethod.badsuffix") - self.assertFalse(cn.notify(None, msg)) - - def test_bad_publisher_id(self): - msg = self._make_msg("myhost", "mymethod.start") - msg['publisher_id'] = 'badpublisher' - self.assertFalse(cn.notify(None, msg)) - - def test_update_called(self): - def _verify_called(host, context, free_ram_mb_delta, - free_disk_gb_delta, work_delta, vm_delta): - self.assertEquals(free_ram_mb_delta, 123) - self.assertEquals(free_disk_gb_delta, 456) - self.assertEquals(vm_delta, -1) - self.assertEquals(work_delta, -1) - - self.stubs.Set(nova.db.api, "compute_node_utilization_update", - _verify_called) - msg = self._make_msg("myhost", "delete.end") - self.assertTrue(cn.notify(None, msg)) diff --git a/nova/tests/notifier/test_list_notifier.py b/nova/tests/notifier/test_list_notifier.py deleted file mode 100644 index bb14fa80ea94..000000000000 --- a/nova/tests/notifier/test_list_notifier.py +++ /dev/null @@ -1,84 +0,0 @@ -# Copyright 2011 OpenStack LLC. -# All Rights Reserved. -# -# 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. - -import nova -import nova.notifier.api -from nova.notifier import list_notifier -import nova.notifier.log_notifier -import nova.notifier.no_op_notifier -from nova.openstack.common import log as logging -from nova import test - - -class NotifierListTestCase(test.TestCase): - """Test case for notifications""" - - def setUp(self): - super(NotifierListTestCase, self).setUp() - list_notifier._reset_drivers() - # Mock log to add one to exception_count when log.exception is called - - def mock_exception(cls, *args): - self.exception_count += 1 - - self.exception_count = 0 - list_notifier_log = logging.getLogger('nova.notifier.list_notifier') - self.stubs.Set(list_notifier_log, "exception", mock_exception) - # Mock no_op notifier to add one to notify_count when called. - - def mock_notify(cls, *args): - self.notify_count += 1 - - self.notify_count = 0 - self.stubs.Set(nova.notifier.no_op_notifier, 'notify', mock_notify) - # Mock log_notifier to raise RuntimeError when called. - - def mock_notify2(cls, *args): - raise RuntimeError("Bad notifier.") - - self.stubs.Set(nova.notifier.log_notifier, 'notify', mock_notify2) - - def tearDown(self): - list_notifier._reset_drivers() - super(NotifierListTestCase, self).tearDown() - - def test_send_notifications_successfully(self): - self.flags(notification_driver='nova.notifier.list_notifier', - list_notifier_drivers=['nova.notifier.no_op_notifier', - 'nova.notifier.no_op_notifier']) - nova.notifier.api.notify('contextarg', 'publisher_id', 'event_type', - nova.notifier.api.WARN, dict(a=3)) - self.assertEqual(self.notify_count, 2) - self.assertEqual(self.exception_count, 0) - - def test_send_notifications_with_errors(self): - - self.flags(notification_driver='nova.notifier.list_notifier', - list_notifier_drivers=['nova.notifier.no_op_notifier', - 'nova.notifier.log_notifier']) - nova.notifier.api.notify('contextarg', 'publisher_id', - 'event_type', nova.notifier.api.WARN, dict(a=3)) - self.assertEqual(self.notify_count, 1) - self.assertEqual(self.exception_count, 1) - - def test_when_driver_fails_to_import(self): - self.flags(notification_driver='nova.notifier.list_notifier', - list_notifier_drivers=['nova.notifier.no_op_notifier', - 'nova.notifier.logo_notifier', - 'fdsjgsdfhjkhgsfkj']) - nova.notifier.api.notify('contextarg', 'publisher_id', - 'event_type', nova.notifier.api.WARN, dict(a=3)) - self.assertEqual(self.exception_count, 2) - self.assertEqual(self.notify_count, 1) diff --git a/nova/tests/test_compute_utils.py b/nova/tests/test_compute_utils.py index 5081536acfe3..c3f06d11c22e 100644 --- a/nova/tests/test_compute_utils.py +++ b/nova/tests/test_compute_utils.py @@ -22,9 +22,9 @@ from nova.compute import utils as compute_utils from nova import context from nova import db from nova import flags -from nova.notifier import test_notifier from nova.openstack.common import importutils from nova.openstack.common import log as logging +from nova.openstack.common.notifier import test_notifier from nova import test from nova.tests import fake_network import nova.tests.image.fake @@ -50,7 +50,7 @@ class UsageInfoTestCase(test.TestCase): self.flags(compute_driver='nova.virt.fake.FakeDriver', stub_network=True, - notification_driver='nova.notifier.test_notifier', + notification_driver='nova.openstack.common.notifier.test_notifier', network_manager='nova.network.manager.FlatManager') self.compute = importutils.import_object(FLAGS.compute_manager) self.user_id = 'fake' diff --git a/nova/tests/test_notifications.py b/nova/tests/test_notifications.py index cf12d5629c94..1b5a83ef2814 100644 --- a/nova/tests/test_notifications.py +++ b/nova/tests/test_notifications.py @@ -27,8 +27,8 @@ from nova import db from nova import flags import nova.network from nova import notifications -from nova.notifier import test_notifier from nova.openstack.common import log as logging +from nova.openstack.common.notifier import test_notifier from nova import test from nova.tests import fake_network @@ -52,7 +52,7 @@ class NotificationsTestCase(test.TestCase): self.flags(compute_driver='nova.virt.fake.FakeDriver', stub_network=True, - notification_driver='nova.notifier.test_notifier', + notification_driver='nova.openstack.common.notifier.test_notifier', network_manager='nova.network.manager.FlatManager', notify_on_state_change="vm_and_task_state", host='testhost') diff --git a/nova/tests/test_notifier.py b/nova/tests/test_notifier.py deleted file mode 100644 index f7f54f374ed0..000000000000 --- a/nova/tests/test_notifier.py +++ /dev/null @@ -1,184 +0,0 @@ -# Copyright 2011 OpenStack LLC. -# All Rights Reserved. -# -# 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. - -import nova -from nova import context -from nova import flags -from nova.notifier import api as notifier_api -import nova.notifier.no_op_notifier -from nova.openstack.common import log -from nova import test - - -ctxt = context.get_admin_context() -ctxt2 = context.get_admin_context() - - -class NotifierTestCase(test.TestCase): - """Test case for notifications""" - def setUp(self): - super(NotifierTestCase, self).setUp() - self.flags(notification_driver='nova.notifier.no_op_notifier') - - def test_send_notification(self): - self.notify_called = False - - def mock_notify(cls, *args): - self.notify_called = True - - self.stubs.Set(nova.notifier.no_op_notifier, 'notify', - mock_notify) - - notifier_api.notify(ctxt, 'publisher_id', 'event_type', - nova.notifier.api.WARN, dict(a=3)) - self.assertEqual(self.notify_called, True) - - def test_verify_message_format(self): - """A test to ensure changing the message format is prohibitively - annoying""" - - def message_assert(context, message): - fields = [('publisher_id', 'publisher_id'), - ('event_type', 'event_type'), - ('priority', 'WARN'), - ('payload', dict(a=3))] - for k, v in fields: - self.assertEqual(message[k], v) - self.assertTrue(len(message['message_id']) > 0) - self.assertTrue(len(message['timestamp']) > 0) - self.assertEqual(context, ctxt) - - self.stubs.Set(nova.notifier.no_op_notifier, 'notify', - message_assert) - notifier_api.notify(ctxt, 'publisher_id', 'event_type', - nova.notifier.api.WARN, dict(a=3)) - - def test_send_rabbit_notification(self): - self.stubs.Set(nova.flags.FLAGS, 'notification_driver', - 'nova.notifier.rabbit_notifier') - self.mock_notify = False - - def mock_notify(cls, *args): - self.mock_notify = True - - self.stubs.Set(nova.openstack.common.rpc, 'notify', mock_notify) - notifier_api.notify(ctxt, 'publisher_id', 'event_type', - nova.notifier.api.WARN, dict(a=3)) - - self.assertEqual(self.mock_notify, True) - - def test_invalid_priority(self): - self.assertRaises(nova.notifier.api.BadPriorityException, - notifier_api.notify, ctxt, 'publisher_id', - 'event_type', 'not a priority', dict(a=3)) - - def test_rabbit_priority_queue(self): - flags.DECLARE('notification_topics', 'nova.notifier.rabbit_notifier') - self.stubs.Set(nova.flags.FLAGS, 'notification_driver', - 'nova.notifier.rabbit_notifier') - self.stubs.Set(nova.flags.FLAGS, 'notification_topics', - ['testnotify', ]) - - self.test_topic = None - - def mock_notify(context, topic, msg): - self.test_topic = topic - - self.stubs.Set(nova.openstack.common.rpc, 'notify', mock_notify) - notifier_api.notify(ctxt, 'publisher_id', - 'event_type', 'DEBUG', dict(a=3)) - self.assertEqual(self.test_topic, 'testnotify.debug') - - def test_error_notification(self): - self.stubs.Set(nova.flags.FLAGS, 'notification_driver', - 'nova.notifier.rabbit_notifier') - self.stubs.Set(nova.flags.FLAGS, 'publish_errors', True) - LOG = log.getLogger('nova') - log.setup('nova') - msgs = [] - - def mock_notify(context, topic, data): - msgs.append(data) - - self.stubs.Set(nova.openstack.common.rpc, 'notify', mock_notify) - LOG.error('foo') - self.assertEqual(1, len(msgs)) - msg = msgs[0] - self.assertEqual(msg['event_type'], 'error_notification') - self.assertEqual(msg['priority'], 'ERROR') - self.assertEqual(msg['payload']['error'], 'foo') - - def test_send_notification_by_decorator(self): - self.notify_called = False - - def example_api(arg1, arg2): - return arg1 + arg2 - - example_api = nova.notifier.api.notify_decorator( - 'example_api', - example_api) - - def mock_notify(cls, *args): - self.notify_called = True - - self.stubs.Set(nova.notifier.no_op_notifier, 'notify', - mock_notify) - - self.assertEqual(3, example_api(1, 2)) - self.assertEqual(self.notify_called, True) - - def test_decorator_context(self): - """Verify that the notify decorator can extract the 'context' arg.""" - self.notify_called = False - self.context_arg = None - - def example_api(arg1, arg2, context): - return arg1 + arg2 - - def example_api2(arg1, arg2, **kw): - return arg1 + arg2 - - example_api = nova.notifier.api.notify_decorator( - 'example_api', - example_api) - - example_api2 = nova.notifier.api.notify_decorator( - 'example_api2', - example_api2) - - def mock_notify(context, cls, _type, _priority, _payload): - self.notify_called = True - self.context_arg = context - - self.stubs.Set(nova.notifier.api, 'notify', - mock_notify) - - # Test positional context - self.assertEqual(3, example_api(1, 2, ctxt)) - self.assertEqual(self.notify_called, True) - self.assertEqual(self.context_arg, ctxt) - - self.notify_called = False - self.context_arg = None - - # Test named context - self.assertEqual(3, example_api2(1, 2, context=ctxt2)) - self.assertEqual(self.notify_called, True) - self.assertEqual(self.context_arg, ctxt2) - - # Test missing context - self.assertEqual(3, example_api2(1, 2, bananas="delicious")) - self.assertEqual(self.notify_called, True) - self.assertEqual(self.context_arg, None) diff --git a/nova/tests/test_volume.py b/nova/tests/test_volume.py index 2e149f950e79..921dc68f5f7a 100644 --- a/nova/tests/test_volume.py +++ b/nova/tests/test_volume.py @@ -28,9 +28,9 @@ from nova import context from nova import db from nova import exception from nova import flags -from nova.notifier import test_notifier from nova.openstack.common import importutils from nova.openstack.common import log as logging +from nova.openstack.common.notifier import test_notifier from nova.openstack.common import rpc import nova.policy from nova import quota @@ -50,7 +50,7 @@ class VolumeTestCase(test.TestCase): self.compute = importutils.import_object(FLAGS.compute_manager) self.flags(compute_driver='nova.virt.fake.FakeDriver') self.stubs.Set(nova.flags.FLAGS, 'notification_driver', - 'nova.notifier.test_notifier') + 'nova.openstack.common.notifier.test_notifier') self.volume = importutils.import_object(FLAGS.volume_manager) self.context = context.get_admin_context() instance = db.instance_create(self.context, {}) diff --git a/nova/tests/test_volume_utils.py b/nova/tests/test_volume_utils.py index 1db0f9eef804..8d0caab2448d 100644 --- a/nova/tests/test_volume_utils.py +++ b/nova/tests/test_volume_utils.py @@ -20,9 +20,9 @@ from nova import context from nova import db from nova import flags -from nova.notifier import test_notifier from nova.openstack.common import importutils from nova.openstack.common import log as logging +from nova.openstack.common.notifier import test_notifier from nova import test from nova.volume import utils as volume_utils @@ -39,7 +39,7 @@ class UsageInfoTestCase(test.TestCase): stub_network=True, host='fake') self.stubs.Set(flags.FLAGS, 'notification_driver', - 'nova.notifier.test_notifier') + 'nova.openstack.common.notifier.test_notifier') self.volume = importutils.import_object(FLAGS.volume_manager) self.user_id = 'fake' self.project_id = 'fake' diff --git a/nova/volume/utils.py b/nova/volume/utils.py index dcaa141f5103..c1367114dfd8 100644 --- a/nova/volume/utils.py +++ b/nova/volume/utils.py @@ -17,8 +17,8 @@ """Volume-related Utilities and helpers.""" from nova import flags -from nova.notifier import api as notifier_api from nova.openstack.common import log as logging +from nova.openstack.common.notifier import api as notifier_api from nova.openstack.common import timeutils from nova import utils diff --git a/openstack-common.conf b/openstack-common.conf index 4eb15e0f2d7c..25f0a1d08d83 100644 --- a/openstack-common.conf +++ b/openstack-common.conf @@ -1,7 +1,7 @@ [DEFAULT] # The list of modules to copy from openstack-common -modules=cfg,excutils,gettextutils,importutils,iniparser,jsonutils,local,log,policy,setup,timeutils,rpc +modules=cfg,context,excutils,gettextutils,importutils,iniparser,jsonutils,local,log,notifier,policy,setup,timeutils,rpc # The base module to hold the copy of openstack.common base=nova