From a4c8e71e0895f6652d1e2c8fbb06b6b2447b6086 Mon Sep 17 00:00:00 2001 From: Chmouel Boudjnah Date: Mon, 6 Aug 2012 10:25:31 +0200 Subject: [PATCH] Use openstack.common.notifier. - Update openstack.common.log to use it (and fixes #1030078 for cinder as well so we can get review I9d4251b4292188c0174ebac1dcd98318df44c0e3 working). - Don't use openstack.common.context but our own just yet. Change-Id: I10feda623788a3b2418cad6bf55cbdb860ba8ee7 --- cinder/exception.py | 7 +- cinder/flags.py | 2 +- cinder/notifier/capacity_notifier.py | 81 ----------- cinder/notifier/list_notifier.py | 71 ---------- cinder/openstack/common/cfg.py | 5 +- cinder/openstack/common/exception.py | 1 - cinder/openstack/common/jsonutils.py | 6 +- cinder/openstack/common/log.py | 37 +++-- .../common}/notifier/__init__.py | 0 cinder/{ => openstack/common}/notifier/api.py | 49 ++++--- .../common/notifier/list_notifier.py | 118 ++++++++++++++++ .../common}/notifier/log_notifier.py | 15 +- .../common}/notifier/no_op_notifier.py | 2 +- .../common}/notifier/rabbit_notifier.py | 26 ++-- .../common}/notifier/test_notifier.py | 5 +- cinder/openstack/common/rpc/common.py | 6 +- cinder/openstack/common/rpc/impl_qpid.py | 2 +- cinder/openstack/common/rpc/proxy.py | 12 +- cinder/openstack/common/setup.py | 6 +- cinder/openstack/common/timeutils.py | 1 - cinder/tests/notifier/__init__.py | 16 --- cinder/tests/notifier/test_list_notifier.py | 84 ----------- cinder/tests/scheduler/test_scheduler.py | 2 +- cinder/tests/test_exception.py | 2 +- cinder/tests/test_notifier.py | 133 ------------------ cinder/utils.py | 5 +- etc/cinder/cinder.conf.sample | 10 +- openstack-common.conf | 2 +- 28 files changed, 222 insertions(+), 484 deletions(-) delete mode 100644 cinder/notifier/capacity_notifier.py delete mode 100644 cinder/notifier/list_notifier.py rename cinder/{ => openstack/common}/notifier/__init__.py (100%) rename cinder/{ => openstack/common}/notifier/api.py (77%) create mode 100644 cinder/openstack/common/notifier/list_notifier.py rename cinder/{ => openstack/common}/notifier/log_notifier.py (76%) rename cinder/{ => openstack/common}/notifier/no_op_notifier.py (95%) rename cinder/{ => openstack/common}/notifier/rabbit_notifier.py (69%) rename cinder/{ => openstack/common}/notifier/test_notifier.py (91%) delete mode 100644 cinder/tests/notifier/__init__.py delete mode 100644 cinder/tests/notifier/test_list_notifier.py delete mode 100644 cinder/tests/test_notifier.py diff --git a/cinder/exception.py b/cinder/exception.py index 5cf10a15f..65241d5d6 100644 --- a/cinder/exception.py +++ b/cinder/exception.py @@ -91,9 +91,10 @@ def wrap_exception(notifier=None, publisher_id=None, event_type=None, get thrown. It logs the exception as well as optionally sending it to the notification system. """ - # TODO(sandy): Find a way to import cinder.notifier.api so we don't have - # to pass it in as a parameter. Otherwise we get a cyclic import of - # cinder.notifier.api -> cinder.utils -> cinder.exception :( + # TODO(sandy): Find a way to import cinder.openstackc.common.notifier.api + # so we don't have to pass it in as a parameter. Otherwise we get a cyclic + # import of cinder.openstack.common.notifier.api -> cinder.utils -> + # cinder.exception :( # TODO(johannes): Also, it would be nice to use # utils.save_and_reraise_exception() without an import loop def inner(f): diff --git a/cinder/flags.py b/cinder/flags.py index 673aae394..fa2c33cb8 100644 --- a/cinder/flags.py +++ b/cinder/flags.py @@ -222,7 +222,7 @@ global_opts = [ default='cinder', help='availability zone of this node'), cfg.StrOpt('notification_driver', - default='cinder.notifier.no_op_notifier', + default='cinder.openstack.common.notifier.no_op_notifier', help='Default driver for sending notifications'), cfg.ListOpt('memcached_servers', default=None, diff --git a/cinder/notifier/capacity_notifier.py b/cinder/notifier/capacity_notifier.py deleted file mode 100644 index 9a3ed5c3b..000000000 --- a/cinder/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 cinder import context -from cinder import db -from cinder.openstack.common import log as logging - - -LOG = logging.getLogger(__name__) - - -def notify(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/cinder/notifier/list_notifier.py b/cinder/notifier/list_notifier.py deleted file mode 100644 index e0756719a..000000000 --- a/cinder/notifier/list_notifier.py +++ /dev/null @@ -1,71 +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 import flags -from cinder.openstack.common import log as logging -from cinder.openstack.common import cfg -from cinder.openstack.common import exception as common_exception -from cinder.openstack.common import importutils - - -list_notifier_drivers_opt = cfg.MultiStrOpt('list_notifier_drivers', - default=['cinder.notifier.no_op_notifier'], - help='List of drivers to send notifications') - -FLAGS = flags.FLAGS -FLAGS.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, message): - raise self.exception - - -def _get_drivers(): - """Instantiates and returns drivers based on the flag values.""" - global drivers - if not drivers: - drivers = [] - for notification_driver in FLAGS.list_notifier_drivers: - try: - drivers.append(importutils.import_module(notification_driver)) - except ImportError as e: - drivers.append(ImportFailureNotifier(e)) - return drivers - - -def notify(message): - """Passes notification to multiple notifiers in a list.""" - for driver in _get_drivers(): - try: - driver.notify(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 diff --git a/cinder/openstack/common/cfg.py b/cinder/openstack/common/cfg.py index 52e242d55..095115aa3 100644 --- a/cinder/openstack/common/cfg.py +++ b/cinder/openstack/common/cfg.py @@ -464,7 +464,7 @@ def _is_opt_registered(opts, opt): :raises: DuplicateOptError if a naming conflict is detected """ if opt.dest in opts: - if opts[opt.dest]['opt'] is not opt: + if opts[opt.dest]['opt'] != opt: raise DuplicateOptError(opt.name) return True else: @@ -527,6 +527,9 @@ class Opt(object): else: self.deprecated_name = None + def __ne__(self, another): + return vars(self) != vars(another) + def _get_from_config_parser(self, cparser, section): """Retrieves the option value from a MultiConfigParser object. diff --git a/cinder/openstack/common/exception.py b/cinder/openstack/common/exception.py index e5da94b94..ba32da550 100644 --- a/cinder/openstack/common/exception.py +++ b/cinder/openstack/common/exception.py @@ -19,7 +19,6 @@ Exceptions common to OpenStack projects """ -import itertools import logging diff --git a/cinder/openstack/common/jsonutils.py b/cinder/openstack/common/jsonutils.py index 7cf8bbda2..bab6a3651 100644 --- a/cinder/openstack/common/jsonutils.py +++ b/cinder/openstack/common/jsonutils.py @@ -107,9 +107,11 @@ def to_primitive(value, convert_instances=False, level=0): elif hasattr(value, 'iteritems'): return to_primitive(dict(value.iteritems()), convert_instances=convert_instances, - level=level) + level=level + 1) elif hasattr(value, '__iter__'): - return to_primitive(list(value), level) + return to_primitive(list(value), + convert_instances=convert_instances, + level=level) elif convert_instances and hasattr(value, '__dict__'): # Likely an instance of something. Watch for cycles. # Ignore class member vars. diff --git a/cinder/openstack/common/log.py b/cinder/openstack/common/log.py index 5dbadb27a..c3520893c 100644 --- a/cinder/openstack/common/log.py +++ b/cinder/openstack/common/log.py @@ -44,7 +44,7 @@ from cinder.openstack.common import cfg from cinder.openstack.common.gettextutils import _ from cinder.openstack.common import jsonutils from cinder.openstack.common import local -from cinder import notifier +from cinder.openstack.common import notifier log_opts = [ @@ -251,22 +251,24 @@ class PublishErrorsHandler(logging.Handler): if ('cinder.openstack.common.notifier.log_notifier' in CONF.list_notifier_drivers): return - notifier.api.notify('error.publisher', + notifier.api.notify(None, 'error.publisher', 'error_notification', notifier.api.ERROR, dict(error=record.msg)) -def handle_exception(type, value, tb): - extra = {} - if CONF.verbose: - extra['exc_info'] = (type, value, tb) - getLogger().critical(str(value), **extra) +def _create_logging_excepthook(product_name): + def logging_excepthook(type, value, tb): + extra = {} + if CONF.verbose: + extra['exc_info'] = (type, value, tb) + getLogger(product_name).critical(str(value), **extra) + return logging_excepthook def setup(product_name): """Setup logging.""" - sys.excepthook = handle_exception + sys.excepthook = _create_logging_excepthook(product_name) if CONF.log_config: try: @@ -357,17 +359,6 @@ def _setup_logging_from_conf(product_name): for handler in log_root.handlers: logger.addHandler(handler) - # NOTE(jkoelker) Clear the handlers for the root logger that was setup - # by basicConfig in nova/__init__.py and install the - # NullHandler. - root = logging.getLogger() - for handler in root.handlers: - root.removeHandler(handler) - handler = NullHandler() - handler.setFormatter(logging.Formatter()) - root.addHandler(handler) - - _loggers = {} @@ -405,8 +396,12 @@ class LegacyFormatter(logging.Formatter): def format(self, record): """Uses contextstring if request_id is set, otherwise default.""" - if 'instance' not in record.__dict__: - record.__dict__['instance'] = '' + # NOTE(sdague): default the fancier formating params + # to an empty string so we don't throw an exception if + # they get used + for key in ('instance', 'color'): + if key not in record.__dict__: + record.__dict__[key] = '' if record.__dict__.get('request_id', None): self._fmt = CONF.logging_context_format_string diff --git a/cinder/notifier/__init__.py b/cinder/openstack/common/notifier/__init__.py similarity index 100% rename from cinder/notifier/__init__.py rename to cinder/openstack/common/notifier/__init__.py diff --git a/cinder/notifier/api.py b/cinder/openstack/common/notifier/api.py similarity index 77% rename from cinder/notifier/api.py rename to cinder/openstack/common/notifier/api.py index 327bd9714..c69296681 100644 --- a/cinder/notifier/api.py +++ b/cinder/openstack/common/notifier/api.py @@ -13,30 +13,34 @@ # License for the specific language governing permissions and limitations # under the License. +import inspect import uuid -from cinder import flags -from cinder import utils -from cinder.openstack.common import log as logging from cinder.openstack.common import cfg +from cinder import context +from cinder.openstack.common.gettextutils import _ from cinder.openstack.common import importutils from cinder.openstack.common import jsonutils +from cinder.openstack.common import log as logging 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.StrOpt('default_notification_level', default='INFO', help='Default notification level for outgoing notifications'), cfg.StrOpt('default_publisher_id', default='$host', 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' @@ -67,21 +71,24 @@ def notify_decorator(name, fn): body['args'].append(arg) for key in kwarg: body['kwarg'][key] = kwarg[key] - notify(FLAGS.default_publisher_id, - name, - FLAGS.default_notification_level, - body) + + ctxt = context.get_context_from_function_and_args(fn, args, kwarg) + notify(ctxt, + CONF.default_publisher_id, + name, + CONF.default_notification_level, + body) return fn(*args, **kwarg) return wrapped_func def publisher_id(service, host=None): if not host: - host = FLAGS.host + host = CONF.host return "%s.%s" % (service, host) -def notify(publisher_id, event_type, priority, payload): +def notify(context, publisher_id, event_type, priority, payload): """Sends a notification using the specified driver :param publisher_id: the source worker_type.host of the message @@ -115,21 +122,21 @@ def notify(publisher_id, event_type, priority, payload): """ if priority not in log_levels: raise BadPriorityException( - _('%s not in valid priorities') % priority) + _('%s not in valid priorities') % priority) # 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, - priority=priority, - payload=payload, - timestamp=str(timeutils.utcnow())) + publisher_id=publisher_id, + event_type=event_type, + priority=priority, + payload=payload, + timestamp=str(timeutils.utcnow())) try: - driver.notify(msg) + driver.notify(context, msg) except Exception, e: LOG.exception(_("Problem '%(e)s' attempting to " "send to notification system. Payload=%(payload)s") % - locals()) + locals()) diff --git a/cinder/openstack/common/notifier/list_notifier.py b/cinder/openstack/common/notifier/list_notifier.py new file mode 100644 index 000000000..eb64f8cc3 --- /dev/null +++ b/cinder/openstack/common/notifier/list_notifier.py @@ -0,0 +1,118 @@ +# 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 diff --git a/cinder/notifier/log_notifier.py b/cinder/openstack/common/notifier/log_notifier.py similarity index 76% rename from cinder/notifier/log_notifier.py rename to cinder/openstack/common/notifier/log_notifier.py index 47bf016b9..ae9b45b28 100644 --- a/cinder/notifier/log_notifier.py +++ b/cinder/openstack/common/notifier/log_notifier.py @@ -14,21 +14,22 @@ # under the License. -from cinder import flags -from cinder.openstack.common import log as logging +from cinder.openstack.common import cfg from cinder.openstack.common import jsonutils +from cinder.openstack.common import log as logging -FLAGS = flags.FLAGS +CONF = cfg.CONF -def notify(message): +def notify(_context, message): """Notifies the recipient of the desired event given the model. - Log notifications using cinder'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( - 'cinder.notification.%s' % message['event_type']) + 'cinder.openstack.common.notification.%s' % + message['event_type']) getattr(logger, priority)(jsonutils.dumps(message)) diff --git a/cinder/notifier/no_op_notifier.py b/cinder/openstack/common/notifier/no_op_notifier.py similarity index 95% rename from cinder/notifier/no_op_notifier.py rename to cinder/openstack/common/notifier/no_op_notifier.py index 029710505..ee1ddbdca 100644 --- a/cinder/notifier/no_op_notifier.py +++ b/cinder/openstack/common/notifier/no_op_notifier.py @@ -14,6 +14,6 @@ # under the License. -def notify(message): +def notify(_context, message): """Notifies the recipient of the desired event given the model""" pass diff --git a/cinder/notifier/rabbit_notifier.py b/cinder/openstack/common/notifier/rabbit_notifier.py similarity index 69% rename from cinder/notifier/rabbit_notifier.py rename to cinder/openstack/common/notifier/rabbit_notifier.py index 098ed904d..89b69ca7e 100644 --- a/cinder/notifier/rabbit_notifier.py +++ b/cinder/openstack/common/notifier/rabbit_notifier.py @@ -14,30 +14,30 @@ # under the License. -import cinder.context - -from cinder import flags -from cinder.openstack.common import log as logging from cinder.openstack.common import cfg +from cinder.openstack.common import context as req_context +from cinder.openstack.common.gettextutils import _ +from cinder.openstack.common import log as logging from cinder.openstack.common import rpc LOG = logging.getLogger(__name__) -notification_topic_opt = cfg.ListOpt('notification_topics', - default=['notifications', ], - help='AMQP topic used for Cinder notifications') +notification_topic_opt = cfg.ListOpt( + 'notification_topics', default=['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(message): +def notify(context, message): """Sends a notification to the RabbitMQ""" - context = cinder.context.get_admin_context() + if not 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/cinder/notifier/test_notifier.py b/cinder/openstack/common/notifier/test_notifier.py similarity index 91% rename from cinder/notifier/test_notifier.py rename to cinder/openstack/common/notifier/test_notifier.py index 6624a90aa..5e348803d 100644 --- a/cinder/notifier/test_notifier.py +++ b/cinder/openstack/common/notifier/test_notifier.py @@ -13,13 +13,10 @@ # License for the specific language governing permissions and limitations # under the License. -from cinder import flags - -FLAGS = flags.FLAGS NOTIFICATIONS = [] -def notify(message): +def notify(_context, message): """Test notifier, stores notifications in memory for unittests.""" NOTIFICATIONS.append(message) diff --git a/cinder/openstack/common/rpc/common.py b/cinder/openstack/common/rpc/common.py index 5674490fc..409e0f12d 100644 --- a/cinder/openstack/common/rpc/common.py +++ b/cinder/openstack/common/rpc/common.py @@ -108,7 +108,7 @@ class Connection(object): """ raise NotImplementedError() - def create_consumer(self, conf, topic, proxy, fanout=False): + def create_consumer(self, topic, proxy, fanout=False): """Create a consumer on this connection. A consumer is associated with a message queue on the backend message @@ -117,7 +117,6 @@ class Connection(object): off of the queue will determine which method gets called on the proxy object. - :param conf: An openstack.common.cfg configuration object. :param topic: This is a name associated with what to consume from. Multiple instances of a service may consume from the same topic. For example, all instances of nova-compute consume @@ -133,7 +132,7 @@ class Connection(object): """ raise NotImplementedError() - def create_worker(self, conf, topic, proxy, pool_name): + def create_worker(self, topic, proxy, pool_name): """Create a worker on this connection. A worker is like a regular consumer of messages directed to a @@ -143,7 +142,6 @@ class Connection(object): be asked to process it. Load is distributed across the members of the pool in round-robin fashion. - :param conf: An openstack.common.cfg configuration object. :param topic: This is a name associated with what to consume from. Multiple instances of a service may consume from the same topic. diff --git a/cinder/openstack/common/rpc/impl_qpid.py b/cinder/openstack/common/rpc/impl_qpid.py index e7b6a0b86..382a2f286 100644 --- a/cinder/openstack/common/rpc/impl_qpid.py +++ b/cinder/openstack/common/rpc/impl_qpid.py @@ -329,7 +329,7 @@ class Connection(object): if self.conf.qpid_reconnect_interval: self.connection.reconnect_interval = ( self.conf.qpid_reconnect_interval) - self.connection.hearbeat = self.conf.qpid_heartbeat + self.connection.heartbeat = self.conf.qpid_heartbeat self.connection.protocol = self.conf.qpid_protocol self.connection.tcp_nodelay = self.conf.qpid_tcp_nodelay diff --git a/cinder/openstack/common/rpc/proxy.py b/cinder/openstack/common/rpc/proxy.py index 179f4ccd5..23305d41d 100644 --- a/cinder/openstack/common/rpc/proxy.py +++ b/cinder/openstack/common/rpc/proxy.py @@ -112,11 +112,12 @@ class RpcProxy(object): self._set_version(msg, version) rpc.cast(context, self._get_topic(topic), msg) - def fanout_cast(self, context, msg, version=None): + def fanout_cast(self, context, msg, topic=None, version=None): """rpc.fanout_cast() a remote method. :param context: The request context :param msg: The message to send, including the method and args. + :param topic: Override the topic for this message. :param version: (Optional) Override the requested API version in this message. @@ -124,7 +125,7 @@ class RpcProxy(object): from the remote method. """ self._set_version(msg, version) - rpc.fanout_cast(context, self.topic, msg) + rpc.fanout_cast(context, self._get_topic(topic), msg) def cast_to_server(self, context, server_params, msg, topic=None, version=None): @@ -144,13 +145,15 @@ class RpcProxy(object): self._set_version(msg, version) rpc.cast_to_server(context, server_params, self._get_topic(topic), msg) - def fanout_cast_to_server(self, context, server_params, msg, version=None): + def fanout_cast_to_server(self, context, server_params, msg, topic=None, + version=None): """rpc.fanout_cast_to_server() a remote method. :param context: The request context :param server_params: Server parameters. See rpc.cast_to_server() for details. :param msg: The message to send, including the method and args. + :param topic: Override the topic for this message. :param version: (Optional) Override the requested API version in this message. @@ -158,4 +161,5 @@ class RpcProxy(object): return values. """ self._set_version(msg, version) - rpc.fanout_cast_to_server(context, server_params, self.topic, msg) + rpc.fanout_cast_to_server(context, server_params, + self._get_topic(topic), msg) diff --git a/cinder/openstack/common/setup.py b/cinder/openstack/common/setup.py index ee7dc3627..628f5e3c9 100644 --- a/cinder/openstack/common/setup.py +++ b/cinder/openstack/common/setup.py @@ -35,7 +35,6 @@ def parse_mailmap(mailmap='.mailmap'): for l in fp: l = l.strip() if not l.startswith('#') and ' ' in l: - print l canonical_email, alias = [x for x in l.split(' ') if x.startswith('<')] mapping[alias] = canonical_email @@ -53,7 +52,6 @@ def canonicalize_emails(changelog, mapping): # Get requirements from the first file that exists def get_reqs_from_files(requirements_files): - reqs_in = [] for requirements_file in requirements_files: if os.path.exists(requirements_file): return open(requirements_file, 'r').read().split('\n') @@ -145,8 +143,8 @@ def _get_git_next_version_suffix(branch_name): # where the bit after the last . is the short sha, and the bit between # the last and second to last is the revno count (revno, sha) = post_version.split(".")[-2:] - first_half = "%(milestonever)s~%(datestamp)s" % locals() - second_half = "%(revno_prefix)s%(revno)s.%(sha)s" % locals() + first_half = "%s~%s" % (milestonever, datestamp) + second_half = "%s%s.%s" % (revno_prefix, revno, sha) return ".".join((first_half, second_half)) diff --git a/cinder/openstack/common/timeutils.py b/cinder/openstack/common/timeutils.py index 5eeaf70aa..4416a3b19 100644 --- a/cinder/openstack/common/timeutils.py +++ b/cinder/openstack/common/timeutils.py @@ -21,7 +21,6 @@ Time related utilities and helper functions. import calendar import datetime -import time import iso8601 diff --git a/cinder/tests/notifier/__init__.py b/cinder/tests/notifier/__init__.py deleted file mode 100644 index 643e7c463..000000000 --- a/cinder/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 cinder.tests import * diff --git a/cinder/tests/notifier/test_list_notifier.py b/cinder/tests/notifier/test_list_notifier.py deleted file mode 100644 index 83d5b16c4..000000000 --- a/cinder/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 cinder -from cinder.openstack.common import log as logging -import cinder.notifier.api -import cinder.notifier.log_notifier -import cinder.notifier.no_op_notifier -from cinder.notifier import list_notifier -from cinder 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('cinder.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(cinder.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(cinder.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='cinder.notifier.list_notifier', - list_notifier_drivers=['cinder.notifier.no_op_notifier', - 'cinder.notifier.no_op_notifier']) - cinder.notifier.api.notify('publisher_id', 'event_type', - cinder.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='cinder.notifier.list_notifier', - list_notifier_drivers=['cinder.notifier.no_op_notifier', - 'cinder.notifier.log_notifier']) - cinder.notifier.api.notify('publisher_id', - 'event_type', cinder.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='cinder.notifier.list_notifier', - list_notifier_drivers=['cinder.notifier.no_op_notifier', - 'cinder.notifier.logo_notifier', - 'fdsjgsdfhjkhgsfkj']) - cinder.notifier.api.notify('publisher_id', - 'event_type', cinder.notifier.api.WARN, dict(a=3)) - self.assertEqual(self.exception_count, 2) - self.assertEqual(self.notify_count, 1) diff --git a/cinder/tests/scheduler/test_scheduler.py b/cinder/tests/scheduler/test_scheduler.py index d4d798028..761698338 100644 --- a/cinder/tests/scheduler/test_scheduler.py +++ b/cinder/tests/scheduler/test_scheduler.py @@ -26,7 +26,7 @@ from cinder import context from cinder import db from cinder import exception from cinder import flags -from cinder.notifier import api as notifier +from cinder.openstack.common.notifier import api as notifier from cinder.openstack.common import rpc from cinder.openstack.common.rpc import common as rpc_common from cinder.openstack.common import timeutils diff --git a/cinder/tests/test_exception.py b/cinder/tests/test_exception.py index 717fb3d85..86956c97a 100644 --- a/cinder/tests/test_exception.py +++ b/cinder/tests/test_exception.py @@ -21,7 +21,7 @@ from cinder import exception class FakeNotifier(object): - """Acts like the cinder.notifier.api module.""" + """Acts like the cinder.openstack.common.notifier.api module.""" ERROR = 88 def __init__(self): diff --git a/cinder/tests/test_notifier.py b/cinder/tests/test_notifier.py deleted file mode 100644 index f4291044d..000000000 --- a/cinder/tests/test_notifier.py +++ /dev/null @@ -1,133 +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 cinder -from cinder import flags -from cinder.openstack.common import log as logging -import cinder.notifier.no_op_notifier -from cinder.notifier import api as notifier_api -from cinder import test - - -class NotifierTestCase(test.TestCase): - """Test case for notifications""" - def setUp(self): - super(NotifierTestCase, self).setUp() - self.flags(notification_driver='cinder.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(cinder.notifier.no_op_notifier, 'notify', - mock_notify) - - notifier_api.notify('publisher_id', 'event_type', - cinder.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(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.stubs.Set(cinder.notifier.no_op_notifier, 'notify', - message_assert) - notifier_api.notify('publisher_id', 'event_type', - cinder.notifier.api.WARN, dict(a=3)) - - def test_send_rabbit_notification(self): - self.stubs.Set(cinder.flags.FLAGS, 'notification_driver', - 'cinder.notifier.rabbit_notifier') - self.mock_notify = False - - def mock_notify(cls, *args): - self.mock_notify = True - - self.stubs.Set(cinder.openstack.common.rpc, 'notify', mock_notify) - notifier_api.notify('publisher_id', 'event_type', - cinder.notifier.api.WARN, dict(a=3)) - - self.assertEqual(self.mock_notify, True) - - def test_invalid_priority(self): - self.assertRaises(cinder.notifier.api.BadPriorityException, - notifier_api.notify, 'publisher_id', - 'event_type', 'not a priority', dict(a=3)) - - def test_rabbit_priority_queue(self): - flags.DECLARE('notification_topics', 'cinder.notifier.rabbit_notifier') - self.stubs.Set(cinder.flags.FLAGS, 'notification_driver', - 'cinder.notifier.rabbit_notifier') - self.stubs.Set(cinder.flags.FLAGS, 'notification_topics', - ['testnotify', ]) - - self.test_topic = None - - def mock_notify(context, topic, msg): - self.test_topic = topic - - self.stubs.Set(cinder.openstack.common.rpc, 'notify', mock_notify) - notifier_api.notify('publisher_id', 'event_type', 'DEBUG', dict(a=3)) - self.assertEqual(self.test_topic, 'testnotify.debug') - - def test_error_notification(self): - self.stubs.Set(cinder.flags.FLAGS, 'notification_driver', - 'cinder.notifier.rabbit_notifier') - self.stubs.Set(cinder.flags.FLAGS, 'publish_errors', True) - LOG = logging.getLogger('cinder') - logging.setup("cinder") - msgs = [] - - def mock_notify(context, topic, data): - msgs.append(data) - - self.stubs.Set(cinder.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 = cinder.notifier.api.notify_decorator( - 'example_api', - example_api) - - def mock_notify(cls, *args): - self.notify_called = True - - self.stubs.Set(cinder.notifier.no_op_notifier, 'notify', - mock_notify) - - self.assertEqual(3, example_api(1, 2)) - self.assertEqual(self.notify_called, True) diff --git a/cinder/utils.py b/cinder/utils.py index fbe29efb0..706e9f2f7 100644 --- a/cinder/utils.py +++ b/cinder/utils.py @@ -805,10 +805,11 @@ def monkey_patch(): You can set decorators for each modules using FLAGS.monkey_patch_modules. The format is "Module path:Decorator function". - Example: 'cinder.api.ec2.cloud:cinder.notifier.api.notify_decorator' + Example: 'cinder.api.ec2.cloud:' \ + cinder.openstack.common.notifier.api.notify_decorator' Parameters of the decorator is as follows. - (See cinder.notifier.api.notify_decorator) + (See cinder.openstack.common.notifier.api.notify_decorator) name - name of the function function - object of the function diff --git a/etc/cinder/cinder.conf.sample b/etc/cinder/cinder.conf.sample index ee97e6503..9a382e5dc 100644 --- a/etc/cinder/cinder.conf.sample +++ b/etc/cinder/cinder.conf.sample @@ -118,13 +118,13 @@ ###### (BoolOpt) Whether to log monkey patching # monkey_patch=false ###### (ListOpt) List of modules/decorators to monkey patch -# monkey_patch_modules="cinder.api.ec2.cloud:cinder.notifier.api.notify_decorator,cinder.compute.api:cinder.notifier.api.notify_decorator" +# monkey_patch_modules="cinder.api.ec2.cloud:cinder.openstack.common.notifier.api.notify_decorator,cinder.compute.api:cinder.openstack.common.notifier.api.notify_decorator" ###### (StrOpt) ip address of this host # my_ip="10.0.0.1" ###### (StrOpt) availability zone of this node # node_availability_zone="cinder" ###### (StrOpt) Default driver for sending notifications -# notification_driver="cinder.notifier.no_op_notifier" +# notification_driver="cinder.openstack.common.notifier.no_op_notifier" ###### (StrOpt) kernel image that indicates not to use a kernel, but to use a raw disk image instead # null_kernel="nokernel" ###### (ListOpt) Specify list of extensions to load when using osapi_compute_extension option with cinder.api.openstack.compute.contrib.select_extensions @@ -450,12 +450,12 @@ ###### (StrOpt) Tilera command line program for Bare-metal driver # tile_monitor="/usr/local/TileraMDE/bin/tile-monitor" -######### defined in cinder.notifier.list_notifier ######### +######### defined in cinder.openstack.common.notifier.list_notifier ######### ###### (MultiStrOpt) List of drivers to send notifications -# list_notifier_drivers="cinder.notifier.no_op_notifier" +# list_notifier_drivers="cinder.openstack.common.notifier.no_op_notifier" -######### defined in cinder.notifier.rabbit_notifier ######### +######### defined in cinder.openstack.common.notifier.rabbit_notifier ######### ###### (ListOpt) AMQP topic used for Cinder notifications # notification_topics="notifications" diff --git a/openstack-common.conf b/openstack-common.conf index 9456869ec..d75d4f79e 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,exception,excutils,gettextutils,importutils,iniparser,jsonutils,local,rpc,timeutils,log,setup +modules=cfg,exception,excutils,gettextutils,importutils,iniparser,jsonutils,local,rpc,timeutils,log,setup,notifier # The base module to hold the copy of openstack.common base=cinder -- 2.45.2