]> review.fuel-infra Code Review - openstack-build/cinder-build.git/commitdiff
Sync notifier changes from openstack-common
authorMark McLoughlin <markmc@redhat.com>
Wed, 5 Sep 2012 11:15:41 +0000 (12:15 +0100)
committerMark McLoughlin <markmc@redhat.com>
Fri, 7 Sep 2012 08:26:59 +0000 (09:26 +0100)
Syncs the following from stable/folsom:

 c767e9b Add multiple-driver support to the notifier api.

Also remove notification_driver from cinder.flags. This should
have been done when first adopting this code from openstack-common
since the option is defined there now.

Note: I've left the cinder-specific change to use cinder's context
rather than openstack-common's context.

Change-Id: I6ff4b5d45ca9cc4acaf37c62c143f2886ebee423

cinder/flags.py
cinder/openstack/common/log.py
cinder/openstack/common/notifier/api.py
cinder/openstack/common/notifier/list_notifier.py [deleted file]
cinder/tests/test_volume.py
cinder/tests/test_volume_utils.py

index d0056364ce9565663b4dd69286b345abd21dd993..ab10537c0a4db5fb75aba17f30ffe43aea49fdeb 100644 (file)
@@ -184,9 +184,9 @@ global_opts = [
     cfg.StrOpt('storage_availability_zone',
                default='cinder',
                help='availability zone of this node'),
-    cfg.StrOpt('notification_driver',
-               default='cinder.openstack.common.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.'),
     cfg.StrOpt('instance_usage_audit_period',
                default='month',
                help='time period to generate instance usages for.  '
index c3520893c8258598c03292d147d9fbe91dadac63..6e46ed383181e1a1a5683d177b793dd3e5b3eee2 100644 (file)
@@ -247,10 +247,9 @@ class JSONFormatter(logging.Formatter):
 
 class PublishErrorsHandler(logging.Handler):
     def emit(self, record):
-        if 'list_notifier_drivers' in CONF:
-            if ('cinder.openstack.common.notifier.log_notifier' in
-                CONF.list_notifier_drivers):
-                return
+        if ('cinder.openstack.common.notifier.log_notifier' in
+            CONF.notification_driver):
+            return
         notifier.api.notify(None, 'error.publisher',
                             'error_notification',
                             notifier.api.ERROR,
index 5479cbeba5fe7e4eb8da0257eb5a03fe81d70061..aea9346329329ed954efbca52f151d17bf97d923 100644 (file)
@@ -27,9 +27,10 @@ from cinder.openstack.common import timeutils
 LOG = logging.getLogger(__name__)
 
 notifier_opts = [
-    cfg.StrOpt('notification_driver',
-               default='cinder.openstack.common.notifier.no_op_notifier',
-               help='Default driver for sending notifications'),
+    cfg.MultiStrOpt('notification_driver',
+                    default=[],
+                    deprecated_name='list_notifier_drivers',
+                    help='Driver or drivers to handle sending notifications'),
     cfg.StrOpt('default_notification_level',
                default='INFO',
                help='Default notification level for outgoing notifications'),
@@ -126,16 +127,55 @@ 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(CONF.notification_driver)
     msg = dict(message_id=str(uuid.uuid4()),
                publisher_id=publisher_id,
                event_type=event_type,
                priority=priority,
                payload=payload,
                timestamp=str(timeutils.utcnow()))
-    try:
-        driver.notify(context, msg)
-    except Exception, e:
-        LOG.exception(_("Problem '%(e)s' attempting to "
-                        "send to notification system. Payload=%(payload)s") %
-                      locals())
+
+    for driver in _get_drivers():
+        try:
+            driver.notify(context, msg)
+        except Exception, e:
+            LOG.exception(_("Problem '%(e)s' attempting to "
+              "send to notification system. Payload=%(payload)s") %
+                            locals())
+
+
+_drivers = None
+
+
+def _get_drivers():
+    """Instantiate, cache, and return drivers based on the CONF."""
+    global _drivers
+    if _drivers is None:
+        _drivers = {}
+        for notification_driver in CONF.notification_driver:
+            add_driver(notification_driver)
+
+    return _drivers.values()
+
+
+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:
+            driver = importutils.import_module(notification_driver)
+            _drivers[notification_driver] = driver
+        except ImportError as e:
+            LOG.exception(_("Failed to load notifier %s. "
+                            "These notifications will not be sent.") %
+                            notification_driver)
+    else:
+        # Driver is already loaded; just add the object.
+        _drivers[notification_driver] = notification_driver
+
+
+def _reset_drivers():
+    """Used by unit tests to reset the drivers."""
+    global _drivers
+    _drivers = None
diff --git a/cinder/openstack/common/notifier/list_notifier.py b/cinder/openstack/common/notifier/list_notifier.py
deleted file mode 100644 (file)
index eb64f8c..0000000
+++ /dev/null
@@ -1,118 +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 cinder.openstack.common import cfg
-from cinder.openstack.common.gettextutils import _
-from cinder.openstack.common import importutils
-from cinder.openstack.common import log as logging
-
-
-list_notifier_drivers_opt = cfg.MultiStrOpt(
-    'list_notifier_drivers',
-    default=['cinder.openstack.common.notifier.no_op_notifier'],
-    help='List of drivers to send notifications')
-
-CONF = cfg.CONF
-CONF.register_opt(list_notifier_drivers_opt)
-
-LOG = logging.getLogger(__name__)
-
-drivers = None
-
-
-class ImportFailureNotifier(object):
-    """Noisily re-raises some exception over-and-over when notify is called."""
-
-    def __init__(self, exception):
-        self.exception = exception
-
-    def notify(self, context, message):
-        raise self.exception
-
-
-def _get_drivers():
-    """Instantiates and returns drivers based on the flag values."""
-    global drivers
-    if drivers is None:
-        drivers = []
-        for notification_driver in CONF.list_notifier_drivers:
-            try:
-                drivers.append(importutils.import_module(notification_driver))
-            except ImportError as e:
-                drivers.append(ImportFailureNotifier(e))
-    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():
-        try:
-            driver.notify(context, message)
-        except Exception as e:
-            LOG.exception(_("Problem '%(e)s' attempting to send to "
-                            "notification driver %(driver)s."), locals())
-
-
-def _reset_drivers():
-    """Used by unit tests to reset the drivers."""
-    global drivers
-    drivers = None
index 8c0513968b6c64fbbbb621a4834fba793d0a440c..5a307ffefe7e12456b4679519c224c3212c73100 100644 (file)
@@ -33,6 +33,7 @@ from cinder import db
 from cinder import flags
 from cinder.tests.image import fake as fake_image
 from cinder.openstack.common import importutils
+from cinder.openstack.common.notifier import api as notifier_api
 from cinder.openstack.common.notifier import test_notifier
 from cinder.openstack.common import rpc
 import cinder.policy
@@ -51,11 +52,10 @@ class VolumeTestCase(test.TestCase):
         super(VolumeTestCase, self).setUp()
         vol_tmpdir = tempfile.mkdtemp()
         self.flags(connection_type='fake',
-                   volumes_dir=vol_tmpdir)
+                   volumes_dir=vol_tmpdir,
+                   notification_driver=[test_notifier.__name__])
         self.volume = importutils.import_object(FLAGS.volume_manager)
         self.context = context.get_admin_context()
-        self.stubs.Set(cinder.flags.FLAGS, 'notification_driver',
-            'cinder.openstack.common.notifier.test_notifier')
         self.stubs.Set(iscsi.TgtAdm, '_get_target', self.fake_get_target)
         fake_image.stub_out_image_service(self.stubs)
         test_notifier.NOTIFICATIONS = []
@@ -65,6 +65,7 @@ class VolumeTestCase(test.TestCase):
             shutil.rmtree(FLAGS.volumes_dir)
         except OSError:
             pass
+        notifier_api._reset_drivers()
         super(VolumeTestCase, self).tearDown()
 
     def fake_get_target(obj, iqn):
index da3205ee354e7c506387cba20bd09f630fde4fb4..3a644d34b0858775961ed4b4aa78b67f59cc3ccd 100644 (file)
@@ -24,6 +24,7 @@ from cinder import test
 from cinder.volume import utils as volume_utils
 from cinder.openstack.common import importutils
 from cinder.openstack.common import log as logging
+from cinder.openstack.common.notifier import api as notifier_api
 from cinder.openstack.common.notifier import test_notifier
 
 
@@ -36,10 +37,8 @@ class UsageInfoTestCase(test.TestCase):
     def setUp(self):
         super(UsageInfoTestCase, self).setUp()
         self.flags(connection_type='fake',
-         host='fake',
-         notification_driver='cinder.openstack.common.notifier.test_notifier')
-        self.stubs.Set(flags.FLAGS, 'notification_driver',
-                'cinder.openstack.common.notifier.test_notifier')
+                   host='fake',
+                   notification_driver=[test_notifier.__name__])
         self.volume = importutils.import_object(FLAGS.volume_manager)
         self.user_id = 'fake'
         self.project_id = 'fake'
@@ -48,6 +47,10 @@ class UsageInfoTestCase(test.TestCase):
         self.context = context.RequestContext(self.user_id, self.project_id)
         test_notifier.NOTIFICATIONS = []
 
+    def tearDown(self):
+        notifier_api._reset_drivers()
+        super(UsageInfoTestCase, self).tearDown()
+
     def _create_volume(self, params={}):
         """Create a test volume"""
         vol = {}